Merge tag 'asoc-v5.6-2' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie...
authorTakashi Iwai <tiwai@suse.de>
Wed, 5 Feb 2020 11:33:45 +0000 (12:33 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 5 Feb 2020 11:33:45 +0000 (12:33 +0100)
ASoC: Fixes for v5.6

A collection of updates for bugs fixed since the initial pull
request, the most important one being the addition of COMMON_CLK
for wcd934x which is needed for MFD to be merged.

1939 files changed:
.mailmap
Documentation/ABI/stable/sysfs-driver-mlxreg-io
Documentation/ABI/testing/sysfs-platform-mellanox-bootctl
Documentation/admin-guide/device-mapper/dm-integrity.rst
Documentation/admin-guide/device-mapper/index.rst
Documentation/admin-guide/devices.txt
Documentation/admin-guide/ext4.rst
Documentation/admin-guide/xfs.rst
Documentation/dev-tools/kcov.rst
Documentation/dev-tools/kselftest.rst
Documentation/dev-tools/kunit/index.rst
Documentation/dev-tools/kunit/kunit-tool.rst [new file with mode: 0644]
Documentation/dev-tools/kunit/start.rst
Documentation/dev-tools/kunit/usage.rst
Documentation/devicetree/bindings/arm/sunxi.yaml
Documentation/devicetree/bindings/bus/allwinner,sun50i-a64-de2.yaml
Documentation/devicetree/bindings/bus/allwinner,sun8i-a23-rsb.yaml
Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml
Documentation/devicetree/bindings/crypto/allwinner,sun4i-a10-crypto.yaml
Documentation/devicetree/bindings/display/allwinner,sun6i-a31-mipi-dsi.yaml
Documentation/devicetree/bindings/display/panel/ronbo,rb070d30.yaml
Documentation/devicetree/bindings/dma/allwinner,sun4i-a10-dma.yaml
Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml
Documentation/devicetree/bindings/dma/allwinner,sun6i-a31-dma.yaml
Documentation/devicetree/bindings/i2c/allwinner,sun6i-a31-p2wi.yaml
Documentation/devicetree/bindings/i2c/i2c-at91.txt
Documentation/devicetree/bindings/iio/adc/adi,ad7292.yaml
Documentation/devicetree/bindings/iio/adc/allwinner,sun8i-a33-ths.yaml
Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml
Documentation/devicetree/bindings/interrupt-controller/allwinner,sun4i-a10-ic.yaml
Documentation/devicetree/bindings/interrupt-controller/allwinner,sun7i-a20-sc-nmi.yaml
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-csi.yaml
Documentation/devicetree/bindings/media/allwinner,sun4i-a10-ir.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra124-mc.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-emc.yaml
Documentation/devicetree/bindings/memory-controllers/nvidia,tegra30-mc.yaml
Documentation/devicetree/bindings/mfd/allwinner,sun4i-a10-ts.yaml
Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml
Documentation/devicetree/bindings/mtd/allwinner,sun4i-a10-nand.yaml
Documentation/devicetree/bindings/net/allwinner,sun4i-a10-emac.yaml
Documentation/devicetree/bindings/net/allwinner,sun4i-a10-mdio.yaml
Documentation/devicetree/bindings/net/allwinner,sun7i-a20-gmac.yaml
Documentation/devicetree/bindings/net/allwinner,sun8i-a83t-emac.yaml
Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml
Documentation/devicetree/bindings/net/can/tcan4x5x.txt
Documentation/devicetree/bindings/net/snps,dwmac.yaml
Documentation/devicetree/bindings/net/ti,cpsw-switch.yaml
Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml
Documentation/devicetree/bindings/phy/allwinner,sun6i-a31-mipi-dphy.yaml
Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml
Documentation/devicetree/bindings/pwm/allwinner,sun4i-a10-pwm.yaml
Documentation/devicetree/bindings/remoteproc/st,stm32-rproc.yaml
Documentation/devicetree/bindings/reset/brcm,brcmstb-reset.txt
Documentation/devicetree/bindings/rtc/allwinner,sun4i-a10-rtc.yaml
Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
Documentation/devicetree/bindings/serio/allwinner,sun4i-a10-ps2.yaml
Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-codec.yaml
Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml
Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml
Documentation/devicetree/bindings/sound/allwinner,sun50i-a64-codec-analog.yaml
Documentation/devicetree/bindings/sound/allwinner,sun8i-a23-codec-analog.yaml
Documentation/devicetree/bindings/sound/allwinner,sun8i-a33-codec.yaml
Documentation/devicetree/bindings/spi/allwinner,sun4i-a10-spi.yaml
Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml
Documentation/devicetree/bindings/spi/spi-controller.yaml
Documentation/devicetree/bindings/timer/allwinner,sun4i-a10-timer.yaml
Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.yaml
Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml
Documentation/features/debug/gcov-profile-all/arch-support.txt
Documentation/filesystems/erofs.txt
Documentation/filesystems/overlayfs.rst [moved from Documentation/filesystems/overlayfs.txt with 99% similarity]
Documentation/kbuild/kconfig-language.rst
Documentation/kbuild/makefiles.rst
Documentation/media/v4l-drivers/meye.rst
Documentation/networking/dsa/sja1105.rst
Documentation/networking/ip-sysctl.txt
Documentation/networking/j1939.rst
Documentation/networking/netdev-FAQ.rst
Documentation/process/coding-style.rst
Documentation/process/embargoed-hardware-issues.rst
Documentation/process/index.rst
Documentation/riscv/index.rst
Documentation/riscv/patch-acceptance.rst [new file with mode: 0644]
Documentation/scsi/smartpqi.txt
Documentation/sound/alsa-configuration.rst
Documentation/sound/kernel-api/writing-an-alsa-driver.rst
Documentation/translations/it_IT/process/coding-style.rst
Documentation/translations/zh_CN/process/coding-style.rst
MAINTAINERS
Makefile
arch/arc/include/asm/entry-arcv2.h
arch/arc/include/asm/hugepage.h
arch/arc/kernel/asm-offsets.c
arch/arc/kernel/unwind.c
arch/arc/plat-eznps/Kconfig
arch/arm/Kconfig
arch/arm/boot/dts/am335x-sancloud-bbe.dts
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/am571x-idk.dts
arch/arm/boot/dts/am572x-idk-common.dtsi
arch/arm/boot/dts/am57xx-beagle-x15-common.dtsi
arch/arm/boot/dts/aspeed-bmc-ibm-rainier.dts
arch/arm/boot/dts/aspeed-bmc-opp-tacoma.dts
arch/arm/boot/dts/aspeed-g6.dtsi
arch/arm/boot/dts/bcm-cygnus.dtsi
arch/arm/boot/dts/bcm2711.dtsi
arch/arm/boot/dts/bcm283x.dtsi
arch/arm/boot/dts/bcm5301x.dtsi
arch/arm/boot/dts/e60k02.dtsi
arch/arm/boot/dts/imx6dl-icore-mipi.dts
arch/arm/boot/dts/imx6q-dhcom-pdk2.dts
arch/arm/boot/dts/imx6q-dhcom-som.dtsi
arch/arm/boot/dts/imx6qdl-sabresd.dtsi
arch/arm/boot/dts/imx6sl-evk.dts
arch/arm/boot/dts/imx6sll-evk.dts
arch/arm/boot/dts/imx6sx-sdb-reva.dts
arch/arm/boot/dts/imx6sx-sdb.dts
arch/arm/boot/dts/imx6ul-14x14-evk.dtsi
arch/arm/boot/dts/imx7s-colibri.dtsi
arch/arm/boot/dts/imx7ulp.dtsi
arch/arm/boot/dts/meson8.dtsi
arch/arm/boot/dts/mmp3.dtsi
arch/arm/boot/dts/sun8i-a83t-cubietruck-plus.dts
arch/arm/configs/exynos_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/shmobile_defconfig
arch/arm/crypto/curve25519-glue.c
arch/arm/kernel/process.c
arch/arm/mach-bcm/bcm2711.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-imx/cpu.c
arch/arm/mach-mmp/pxa168.h
arch/arm/mach-mmp/time.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/pdata-quirks.c
arch/arm/mach-vexpress/spc.c
arch/arm64/Kconfig
arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino-emmc.dts
arch/arm64/boot/dts/allwinner/sun50i-a64-olinuxino.dts
arch/arm64/boot/dts/altera/socfpga_stratix10.dtsi
arch/arm64/boot/dts/amlogic/meson-sm1-sei610.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
arch/arm64/boot/dts/freescale/imx8mm.dtsi
arch/arm64/boot/dts/freescale/imx8mq-librem5-devkit.dts
arch/arm64/boot/dts/intel/socfpga_agilex.dtsi
arch/arm64/boot/dts/rockchip/rk3328-a1.dts
arch/arm64/include/asm/pgtable-prot.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/unistd.h
arch/arm64/include/uapi/asm/unistd.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/process.c
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/sys_regs.h
arch/arm64/mm/fault.c
arch/arm64/mm/mmu.c
arch/hexagon/include/asm/atomic.h
arch/hexagon/include/asm/bitops.h
arch/hexagon/include/asm/cmpxchg.h
arch/hexagon/include/asm/futex.h
arch/hexagon/include/asm/io.h
arch/hexagon/include/asm/spinlock.h
arch/hexagon/kernel/stacktrace.c
arch/hexagon/kernel/vm_entry.S
arch/ia64/mm/init.c
arch/mips/Kconfig
arch/mips/boot/compressed/Makefile
arch/mips/cavium-octeon/executive/cvmx-bootmem.c
arch/mips/include/asm/cpu-type.h
arch/mips/include/asm/thread_info.h
arch/mips/include/asm/vdso/gettimeofday.h
arch/mips/kernel/cacheinfo.c
arch/mips/net/ebpf_jit.c
arch/mips/vdso/vgettimeofday.c
arch/nds32/include/asm/cacheflush.h
arch/nds32/include/asm/pgtable.h
arch/nios2/mm/ioremap.c
arch/parisc/Kconfig
arch/parisc/include/asm/cmpxchg.h
arch/parisc/include/asm/kexec.h
arch/parisc/kernel/Makefile
arch/parisc/kernel/drivers.c
arch/parisc/kernel/pdt.c
arch/parisc/kernel/process.c
arch/parisc/mm/init.c
arch/powerpc/include/asm/spinlock.h
arch/powerpc/include/asm/uaccess.h
arch/powerpc/kernel/irq.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/lib/string_32.S
arch/powerpc/lib/string_64.S
arch/powerpc/mm/mem.c
arch/powerpc/mm/nohash/8xx.c
arch/powerpc/mm/slice.c
arch/powerpc/net/bpf_jit32.h
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/platforms/pseries/cmm.c
arch/powerpc/platforms/pseries/setup.c
arch/riscv/Kconfig
arch/riscv/Kconfig.socs
arch/riscv/boot/Makefile
arch/riscv/boot/dts/sifive/fu540-c000.dtsi
arch/riscv/include/asm/asm-prototypes.h
arch/riscv/include/asm/csr.h
arch/riscv/include/asm/pgtable.h
arch/riscv/kernel/entry.S
arch/riscv/kernel/ftrace.c
arch/riscv/kernel/head.S
arch/riscv/kernel/irq.c
arch/riscv/kernel/process.c
arch/riscv/kernel/riscv_ksyms.c
arch/riscv/kernel/vdso/Makefile
arch/riscv/lib/tishift.S
arch/riscv/lib/uaccess.S
arch/riscv/mm/Makefile
arch/riscv/mm/cacheflush.c
arch/riscv/mm/init.c
arch/riscv/net/bpf_jit_comp.c
arch/s390/Kconfig
arch/s390/include/asm/setup.h
arch/s390/include/asm/timex.h
arch/s390/include/asm/uv.h
arch/s390/kernel/early.c
arch/s390/kernel/mcount.S
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/setup.c
arch/s390/kernel/smp.c
arch/s390/kernel/unwind_bc.c
arch/s390/lib/spinlock.c
arch/s390/lib/test_unwind.c
arch/s390/mm/init.c
arch/s390/mm/kasan_init.c
arch/s390/purgatory/.gitignore
arch/s390/purgatory/Makefile
arch/s390/purgatory/string.c [new file with mode: 0644]
arch/sh/drivers/platform_early.c
arch/sh/kernel/kgdb.c
arch/sh/mm/init.c
arch/sparc/net/bpf_jit_comp_32.c
arch/um/Kconfig
arch/um/include/asm/ptrace-generic.h
arch/um/kernel/process.c
arch/x86/boot/compressed/Makefile
arch/x86/boot/compressed/head_64.S
arch/x86/events/core.c
arch/x86/events/intel/bts.c
arch/x86/events/intel/uncore_snb.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/mce/amd.c
arch/x86/kernel/cpu/mce/core.c
arch/x86/kernel/cpu/mce/therm_throt.c
arch/x86/kernel/cpu/resctrl/core.c
arch/x86/kernel/cpu/resctrl/rdtgroup.c
arch/x86/kernel/early-quirks.c
arch/x86/kernel/fpu/xstate.c
arch/x86/kernel/ftrace.c
arch/x86/kvm/cpuid.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/platform/efi/quirks.c
arch/x86/um/tls_32.c
arch/x86/um/tls_64.c
arch/xtensa/Kconfig
arch/xtensa/kernel/process.c
block/bio.c
block/blk-cgroup.c
block/blk-core.c
block/blk-flush.c
block/blk-iocost.c
block/blk-map.c
block/blk-merge.c
block/blk-settings.c
block/blk.h
block/bsg-lib.c
block/compat_ioctl.c
crypto/adiantum.c
crypto/asymmetric_keys/asym_tpm.c
crypto/asymmetric_keys/public_key.c
crypto/essiv.c
drivers/acpi/device_pm.c
drivers/android/binder.c
drivers/ata/ahci_brcm.c
drivers/ata/libahci_platform.c
drivers/ata/libata-core.c
drivers/ata/sata_fsl.c
drivers/ata/sata_mv.c
drivers/ata/sata_nv.c
drivers/atm/eni.c
drivers/base/devtmpfs.c
drivers/base/firmware_loader/builtin/Makefile
drivers/base/platform.c
drivers/block/nbd.c
drivers/block/null_blk_zoned.c
drivers/block/pktcdvd.c
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/bus/ti-sysc.c
drivers/char/agp/isoch.c
drivers/char/random.c
drivers/char/tpm/tpm-dev-common.c
drivers/char/tpm/tpm-dev.h
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm2-cmd.c
drivers/char/tpm/tpm_ftpm_tee.c
drivers/char/tpm/tpm_tis_core.c
drivers/clk/at91/at91sam9260.c
drivers/clk/at91/at91sam9rl.c
drivers/clk/at91/at91sam9x5.c
drivers/clk/at91/pmc.c
drivers/clk/at91/sama5d2.c
drivers/clk/at91/sama5d4.c
drivers/clk/clk.c
drivers/clk/imx/clk-composite-8m.c
drivers/clk/imx/clk-imx7ulp.c
drivers/clk/imx/clk-pll14xx.c
drivers/clk/mmp/clk-of-mmp2.c
drivers/clk/qcom/gcc-sc7180.c
drivers/clk/qcom/gcc-sdm845.c
drivers/clk/qcom/gpucc-msm8998.c
drivers/clk/samsung/clk-exynos5420.c
drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
drivers/clk/sunxi-ng/ccu-sun8i-r.c
drivers/clk/sunxi-ng/ccu-sun8i-r40.c
drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
drivers/clk/sunxi-ng/ccu-sun8i-v3s.h
drivers/clk/tegra/clk.c
drivers/clk/ti/clk-dra7-atl.c
drivers/clocksource/timer-riscv.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/vexpress-spc-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/driver.c
drivers/cpuidle/governors/teo.c
drivers/crypto/hisilicon/sec2/sec.h
drivers/crypto/hisilicon/sec2/sec_crypto.c
drivers/crypto/hisilicon/sec2/sec_main.c
drivers/devfreq/Kconfig
drivers/devfreq/devfreq.c
drivers/dma-buf/sync_file.c
drivers/dma/dma-jz4780.c
drivers/dma/ioat/dma.c
drivers/dma/k3dma.c
drivers/dma/virt-dma.c
drivers/edac/Kconfig
drivers/edac/sifive_edac.c
drivers/firmware/broadcom/tee_bnxt_fw.c
drivers/firmware/efi/earlycon.c
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/gop.c
drivers/firmware/efi/libstub/random.c
drivers/firmware/efi/rci2-table.c
drivers/gpio/Kconfig
drivers/gpio/gpio-aspeed-sgpio.c
drivers/gpio/gpio-mockup.c
drivers/gpio/gpio-mpc8xxx.c
drivers/gpio/gpio-pca953x.c
drivers/gpio/gpio-thunderx.c
drivers/gpio/gpio-xgs-iproc.c
drivers/gpio/gpio-xtensa.c
drivers/gpio/gpio-zynq.c
drivers/gpio/gpiolib-acpi.c
drivers/gpio/gpiolib-of.c
drivers/gpio/gpiolib.c
drivers/gpu/drm/amd/acp/Kconfig
drivers/gpu/drm/amd/amdgpu/Kconfig
drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.h
drivers/gpu/drm/amd/amdgpu/df_v3_6.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v10_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdkfd/Kconfig
drivers/gpu/drm/amd/display/Kconfig
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/core/dc_link_ddc.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/dce/dce_aux.c
drivers/gpu/drm/amd/display/dc/dcn20/Makefile
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_stream_encoder.c
drivers/gpu/drm/amd/display/dc/dcn21/Makefile
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/dsc/Makefile
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
drivers/gpu/drm/amd/display/include/i2caux_interface.h
drivers/gpu/drm/amd/display/modules/freesync/freesync.c
drivers/gpu/drm/amd/display/modules/inc/mod_freesync.h
drivers/gpu/drm/amd/powerplay/amdgpu_smu.c
drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
drivers/gpu/drm/amd/powerplay/inc/amdgpu_smu.h
drivers/gpu/drm/amd/powerplay/navi10_ppt.c
drivers/gpu/drm/amd/powerplay/vega20_ppt.c
drivers/gpu/drm/arm/malidp_mw.c
drivers/gpu/drm/drm_dp_mst_topology.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/exynos/exynos_drm_gsc.c
drivers/gpu/drm/i915/display/intel_audio.c
drivers/gpu/drm/i915/display/intel_ddi.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/display/intel_display_power.c
drivers/gpu/drm/i915/display/intel_dp.c
drivers/gpu/drm/i915/display/intel_fbc.c
drivers/gpu/drm/i915/display/intel_frontbuffer.c
drivers/gpu/drm/i915/display/intel_frontbuffer.h
drivers/gpu/drm/i915/display/intel_hdcp.c
drivers/gpu/drm/i915/display/intel_hdcp.h
drivers/gpu/drm/i915/display/intel_hdmi.c
drivers/gpu/drm/i915/display/intel_overlay.c
drivers/gpu/drm/i915/gem/i915_gem_clflush.c
drivers/gpu/drm/i915/gem/i915_gem_context.c
drivers/gpu/drm/i915/gem/i915_gem_domain.c
drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c
drivers/gpu/drm/i915/gem/i915_gem_object.c
drivers/gpu/drm/i915/gem/i915_gem_object.h
drivers/gpu/drm/i915/gem/i915_gem_object_types.h
drivers/gpu/drm/i915/gt/intel_context.c
drivers/gpu/drm/i915/gt/intel_gt_pm.c
drivers/gpu/drm/i915/gt/intel_lrc.c
drivers/gpu/drm/i915/gt/intel_ring_submission.c
drivers/gpu/drm/i915/gvt/dmabuf.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/hypercall.h
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mpt.h
drivers/gpu/drm/i915/gvt/vgpu.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/i915/i915_pmu.c
drivers/gpu/drm/i915/i915_pmu.h
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/i915/i915_request.c
drivers/gpu/drm/i915/i915_scheduler.c
drivers/gpu/drm/i915/i915_sw_fence_work.c
drivers/gpu/drm/i915/i915_vma.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/selftests/i915_random.h
drivers/gpu/drm/mcde/mcde_dsi.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_dsi.c
drivers/gpu/drm/meson/meson_venc_cvbs.c
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/nouveau/dispnv50/atom.h
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/dispnv50/head.c
drivers/gpu/drm/nouveau/nouveau_connector.c
drivers/gpu/drm/nouveau/nouveau_connector.h
drivers/gpu/drm/panfrost/panfrost_devfreq.c
drivers/gpu/drm/panfrost/panfrost_drv.c
drivers/gpu/drm/panfrost/panfrost_gem.c
drivers/gpu/drm/panfrost/panfrost_gem.h
drivers/gpu/drm/panfrost/panfrost_perfcnt.c
drivers/gpu/drm/panfrost/panfrost_perfcnt.h
drivers/gpu/drm/rockchip/cdn-dp-core.h
drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
drivers/gpu/drm/sun4i/sun4i_tcon.c
drivers/gpu/drm/sun4i/sun4i_tcon.h
drivers/gpu/drm/virtio/virtgpu_plane.c
drivers/hid/hid-asus.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-input.c
drivers/hid/hid-ite.c
drivers/hid/hid-multitouch.c
drivers/hid/hid-quirks.c
drivers/hid/hid-steam.c
drivers/hid/hidraw.c
drivers/hid/i2c-hid/i2c-hid-core.c
drivers/hid/intel-ish-hid/ipc/hw-ish.h
drivers/hid/intel-ish-hid/ipc/pci-ish.c
drivers/hid/uhid.c
drivers/hid/usbhid/hiddev.c
drivers/hid/wacom_wac.c
drivers/hwtracing/coresight/coresight-etm4x.c
drivers/hwtracing/intel_th/core.c
drivers/hwtracing/intel_th/intel_th.h
drivers/hwtracing/intel_th/msu.c
drivers/hwtracing/intel_th/pci.c
drivers/i2c/busses/i2c-at91-core.c
drivers/i2c/busses/i2c-bcm2835.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/i2c-core-base.c
drivers/iio/accel/st_accel_core.c
drivers/iio/adc/ad7124.c
drivers/iio/adc/ad7606.c
drivers/iio/adc/ad7949.c
drivers/iio/adc/intel_mrfld_adc.c
drivers/iio/adc/max1027.c
drivers/iio/adc/max9611.c
drivers/iio/chemical/Kconfig
drivers/iio/humidity/hdc100x.c
drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
drivers/iio/industrialio-buffer.c
drivers/iio/light/vcnl4000.c
drivers/iio/temperature/ltc2983.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/counters.c
drivers/infiniband/core/ib_core_uverbs.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/qplib_fp.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/hfi1/iowait.c
drivers/infiniband/hw/hfi1/sdma.c
drivers/infiniband/hw/hfi1/tid_rdma.c
drivers/infiniband/hw/hfi1/verbs.h
drivers/infiniband/hw/i40iw/i40iw_verbs.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/mlx5/cmd.c
drivers/infiniband/hw/mlx5/cmd.h
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mlx5_ib.h
drivers/infiniband/sw/rxe/rxe_recv.c
drivers/infiniband/sw/rxe/rxe_req.c
drivers/infiniband/sw/rxe/rxe_resp.c
drivers/infiniband/ulp/opa_vnic/opa_vnic_ethtool.c
drivers/input/evdev.c
drivers/input/input.c
drivers/input/keyboard/imx_sc_key.c
drivers/input/misc/uinput.c
drivers/interconnect/qcom/Kconfig
drivers/interconnect/qcom/msm8974.c
drivers/interconnect/qcom/qcs404.c
drivers/interconnect/qcom/sdm845.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
drivers/iommu/iommu.c
drivers/iommu/iova.c
drivers/irqchip/irq-ingenic.c
drivers/irqchip/irq-sifive-plic.c
drivers/md/dm-clone-metadata.c
drivers/md/dm-clone-metadata.h
drivers/md/dm-clone-target.c
drivers/md/dm-mpath.c
drivers/md/dm-snap-persistent.c
drivers/md/dm-thin-metadata.c
drivers/md/dm-thin-metadata.h
drivers/md/dm-thin.c
drivers/md/md.c
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid5-ppl.c
drivers/md/raid5.c
drivers/media/cec/cec-adap.c
drivers/media/platform/omap3isp/isppreview.c
drivers/media/usb/pulse8-cec/pulse8-cec.c
drivers/media/v4l2-core/v4l2-ioctl.c
drivers/message/fusion/mptctl.c
drivers/misc/enclosure.c
drivers/misc/habanalabs/command_submission.c
drivers/misc/habanalabs/context.c
drivers/misc/habanalabs/goya/goya.c
drivers/misc/lkdtm/bugs.c
drivers/misc/ocxl/context.c
drivers/misc/ocxl/file.c
drivers/mmc/host/mtk-sd.c
drivers/mmc/host/sdhci-msm.c
drivers/mmc/host/sdhci-of-esdhc.c
drivers/mmc/host/sdhci-pci-core.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mtd/nand/onenand/omap2.c
drivers/mtd/nand/onenand/onenand_base.c
drivers/mtd/nand/onenand/samsung_mtd.c
drivers/mtd/nand/raw/cadence-nand-controller.c
drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/raw/stm32_fmc2_nand.c
drivers/mtd/sm_ftl.c
drivers/mtd/spi-nor/spi-nor.c
drivers/net/bonding/bond_main.c
drivers/net/can/flexcan.c
drivers/net/can/m_can/tcan4x5x.c
drivers/net/can/mscan/mscan.c
drivers/net/can/usb/gs_usb.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c
drivers/net/can/xilinx_can.c
drivers/net/dsa/b53/b53_common.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/bcm_sf2_cfp.c
drivers/net/dsa/mv88e6xxx/global1.c
drivers/net/dsa/mv88e6xxx/global1.h
drivers/net/dsa/mv88e6xxx/port.c
drivers/net/dsa/ocelot/Kconfig
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/dsa/sja1105/sja1105_ptp.c
drivers/net/dsa/sja1105/sja1105_static_config.c
drivers/net/dsa/sja1105/sja1105_tas.c
drivers/net/ethernet/amazon/ena/ena_com.h
drivers/net/ethernet/amazon/ena/ena_ethtool.c
drivers/net/ethernet/amazon/ena/ena_netdev.c
drivers/net/ethernet/amd/xgbe/xgbe-ethtool.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c
drivers/net/ethernet/atheros/ag71xx.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.c
drivers/net/ethernet/broadcom/bnxt/bnxt_devlink.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_vfr.c
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/liquidio/octeon_console.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_matchall.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_mqprio.c
drivers/net/ethernet/chelsio/cxgb4/sched.c
drivers/net/ethernet/chelsio/cxgb4/sched.h
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4vf/cxgb4vf_main.c
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_common.h
drivers/net/ethernet/chelsio/cxgb4vf/t4vf_hw.c
drivers/net/ethernet/cortina/gemini.c
drivers/net/ethernet/emulex/benet/be_ethtool.c
drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/google/gve/gve_rx.c
drivers/net/ethernet/google/gve/gve_tx.c
drivers/net/ethernet/hisilicon/hip04_eth.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/huawei/hinic/hinic_ethtool.c
drivers/net/ethernet/ibm/ibmvnic.c
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/fm10k/fm10k_ethtool.c
drivers/net/ethernet/intel/i40e/i40e.h
drivers/net/ethernet/intel/i40e/i40e_adminq.c
drivers/net/ethernet/intel/i40e/i40e_ethtool.c
drivers/net/ethernet/intel/i40e/i40e_lan_hmc.c
drivers/net/ethernet/intel/i40e/i40e_main.c
drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
drivers/net/ethernet/intel/i40e/i40e_xsk.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/igb_ethtool.c
drivers/net/ethernet/intel/igc/igc_ethtool.c
drivers/net/ethernet/intel/ixgb/ixgb_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
drivers/net/ethernet/intel/ixgbevf/ethtool.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/mellanox/mlx4/crdump.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en/fs.h
drivers/net/ethernet/mellanox/mlx5/core/en/health.c
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.h
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/setup.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_rule.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
drivers/net/ethernet/mellanox/mlxfw/mlxfw_mfa2.c
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/mellanox/mlxsw/spectrum.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_qdisc.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/switchx2.c
drivers/net/ethernet/netronome/nfp/bpf/jit.c
drivers/net/ethernet/netronome/nfp/bpf/main.c
drivers/net/ethernet/netronome/nfp/bpf/offload.c
drivers/net/ethernet/netronome/nfp/flower/main.h
drivers/net/ethernet/netronome/nfp/flower/metadata.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_ethtool.c
drivers/net/ethernet/qlogic/qede/qede.h
drivers/net/ethernet/qlogic/qede/qede_filter.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/realtek/r8169_firmware.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/net_driver.h
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/socionext/sni_ave.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_dma.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ethernet/ti/Kconfig
drivers/net/ethernet/ti/Makefile
drivers/net/ethernet/ti/cpsw_ethtool.c
drivers/net/ethernet/ti/davinci_cpdma.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/fjes/fjes_ethtool.c
drivers/net/fjes/fjes_main.c
drivers/net/geneve.c
drivers/net/gtp.c
drivers/net/hamradio/6pack.c
drivers/net/hamradio/mkiss.c
drivers/net/hyperv/hyperv_net.h
drivers/net/hyperv/netvsc_drv.c
drivers/net/hyperv/rndis_filter.c
drivers/net/macvlan.c
drivers/net/netdevsim/dev.c
drivers/net/phy/Kconfig
drivers/net/phy/aquantia_main.c
drivers/net/phy/dp83867.c
drivers/net/phy/phy_device.c
drivers/net/phy/phylink.c
drivers/net/usb/lan78xx.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/r8152.c
drivers/net/usb/sierra_net.c
drivers/net/usb/usbnet.c
drivers/net/vxlan.c
drivers/net/wan/fsl_ucc_hdlc.c
drivers/net/wan/lapbether.c
drivers/net/wan/sdla.c
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/ath9k/ath9k_pci_owl_loader.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/marvell/libertas/debugfs.c
drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
drivers/net/wireless/marvell/mwifiex/tdls.c
drivers/net/wireless/marvell/mwifiex/util.h
drivers/net/wireless/mediatek/mt76/mt76x0/eeprom.c
drivers/net/xen-netback/interface.c
drivers/nfc/nxp-nci/i2c.c
drivers/nfc/pn533/usb.c
drivers/nfc/s3fwrn5/firmware.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/nvme.h
drivers/nvme/host/pci.c
drivers/nvme/host/rdma.c
drivers/nvme/target/admin-cmd.c
drivers/nvme/target/fcloop.c
drivers/nvme/target/loop.c
drivers/of/of_mdio.c
drivers/of/platform.c
drivers/pci/controller/pcie-rockchip-host.c
drivers/perf/arm_smmuv3_pmu.c
drivers/phy/motorola/phy-cpcap-usb.c
drivers/phy/motorola/phy-mapphone-mdm6600.c
drivers/phy/qualcomm/phy-qcom-qmp.c
drivers/phy/rockchip/phy-rockchip-inno-hdmi.c
drivers/pinctrl/Kconfig
drivers/pinctrl/aspeed/pinctrl-aspeed-g6.c
drivers/pinctrl/cirrus/Kconfig
drivers/pinctrl/intel/pinctrl-baytrail.c
drivers/pinctrl/intel/pinctrl-cherryview.c
drivers/pinctrl/meson/pinctrl-meson.c
drivers/pinctrl/pinctrl-ingenic.c
drivers/pinctrl/pinmux.c
drivers/platform/chrome/wilco_ec/keyboard_leds.c
drivers/platform/mellanox/mlxbf-bootctl.c
drivers/platform/mellanox/mlxbf-tmfifo.c
drivers/platform/mips/Kconfig
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/gpd-pocket-fan.c
drivers/platform/x86/hp-wmi.c
drivers/platform/x86/intel_ips.h
drivers/platform/x86/intel_pmc_core.h
drivers/platform/x86/intel_pmc_core_pltdrv.c
drivers/platform/x86/pcengines-apuv2.c
drivers/platform/x86/pmc_atom.c
drivers/powercap/intel_rapl_common.c
drivers/ptp/Kconfig
drivers/ptp/ptp_clock.c
drivers/ptp/ptp_private.h
drivers/regulator/axp20x-regulator.c
drivers/regulator/bd70528-regulator.c
drivers/regulator/core.c
drivers/regulator/max77650-regulator.c
drivers/regulator/rn5t618-regulator.c
drivers/regulator/s5m8767.c
drivers/reset/core.c
drivers/reset/reset-brcmstb.c
drivers/rtc/rtc-mc146818-lib.c
drivers/rtc/rtc-mt6397.c
drivers/rtc/rtc-sun6i.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_fba.h
drivers/s390/block/dasd_proc.c
drivers/s390/cio/device_ops.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/ap_queue.c
drivers/s390/crypto/zcrypt_ccamisc.c
drivers/s390/crypto/zcrypt_cex2a.c
drivers/s390/crypto/zcrypt_cex2c.c
drivers/s390/crypto/zcrypt_cex4.c
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_core_mpc.h
drivers/s390/net/qeth_core_sys.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l2_sys.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/qeth_l3_sys.c
drivers/scsi/aacraid/aachba.c
drivers/scsi/be2iscsi/be_cmds.h
drivers/scsi/cxgbi/libcxgbi.c
drivers/scsi/fnic/vnic_dev.c
drivers/scsi/libiscsi.c
drivers/scsi/libsas/sas_discover.c
drivers/scsi/lpfc/lpfc_bsg.c
drivers/scsi/lpfc/lpfc_debugfs.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_nvme.c
drivers/scsi/lpfc/lpfc_sli.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/qla2xxx/qla_attr.c
drivers/scsi/qla2xxx/qla_bsg.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_fw.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_mbx.c
drivers/scsi/qla2xxx/qla_nvme.c
drivers/scsi/qla2xxx/qla_sup.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/scsi/qla4xxx/ql4_os.c
drivers/scsi/scsi_transport_iscsi.c
drivers/scsi/sd.c
drivers/scsi/smartpqi/smartpqi_init.c
drivers/scsi/storvsc_drv.c
drivers/scsi/ufs/cdns-pltfrm.c
drivers/scsi/ufs/ufs_bsg.c
drivers/soc/Kconfig
drivers/soc/Makefile
drivers/soc/amlogic/meson-ee-pwrc.c
drivers/soc/sifive/Kconfig [new file with mode: 0644]
drivers/soc/sifive/Makefile [new file with mode: 0644]
drivers/soc/sifive/sifive_l2_cache.c [moved from arch/riscv/mm/sifive_l2_cache.c with 99% similarity]
drivers/soc/ti/wkup_m3_ipc.c
drivers/spi/spi-cadence.c
drivers/spi/spi-cavium-thunderx.c
drivers/spi/spi-dw.c
drivers/spi/spi-dw.h
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-fsl-spi.c
drivers/spi/spi-nxp-fspi.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-sprd.c
drivers/spi/spi-ti-qspi.c
drivers/spi/spi-uniphier.c
drivers/spi/spi.c
drivers/staging/axis-fifo/Kconfig
drivers/staging/comedi/drivers/adv_pci1710.c
drivers/staging/comedi/drivers/gsc_hpdi.c
drivers/staging/comedi/drivers/ni_routes.c
drivers/staging/exfat/exfat.h
drivers/staging/exfat/exfat_core.c
drivers/staging/exfat/exfat_super.c
drivers/staging/fbtft/fb_uc1611.c
drivers/staging/fbtft/fb_watterott.c
drivers/staging/fbtft/fbtft-core.c
drivers/staging/hp/Kconfig
drivers/staging/isdn/gigaset/usb-gigaset.c
drivers/staging/media/ipu3/include/intel-ipu3.h
drivers/staging/octeon/Kconfig
drivers/staging/qlge/qlge_ethtool.c
drivers/staging/rtl8188eu/os_dep/usb_intf.c
drivers/staging/rtl8712/usb_intf.c
drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
drivers/staging/vt6656/baseband.c
drivers/staging/vt6656/card.c
drivers/staging/vt6656/device.h
drivers/staging/vt6656/main_usb.c
drivers/staging/vt6656/usbpipe.c
drivers/staging/vt6656/usbpipe.h
drivers/staging/vt6656/wcmd.c
drivers/staging/wfx/data_tx.c
drivers/staging/wfx/data_tx.h
drivers/staging/wfx/hif_tx_mib.h
drivers/staging/wfx/main.c
drivers/staging/wfx/queue.c
drivers/staging/wfx/sta.c
drivers/staging/wlan-ng/Kconfig
drivers/target/iscsi/cxgbit/cxgbit_main.c
drivers/target/target_core_iblock.c
drivers/tee/optee/shm_pool.c
drivers/thermal/Kconfig
drivers/thermal/qcom/tsens.c
drivers/tty/serdev/core.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/msm_serial.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sprd_serial.c
drivers/usb/atm/ueagle-atm.c
drivers/usb/atm/usbatm.c
drivers/usb/cdns3/gadget.c
drivers/usb/chipidea/host.c
drivers/usb/common/usb-conn-gpio.c
drivers/usb/core/config.c
drivers/usb/core/hcd.c
drivers/usb/core/hub.c
drivers/usb/core/urb.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_ecm.c
drivers/usb/gadget/function/f_fs.c
drivers/usb/gadget/function/f_rndis.c
drivers/usb/gadget/udc/Kconfig
drivers/usb/host/ehci-q.c
drivers/usb/host/ohci-da8xx.c
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/misc/adutux.c
drivers/usb/misc/idmouse.c
drivers/usb/mon/mon_bin.c
drivers/usb/musb/jz4740.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musbhsdma.c
drivers/usb/roles/class.c
drivers/usb/serial/ch341.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/usb-serial-simple.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/usb-wwan.h
drivers/usb/serial/usb_wwan.c
drivers/usb/storage/scsiglue.c
drivers/usb/typec/class.c
drivers/usb/typec/tcpm/Kconfig
drivers/usb/typec/tcpm/tcpci.c
drivers/usb/typec/ucsi/ucsi.h
drivers/usb/usbip/usbip_common.c
drivers/usb/usbip/vhci_rx.c
drivers/virtio/virtio_balloon.c
drivers/watchdog/Kconfig
drivers/watchdog/imx7ulp_wdt.c
drivers/watchdog/orion_wdt.c
drivers/watchdog/rn5t618_wdt.c
drivers/watchdog/w83627hf_wdt.c
drivers/xen/balloon.c
drivers/xen/grant-table.c
drivers/xen/xenbus/xenbus.h
drivers/xen/xenbus/xenbus_probe.c
drivers/xen/xenbus/xenbus_probe_backend.c
drivers/xen/xenbus/xenbus_probe_frontend.c
fs/afs/dir.c
fs/afs/dynroot.c
fs/afs/mntpt.c
fs/afs/proc.c
fs/afs/server.c
fs/afs/super.c
fs/btrfs/Kconfig
fs/btrfs/compression.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/qgroup.c
fs/btrfs/relocation.c
fs/btrfs/root-tree.c
fs/btrfs/send.c
fs/btrfs/tests/free-space-tree-tests.c
fs/btrfs/tests/qgroup-tests.c
fs/btrfs/tree-checker.c
fs/btrfs/tree-log.c
fs/btrfs/uuid-tree.c
fs/btrfs/volumes.c
fs/buffer.c
fs/ceph/caps.c
fs/ceph/debugfs.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/mdsmap.c
fs/ceph/super.c
fs/ceph/super.h
fs/char_dev.c
fs/cifs/cifsglob.h
fs/cifs/cifssmb.c
fs/cifs/readdir.c
fs/cifs/smb2file.c
fs/cifs/smb2inode.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2proto.h
fs/crypto/keyring.c
fs/direct-io.c
fs/drop_caches.c
fs/erofs/xattr.c
fs/ext4/block_validity.c
fs/ext4/dir.c
fs/ext4/ialloc.c
fs/ext4/inode-test.c
fs/ext4/inode.c
fs/ext4/namei.c
fs/ext4/super.c
fs/fuse/file.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/internal.h
fs/io-wq.c
fs/io-wq.h
fs/io_uring.c
fs/locks.c
fs/mpage.c
fs/namei.c
fs/namespace.c
fs/nfs/nfstrace.h
fs/notify/fsnotify.c
fs/nsfs.c
fs/ocfs2/dlmglue.c
fs/ocfs2/journal.c
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/export.c
fs/overlayfs/inode.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/super.c
fs/pipe.c
fs/posix_acl.c
fs/proc/stat.c
fs/pstore/ram.c
fs/pstore/ram_core.c
fs/quota/dquot.c
fs/super.c
fs/verity/enable.c
fs/xfs/libxfs/xfs_alloc.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_dir2.c
fs/xfs/libxfs/xfs_dir2_priv.h
fs/xfs/libxfs/xfs_dir2_sf.c
fs/xfs/libxfs/xfs_ialloc.c
fs/xfs/libxfs/xfs_ialloc.h
fs/xfs/libxfs/xfs_trans_resv.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_buf_item.c
fs/xfs/xfs_mount.c
fs/xfs/xfs_trace.h
include/asm-generic/cacheflush.h
include/drm/drm_dp_mst_helper.h
include/dt-bindings/reset/amlogic,meson8b-reset.h
include/linux/ahci_platform.h
include/linux/bio.h
include/linux/blk-cgroup.h
include/linux/blkdev.h
include/linux/bpf-cgroup.h
include/linux/bpf.h
include/linux/bvec.h
include/linux/can/dev.h
include/linux/cpufreq.h
include/linux/devfreq.h
include/linux/device.h
include/linux/dmaengine.h
include/linux/efi.h
include/linux/filter.h
include/linux/ftrace.h
include/linux/i2c.h
include/linux/if_ether.h
include/linux/initrd.h
include/linux/jbd2.h
include/linux/kasan.h
include/linux/kernel.h
include/linux/kvm_host.h
include/linux/libata.h
include/linux/memory_hotplug.h
include/linux/mfd/mt6397/rtc.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/mod_devicetable.h
include/linux/mtd/flashchip.h
include/linux/namei.h
include/linux/netdevice.h
include/linux/nvme-fc-driver.h
include/linux/of_mdio.h
include/linux/phy.h
include/linux/phy_led_triggers.h
include/linux/platform_data/ti-sysc.h
include/linux/posix-clock.h
include/linux/printk.h
include/linux/rculist_nulls.h
include/linux/sched.h
include/linux/sched/cpufreq.h
include/linux/skmsg.h
include/linux/spi/spi.h
include/linux/sxgbe_platform.h
include/linux/syscalls.h
include/linux/tnum.h
include/linux/tpm.h
include/net/cfg80211.h
include/net/devlink.h
include/net/dst.h
include/net/dst_ops.h
include/net/garp.h
include/net/inet_hashtables.h
include/net/ip_tunnels.h
include/net/mrp.h
include/net/neighbour.h
include/net/netfilter/nf_conntrack_helper.h
include/net/netfilter/nf_flow_table.h
include/net/netfilter/nf_tables_core.h
include/net/sch_generic.h
include/net/sock.h
include/net/tcp.h
include/net/x25.h
include/rdma/ib_verbs.h
include/soc/sifive/sifive_l2_cache.h [moved from arch/riscv/include/asm/sifive_l2_cache.h with 72% similarity]
include/sound/ac97_codec.h
include/sound/control.h
include/sound/core.h
include/sound/hda_codec.h
include/sound/hda_regmap.h
include/sound/hdaudio.h
include/sound/info.h
include/sound/initval.h
include/sound/pcm.h
include/sound/seq_midi_emul.h
include/sound/soc-component.h
include/sound/timer.h
include/sound/vx_core.h
include/trace/events/afs.h
include/trace/events/huge_memory.h
include/trace/events/preemptirq.h
include/uapi/linux/input.h
include/uapi/linux/io_uring.h
include/uapi/linux/kcov.h
include/uapi/linux/netfilter/xt_sctp.h
include/uapi/linux/nl80211.h
include/uapi/sound/asoc.h
include/uapi/sound/asound.h
include/uapi/sound/emu10k1.h
include/uapi/sound/hdsp.h
include/uapi/sound/hdspm.h
include/xen/interface/io/ring.h
include/xen/xenbus.h
init/do_mounts.c
init/do_mounts_initrd.c
init/main.c
ipc/util.c
kernel/bpf/btf.c
kernel/bpf/cgroup.c
kernel/bpf/core.c
kernel/bpf/local_storage.c
kernel/bpf/tnum.c
kernel/bpf/trampoline.c
kernel/bpf/verifier.c
kernel/cpu.c
kernel/cred.c
kernel/events/core.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/locking/lockdep.c
kernel/locking/mutex.c
kernel/locking/rwsem.c
kernel/locking/spinlock_debug.c
kernel/module.c
kernel/ptrace.c
kernel/rseq.c
kernel/sched/cpufreq.c
kernel/sched/cpufreq_schedutil.c
kernel/sched/fair.c
kernel/sched/psi.c
kernel/seccomp.c
kernel/taskstats.c
kernel/time/posix-clock.c
kernel/time/posix-stubs.c
kernel/time/tick-sched.c
kernel/trace/fgraph.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/trace/trace_events_filter.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_inject.c
kernel/trace/trace_sched_wakeup.c
kernel/trace/trace_seq.c
kernel/trace/trace_stack.c
kernel/trace/tracing_map.c
kernel/workqueue.c
lib/Kconfig.debug
lib/iov_iter.c
lib/raid6/unroll.awk
lib/sbitmap.c
lib/vdso/gettimeofday.c
mm/gup_benchmark.c
mm/huge_memory.c
mm/hugetlb.c
mm/kasan/common.c
mm/memcontrol.c
mm/memory.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/memremap.c
mm/migrate.c
mm/mmap.c
mm/oom_kill.c
mm/page-writeback.c
mm/page_alloc.c
mm/shmem.c
mm/slab.c
mm/slab_common.c
mm/slub.c
mm/sparse.c
mm/vmalloc.c
mm/vmscan.c
mm/zsmalloc.c
net/802/mrp.c
net/8021q/vlan.h
net/8021q/vlan_dev.c
net/8021q/vlan_netlink.c
net/batman-adv/distributed-arp-table.c
net/batman-adv/main.c
net/bpf/test_run.c
net/bridge/br.c
net/bridge/br_netfilter_hooks.c
net/bridge/br_nf_core.c
net/bridge/netfilter/ebtables.c
net/can/j1939/socket.c
net/core/dev.c
net/core/devlink.c
net/core/filter.c
net/core/flow_dissector.c
net/core/neighbour.c
net/core/net-sysfs.c
net/core/skmsg.c
net/core/sock.c
net/core/sock_map.c
net/core/sysctl_net_core.c
net/core/xdp.c
net/dccp/proto.c
net/decnet/dn_route.c
net/dsa/dsa2.c
net/dsa/tag_gswip.c
net/dsa/tag_ksz.c
net/dsa/tag_qca.c
net/hsr/hsr_debugfs.c
net/hsr/hsr_device.c
net/hsr/hsr_framereg.c
net/hsr/hsr_framereg.h
net/hsr/hsr_main.c
net/hsr/hsr_main.h
net/hsr/hsr_netlink.c
net/ipv4/fib_trie.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_diag.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_gre.c
net/ipv4/ip_tunnel.c
net/ipv4/ip_vti.c
net/ipv4/netfilter/arp_tables.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_bbr.c
net/ipv4/tcp_bpf.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/tcp_ulp.c
net/ipv4/udp.c
net/ipv4/xfrm4_policy.c
net/ipv6/addrconf.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_gre.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/route.c
net/ipv6/sit.c
net/ipv6/xfrm6_policy.c
net/iucv/af_iucv.c
net/llc/llc_station.c
net/mac80211/airtime.c
net/mac80211/cfg.c
net/mac80211/debugfs_sta.c
net/mac80211/main.c
net/mac80211/mesh_hwmp.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tkip.c
net/mac80211/tx.c
net/netfilter/ipset/ip_set_bitmap_gen.h
net/netfilter/ipset/ip_set_core.c
net/netfilter/ipvs/ip_vs_xmit.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_dccp.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_ip.c
net/netfilter/nf_flow_table_offload.c
net/netfilter/nf_nat_proto.c
net/netfilter/nf_queue.c
net/netfilter/nf_tables_api.c
net/netfilter/nf_tables_offload.c
net/netfilter/nfnetlink_cthelper.c
net/netfilter/nft_bitwise.c
net/netfilter/nft_cmp.c
net/netfilter/nft_ct.c
net/netfilter/nft_flow_offload.c
net/netfilter/nft_masq.c
net/netfilter/nft_nat.c
net/netfilter/nft_range.c
net/netfilter/nft_redir.c
net/netfilter/nft_set_rbtree.c
net/netfilter/nft_tproxy.c
net/netfilter/nft_tunnel.c
net/netfilter/xt_RATEEST.c
net/netlink/af_netlink.c
net/nfc/nci/uart.c
net/openvswitch/datapath.c
net/openvswitch/flow.h
net/packet/af_packet.c
net/qrtr/qrtr.c
net/rfkill/core.c
net/rxrpc/af_rxrpc.c
net/rxrpc/ar-internal.h
net/rxrpc/call_accept.c
net/rxrpc/conn_event.c
net/rxrpc/conn_service.c
net/rxrpc/input.c
net/rxrpc/rxkad.c
net/rxrpc/security.c
net/sched/act_ct.c
net/sched/act_ctinfo.c
net/sched/act_ife.c
net/sched/act_mirred.c
net/sched/cls_api.c
net/sched/cls_flower.c
net/sched/sch_cake.c
net/sched/sch_fq.c
net/sched/sch_prio.c
net/sctp/protocol.c
net/sctp/sm_sideeffect.c
net/sctp/stream.c
net/sctp/transport.c
net/smc/af_smc.c
net/smc/smc_core.c
net/socket.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/tipc/Makefile
net/tipc/bcast.c
net/tipc/discover.c
net/tipc/name_table.c
net/tipc/netlink_compat.c
net/tipc/socket.c
net/tls/tls_main.c
net/tls/tls_sw.c
net/unix/af_unix.c
net/vmw_vsock/hyperv_transport.c
net/vmw_vsock/virtio_transport_common.c
net/wireless/core.c
net/wireless/nl80211.c
net/wireless/rdev-ops.h
net/wireless/reg.c
net/wireless/sme.c
net/wireless/trace.h
net/wireless/util.c
net/wireless/wext-core.c
net/x25/af_x25.c
net/x25/x25_in.c
net/xdp/xsk.c
samples/bpf/syscall_tp_kern.c
samples/bpf/trace_event_user.c
samples/seccomp/user-trap.c
samples/trace_printk/trace-printk.c
scripts/checkpatch.pl
scripts/gcc-plugins/Kconfig
scripts/kallsyms.c
scripts/kconfig/expr.c
scripts/mkcompile_h
scripts/package/mkdebian
security/apparmor/apparmorfs.c
security/apparmor/domain.c
security/apparmor/file.c
security/apparmor/mount.c
security/apparmor/policy.c
security/integrity/ima/ima_policy.c
security/keys/Kconfig
security/keys/Makefile
security/keys/compat.c
security/keys/internal.h
security/keys/trusted-keys/trusted_tpm2.c
security/tomoyo/common.c
security/tomoyo/domain.c
security/tomoyo/group.c
security/tomoyo/realpath.c
security/tomoyo/util.c
sound/ac97/snd_ac97_compat.c
sound/ac97_bus.c
sound/aoa/aoa.h
sound/aoa/codecs/onyx.c
sound/aoa/codecs/tas-basstreble.h
sound/aoa/codecs/tas-gain-table.h
sound/aoa/codecs/tas.c
sound/aoa/codecs/toonie.c
sound/aoa/core/alsa.c
sound/aoa/fabrics/layout.c
sound/aoa/soundbus/i2sbus/core.c
sound/aoa/soundbus/i2sbus/pcm.c
sound/arm/aaci.c
sound/arm/pxa2xx-ac97.c
sound/atmel/ac97c.c
sound/core/Kconfig
sound/core/compress_offload.c
sound/core/control.c
sound/core/device.c
sound/core/hwdep.c
sound/core/info.c
sound/core/init.c
sound/core/jack.c
sound/core/oss/mixer_oss.c
sound/core/oss/pcm_plugin.c
sound/core/pcm.c
sound/core/pcm_compat.c
sound/core/pcm_lib.c
sound/core/pcm_local.h
sound/core/pcm_memory.c
sound/core/pcm_misc.c
sound/core/pcm_native.c
sound/core/pcm_timer.c
sound/core/rawmidi.c
sound/core/rawmidi_compat.c
sound/core/seq/oss/seq_oss_init.c
sound/core/seq/seq_midi_emul.c
sound/core/seq/seq_midi_event.c
sound/core/seq/seq_timer.c
sound/core/seq_device.c
sound/core/timer.c
sound/core/timer_compat.c
sound/drivers/aloop.c
sound/drivers/dummy.c
sound/drivers/ml403-ac97cr.c
sound/drivers/mts64.c
sound/drivers/opl3/opl3_drums.c
sound/drivers/opl3/opl3_lib.c
sound/drivers/opl3/opl3_midi.c
sound/drivers/opl3/opl3_oss.c
sound/drivers/opl3/opl3_seq.c
sound/drivers/opl3/opl3_voice.h
sound/drivers/opl4/opl4_lib.c
sound/drivers/opl4/opl4_mixer.c
sound/drivers/opl4/opl4_proc.c
sound/drivers/opl4/opl4_seq.c
sound/drivers/opl4/opl4_synth.c
sound/drivers/pcsp/pcsp.c
sound/drivers/pcsp/pcsp_lib.c
sound/drivers/pcsp/pcsp_mixer.c
sound/drivers/serial-u16550.c
sound/drivers/vx/vx_cmd.c
sound/drivers/vx/vx_core.c
sound/drivers/vx/vx_hwdep.c
sound/drivers/vx/vx_mixer.c
sound/drivers/vx/vx_pcm.c
sound/firewire/bebob/bebob_pcm.c
sound/firewire/dice/dice-alesis.c
sound/firewire/dice/dice-extension.c
sound/firewire/dice/dice-pcm.c
sound/firewire/dice/dice-stream.c
sound/firewire/dice/dice.c
sound/firewire/dice/dice.h
sound/firewire/digi00x/digi00x-pcm.c
sound/firewire/fireface/ff-pcm.c
sound/firewire/fireworks/fireworks_pcm.c
sound/firewire/isight.c
sound/firewire/motu/motu-pcm.c
sound/firewire/oxfw/oxfw-command.c
sound/firewire/oxfw/oxfw-pcm.c
sound/firewire/oxfw/oxfw-stream.c
sound/firewire/oxfw/oxfw.c
sound/firewire/oxfw/oxfw.h
sound/firewire/tascam/amdtp-tascam.c
sound/firewire/tascam/tascam-pcm.c
sound/hda/Kconfig
sound/hda/ext/hdac_ext_bus.c
sound/hda/ext/hdac_ext_controller.c
sound/hda/ext/hdac_ext_stream.c
sound/hda/hdac_bus.c
sound/hda/hdac_component.c
sound/hda/hdac_controller.c
sound/hda/hdac_device.c
sound/hda/hdac_regmap.c
sound/hda/hdac_stream.c
sound/hda/hdmi_chmap.c
sound/hda/intel-nhlt.c
sound/i2c/cs8427.c
sound/i2c/i2c.c
sound/i2c/other/ak4113.c
sound/i2c/other/ak4114.c
sound/i2c/other/ak4117.c
sound/i2c/tea6330t.c
sound/isa/ad1816a/ad1816a_lib.c
sound/isa/cmi8328.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4236_lib.c
sound/isa/es1688/es1688.c
sound/isa/es1688/es1688_lib.c
sound/isa/es18xx.c
sound/isa/gus/gus_io.c
sound/isa/gus/gus_main.c
sound/isa/gus/gus_mem_proc.c
sound/isa/gus/gus_mixer.c
sound/isa/gus/gus_pcm.c
sound/isa/gus/gus_timer.c
sound/isa/gus/gus_volume.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/gus/interwave.c
sound/isa/msnd/msnd.c
sound/isa/msnd/msnd_pinnacle.c
sound/isa/msnd/msnd_pinnacle_mixer.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/emu8000.c
sound/isa/sb/emu8000_pcm.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sb/sb16_main.c
sound/isa/sb/sb8.c
sound/isa/sb/sb8_main.c
sound/isa/sb/sb_common.c
sound/isa/sb/sb_mixer.c
sound/isa/sc6000.c
sound/isa/wavefront/wavefront.c
sound/isa/wss/wss_lib.c
sound/mips/hal2.c
sound/mips/sgio2audio.c
sound/parisc/harmony.c
sound/pci/ac97/ac97_codec.c
sound/pci/ac97/ac97_patch.c
sound/pci/ac97/ac97_pcm.c
sound/pci/ad1889.c
sound/pci/ak4531_codec.c
sound/pci/ali5451/ali5451.c
sound/pci/als300.c
sound/pci/als4000.c
sound/pci/asihpi/asihpi.c
sound/pci/asihpi/hpimsgx.c
sound/pci/atiixp.c
sound/pci/atiixp_modem.c
sound/pci/au88x0/au88x0.c
sound/pci/au88x0/au88x0_core.c
sound/pci/au88x0/au88x0_eq.c
sound/pci/au88x0/au88x0_eqdata.c
sound/pci/au88x0/au88x0_mixer.c
sound/pci/au88x0/au88x0_pcm.c
sound/pci/aw2/aw2-alsa.c
sound/pci/aw2/aw2-tsl.c
sound/pci/azt3328.c
sound/pci/bt87x.c
sound/pci/ca0106/ca0106.h
sound/pci/ca0106/ca0106_main.c
sound/pci/ca0106/ca0106_mixer.c
sound/pci/ca0106/ca0106_proc.c
sound/pci/cmipci.c
sound/pci/cs4281.c
sound/pci/cs46xx/cs46xx_lib.c
sound/pci/cs46xx/dsp_spos.c
sound/pci/cs46xx/dsp_spos_scb_lib.c
sound/pci/cs5530.c
sound/pci/cs5535audio/cs5535audio.c
sound/pci/cs5535audio/cs5535audio_olpc.c
sound/pci/cs5535audio/cs5535audio_pcm.c
sound/pci/ctxfi/ctatc.c
sound/pci/ctxfi/ctdaio.c
sound/pci/ctxfi/cthw20k1.c
sound/pci/ctxfi/cthw20k2.c
sound/pci/ctxfi/ctpcm.c
sound/pci/ctxfi/ctresource.c
sound/pci/echoaudio/darla20.c
sound/pci/echoaudio/darla24.c
sound/pci/echoaudio/echo3g.c
sound/pci/echoaudio/echoaudio.c
sound/pci/echoaudio/echoaudio_dsp.c
sound/pci/echoaudio/gina20.c
sound/pci/echoaudio/gina24.c
sound/pci/echoaudio/indigo.c
sound/pci/echoaudio/indigodj.c
sound/pci/echoaudio/indigodjx.c
sound/pci/echoaudio/indigoio.c
sound/pci/echoaudio/indigoiox.c
sound/pci/echoaudio/layla20.c
sound/pci/echoaudio/layla24.c
sound/pci/echoaudio/mia.c
sound/pci/echoaudio/mona.c
sound/pci/emu10k1/emu10k1_main.c
sound/pci/emu10k1/emu10k1x.c
sound/pci/emu10k1/emufx.c
sound/pci/emu10k1/emumixer.c
sound/pci/emu10k1/emupcm.c
sound/pci/emu10k1/emuproc.c
sound/pci/emu10k1/io.c
sound/pci/emu10k1/p16v.c
sound/pci/emu10k1/timer.c
sound/pci/ens1370.c
sound/pci/es1938.c
sound/pci/es1968.c
sound/pci/fm801.c
sound/pci/hda/hda_beep.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_controller.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_local.h
sound/pci/hda/hda_proc.c
sound/pci/hda/hda_sysfs.c
sound/pci/hda/hda_tegra.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_ca0110.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/pci/hda/patch_via.c
sound/pci/ice1712/aureon.c
sound/pci/ice1712/delta.c
sound/pci/ice1712/ews.c
sound/pci/ice1712/ice1712.c
sound/pci/ice1712/ice1712.h
sound/pci/ice1712/ice1724.c
sound/pci/ice1712/juli.c
sound/pci/ice1712/maya44.c
sound/pci/ice1712/phase.c
sound/pci/ice1712/pontis.c
sound/pci/ice1712/prodigy192.c
sound/pci/ice1712/prodigy_hifi.c
sound/pci/ice1712/psc724.c
sound/pci/ice1712/quartet.c
sound/pci/ice1712/se.c
sound/pci/ice1712/vt1720_mobo.c
sound/pci/ice1712/wm8766.c
sound/pci/ice1712/wm8776.c
sound/pci/ice1712/wtm.c
sound/pci/intel8x0.c
sound/pci/intel8x0m.c
sound/pci/korg1212/korg1212.c
sound/pci/lola/lola.c
sound/pci/lola/lola_pcm.c
sound/pci/lx6464es/lx6464es.c
sound/pci/lx6464es/lx_core.c
sound/pci/maestro3.c
sound/pci/mixart/mixart.c
sound/pci/mixart/mixart_hwdep.c
sound/pci/mixart/mixart_mixer.c
sound/pci/nm256/nm256.c
sound/pci/nm256/nm256_coef.c
sound/pci/oxygen/oxygen_lib.c
sound/pci/oxygen/oxygen_pcm.c
sound/pci/pcxhr/pcxhr.c
sound/pci/pcxhr/pcxhr_core.c
sound/pci/pcxhr/pcxhr_hwdep.c
sound/pci/riptide/riptide.c
sound/pci/rme32.c
sound/pci/rme96.c
sound/pci/rme9652/hdsp.c
sound/pci/rme9652/hdspm.c
sound/pci/rme9652/rme9652.c
sound/pci/sis7019.c
sound/pci/sonicvibes.c
sound/pci/trident/trident_main.c
sound/pci/via82xx.c
sound/pci/via82xx_modem.c
sound/pci/vx222/vx222.c
sound/pci/vx222/vx222.h
sound/pci/vx222/vx222_ops.c
sound/pci/ymfpci/ymfpci_main.c
sound/pcmcia/pdaudiocf/pdaudiocf.c
sound/pcmcia/pdaudiocf/pdaudiocf_core.c
sound/pcmcia/pdaudiocf/pdaudiocf_pcm.c
sound/pcmcia/vx/vxp_ops.c
sound/pcmcia/vx/vxpocket.c
sound/pcmcia/vx/vxpocket.h
sound/ppc/awacs.c
sound/ppc/beep.c
sound/ppc/burgundy.c
sound/ppc/daca.c
sound/ppc/pmac.c
sound/ppc/pmac.h
sound/ppc/snd_ps3.c
sound/ppc/tumbler.c
sound/ppc/tumbler_volume.h
sound/sh/aica.c
sound/sh/sh_dac_audio.c
sound/soc/codecs/cs47l15.c
sound/soc/codecs/cs47l35.c
sound/soc/codecs/cs47l85.c
sound/soc/codecs/cs47l90.c
sound/soc/codecs/cs47l92.c
sound/soc/codecs/hdmi-codec.c
sound/soc/codecs/madera.c
sound/soc/codecs/madera.h
sound/soc/codecs/wm_adsp.c
sound/soc/intel/boards/skl_hda_dsp_common.c
sound/soc/intel/skylake/skl-pcm.c
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-pcm.c
sound/soc/soc-topology.c
sound/soc/sof/intel/hda.h
sound/sparc/amd7930.c
sound/sparc/cs4231.c
sound/sparc/dbri.c
sound/spi/at73c213.c
sound/synth/emux/emux_nrpn.c
sound/synth/emux/emux_oss.c
sound/synth/emux/emux_seq.c
sound/synth/emux/emux_synth.c
sound/synth/emux/soundfont.c
sound/usb/6fire/control.c
sound/usb/6fire/pcm.c
sound/usb/bcd2000/bcd2000.c
sound/usb/caiaq/audio.c
sound/usb/caiaq/control.c
sound/usb/caiaq/input.c
sound/usb/card.c
sound/usb/card.h
sound/usb/format.c
sound/usb/hiface/pcm.c
sound/usb/line6/capture.c
sound/usb/line6/pcm.c
sound/usb/line6/playback.c
sound/usb/line6/pod.c
sound/usb/line6/podhd.c
sound/usb/line6/toneport.c
sound/usb/midi.c
sound/usb/misc/ua101.c
sound/usb/mixer.c
sound/usb/mixer.h
sound/usb/mixer_maps.c
sound/usb/mixer_quirks.c
sound/usb/mixer_scarlett.c
sound/usb/mixer_scarlett_gen2.c
sound/usb/mixer_us16x08.c
sound/usb/mixer_us16x08.h
sound/usb/pcm.c
sound/usb/proc.c
sound/usb/quirks-table.h
sound/usb/quirks.c
sound/usb/quirks.h
sound/usb/stream.c
sound/usb/usbaudio.h
sound/usb/usx2y/us122l.c
sound/usb/usx2y/usX2Yhwdep.c
sound/usb/usx2y/usbusx2yaudio.c
sound/usb/usx2y/usx2yhwdeppcm.c
sound/usb/validate.c
sound/x86/intel_hdmi_audio.c
sound/xen/xen_snd_front_alsa.c
tools/arch/arm/include/uapi/asm/kvm.h
tools/arch/arm64/include/uapi/asm/kvm.h
tools/arch/powerpc/include/uapi/asm/kvm.h
tools/arch/x86/include/asm/cpufeatures.h
tools/arch/x86/include/asm/msr-index.h
tools/arch/x86/lib/memcpy_64.S
tools/arch/x86/lib/memset_64.S
tools/bpf/bpftool/btf_dumper.c
tools/bpf/bpftool/prog.c
tools/bpf/bpftool/xlated_dumper.c
tools/include/uapi/drm/drm.h
tools/include/uapi/drm/i915_drm.h
tools/include/uapi/linux/fscrypt.h
tools/include/uapi/linux/kvm.h
tools/include/uapi/linux/sched.h
tools/include/uapi/linux/stat.h
tools/lib/bpf/Makefile
tools/lib/traceevent/Makefile
tools/lib/traceevent/parse-filter.c
tools/lib/traceevent/plugins/Makefile
tools/perf/Documentation/perf-kvm.txt
tools/perf/arch/arm/tests/regs_load.S
tools/perf/arch/arm64/tests/regs_load.S
tools/perf/arch/x86/tests/regs_load.S
tools/perf/builtin-inject.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-stat.c
tools/perf/builtin-top.c
tools/perf/check-headers.sh
tools/perf/lib/cpumap.c
tools/perf/lib/evlist.c
tools/perf/lib/evsel.c
tools/perf/lib/include/internal/evlist.h
tools/perf/lib/include/perf/cpumap.h
tools/perf/lib/include/perf/evsel.h
tools/perf/pmu-events/arch/s390/cf_z13/extended.json
tools/perf/pmu-events/arch/s390/cf_z14/extended.json
tools/perf/pmu-events/arch/x86/broadwell/bdw-metrics.json
tools/perf/pmu-events/arch/x86/broadwellde/bdwde-metrics.json
tools/perf/pmu-events/arch/x86/broadwellx/bdx-metrics.json
tools/perf/pmu-events/arch/x86/cascadelakex/clx-metrics.json
tools/perf/pmu-events/arch/x86/haswell/hsw-metrics.json
tools/perf/pmu-events/arch/x86/haswellx/hsx-metrics.json
tools/perf/pmu-events/arch/x86/ivybridge/ivb-metrics.json
tools/perf/pmu-events/arch/x86/ivytown/ivt-metrics.json
tools/perf/pmu-events/arch/x86/jaketown/jkt-metrics.json
tools/perf/pmu-events/arch/x86/sandybridge/snb-metrics.json
tools/perf/pmu-events/arch/x86/skylake/skl-metrics.json
tools/perf/pmu-events/arch/x86/skylakex/skx-metrics.json
tools/perf/tests/Build
tools/perf/tests/builtin-test.c
tools/perf/tests/cpumap.c
tools/perf/tests/event-times.c
tools/perf/tests/genelf.c [new file with mode: 0644]
tools/perf/tests/tests.h
tools/perf/trace/beauty/clone.c
tools/perf/util/cpumap.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/genelf.c
tools/perf/util/header.c
tools/perf/util/hist.h
tools/perf/util/include/linux/linkage.h
tools/perf/util/machine.c
tools/perf/util/metricgroup.c
tools/perf/util/sort.c
tools/perf/util/stat.c
tools/perf/util/stat.h
tools/perf/util/symbol-elf.c
tools/testing/kunit/kunit.py
tools/testing/kunit/kunit_kernel.py
tools/testing/kunit/kunit_tool_test.py
tools/testing/nvdimm/Kbuild
tools/testing/nvdimm/test/iomap.c
tools/testing/selftests/bpf/.gitignore
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/test_ftrace.sh [new file with mode: 0755]
tools/testing/selftests/bpf/test_verifier.c
tools/testing/selftests/bpf/verifier/ref_tracking.c
tools/testing/selftests/bpf/verifier/runtime_jit.c
tools/testing/selftests/drivers/net/mlxsw/qos_mc_aware.sh
tools/testing/selftests/filesystems/epoll/Makefile
tools/testing/selftests/firmware/fw_lib.sh
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-stacktrace.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_cpumask.tc
tools/testing/selftests/ftrace/test.d/functions
tools/testing/selftests/ftrace/test.d/kprobe/multiple_kprobes.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-action-hist-xfail.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-onchange-action-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/inter-event/trigger-snapshot-action-hist.tc
tools/testing/selftests/kselftest/module.sh
tools/testing/selftests/kselftest/prefix.pl
tools/testing/selftests/kselftest/runner.sh
tools/testing/selftests/livepatch/functions.sh
tools/testing/selftests/livepatch/test-state.sh
tools/testing/selftests/net/forwarding/loopback.sh
tools/testing/selftests/net/forwarding/router_bridge_vlan.sh
tools/testing/selftests/net/pmtu.sh
tools/testing/selftests/net/tls.c
tools/testing/selftests/netfilter/nft_flowtable.sh
tools/testing/selftests/netfilter/nft_nat.sh
tools/testing/selftests/rseq/param_test.c
tools/testing/selftests/rseq/rseq.h
tools/testing/selftests/rseq/settings [new file with mode: 0644]
tools/testing/selftests/safesetid/Makefile
tools/testing/selftests/safesetid/safesetid-test.c
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/tc-testing/tc-tests/filters/basic.json
tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
tools/testing/selftests/tc-testing/tc-tests/filters/u32.json [new file with mode: 0644]
tools/testing/selftests/tpm2/test_smoke.sh
tools/testing/selftests/tpm2/tpm2.py
tools/testing/selftests/tpm2/tpm2_tests.py
usr/gen_initramfs_list.sh
usr/include/Makefile
virt/kvm/arm/arm.c
virt/kvm/arm/mmu.c
virt/kvm/arm/vgic/vgic-init.c

index c24773d..d9d5c80 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -99,6 +99,7 @@ Jacob Shin <Jacob.Shin@amd.com>
 Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@google.com>
 Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@motorola.com>
 Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk.kim@samsung.com>
+Jakub Kicinski <kuba@kernel.org> <jakub.kicinski@netronome.com>
 James Bottomley <jejb@mulgrave.(none)>
 James Bottomley <jejb@titanic.il.steeleye.com>
 James E Wilson <wilson@specifix.com>
@@ -152,6 +153,7 @@ Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@web.de>
 Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
 Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
 Li Yang <leoyang.li@nxp.com> <leoli@freescale.com>
+Lukasz Luba <lukasz.luba@arm.com> <l.luba@partner.samsung.com>
 Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
 Marc Zyngier <maz@kernel.org> <marc.zyngier@arm.com>
 Marcin Nowakowski <marcin.nowakowski@mips.com> <marcin.nowakowski@imgtec.com>
@@ -265,6 +267,7 @@ Vinod Koul <vkoul@kernel.org> <vkoul@infradead.org>
 Viresh Kumar <vireshk@kernel.org> <viresh.kumar@st.com>
 Viresh Kumar <vireshk@kernel.org> <viresh.linux@gmail.com>
 Viresh Kumar <vireshk@kernel.org> <viresh.kumar2@arm.com>
+Vivien Didelot <vivien.didelot@gmail.com> <vivien.didelot@savoirfairelinux.com>
 Vlad Dogaru <ddvlad@gmail.com> <vlad.dogaru@intel.com>
 Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@virtuozzo.com>
 Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@parallels.com>
@@ -276,3 +279,5 @@ Gustavo Padovan <gustavo@las.ic.unicamp.br>
 Gustavo Padovan <padovan@profusion.mobi>
 Changbin Du <changbin.du@intel.com> <changbin.du@intel.com>
 Changbin Du <changbin.du@intel.com> <changbin.du@gmail.com>
+Steve Wise <larrystevenwise@gmail.com> <swise@chelsio.com>
+Steve Wise <larrystevenwise@gmail.com> <swise@opengridcomputing.com>
index 8ca4984..05601a9 100644 (file)
@@ -29,13 +29,13 @@ Description:        This file shows the system fans direction:
 
                The files are read only.
 
-What:          /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/jtag_enable
+What:          /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld3_version
 
 Date:          November 2018
 KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files show with which CPLD versions have been burned
-               on LED board.
+               on LED or Gearbox board.
 
                The files are read only.
 
@@ -121,6 +121,15 @@ Description:       These files show the system reset cause, as following: ComEx
 
                The files are read only.
 
+What:          /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/cpld4_version
+Date:          November 2018
+KernelVersion: 5.0
+Contact:       Vadim Pasternak <vadimpmellanox.com>
+Description:   These files show with which CPLD versions have been burned
+               on LED board.
+
+               The files are read only.
+
 Date:          June 2019
 KernelVersion: 5.3
 Contact:       Vadim Pasternak <vadimpmellanox.com>
index c65a805..401d202 100644 (file)
@@ -1,4 +1,4 @@
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/lifecycle_state
+What:          /sys/bus/platform/devices/MLNXBF04:00/lifecycle_state
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
@@ -10,7 +10,7 @@ Description:
                  GA Non-Secured - Non-Secure chip and not able to change state
                  RMA - Return Merchandise Authorization
 
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/post_reset_wdog
+What:          /sys/bus/platform/devices/MLNXBF04:00/post_reset_wdog
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
@@ -19,7 +19,7 @@ Description:
                to reboot the chip and recover it to the old state if the new
                boot partition fails.
 
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/reset_action
+What:          /sys/bus/platform/devices/MLNXBF04:00/reset_action
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
@@ -30,7 +30,7 @@ Description:
                  emmc - boot from the onchip eMMC
                  emmc_legacy - boot from the onchip eMMC in legacy (slow) mode
 
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/second_reset_action
+What:          /sys/bus/platform/devices/MLNXBF04:00/second_reset_action
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
@@ -44,7 +44,7 @@ Description:
                  swap_emmc - swap the primary / secondary boot partition
                  none - cancel the action
 
-What:          /sys/bus/platform/devices/MLNXBF04:00/driver/secure_boot_fuse_state
+What:          /sys/bus/platform/devices/MLNXBF04:00/secure_boot_fuse_state
 Date:          Oct 2019
 KernelVersion: 5.5
 Contact:       "Liming Sun <lsun@mellanox.com>"
index 594095b..c00f9f1 100644 (file)
@@ -144,7 +144,7 @@ journal_crypt:algorithm(:key)       (the key is optional)
        Encrypt the journal using given algorithm to make sure that the
        attacker can't read the journal. You can use a block cipher here
        (such as "cbc(aes)") or a stream cipher (for example "chacha20",
-       "salsa20", "ctr(aes)" or "ecb(arc4)").
+       "salsa20" or "ctr(aes)").
 
        The journal contains history of last writes to the block device,
        an attacker reading the journal could see the last sector nubmers
index 4872fb6..ec62fcc 100644 (file)
@@ -8,6 +8,7 @@ Device Mapper
     cache-policies
     cache
     delay
+    dm-clone
     dm-crypt
     dm-dust
     dm-flakey
index 1c5d228..2a97aae 100644 (file)
                182 = /dev/perfctr      Performance-monitoring counters
                183 = /dev/hwrng        Generic random number generator
                184 = /dev/cpu/microcode CPU microcode update interface
-               186 = /dev/atomicps     Atomic shapshot of process state data
+               186 = /dev/atomicps     Atomic snapshot of process state data
                187 = /dev/irnet        IrNET device
                188 = /dev/smbusbios    SMBus BIOS
                189 = /dev/ussp_ctl     User space serial port control
index 059ddcb..9bc93f0 100644 (file)
@@ -181,14 +181,17 @@ When mounting an ext4 filesystem, the following option are accepted:
         system after its metadata has been committed to the journal.
 
   commit=nrsec (*)
-        Ext4 can be told to sync all its data and metadata every 'nrsec'
-        seconds. The default value is 5 seconds.  This means that if you lose
-        your power, you will lose as much as the latest 5 seconds of work (your
-        filesystem will not be damaged though, thanks to the journaling).  This
-        default value (or any low value) will hurt performance, but it's good
-        for data-safety.  Setting it to 0 will have the same effect as leaving
-        it at the default (5 seconds).  Setting it to very large values will
-        improve performance.
+        This setting limits the maximum age of the running transaction to
+        'nrsec' seconds.  The default value is 5 seconds.  This means that if
+        you lose your power, you will lose as much as the latest 5 seconds of
+        metadata changes (your filesystem will not be damaged though, thanks
+        to the journaling). This default value (or any low value) will hurt
+        performance, but it's good for data-safety.  Setting it to 0 will have
+        the same effect as leaving it at the default (5 seconds).  Setting it
+        to very large values will improve performance.  Note that due to
+        delayed allocation even older data can be lost on power failure since
+        writeback of those data begins only after time set in
+        /proc/sys/vm/dirty_expire_centisecs.
 
   barrier=<0|1(*)>, barrier(*), nobarrier
         This enables/disables the use of write barriers in the jbd code.
index fb5b39f..ad911be 100644 (file)
@@ -253,7 +253,7 @@ The following sysctls are available for the XFS filesystem:
        pool.
 
   fs.xfs.speculative_prealloc_lifetime
-               (Units: seconds   Min: 1  Default: 300  Max: 86400)
+       (Units: seconds   Min: 1  Default: 300  Max: 86400)
        The interval at which the background scanning for inodes
        with unused speculative preallocation runs. The scan
        removes unused preallocation from clean inodes and releases
index 36890b0..1c4e182 100644 (file)
@@ -251,11 +251,11 @@ selectively from different subsystems.
 .. code-block:: c
 
     struct kcov_remote_arg {
-       unsigned        trace_mode;
-       unsigned        area_size;
-       unsigned        num_handles;
-       uint64_t        common_handle;
-       uint64_t        handles[0];
+       __u32           trace_mode;
+       __u32           area_size;
+       __u32           num_handles;
+       __aligned_u64   common_handle;
+       __aligned_u64   handles[0];
     };
 
     #define KCOV_INIT_TRACE                    _IOR('c', 1, unsigned long)
index ecdfdc9..61ae13c 100644 (file)
@@ -203,12 +203,12 @@ Test Module
 Kselftest tests the kernel from userspace.  Sometimes things need
 testing from within the kernel, one method of doing this is to create a
 test module.  We can tie the module into the kselftest framework by
-using a shell script test runner.  ``kselftest_module.sh`` is designed
+using a shell script test runner.  ``kselftest/module.sh`` is designed
 to facilitate this process.  There is also a header file provided to
 assist writing kernel modules that are for use with kselftest:
 
 - ``tools/testing/kselftest/kselftest_module.h``
-- ``tools/testing/kselftest/kselftest_module.sh``
+- ``tools/testing/kselftest/kselftest/module.sh``
 
 How to use
 ----------
@@ -247,7 +247,7 @@ A bare bones test module might look like this:
 
    #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-   #include "../tools/testing/selftests/kselftest_module.h"
+   #include "../tools/testing/selftests/kselftest/module.h"
 
    KSTM_MODULE_GLOBALS();
 
@@ -276,7 +276,7 @@ Example test script
 
     #!/bin/bash
     # SPDX-License-Identifier: GPL-2.0+
-    $(dirname $0)/../kselftest_module.sh "foo" test_foo
+    $(dirname $0)/../kselftest/module.sh "foo" test_foo
 
 
 Test Harness
index 26ffb46..c60d760 100644 (file)
@@ -9,6 +9,7 @@ KUnit - Unit Testing for the Linux Kernel
 
        start
        usage
+       kunit-tool
        api/index
        faq
 
diff --git a/Documentation/dev-tools/kunit/kunit-tool.rst b/Documentation/dev-tools/kunit/kunit-tool.rst
new file mode 100644 (file)
index 0000000..50d4639
--- /dev/null
@@ -0,0 +1,57 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=================
+kunit_tool How-To
+=================
+
+What is kunit_tool?
+===================
+
+kunit_tool is a script (``tools/testing/kunit/kunit.py``) that aids in building
+the Linux kernel as UML (`User Mode Linux
+<http://user-mode-linux.sourceforge.net/>`_), running KUnit tests, parsing
+the test results and displaying them in a user friendly manner.
+
+What is a kunitconfig?
+======================
+
+It's just a defconfig that kunit_tool looks for in the base directory.
+kunit_tool uses it to generate a .config as you might expect. In addition, it
+verifies that the generated .config contains the CONFIG options in the
+kunitconfig; the reason it does this is so that it is easy to be sure that a
+CONFIG that enables a test actually ends up in the .config.
+
+How do I use kunit_tool?
+========================
+
+If a kunitconfig is present at the root directory, all you have to do is:
+
+.. code-block:: bash
+
+       ./tools/testing/kunit/kunit.py run
+
+However, you most likely want to use it with the following options:
+
+.. code-block:: bash
+
+       ./tools/testing/kunit/kunit.py run --timeout=30 --jobs=`nproc --all`
+
+- ``--timeout`` sets a maximum amount of time to allow tests to run.
+- ``--jobs`` sets the number of threads to use to build the kernel.
+
+If you just want to use the defconfig that ships with the kernel, you can
+append the ``--defconfig`` flag as well:
+
+.. code-block:: bash
+
+       ./tools/testing/kunit/kunit.py run --timeout=30 --jobs=`nproc --all` --defconfig
+
+.. note::
+       This command is particularly helpful for getting started because it
+       just works. No kunitconfig needs to be present.
+
+For a list of all the flags supported by kunit_tool, you can run:
+
+.. code-block:: bash
+
+       ./tools/testing/kunit/kunit.py run --help
index aeeddfa..4e1d24d 100644 (file)
@@ -19,21 +19,21 @@ The wrapper can be run with:
 
 .. code-block:: bash
 
-   ./tools/testing/kunit/kunit.py run
+       ./tools/testing/kunit/kunit.py run --defconfig
 
-Creating a kunitconfig
-======================
-The Python script is a thin wrapper around Kbuild as such, it needs to be
-configured with a ``kunitconfig`` file. This file essentially contains the
+For more information on this wrapper (also called kunit_tool) checkout the
+:doc:`kunit-tool` page.
+
+Creating a .kunitconfig
+=======================
+The Python script is a thin wrapper around Kbuild. As such, it needs to be
+configured with a ``.kunitconfig`` file. This file essentially contains the
 regular Kernel config, with the specific test targets as well.
 
 .. code-block:: bash
 
-       git clone -b master https://kunit.googlesource.com/kunitconfig $PATH_TO_KUNITCONFIG_REPO
        cd $PATH_TO_LINUX_REPO
-       ln -s $PATH_TO_KUNIT_CONFIG_REPO/kunitconfig kunitconfig
-
-You may want to add kunitconfig to your local gitignore.
+       cp arch/um/configs/kunit_defconfig .kunitconfig
 
 Verifying KUnit Works
 ---------------------
@@ -59,8 +59,8 @@ If everything worked correctly, you should see the following:
 followed by a list of tests that are run. All of them should be passing.
 
 .. note::
-   Because it is building a lot of sources for the first time, the ``Building
-   kunit kernel`` step may take a while.
+       Because it is building a lot of sources for the first time, the
+       ``Building KUnit kernel`` step may take a while.
 
 Writing your first test
 =======================
@@ -148,7 +148,7 @@ and the following to ``drivers/misc/Makefile``:
 
        obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o
 
-Now add it to your ``kunitconfig``:
+Now add it to your ``.kunitconfig``:
 
 .. code-block:: none
 
@@ -159,7 +159,7 @@ Now you can run the test:
 
 .. code-block:: bash
 
-       ./tools/testing/kunit/kunit.py
+       ./tools/testing/kunit/kunit.py run
 
 You should see the following failure:
 
index c6e6963..b9a065a 100644 (file)
@@ -16,7 +16,7 @@ Organization of this document
 =============================
 
 This document is organized into two main sections: Testing and Isolating
-Behavior. The first covers what a unit test is and how to use KUnit to write
+Behavior. The first covers what unit tests are and how to use KUnit to write
 them. The second covers how to use KUnit to isolate code and make it possible
 to unit test code that was otherwise un-unit-testable.
 
@@ -174,13 +174,13 @@ Test Suites
 ~~~~~~~~~~~
 
 Now obviously one unit test isn't very helpful; the power comes from having
-many test cases covering all of your behaviors. Consequently it is common to
-have many *similar* tests; in order to reduce duplication in these closely
-related tests most unit testing frameworks provide the concept of a *test
-suite*, in KUnit we call it a *test suite*; all it is is just a collection of
-test cases for a unit of code with a set up function that gets invoked before
-every test cases and then a tear down function that gets invoked after every
-test case completes.
+many test cases covering all of a unit's behaviors. Consequently it is common
+to have many *similar* tests; in order to reduce duplication in these closely
+related tests most unit testing frameworks - including KUnit - provide the
+concept of a *test suite*. A *test suite* is just a collection of test cases
+for a unit of code with a set up function that gets invoked before every test
+case and then a tear down function that gets invoked after every test case
+completes.
 
 Example:
 
@@ -211,7 +211,7 @@ KUnit test framework.
 .. note::
    A test case will only be run if it is associated with a test suite.
 
-For more information on these types of things see the :doc:`api/test`.
+For more information on these types of things see the :doc:`api/test`.
 
 Isolating Behavior
 ==================
@@ -338,7 +338,7 @@ We can easily test this code by *faking out* the underlying EEPROM:
                return count;
        }
 
-       ssize_t fake_eeprom_write(struct eeprom *this, size_t offset, const char *buffer, size_t count)
+       ssize_t fake_eeprom_write(struct eeprom *parent, size_t offset, const char *buffer, size_t count)
        {
                struct fake_eeprom *this = container_of(parent, struct fake_eeprom, parent);
 
@@ -454,7 +454,7 @@ KUnit on non-UML architectures
 By default KUnit uses UML as a way to provide dependencies for code under test.
 Under most circumstances KUnit's usage of UML should be treated as an
 implementation detail of how KUnit works under the hood. Nevertheless, there
-are instances where being able to run architecture specific code, or test
+are instances where being able to run architecture specific code or test
 against real hardware is desirable. For these reasons KUnit supports running on
 other architectures.
 
@@ -557,7 +557,7 @@ run your tests on your hardware setup just by compiling for your architecture.
 .. important::
    Always prefer tests that run on UML to tests that only run under a particular
    architecture, and always prefer tests that run under QEMU or another easy
-   (and monitarily free) to obtain software environment to a specific piece of
+   (and monetarily free) to obtain software environment to a specific piece of
    hardware.
 
 Nevertheless, there are still valid reasons to write an architecture or hardware
index 8a1e38a..cffe8bb 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner platforms device tree bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   $nodename:
index d2a8722..f0b3d30 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A64 Display Engine Bus Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   $nodename:
index be32f08..9fe11ce 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A23 RSB Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells":
index 64938fd..4d38212 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner Clock Control Unit Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#clock-cells":
index 80b3e73..33c7842 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Security System Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index dafc098..0f70749 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 MIPI-DSI Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index 0e7987f..d67617f 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Ronbo RB070D30 DSI Display Panel
 
 maintainers:
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 15abc0f..8380819 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 DMA Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "dma-controller.yaml#"
index 387d599..9e53472 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A64 DMA Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "dma-controller.yaml#"
index 740b7f9..c1676b9 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 DMA Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "dma-controller.yaml#"
index 9346ef6..6097e8a 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 P2WI (Push/Pull 2 Wires Interface) Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: /schemas/i2c/i2c-controller.yaml#
index 2210f43..8347b1e 100644 (file)
@@ -18,8 +18,10 @@ Optional properties:
 - dma-names: should contain "tx" and "rx".
 - atmel,fifo-size: maximum number of data the RX and TX FIFOs can store for FIFO
   capable I2C controllers.
-- i2c-sda-hold-time-ns: TWD hold time, only available for "atmel,sama5d4-i2c"
-  and "atmel,sama5d2-i2c".
+- i2c-sda-hold-time-ns: TWD hold time, only available for:
+       "atmel,sama5d4-i2c",
+       "atmel,sama5d2-i2c",
+       "microchip,sam9x60-i2c".
 - Child nodes conforming to i2c bus binding
 
 Examples :
index b68be3a..e1f6d64 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
 $id: http://devicetree.org/schemas/iio/adc/adi,ad7292.yaml#
@@ -53,7 +53,8 @@ patternProperties:
         description: |
           The channel number. It can have up to 8 channels numbered from 0 to 7.
         items:
-          maximum: 7
+          - minimum: 0
+            maximum: 7
 
       diff-channels:
         description: see Documentation/devicetree/bindings/iio/adc/adc.txt
index d74962c..15c514b 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A33 Thermal Sensor Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#io-channel-cells":
index b3bd8ef..5b3b71c 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 LRADC Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 23a202d..953d875 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Interrupt Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: /schemas/interrupt-controller.yaml#
index 8cd08cf..cf09055 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A20 Non-Maskable Interrupt Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: /schemas/interrupt-controller.yaml#
index d3e423f..0f6374c 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 CMOS Sensor Interface (CSI) Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 description: |-
   The Allwinner A10 and later has a CMOS Sensor Interface to retrieve
index dea36d6..7838804 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Infrared Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "rc.yaml#"
index 30d9fb1..22a94b6 100644 (file)
@@ -60,7 +60,8 @@ patternProperties:
             maximum: 1066000000
 
           nvidia,emem-configuration:
-            $ref: /schemas/types.yaml#/definitions/uint32-array
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32-array
             description: |
               Values to be written to the EMEM register block. See section
               "15.6.1 MC Registers" in the TRM.
index 7fe0ca1..e4135ba 100644 (file)
@@ -56,7 +56,8 @@ patternProperties:
             maximum: 900000000
 
           nvidia,emc-auto-cal-interval:
-            $ref: /schemas/types.yaml#/definitions/uint32
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
             description:
               Pad calibration interval in microseconds.
             minimum: 0
@@ -78,7 +79,8 @@ patternProperties:
               Mode Register 0.
 
           nvidia,emc-zcal-cnt-long:
-            $ref: /schemas/types.yaml#/definitions/uint32
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32
             description:
               Number of EMC clocks to wait before issuing any commands after
               sending ZCAL_MRW_CMD.
@@ -96,7 +98,8 @@ patternProperties:
               FBIO "read" FIFO periodic resetting enabled.
 
           nvidia,emc-configuration:
-            $ref: /schemas/types.yaml#/definitions/uint32-array
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32-array
             description:
               EMC timing characterization data. These are the registers
               (see section "18.13.2 EMC Registers" in the TRM) whose values
index 84fd57b..4b9196c 100644 (file)
@@ -77,7 +77,8 @@ patternProperties:
             maximum: 900000000
 
           nvidia,emem-configuration:
-            $ref: /schemas/types.yaml#/definitions/uint32-array
+            allOf:
+              - $ref: /schemas/types.yaml#/definitions/uint32-array
             description: |
               Values to be written to the EMEM register block. See section
               "18.13.1 MC Registers" in the TRM.
index 4b1a09a..39afacc 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Resistive Touchscreen Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#thermal-sensor-cells":
index 64bca41..e82c9a0 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index b5b3cf5..5d3fa41 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index ae4796e..8d8560a 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index e5562c5..767193e 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 MDIO Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "mdio.yaml#"
index f683b71..703d0d8 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 11654d4..db36b4d 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A83t EMAC Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 770af7c..a95960e 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 CAN Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 27e1b4c..6bdcc3f 100644 (file)
@@ -10,7 +10,6 @@ Required properties:
        - #size-cells: 0
        - spi-max-frequency: Maximum frequency of the SPI bus the chip can
                             operate at should be less than or equal to 18 MHz.
-       - device-wake-gpios: Wake up GPIO to wake up the TCAN device.
        - interrupt-parent: the phandle to the interrupt controller which provides
                     the interrupt.
        - interrupts: interrupt specification for data-ready.
@@ -23,6 +22,7 @@ Optional properties:
                       reset.
        - device-state-gpios: Input GPIO that indicates if the device is in
                              a sleep state or if the device is active.
+       - device-wake-gpios: Wake up GPIO to wake up the TCAN device.
 
 Example:
 tcan4x5x: tcan4x5x@0 {
@@ -36,5 +36,5 @@ tcan4x5x: tcan4x5x@0 {
                interrupts = <14 GPIO_ACTIVE_LOW>;
                device-state-gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
                device-wake-gpios = <&gpio1 15 GPIO_ACTIVE_HIGH>;
-               reset-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>;
+               reset-gpios = <&gpio1 27 GPIO_ACTIVE_HIGH>;
 };
index 4845e29..e08cd4c 100644 (file)
@@ -347,6 +347,7 @@ allOf:
               - st,spear600-gmac
 
     then:
+      properties:
         snps,tso:
           $ref: /schemas/types.yaml#definitions/flag
           description:
index 81ae8ca..ac8c763 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
 %YAML 1.2
 ---
 $id: http://devicetree.org/schemas/net/ti,cpsw-switch.yaml#
@@ -44,7 +44,6 @@ properties:
     description: CPSW functional clock
 
   clock-names:
-    maxItems: 1
     items:
       - const: fck
 
@@ -70,7 +69,6 @@ properties:
       Phandle to the system control device node which provides access to
       efuse IO range with MAC addresses
 
-
   ethernet-ports:
     type: object
     properties:
@@ -82,8 +80,6 @@ properties:
     patternProperties:
       "^port@[0-9]+$":
           type: object
-          minItems: 1
-          maxItems: 2
           description: CPSW external ports
 
           allOf:
@@ -91,23 +87,20 @@ properties:
 
           properties:
             reg:
-              maxItems: 1
-              enum: [1, 2]
+              items:
+                - enum: [1, 2]
               description: CPSW port number
 
             phys:
-              $ref: /schemas/types.yaml#definitions/phandle-array
               maxItems: 1
               description:  phandle on phy-gmii-sel PHY
 
             label:
-              $ref: /schemas/types.yaml#/definitions/string-array
-              maxItems: 1
               description: label associated with this port
 
             ti,dual-emac-pvid:
-              $ref: /schemas/types.yaml#/definitions/uint32
-              maxItems: 1
+              allOf:
+                - $ref: /schemas/types.yaml#/definitions/uint32
               minimum: 1
               maximum: 1024
               description:
@@ -136,7 +129,6 @@ properties:
         description: CPTS reference clock
 
       clock-names:
-        maxItems: 1
         items:
           - const: cpts
 
@@ -201,7 +193,7 @@ examples:
                         phys = <&phy_gmii_sel 1>;
                         phy-handle = <&ethphy0_sw>;
                         phy-mode = "rgmii";
-                        ti,dual_emac_pvid = <1>;
+                        ti,dual-emac-pvid = <1>;
                 };
 
                 cpsw_port2: port@2 {
@@ -211,7 +203,7 @@ examples:
                         phys = <&phy_gmii_sel 2>;
                         phy-handle = <&ethphy1_sw>;
                         phy-mode = "rgmii";
-                        ti,dual_emac_pvid = <2>;
+                        ti,dual-emac-pvid = <2>;
                 };
         };
 
index 659b020..daf1321 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Security ID Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 allOf:
   - $ref: "nvmem.yaml#"
index fa46670..230d74f 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 MIPI D-PHY Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#phy-cells":
index cd0503b..bfefd09 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Pin Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#gpio-cells":
index 0ac52f8..4a21fe7 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 PWM Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#pwm-cells":
index acf18d1..c0d8386 100644 (file)
@@ -50,6 +50,8 @@ properties:
     description: Should contain the WWDG1 watchdog reset interrupt
     maxItems: 1
 
+  wakeup-source: true
+
   mboxes:
     description:
       This property is required only if the rpmsg/virtio functionality is used.
index 6e5341b..ee59409 100644 (file)
@@ -22,6 +22,6 @@ Example:
        };
 
        &ethernet_switch {
-               resets = <&reset>;
+               resets = <&reset 26>;
                reset-names = "switch";
        };
index 46d69c3..478b023 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index d7a57ec..37c2a60 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A31 RTC Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#clock-cells":
index ee9712f..2ecab8e 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 PS2 Host Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 description:
   A20 PS2 is dual role controller (PS2 host and PS2 device). These
index b8f89c7..ea1d2ef 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Codec Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#sound-dai-cells":
index eb39921..112ae00 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 I2S Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#sound-dai-cells":
index 38d4ced..444a432 100644 (file)
@@ -10,7 +10,7 @@ maintainers:
   - Chen-Yu Tsai <wens@csie.org>
   - Liam Girdwood <lgirdwood@gmail.com>
   - Mark Brown <broonie@kernel.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#sound-dai-cells":
index f290eb7..3b76441 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A64 Analog Codec Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 85305b4..9718358 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A23 Analog Codec Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 5e7cc05..55d2826 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A33 Codec Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#sound-dai-cells":
index 6d1329c..8036499 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index f36c46d..0565dc4 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   "#address-cells": true
index 7323392..1e0ca6c 100644 (file)
@@ -111,7 +111,7 @@ patternProperties:
       spi-rx-bus-width:
         allOf:
           - $ref: /schemas/types.yaml#/definitions/uint32
-          - enum: [ 1, 2, 4 ]
+          - enum: [ 1, 2, 4, 8 ]
           - default: 1
         description:
           Bus width to the SPI bus used for MISO.
@@ -123,7 +123,7 @@ patternProperties:
       spi-tx-bus-width:
         allOf:
           - $ref: /schemas/types.yaml#/definitions/uint32
-          - enum: [ 1, 2, 4 ]
+          - enum: [ 1, 2, 4, 8 ]
           - default: 1
         description:
           Bus width to the SPI bus used for MOSI.
index 20adc1c..23e989e 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 Timer Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index dfa0c41..40fc4bc 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A13 High-Speed Timer Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 0af70fc..d9207bf 100644 (file)
@@ -8,7 +8,7 @@ title: Allwinner A10 mUSB OTG Controller Device Tree Bindings
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 3a54f58..e8f2263 100644 (file)
@@ -11,7 +11,7 @@ allOf:
 
 maintainers:
   - Chen-Yu Tsai <wens@csie.org>
-  - Maxime Ripard <maxime.ripard@bootlin.com>
+  - Maxime Ripard <mripard@kernel.org>
 
 properties:
   compatible:
index 059d58a..6fb2b06 100644 (file)
@@ -23,7 +23,7 @@
     |    openrisc: | TODO |
     |      parisc: | TODO |
     |     powerpc: |  ok  |
-    |       riscv: | TODO |
+    |       riscv: |  ok  |
     |        s390: |  ok  |
     |          sh: |  ok  |
     |       sparc: | TODO |
index b0c0853..db6d39c 100644 (file)
@@ -24,11 +24,11 @@ Here is the main features of EROFS:
  - Metadata & data could be mixed by design;
 
  - 2 inode versions for different requirements:
-                          v1            v2
+                          compact (v1)  extended (v2)
    Inode metadata size:   32 bytes      64 bytes
    Max file size:         4 GB          16 EB (also limited by max. vol size)
    Max uids/gids:         65536         4294967296
-   File creation time:    no            yes (64 + 32-bit timestamp)
+   File change time:      no            yes (64 + 32-bit timestamp)
    Max hardlinks:         65536         4294967296
    Metadata reserved:     4 bytes       14 bytes
 
@@ -39,7 +39,7 @@ Here is the main features of EROFS:
  - Support POSIX.1e ACLs by using xattrs;
 
  - Support transparent file compression as an option:
-   LZ4 algorithm with 4 KB fixed-output compression for high performance;
+   LZ4 algorithm with 4 KB fixed-sized output compression for high performance.
 
 The following git tree provides the file system user-space tools under
 development (ex, formatting tool mkfs.erofs):
@@ -85,7 +85,7 @@ All data areas should be aligned with the block size, but metadata areas
 may not. All metadatas can be now observed in two different spaces (views):
  1. Inode metadata space
     Each valid inode should be aligned with an inode slot, which is a fixed
-    value (32 bytes) and designed to be kept in line with v1 inode size.
+    value (32 bytes) and designed to be kept in line with compact inode size.
 
     Each inode can be directly found with the following formula:
          inode offset = meta_blkaddr * block_size + 32 * nid
@@ -117,10 +117,10 @@ may not. All metadatas can be now observed in two different spaces (views):
                                                        |-> aligned with 4B
 
     Inode could be 32 or 64 bytes, which can be distinguished from a common
-    field which all inode versions have -- i_advise:
+    field which all inode versions have -- i_format:
 
         __________________               __________________
-       |     i_advise     |             |     i_advise     |
+       |     i_format     |             |     i_format     |
        |__________________|             |__________________|
        |        ...       |             |        ...       |
        |                  |             |                  |
@@ -129,12 +129,13 @@ may not. All metadatas can be now observed in two different spaces (views):
                                         |__________________| 64 bytes
 
     Xattrs, extents, data inline are followed by the corresponding inode with
-    proper alignes, and they could be optional for different data mappings,
-    _currently_ there are totally 3 valid data mappings supported:
+    proper alignment, and they could be optional for different data mappings.
+    _currently_ total 4 valid data mappings are supported:
 
-     1) flat file data without data inline (no extent);
-     2) fixed-output size data compression (must have extents);
-     3) flat file data with tail-end data inline (no extent);
+     0  flat file data without data inline (no extent);
+     1  fixed-sized output data compression (with non-compacted indexes);
+     2  flat file data with tail packing data inline (no extent);
+     3  fixed-sized output data compression (with compacted indexes, v5.3+).
 
     The size of the optional xattrs is indicated by i_xattr_count in inode
     header. Large xattrs or xattrs shared by many different files can be
@@ -182,8 +183,8 @@ introduce another on-disk field at all.
 
 Compression
 -----------
-Currently, EROFS supports 4KB fixed-output clustersize transparent file
-compression, as illustrated below:
+Currently, EROFS supports 4KB fixed-sized output transparent file compression,
+as illustrated below:
 
          |---- Variant-Length Extent ----|-------- VLE --------|----- VLE -----
          clusterofs                      clusterofs            clusterofs
similarity index 99%
rename from Documentation/filesystems/overlayfs.txt
rename to Documentation/filesystems/overlayfs.rst
index 845d689..e443be7 100644 (file)
@@ -1,3 +1,5 @@
+.. SPDX-License-Identifier: GPL-2.0
+
 Written by: Neil Brown
 Please see MAINTAINERS file for where to send questions.
 
@@ -181,7 +183,7 @@ Kernel config options:
     worried about backward compatibility with kernels that have the redirect_dir
     feature and follow redirects even if turned off.
 
-Module options (can also be changed through /sys/module/overlay/parameters/*):
+Module options (can also be changed through /sys/module/overlay/parameters/):
 
 - "redirect_dir=BOOL":
     See OVERLAY_FS_REDIRECT_DIR kernel config option above.
@@ -263,7 +265,7 @@ top, lower2 the middle and lower3 the bottom layer.
 
 
 Metadata only copy up
---------------------
+---------------------
 
 When metadata only copy up feature is enabled, overlayfs will only copy
 up metadata (as opposed to whole file), when a metadata specific operation
@@ -286,10 +288,10 @@ pointed by REDIRECT. This should not be possible on local system as setting
 "trusted." xattrs will require CAP_SYS_ADMIN. But it should be possible
 for untrusted layers like from a pen drive.
 
-Note: redirect_dir={off|nofollow|follow(*)} conflicts with metacopy=on, and
+Note: redirect_dir={off|nofollow|follow[*]} conflicts with metacopy=on, and
 results in an error.
 
-(*) redirect_dir=follow only conflicts with metacopy=on if upperdir=... is
+[*] redirect_dir=follow only conflicts with metacopy=on if upperdir=... is
 given.
 
 Sharing and copying layers
index 74bef19..231e6a6 100644 (file)
@@ -196,14 +196,11 @@ applicable everywhere (see syntax).
   or equal to the first symbol and smaller than or equal to the second
   symbol.
 
-- help text: "help" or "---help---"
+- help text: "help"
 
   This defines a help text. The end of the help text is determined by
   the indentation level, this means it ends at the first line which has
   a smaller indentation than the first line of the help text.
-  "---help---" and "help" do not differ in behaviour, "---help---" is
-  used to help visually separate configuration logic from help within
-  the file as an aid to developers.
 
 - misc options: "option" <symbol>[=<value>]
 
index b9b5055..d7e6534 100644 (file)
@@ -297,9 +297,19 @@ more details, with real examples.
        If CONFIG_EXT2_FS is set to either 'y' (built-in) or 'm' (modular)
        the corresponding obj- variable will be set, and kbuild will descend
        down in the ext2 directory.
-       Kbuild only uses this information to decide that it needs to visit
-       the directory, it is the Makefile in the subdirectory that
-       specifies what is modular and what is built-in.
+
+       Kbuild uses this information not only to decide that it needs to visit
+       the directory, but also to decide whether or not to link objects from
+       the directory into vmlinux.
+
+       When Kbuild descends into the directory with 'y', all built-in objects
+       from that directory are combined into the built-in.a, which will be
+       eventually linked into vmlinux.
+
+       When Kbuild descends into the directory with 'm', in contrast, nothing
+       from that directory will be linked into vmlinux. If the Makefile in
+       that directory specifies obj-y, those objects will be left orphan.
+       It is very likely a bug of the Makefile or of dependencies in Kconfig.
 
        It is good practice to use a `CONFIG_` variable when assigning directory
        names. This allows kbuild to totally skip the directory if the
index a572996..dc57a6a 100644 (file)
@@ -95,7 +95,7 @@ so all video4linux tools (like xawtv) should work with this driver.
 
 Besides the video4linux interface, the driver has a private interface
 for accessing the Motion Eye extended parameters (camera sharpness,
-agc, video framerate), the shapshot and the MJPEG capture facilities.
+agc, video framerate), the snapshot and the MJPEG capture facilities.
 
 This interface consists of several ioctls (prototypes and structures
 can be found in include/linux/meye.h):
index eef20d0..64553d8 100644 (file)
@@ -230,12 +230,6 @@ simultaneously on two ports. The driver checks the consistency of the schedules
 against this restriction and errors out when appropriate. Schedule analysis is
 needed to avoid this, which is outside the scope of the document.
 
-At the moment, the time-aware scheduler can only be triggered based on a
-standalone clock and not based on PTP time. This means the base-time argument
-from tc-taprio is ignored and the schedule starts right away. It also means it
-is more difficult to phase-align the scheduler with the other devices in the
-network.
-
 Device Tree bindings and board design
 =====================================
 
index fd26788..48ccb1b 100644 (file)
@@ -603,7 +603,7 @@ tcp_synack_retries - INTEGER
        with the current initial RTO of 1second. With this the final timeout
        for a passive TCP connection will happen after 63seconds.
 
-tcp_syncookies - BOOLEAN
+tcp_syncookies - INTEGER
        Only valid when the kernel was compiled with CONFIG_SYN_COOKIES
        Send out syncookies when the syn backlog queue of a socket
        overflows. This is to prevent against the common 'SYN flood attack'
index dc60b13..f5be243 100644 (file)
@@ -339,7 +339,7 @@ To claim an address following code example can be used:
                        .pgn = J1939_PGN_ADDRESS_CLAIMED,
                        .pgn_mask = J1939_PGN_PDU1_MAX,
                }, {
-                       .pgn = J1939_PGN_ADDRESS_REQUEST,
+                       .pgn = J1939_PGN_REQUEST,
                        .pgn_mask = J1939_PGN_PDU1_MAX,
                }, {
                        .pgn = J1939_PGN_ADDRESS_COMMANDED,
index 642fa96..d5c9320 100644 (file)
@@ -34,8 +34,8 @@ the names, the ``net`` tree is for fixes to existing code already in the
 mainline tree from Linus, and ``net-next`` is where the new code goes
 for the future release.  You can find the trees here:
 
-- https://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
-- https://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
+- https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
+- https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 
 Q: How often do changes from these trees make it to the mainline Linus tree?
 ----------------------------------------------------------------------------
index ada573b..edb296c 100644 (file)
@@ -988,7 +988,7 @@ Similarly, if you need to calculate the size of some structure member, use
 
 .. code-block:: c
 
-       #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+       #define sizeof_field(t, f) (sizeof(((t*)0)->f))
 
 There are also min() and max() macros that do strict type checking if you
 need them.  Feel free to peruse that header file to see what else is already
index 799580a..5d54946 100644 (file)
@@ -255,7 +255,7 @@ an involved disclosed party. The current ambassadors list:
   Red Hat      Josh Poimboeuf <jpoimboe@redhat.com>
   SUSE         Jiri Kosina <jkosina@suse.cz>
 
-  Amazon
+  Amazon       Peter Bowen <pzb@amzn.com>
   Google       Kees Cook <keescook@chromium.org>
   ============= ========================================================
 
index 21aa7d5..6399d92 100644 (file)
@@ -60,6 +60,7 @@ lack of a better place.
    volatile-considered-harmful
    botching-up-ioctls
    clang-format
+   ../riscv/patch-acceptance
 
 .. only::  subproject and html
 
index 215fd3c..fa33bff 100644 (file)
@@ -7,6 +7,7 @@ RISC-V architecture
 
     boot-image-header
     pmu
+    patch-acceptance
 
 .. only::  subproject and html
 
diff --git a/Documentation/riscv/patch-acceptance.rst b/Documentation/riscv/patch-acceptance.rst
new file mode 100644 (file)
index 0000000..dfe0ac5
--- /dev/null
@@ -0,0 +1,35 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+arch/riscv maintenance guidelines for developers
+================================================
+
+Overview
+--------
+The RISC-V instruction set architecture is developed in the open:
+in-progress drafts are available for all to review and to experiment
+with implementations.  New module or extension drafts can change
+during the development process - sometimes in ways that are
+incompatible with previous drafts.  This flexibility can present a
+challenge for RISC-V Linux maintenance.  Linux maintainers disapprove
+of churn, and the Linux development process prefers well-reviewed and
+tested code over experimental code.  We wish to extend these same
+principles to the RISC-V-related code that will be accepted for
+inclusion in the kernel.
+
+Submit Checklist Addendum
+-------------------------
+We'll only accept patches for new modules or extensions if the
+specifications for those modules or extensions are listed as being
+"Frozen" or "Ratified" by the RISC-V Foundation.  (Developers may, of
+course, maintain their own Linux kernel trees that contain code for
+any draft extensions that they wish.)
+
+Additionally, the RISC-V specification allows implementors to create
+their own custom extensions.  These custom extensions aren't required
+to go through any review or ratification process by the RISC-V
+Foundation.  To avoid the maintenance complexity and potential
+performance impact of adding kernel code for implementor-specific
+RISC-V extensions, we'll only to accept patches for extensions that
+have been officially frozen or ratified by the RISC-V Foundation.
+(Implementors, may, of course, maintain their own Linux kernel trees
+containing code for any custom extensions that they wish.)
index 201f80c..df129f5 100644 (file)
@@ -29,7 +29,7 @@ smartpqi specific entries in /sys
   smartpqi host attributes:
   -------------------------
   /sys/class/scsi_host/host*/rescan
-  /sys/class/scsi_host/host*/version
+  /sys/class/scsi_host/host*/driver_version
 
   The host rescan attribute is a write only attribute. Writing to this
   attribute will trigger the driver to scan for new, changed, or removed
index 02aacd6..392875a 100644 (file)
@@ -495,7 +495,8 @@ Module for C-Media CMI8338/8738/8768/8770 PCI sound cards.
 mpu_port
     port address of MIDI interface (8338 only):
     0x300,0x310,0x320,0x330 = legacy port,
-    0 = disable (default)
+    1 = integrated PCI port (default on 8738),
+    0 = disable
 fm_port
     port address of OPL-3 FM synthesizer (8x38 only):
     0x388 = legacy port,
index f169d58..8204e3b 100644 (file)
@@ -259,7 +259,7 @@ to details explained in the following section.
       {
               struct mychip *chip;
               int err;
-              static struct snd_device_ops ops = {
+              static const struct snd_device_ops ops = {
                      .dev_free = snd_mychip_dev_free,
               };
 
@@ -675,7 +675,7 @@ low-level device with a specified ``ops``,
 
 ::
 
-  static struct snd_device_ops ops = {
+  static const struct snd_device_ops ops = {
           .dev_free =        snd_mychip_dev_free,
   };
   ....
@@ -761,7 +761,7 @@ destructor and PCI entries. Example code is shown first, below.
       {
               struct mychip *chip;
               int err;
-              static struct snd_device_ops ops = {
+              static const struct snd_device_ops ops = {
                      .dev_free = snd_mychip_dev_free,
               };
 
@@ -3912,7 +3912,7 @@ For a raw-data proc-file, set the attributes as follows:
 
 ::
 
-  static struct snd_info_entry_ops my_file_io_ops = {
+  static const struct snd_info_entry_ops my_file_io_ops = {
           .read = my_file_io_read,
   };
 
index 8995d2d..8725f2b 100644 (file)
@@ -1005,7 +1005,7 @@ struttura, usate
 
 .. code-block:: c
 
-       #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+       #define sizeof_field(t, f) (sizeof(((t*)0)->f))
 
 Ci sono anche le macro min() e max() che, se vi serve, effettuano un controllo
 rigido sui tipi.  Sentitevi liberi di leggere attentamente questo file
index 4f62373..eae10bc 100644 (file)
@@ -826,7 +826,7 @@ inline gcc 也可以自动使其内联。而且其他用户可能会要求移除
 
 .. code-block:: c
 
-       #define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
+       #define sizeof_field(t, f) (sizeof(((t*)0)->f))
 
 还有可以做严格的类型检查的 min() 和 max() 宏,如果你需要可以使用它们。你可以
 自己看看那个头文件里还定义了什么你可以拿来用的东西,如果有定义的话,你就不应
index 5e5382e..9316dcf 100644 (file)
@@ -720,7 +720,7 @@ F:  Documentation/devicetree/bindings/i2c/i2c-altera.txt
 F:     drivers/i2c/busses/i2c-altera.c
 
 ALTERA MAILBOX DRIVER
-M:     Ley Foon Tan <lftan@altera.com>
+M:     Ley Foon Tan <ley.foon.tan@intel.com>
 L:     nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
 S:     Maintained
 F:     drivers/mailbox/mailbox-altera.c
@@ -771,6 +771,8 @@ F:  drivers/thermal/thermal_mmio.c
 
 AMAZON ETHERNET DRIVERS
 M:     Netanel Belgazal <netanel@amazon.com>
+M:     Arthur Kiyanovski <akiyano@amazon.com>
+R:     Guy Tzalik <gtzalik@amazon.com>
 R:     Saeed Bishara <saeedb@amazon.com>
 R:     Zorik Machulsky <zorik@amazon.com>
 L:     netdev@vger.kernel.org
@@ -1405,7 +1407,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
 
 ARM/ACTIONS SEMI ARCHITECTURE
 M:     Andreas Färber <afaerber@suse.de>
-R:     Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+M:     Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 N:     owl
@@ -2272,6 +2274,7 @@ F:        drivers/*/*s3c64xx*
 F:     drivers/*/*s5pv210*
 F:     drivers/memory/samsung/
 F:     drivers/soc/samsung/
+F:     drivers/tty/serial/samsung*
 F:     include/linux/soc/samsung/
 F:     Documentation/arm/samsung/
 F:     Documentation/devicetree/bindings/arm/samsung/
@@ -3147,7 +3150,7 @@ S:        Maintained
 F:     arch/mips/net/
 
 BPF JIT for NFP NICs
-M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+M:     Jakub Kicinski <kuba@kernel.org>
 L:     netdev@vger.kernel.org
 L:     bpf@vger.kernel.org
 S:     Supported
@@ -4970,6 +4973,7 @@ F:        include/linux/dma-buf*
 F:     include/linux/reservation.h
 F:     include/linux/*fence.h
 F:     Documentation/driver-api/dma-buf.rst
+K:     dma_(buf|fence|resv)
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 
 DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
@@ -4999,7 +5003,7 @@ F:        include/linux/dma-mapping.h
 F:     include/linux/dma-noncoherent.h
 
 DMC FREQUENCY DRIVER FOR SAMSUNG EXYNOS5422
-M:     Lukasz Luba <l.luba@partner.samsung.com>
+M:     Lukasz Luba <lukasz.luba@arm.com>
 L:     linux-pm@vger.kernel.org
 L:     linux-samsung-soc@vger.kernel.org
 S:     Maintained
@@ -6025,6 +6029,7 @@ M:        Yash Shah <yash.shah@sifive.com>
 L:     linux-edac@vger.kernel.org
 S:     Supported
 F:     drivers/edac/sifive_edac.c
+F:     drivers/soc/sifive_l2_cache.c
 
 EDAC-SKYLAKE
 M:     Tony Luck <tony.luck@intel.com>
@@ -7031,6 +7036,7 @@ L:        linux-acpi@vger.kernel.org
 S:     Maintained
 F:     Documentation/firmware-guide/acpi/gpio-properties.rst
 F:     drivers/gpio/gpiolib-acpi.c
+F:     drivers/gpio/gpiolib-acpi.h
 
 GPIO IR Transmitter
 M:     Sean Young <sean@mess.org>
@@ -9038,7 +9044,6 @@ F:        include/linux/umh.h
 
 KERNEL VIRTUAL MACHINE (KVM)
 M:     Paolo Bonzini <pbonzini@redhat.com>
-M:     Radim Krčmář <rkrcmar@redhat.com>
 L:     kvm@vger.kernel.org
 W:     http://www.linux-kvm.org
 T:     git git://git.kernel.org/pub/scm/virt/kvm/kvm.git
@@ -9073,9 +9078,9 @@ F:        virt/kvm/arm/
 F:     include/kvm/arm_*
 
 KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
-M:     James Hogan <jhogan@kernel.org>
 L:     linux-mips@vger.kernel.org
-S:     Supported
+L:     kvm@vger.kernel.org
+S:     Orphan
 F:     arch/mips/include/uapi/asm/kvm*
 F:     arch/mips/include/asm/kvm*
 F:     arch/mips/kvm/
@@ -9110,7 +9115,6 @@ F:        tools/testing/selftests/kvm/*/s390x/
 
 KERNEL VIRTUAL MACHINE FOR X86 (KVM/x86)
 M:     Paolo Bonzini <pbonzini@redhat.com>
-M:     Radim Krčmář <rkrcmar@redhat.com>
 R:     Sean Christopherson <sean.j.christopherson@intel.com>
 R:     Vitaly Kuznetsov <vkuznets@redhat.com>
 R:     Wanpeng Li <wanpengli@tencent.com>
@@ -10108,6 +10112,7 @@ S:      Maintained
 F:     drivers/media/radio/radio-maxiradio*
 
 MCAN MMIO DEVICE DRIVER
+M:     Dan Murphy <dmurphy@ti.com>
 M:     Sriram Dash <sriram.dash@samsung.com>
 L:     linux-can@vger.kernel.org
 S:     Maintained
@@ -11426,7 +11431,7 @@ F:      include/uapi/linux/netrom.h
 F:     net/netrom/
 
 NETRONOME ETHERNET DRIVERS
-M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+M:     Jakub Kicinski <kuba@kernel.org>
 L:     oss-drivers@netronome.com
 S:     Maintained
 F:     drivers/net/ethernet/netronome/
@@ -11455,8 +11460,8 @@ M:      "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
 Q:     http://patchwork.ozlabs.org/project/netdev/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 S:     Odd Fixes
 F:     Documentation/devicetree/bindings/net/
 F:     drivers/net/
@@ -11497,8 +11502,8 @@ M:      "David S. Miller" <davem@davemloft.net>
 L:     netdev@vger.kernel.org
 W:     http://www.linuxfoundation.org/en/Net
 Q:     http://patchwork.ozlabs.org/project/netdev/list/
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
 B:     mailto:netdev@vger.kernel.org
 S:     Maintained
 F:     net/
@@ -11543,7 +11548,7 @@ M:      "David S. Miller" <davem@davemloft.net>
 M:     Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
 M:     Hideaki YOSHIFUJI <yoshfuji@linux-ipv6.org>
 L:     netdev@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/davem/net.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 S:     Maintained
 F:     net/ipv4/
 F:     net/ipv6/
@@ -11586,7 +11591,7 @@ M:      Boris Pismenny <borisp@mellanox.com>
 M:     Aviad Yehezkel <aviadye@mellanox.com>
 M:     John Fastabend <john.fastabend@gmail.com>
 M:     Daniel Borkmann <daniel@iogearbox.net>
-M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+M:     Jakub Kicinski <kuba@kernel.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     net/tls/*
@@ -11598,7 +11603,7 @@ L:      linux-wireless@vger.kernel.org
 Q:     http://patchwork.kernel.org/project/linux-wireless/list/
 
 NETDEVSIM
-M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+M:     Jakub Kicinski <kuba@kernel.org>
 S:     Maintained
 F:     drivers/net/netdevsim/*
 
@@ -11675,7 +11680,7 @@ F:      Documentation/scsi/NinjaSCSI.txt
 F:     drivers/scsi/nsp32*
 
 NIOS2 ARCHITECTURE
-M:     Ley Foon Tan <lftan@altera.com>
+M:     Ley Foon Tan <ley.foon.tan@intel.com>
 L:     nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/lftan/nios2.git
 S:     Maintained
@@ -12393,7 +12398,7 @@ L:      linux-unionfs@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git
 S:     Supported
 F:     fs/overlayfs/
-F:     Documentation/filesystems/overlayfs.txt
+F:     Documentation/filesystems/overlayfs.rst
 
 P54 WIRELESS DRIVER
 M:     Christian Lamparter <chunkeey@googlemail.com>
@@ -12559,7 +12564,7 @@ F:      Documentation/devicetree/bindings/pci/aardvark-pci.txt
 F:     drivers/pci/controller/pci-aardvark.c
 
 PCI DRIVER FOR ALTERA PCIE IP
-M:     Ley Foon Tan <lftan@altera.com>
+M:     Ley Foon Tan <ley.foon.tan@intel.com>
 L:     rfi@lists.rocketboards.org (moderated for non-subscribers)
 L:     linux-pci@vger.kernel.org
 S:     Supported
@@ -12738,7 +12743,7 @@ S:      Supported
 F:     Documentation/PCI/pci-error-recovery.rst
 
 PCI MSI DRIVER FOR ALTERA MSI IP
-M:     Ley Foon Tan <lftan@altera.com>
+M:     Ley Foon Tan <ley.foon.tan@intel.com>
 L:     rfi@lists.rocketboards.org (moderated for non-subscribers)
 L:     linux-pci@vger.kernel.org
 S:     Supported
@@ -13674,7 +13679,6 @@ F:      drivers/net/ethernet/qualcomm/emac/
 
 QUALCOMM ETHQOS ETHERNET DRIVER
 M:     Vinod Koul <vkoul@kernel.org>
-M:     Niklas Cassel <niklas.cassel@linaro.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -13708,6 +13712,15 @@ L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 F:     drivers/iommu/qcom_iommu.c
 
+QUALCOMM RMNET DRIVER
+M:     Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+M:     Sean Tranchetti <stranche@codeaurora.org>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/ethernet/qualcomm/rmnet/
+F:     Documentation/networking/device_drivers/qualcomm/rmnet.txt
+F:     include/linux/if_rmnet.h
+
 QUALCOMM TSENS THERMAL DRIVER
 M:     Amit Kucheria <amit.kucheria@linaro.org>
 L:     linux-pm@vger.kernel.org
@@ -14106,6 +14119,7 @@ M:      Paul Walmsley <paul.walmsley@sifive.com>
 M:     Palmer Dabbelt <palmer@dabbelt.com>
 M:     Albert Ou <aou@eecs.berkeley.edu>
 L:     linux-riscv@lists.infradead.org
+P:     Documentation/riscv/patch-acceptance.rst
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git
 S:     Supported
 F:     arch/riscv/
@@ -14533,8 +14547,6 @@ F:      include/linux/platform_data/spi-s3c64xx.h
 
 SAMSUNG SXGBE DRIVERS
 M:     Byungho An <bh74.an@samsung.com>
-M:     Girish K S <ks.giri@samsung.com>
-M:     Vipul Pandya <vipul.pandya@samsung.com>
 S:     Supported
 L:     netdev@vger.kernel.org
 F:     drivers/net/ethernet/samsung/sxgbe/
@@ -16313,12 +16325,10 @@ F:    drivers/media/radio/radio-raremono.c
 
 THERMAL
 M:     Zhang Rui <rui.zhang@intel.com>
-M:     Eduardo Valentin <edubezval@gmail.com>
-R:     Daniel Lezcano <daniel.lezcano@linaro.org>
+M:     Daniel Lezcano <daniel.lezcano@linaro.org>
 R:     Amit Kucheria <amit.kucheria@verdurent.com>
 L:     linux-pm@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux.git
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal.git
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/thermal/linux.git
 Q:     https://patchwork.kernel.org/project/linux-pm/list/
 S:     Supported
 F:     drivers/thermal/
@@ -16532,6 +16542,13 @@ L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Odd Fixes
 F:     sound/soc/codecs/tas571x*
 
+TI TCAN4X5X DEVICE DRIVER
+M:     Dan Murphy <dmurphy@ti.com>
+L:     linux-can@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/net/can/tcan4x5x.txt
+F:     drivers/net/can/m_can/tcan4x5x.c
+
 TI TRF7970A NFC DRIVER
 M:     Mark Greer <mgreer@animalcreek.com>
 L:     linux-wireless@vger.kernel.org
@@ -18024,7 +18041,7 @@ XDP (eXpress Data Path)
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
 M:     David S. Miller <davem@davemloft.net>
-M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+M:     Jakub Kicinski <kuba@kernel.org>
 M:     Jesper Dangaard Brouer <hawk@kernel.org>
 M:     John Fastabend <john.fastabend@gmail.com>
 L:     netdev@vger.kernel.org
index 73e3c28..c50ef91 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc7
 NAME = Kleptomaniac Octopus
 
 # *DOCUMENTATION*
@@ -414,6 +414,7 @@ STRIP               = $(CROSS_COMPILE)strip
 OBJCOPY                = $(CROSS_COMPILE)objcopy
 OBJDUMP                = $(CROSS_COMPILE)objdump
 OBJSIZE                = $(CROSS_COMPILE)size
+READELF                = $(CROSS_COMPILE)readelf
 PAHOLE         = pahole
 LEX            = flex
 YACC           = bison
@@ -472,7 +473,7 @@ GCC_PLUGINS_CFLAGS :=
 CLANG_FLAGS :=
 
 export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE AS LD CC
-export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE PAHOLE LEX YACC AWK INSTALLKERNEL
+export CPP AR NM STRIP OBJCOPY OBJDUMP OBJSIZE READELF PAHOLE LEX YACC AWK INSTALLKERNEL
 export PERL PYTHON PYTHON2 PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
 export KBUILD_HOSTCXXFLAGS KBUILD_HOSTLDFLAGS KBUILD_HOSTLDLIBS LDFLAGS_MODULE
 
index 41b16f2..0b8b63d 100644 (file)
 #endif
 
 #ifdef CONFIG_ARC_HAS_ACCL_REGS
-       ST2     r58, r59, PT_sp + 12
+       ST2     r58, r59, PT_r58
 #endif
 
 .endm
 
        LD2     gp, fp, PT_r26          ; gp (r26), fp (r27)
 
-       ld      r12, [sp, PT_sp + 4]
-       ld      r30, [sp, PT_sp + 8]
+       ld      r12, [sp, PT_r12]
+       ld      r30, [sp, PT_r30]
 
        ; Restore SP (into AUX_USER_SP) only if returning to U mode
        ;  - for K mode, it will be implicitly restored as stack is unwound
 #endif
 
 #ifdef CONFIG_ARC_HAS_ACCL_REGS
-       LD2     r58, r59, PT_sp + 12
+       LD2     r58, r59, PT_r58
 #endif
 .endm
 
index 9a74ce7..30ac40f 100644 (file)
@@ -8,7 +8,6 @@
 #define _ASM_ARC_HUGEPAGE_H
 
 #include <linux/types.h>
-#define __ARCH_USE_5LEVEL_HACK
 #include <asm-generic/pgtable-nopmd.h>
 
 static inline pte_t pmd_pte(pmd_t pmd)
index 1f621e4..c783bcd 100644 (file)
@@ -66,7 +66,15 @@ int main(void)
 
        DEFINE(SZ_CALLEE_REGS, sizeof(struct callee_regs));
        DEFINE(SZ_PT_REGS, sizeof(struct pt_regs));
-       DEFINE(PT_user_r25, offsetof(struct pt_regs, user_r25));
+
+#ifdef CONFIG_ISA_ARCV2
+       OFFSET(PT_r12, pt_regs, r12);
+       OFFSET(PT_r30, pt_regs, r30);
+#endif
+#ifdef CONFIG_ARC_HAS_ACCL_REGS
+       OFFSET(PT_r58, pt_regs, r58);
+       OFFSET(PT_r59, pt_regs, r59);
+#endif
 
        return 0;
 }
index dc05a63..27ea64b 100644 (file)
@@ -42,10 +42,10 @@ do {                                                \
 
 #define EXTRA_INFO(f) { \
                BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \
-                               % FIELD_SIZEOF(struct unwind_frame_info, f)) \
+                               % sizeof_field(struct unwind_frame_info, f)) \
                                + offsetof(struct unwind_frame_info, f) \
-                               / FIELD_SIZEOF(struct unwind_frame_info, f), \
-                               FIELD_SIZEOF(struct unwind_frame_info, f) \
+                               / sizeof_field(struct unwind_frame_info, f), \
+                               sizeof_field(struct unwind_frame_info, f) \
        }
 #define PTREGS_INFO(f) EXTRA_INFO(regs.f)
 
index a376a50..a931d0a 100644 (file)
@@ -7,7 +7,7 @@
 menuconfig ARC_PLAT_EZNPS
        bool "\"EZchip\" ARC dev platform"
        select CPU_BIG_ENDIAN
-       select CLKSRC_NPS
+       select CLKSRC_NPS if !PHYS_ADDR_T_64BIT
        select EZNPS_GIC
        select EZCHIP_NPS_MANAGEMENT_ENET if ETHERNET
        help
index ba75e36..96dab76 100644 (file)
@@ -72,6 +72,7 @@ config ARM
        select HAVE_ARM_SMCCC if CPU_V7
        select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32
        select HAVE_CONTEXT_TRACKING
+       select HAVE_COPY_THREAD_TLS
        select HAVE_C_RECORDMCOUNT
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS if MMU
index 8678e6e..e5fdb7a 100644 (file)
 
 &cpsw_emac0 {
        phy-handle = <&ethphy0>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
 };
 
 &i2c0 {
index cae4500..811c8ca 100644 (file)
@@ -86,7 +86,7 @@
                };
 
        lcd0: display {
-               compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+               compatible = "osddisplays,osd070t1718-19ts", "panel-dpi";
                label = "lcd";
 
                backlight = <&lcd_bl>;
index 9531412..078cb47 100644 (file)
@@ -42,7 +42,7 @@
        };
 
        lcd0: display {
-               compatible = "osddisplays,osd057T0559-34ts", "panel-dpi";
+               compatible = "osddisplays,osd070t1718-19ts", "panel-dpi";
                label = "lcd";
 
                backlight = <&lcd_bl>;
index 820ce3b..669559c 100644 (file)
 
 &pcie1_rc {
        status = "okay";
-       gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
-};
-
-&pcie1_ep {
-       gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
+       gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>;
 };
 
 &mmc1 {
index a064f13..ddf1236 100644 (file)
        gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
 };
 
-&pcie1_ep {
-       gpios = <&gpio3 23 GPIO_ACTIVE_HIGH>;
-};
-
 &mailbox5 {
        status = "okay";
        mbox_ipu1_ipc3x: mbox_ipu1_ipc3x {
index bc76f17..a813a0c 100644 (file)
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
+       main_12v0: fixedregulator-main_12v0 {
+               /* main supply */
+               compatible = "regulator-fixed";
+               regulator-name = "main_12v0";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       evm_5v0: fixedregulator-evm_5v0 {
+               /* Output of TPS54531D */
+               compatible = "regulator-fixed";
+               regulator-name = "evm_5v0";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&main_12v0>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
        vdd_3v3: fixedregulator-vdd_3v3 {
                compatible = "regulator-fixed";
                regulator-name = "vdd_3v3";
        gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
 };
 
-&pcie1_ep {
-       gpios = <&gpio2 8 GPIO_ACTIVE_LOW>;
-};
-
 &mcasp3 {
        #sound-dai-cells = <0>;
        assigned-clocks = <&l4per2_clkctrl DRA7_L4PER2_MCASP3_CLKCTRL 24>;
index c1c9cd3..13f7aef 100644 (file)
                };
        };
 
-       pca0: pca9552@60 {
+       pca0: pca9552@61 {
                compatible = "nxp,pca9552";
-               reg = <0x60>;
+               reg = <0x61>;
                #address-cells = <1>;
                #size-cells = <0>;
 
 
 &i2c13 {
        status = "okay";
-};
-
-&i2c14 {
-       status = "okay";
-};
-
-&i2c15 {
-       status = "okay";
-};
-
-&i2c0 {
-       status = "okay";
-};
-
-&i2c1 {
-       status = "okay";
-};
-
-&i2c2 {
-       status = "okay";
-};
-
-&i2c3 {
-       status = "okay";
-
-       power-supply@68 {
-               compatible = "ibm,cffps2";
-               reg = <0x68>;
-       };
-
-       power-supply@69 {
-               compatible = "ibm,cffps2";
-               reg = <0x69>;
-       };
-
-       power-supply@6a {
-               compatible = "ibm,cffps2";
-               reg = <0x6a>;
-       };
-
-       power-supply@6b {
-               compatible = "ibm,cffps2";
-               reg = <0x6b>;
-       };
-};
-
-&i2c4 {
-       status = "okay";
-
-       tmp275@48 {
-               compatible = "ti,tmp275";
-               reg = <0x48>;
-       };
-
-       tmp275@49 {
-               compatible = "ti,tmp275";
-               reg = <0x49>;
-       };
-
-       tmp275@4a {
-               compatible = "ti,tmp275";
-               reg = <0x4a>;
-       };
-};
-
-&i2c5 {
-       status = "okay";
-
-       tmp275@48 {
-               compatible = "ti,tmp275";
-               reg = <0x48>;
-       };
-
-       tmp275@49 {
-               compatible = "ti,tmp275";
-               reg = <0x49>;
-       };
-};
-
-&i2c6 {
-       status = "okay";
-
-       tmp275@48 {
-               compatible = "ti,tmp275";
-               reg = <0x48>;
-       };
-
-       tmp275@4a {
-               compatible = "ti,tmp275";
-               reg = <0x4a>;
-       };
-
-       tmp275@4b {
-               compatible = "ti,tmp275";
-               reg = <0x4b>;
-       };
-};
-
-&i2c7 {
-       status = "okay";
-
-       si7021-a20@20 {
-               compatible = "silabs,si7020";
-               reg = <0x20>;
-       };
-
-       tmp275@48 {
-               compatible = "ti,tmp275";
-               reg = <0x48>;
-       };
-
-       max31785@52 {
-               compatible = "maxim,max31785a";
-               reg = <0x52>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               fan@0 {
-                       compatible = "pmbus-fan";
-                       reg = <0>;
-                       tach-pulses = <2>;
-               };
-
-               fan@1 {
-                       compatible = "pmbus-fan";
-                       reg = <1>;
-                       tach-pulses = <2>;
-               };
-
-               fan@2 {
-                       compatible = "pmbus-fan";
-                       reg = <2>;
-                       tach-pulses = <2>;
-               };
-
-               fan@3 {
-                       compatible = "pmbus-fan";
-                       reg = <3>;
-                       tach-pulses = <2>;
-               };
-       };
-
-       pca0: pca9552@60 {
-               compatible = "nxp,pca9552";
-               reg = <0x60>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               gpio-controller;
-               #gpio-cells = <2>;
-
-               gpio@0 {
-                       reg = <0>;
-               };
-
-               gpio@1 {
-                       reg = <1>;
-               };
-
-               gpio@2 {
-                       reg = <2>;
-               };
-
-               gpio@3 {
-                       reg = <3>;
-               };
-
-               gpio@4 {
-                       reg = <4>;
-               };
-
-               gpio@5 {
-                       reg = <5>;
-               };
-
-               gpio@6 {
-                       reg = <6>;
-               };
-
-               gpio@7 {
-                       reg = <7>;
-               };
-
-               gpio@8 {
-                       reg = <8>;
-               };
-
-               gpio@9 {
-                       reg = <9>;
-               };
-
-               gpio@10 {
-                       reg = <10>;
-               };
-
-               gpio@11 {
-                       reg = <11>;
-               };
-
-               gpio@12 {
-                       reg = <12>;
-               };
-
-               gpio@13 {
-                       reg = <13>;
-               };
-
-               gpio@14 {
-                       reg = <14>;
-               };
-
-               gpio@15 {
-                       reg = <15>;
-               };
-       };
-
-       dps: dps310@76 {
-               compatible = "infineon,dps310";
-               reg = <0x76>;
-               #io-channel-cells = <0>;
-       };
-};
-
-&i2c8 {
-       status = "okay";
-
-       ucd90320@b {
-               compatible = "ti,ucd90160";
-               reg = <0x0b>;
-       };
-
-       ucd90320@c {
-               compatible = "ti,ucd90160";
-               reg = <0x0c>;
-       };
-
-       ucd90320@11 {
-               compatible = "ti,ucd90160";
-               reg = <0x11>;
-       };
-
-       rtc@32 {
-               compatible = "epson,rx8900";
-               reg = <0x32>;
-       };
-
-       tmp275@48 {
-               compatible = "ti,tmp275";
-               reg = <0x48>;
-       };
-
-       tmp275@4a {
-               compatible = "ti,tmp275";
-               reg = <0x4a>;
-       };
-};
-
-&i2c9 {
-       status = "okay";
-
-       ir35221@42 {
-               compatible = "infineon,ir35221";
-               reg = <0x42>;
-       };
-
-       ir35221@43 {
-               compatible = "infineon,ir35221";
-               reg = <0x43>;
-       };
-
-       ir35221@44 {
-               compatible = "infineon,ir35221";
-               reg = <0x44>;
-       };
-
-       tmp423a@4c {
-               compatible = "ti,tmp423";
-               reg = <0x4c>;
-       };
-
-       tmp423b@4d {
-               compatible = "ti,tmp423";
-               reg = <0x4d>;
-       };
-
-       ir35221@72 {
-               compatible = "infineon,ir35221";
-               reg = <0x72>;
-       };
-
-       ir35221@73 {
-               compatible = "infineon,ir35221";
-               reg = <0x73>;
-       };
-
-       ir35221@74 {
-               compatible = "infineon,ir35221";
-               reg = <0x74>;
-       };
-};
-
-&i2c10 {
-       status = "okay";
-
-       ir35221@42 {
-               compatible = "infineon,ir35221";
-               reg = <0x42>;
-       };
-
-       ir35221@43 {
-               compatible = "infineon,ir35221";
-               reg = <0x43>;
-       };
-
-       ir35221@44 {
-               compatible = "infineon,ir35221";
-               reg = <0x44>;
-       };
-
-       tmp423a@4c {
-               compatible = "ti,tmp423";
-               reg = <0x4c>;
-       };
-
-       tmp423b@4d {
-               compatible = "ti,tmp423";
-               reg = <0x4d>;
-       };
-
-       ir35221@72 {
-               compatible = "infineon,ir35221";
-               reg = <0x72>;
-       };
-
-       ir35221@73 {
-               compatible = "infineon,ir35221";
-               reg = <0x73>;
-       };
-
-       ir35221@74 {
-               compatible = "infineon,ir35221";
-               reg = <0x74>;
-       };
-};
-
-&i2c11 {
-       status = "okay";
-
-       tmp275@48 {
-               compatible = "ti,tmp275";
-               reg = <0x48>;
-       };
-
-       tmp275@49 {
-               compatible = "ti,tmp275";
-               reg = <0x49>;
-       };
-};
-
-&i2c12 {
-       status = "okay";
-};
-
-&i2c13 {
-       status = "okay";
 
        eeprom@50 {
                compatible = "atmel,24c64";
index f02de4a..ff49ec7 100644 (file)
        };
 };
 
-&fmc {
-       status = "okay";
-       flash@0 {
-               status = "okay";
-               m25p,fast-read;
-               label = "bmc";
-               spi-max-frequency = <50000000>;
-#include "openbmc-flash-layout-128.dtsi"
-       };
-
-       flash@1 {
-               status = "okay";
-               m25p,fast-read;
-               label = "alt-bmc";
-               spi-max-frequency = <50000000>;
-       };
-};
-
-&spi1 {
-       status = "okay";
-       pinctrl-names = "default";
-       pinctrl-0 = <&pinctrl_spi1_default>;
-
-       flash@0 {
-               status = "okay";
-               m25p,fast-read;
-               label = "pnor";
-               spi-max-frequency = <100000000>;
-       };
-};
-
 &mac2 {
        status = "okay";
        pinctrl-names = "default";
 
 &emmc {
        status = "okay";
+};
+
+&fsim0 {
+       status = "okay";
+
        #address-cells = <2>;
        #size-cells = <0>;
 
        status = "okay";
 };
 
-&i2c0 {
-       status = "okay";
-};
-
-&i2c1 {
-       status = "okay";
-};
-
-&i2c2 {
-       status = "okay";
-};
-
-&i2c3 {
-       status = "okay";
-
-       bmp: bmp280@77 {
-               compatible = "bosch,bmp280";
-               reg = <0x77>;
-               #io-channel-cells = <1>;
-       };
-
-       max31785@52 {
-               compatible = "maxim,max31785a";
-               reg = <0x52>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               fan@0 {
-                       compatible = "pmbus-fan";
-                       reg = <0>;
-                       tach-pulses = <2>;
-                       maxim,fan-rotor-input = "tach";
-                       maxim,fan-pwm-freq = <25000>;
-                       maxim,fan-dual-tach;
-                       maxim,fan-no-watchdog;
-                       maxim,fan-no-fault-ramp;
-                       maxim,fan-ramp = <2>;
-                       maxim,fan-fault-pin-mon;
-               };
-
-               fan@1 {
-                       compatible = "pmbus-fan";
-                       reg = <1>;
-                       tach-pulses = <2>;
-                       maxim,fan-rotor-input = "tach";
-                       maxim,fan-pwm-freq = <25000>;
-                       maxim,fan-dual-tach;
-                       maxim,fan-no-watchdog;
-                       maxim,fan-no-fault-ramp;
-                       maxim,fan-ramp = <2>;
-                       maxim,fan-fault-pin-mon;
-               };
-
-               fan@2 {
-                       compatible = "pmbus-fan";
-                       reg = <2>;
-                       tach-pulses = <2>;
-                       maxim,fan-rotor-input = "tach";
-                       maxim,fan-pwm-freq = <25000>;
-                       maxim,fan-dual-tach;
-                       maxim,fan-no-watchdog;
-                       maxim,fan-no-fault-ramp;
-                       maxim,fan-ramp = <2>;
-                       maxim,fan-fault-pin-mon;
-               };
-
-               fan@3 {
-                       compatible = "pmbus-fan";
-                       reg = <3>;
-                       tach-pulses = <2>;
-                       maxim,fan-rotor-input = "tach";
-                       maxim,fan-pwm-freq = <25000>;
-                       maxim,fan-dual-tach;
-                       maxim,fan-no-watchdog;
-                       maxim,fan-no-fault-ramp;
-                       maxim,fan-ramp = <2>;
-                       maxim,fan-fault-pin-mon;
-               };
-       };
-
-       dps: dps310@76 {
-               compatible = "infineon,dps310";
-               reg = <0x76>;
-               #io-channel-cells = <0>;
-       };
-
-       pca0: pca9552@60 {
-               compatible = "nxp,pca9552";
-               reg = <0x60>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               gpio-controller;
-               #gpio-cells = <2>;
-
-               gpio@0 {
-                       reg = <0>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@1 {
-                       reg = <1>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@2 {
-                       reg = <2>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@3 {
-                       reg = <3>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@4 {
-                       reg = <4>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@5 {
-                       reg = <5>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@6 {
-                       reg = <6>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@7 {
-                       reg = <7>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@8 {
-                       reg = <8>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@9 {
-                       reg = <9>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@10 {
-                       reg = <10>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@11 {
-                       reg = <11>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@12 {
-                       reg = <12>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@13 {
-                       reg = <13>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@14 {
-                       reg = <14>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@15 {
-                       reg = <15>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-       };
-
-       power-supply@68 {
-               compatible = "ibm,cffps1";
-               reg = <0x68>;
-       };
-
-       power-supply@69 {
-               compatible = "ibm,cffps1";
-               reg = <0x69>;
-       };
-};
-
-&i2c4 {
-       status = "okay";
-
-       tmp423a@4c {
-               compatible = "ti,tmp423";
-               reg = <0x4c>;
-       };
-
-       ir35221@70 {
-               compatible = "infineon,ir35221";
-               reg = <0x70>;
-       };
-
-       ir35221@71 {
-               compatible = "infineon,ir35221";
-               reg = <0x71>;
-       };
-};
-
-&i2c5 {
-       status = "okay";
-
-       tmp423a@4c {
-               compatible = "ti,tmp423";
-               reg = <0x4c>;
-       };
-
-       ir35221@70 {
-               compatible = "infineon,ir35221";
-               reg = <0x70>;
-       };
-
-       ir35221@71 {
-               compatible = "infineon,ir35221";
-               reg = <0x71>;
-       };
-};
-
-&i2c7 {
-       status = "okay";
-};
-
-&i2c9 {
-       status = "okay";
-
-       tmp275@4a {
-               compatible = "ti,tmp275";
-               reg = <0x4a>;
-       };
-};
-
-&i2c10 {
-       status = "okay";
-};
-
-&i2c11 {
-       status = "okay";
-
-       pca9552: pca9552@60 {
-               compatible = "nxp,pca9552";
-               reg = <0x60>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               gpio-controller;
-               #gpio-cells = <2>;
-
-               gpio-line-names = "PS_SMBUS_RESET_N", "APSS_RESET_N",
-                       "GPU0_TH_OVERT_N_BUFF", "GPU1_TH_OVERT_N_BUFF",
-                       "GPU2_TH_OVERT_N_BUFF", "GPU3_TH_OVERT_N_BUFF",
-                       "GPU4_TH_OVERT_N_BUFF", "GPU5_TH_OVERT_N_BUFF",
-                       "GPU0_PWR_GOOD_BUFF", "GPU1_PWR_GOOD_BUFF",
-                       "GPU2_PWR_GOOD_BUFF", "GPU3_PWR_GOOD_BUFF",
-                       "GPU4_PWR_GOOD_BUFF", "GPU5_PWR_GOOD_BUFF",
-                       "12V_BREAKER_FLT_N", "THROTTLE_UNLATCHED_N";
-
-               gpio@0 {
-                       reg = <0>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@1 {
-                       reg = <1>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@2 {
-                       reg = <2>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@3 {
-                       reg = <3>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@4 {
-                       reg = <4>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@5 {
-                       reg = <5>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@6 {
-                       reg = <6>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@7 {
-                       reg = <7>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@8 {
-                       reg = <8>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@9 {
-                       reg = <9>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@10 {
-                       reg = <10>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@11 {
-                       reg = <11>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@12 {
-                       reg = <12>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@13 {
-                       reg = <13>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@14 {
-                       reg = <14>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-
-               gpio@15 {
-                       reg = <15>;
-                       type = <PCA955X_TYPE_GPIO>;
-               };
-       };
-
-       rtc@32 {
-               compatible = "epson,rx8900";
-               reg = <0x32>;
-       };
-
-       eeprom@51 {
-               compatible = "atmel,24c64";
-               reg = <0x51>;
-       };
-
-       ucd90160@64 {
-               compatible = "ti,ucd90160";
-               reg = <0x64>;
-       };
-};
-
-&i2c12 {
-       status = "okay";
-};
-
-&i2c13 {
-       status = "okay";
-};
-
 &pinctrl {
        /* Hog these as no driver is probed for the entire LPC block */
        pinctrl-names = "default";
index 5f6142d..b72afba 100644 (file)
                                spi-max-frequency = <50000000>;
                                status = "disabled";
                        };
-
-                       fsim0: fsi@1e79b000 {
-                               compatible = "aspeed,ast2600-fsi-master", "fsi-master";
-                               reg = <0x1e79b000 0x94>;
-                               interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
-                               pinctrl-names = "default";
-                               pinctrl-0 = <&pinctrl_fsi1_default>;
-                               clocks = <&syscon ASPEED_CLK_GATE_FSICLK>;
-                               status = "disabled";
-                       };
-
-                       fsim1: fsi@1e79b100 {
-                               compatible = "aspeed,ast2600-fsi-master", "fsi-master";
-                               reg = <0x1e79b100 0x94>;
-                               interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
-                               pinctrl-names = "default";
-                               pinctrl-0 = <&pinctrl_fsi2_default>;
-                               clocks = <&syscon ASPEED_CLK_GATE_FSICLK>;
-                               status = "disabled";
-                       };
                };
 
                mdio0: mdio@1e650000 {
                                ranges = <0 0x1e78a000 0x1000>;
                        };
 
+                       fsim0: fsi@1e79b000 {
+                               compatible = "aspeed,ast2600-fsi-master", "fsi-master";
+                               reg = <0x1e79b000 0x94>;
+                               interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_fsi1_default>;
+                               clocks = <&syscon ASPEED_CLK_GATE_FSICLK>;
+                               status = "disabled";
+                       };
+
+                       fsim1: fsi@1e79b100 {
+                               compatible = "aspeed,ast2600-fsi-master", "fsi-master";
+                               reg = <0x1e79b100 0x94>;
+                               interrupts = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_fsi2_default>;
+                               clocks = <&syscon ASPEED_CLK_GATE_FSICLK>;
+                               status = "disabled";
+                       };
                };
        };
 };
index 2dac3ef..1bc45cf 100644 (file)
                mdio: mdio@18002000 {
                        compatible = "brcm,iproc-mdio";
                        reg = <0x18002000 0x8>;
-                       #size-cells = <1>;
-                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       #address-cells = <1>;
                        status = "disabled";
 
                        gphy0: ethernet-phy@0 {
index 961bed8..e2f6ffb 100644 (file)
@@ -43,7 +43,7 @@
                         <0x7c000000  0x0 0xfc000000  0x02000000>,
                         <0x40000000  0x0 0xff800000  0x00800000>;
                /* Emulate a contiguous 30-bit address range for DMA */
-               dma-ranges = <0xc0000000  0x0 0x00000000  0x3c000000>;
+               dma-ranges = <0xc0000000  0x0 0x00000000  0x40000000>;
 
                /*
                 * This node is the provider for the enable-method for
index 3caaa57..8394916 100644 (file)
@@ -37,7 +37,7 @@
 
                        trips {
                                cpu-crit {
-                                       temperature     = <80000>;
+                                       temperature     = <90000>;
                                        hysteresis      = <0>;
                                        type            = "critical";
                                };
index 372dc1e..2d9b4dd 100644 (file)
        mdio: mdio@18003000 {
                compatible = "brcm,iproc-mdio";
                reg = <0x18003000 0x8>;
-               #size-cells = <1>;
-               #address-cells = <0>;
+               #size-cells = <0>;
+               #address-cells = <1>;
        };
 
        mdio-bus-mux@18003000 {
index 6472b05..5a2c532 100644 (file)
                                regulator-name = "LDORTC1";
                                regulator-boot-on;
                        };
-
-                       ldortc2_reg: LDORTC2 {
-                               regulator-name = "LDORTC2";
-                               regulator-boot-on;
-                       };
                };
        };
 };
index e43bccb..d8f3821 100644 (file)
@@ -8,7 +8,7 @@
 /dts-v1/;
 
 #include "imx6dl.dtsi"
-#include "imx6qdl-icore.dtsi"
+#include "imx6qdl-icore-1.5.dtsi"
 
 / {
        model = "Engicam i.CoreM6 DualLite/Solo MIPI Starter Kit";
index 5219553..bb74fc6 100644 (file)
@@ -63,7 +63,7 @@
                #sound-dai-cells = <0>;
                clocks = <&clk_ext_audio_codec>;
                VDDA-supply = <&reg_3p3v>;
-               VDDIO-supply = <&reg_3p3v>;
+               VDDIO-supply = <&sw2_reg>;
        };
 };
 
index 845cfad..87f0aa8 100644 (file)
        };
 
        rtc@56 {
-               compatible = "rv3029c2";
+               compatible = "microcrystal,rv3029";
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_rtc_hw300>;
                reg = <0x56>;
index 71ca76a..fe59dde 100644 (file)
        vin-supply = <&vgen5_reg>;
 };
 
-&reg_vdd3p0 {
-       vin-supply = <&sw2_reg>;
-};
-
 &reg_vdd2p5 {
        vin-supply = <&vgen5_reg>;
 };
index 4829aa6..bc86cfa 100644 (file)
        vin-supply = <&sw2_reg>;
 };
 
-&reg_vdd3p0 {
-       vin-supply = <&sw2_reg>;
-};
-
 &reg_vdd2p5 {
        vin-supply = <&sw2_reg>;
 };
index 3e1d32f..5ace9e6 100644 (file)
        status = "okay";
 };
 
-&reg_3p0 {
-       vin-supply = <&sw2_reg>;
-};
-
 &snvs_poweroff {
        status = "okay";
 };
index f1830ed..91a7548 100644 (file)
        vin-supply = <&vgen6_reg>;
 };
 
-&reg_vdd3p0 {
-       vin-supply = <&sw2_reg>;
-};
-
 &reg_vdd2p5 {
        vin-supply = <&vgen6_reg>;
 };
index a8ee708..5a63ca6 100644 (file)
        vin-supply = <&vgen6_reg>;
 };
 
-&reg_vdd3p0 {
-       vin-supply = <&sw2_reg>;
-};
-
 &reg_vdd2p5 {
        vin-supply = <&vgen6_reg>;
 };
index 1506eb1..2121445 100644 (file)
                enable-active-high;
        };
 
-       reg_sensors: regulator-sensors {
+       reg_peri_3v3: regulator-peri-3v3 {
                compatible = "regulator-fixed";
                pinctrl-names = "default";
-               pinctrl-0 = <&pinctrl_sensors_reg>;
-               regulator-name = "sensors-supply";
+               pinctrl-0 = <&pinctrl_peri_3v3>;
+               regulator-name = "VPERI_3V3";
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
                gpio = <&gpio5 2 GPIO_ACTIVE_LOW>;
+               /*
+                * If you want to want to make this dynamic please
+                * check schematics and test all affected peripherals:
+                *
+                * - sensors
+                * - ethernet phy
+                * - can
+                * - bluetooth
+                * - wm8960 audio codec
+                * - ov5640 camera
+                */
+               regulator-always-on;
        };
 
        reg_can_3v3: regulator-can-3v3 {
        pinctrl-0 = <&pinctrl_enet1>;
        phy-mode = "rmii";
        phy-handle = <&ethphy0>;
+       phy-supply = <&reg_peri_3v3>;
        status = "okay";
 };
 
        pinctrl-0 = <&pinctrl_enet2>;
        phy-mode = "rmii";
        phy-handle = <&ethphy1>;
+       phy-supply = <&reg_peri_3v3>;
        status = "okay";
 
        mdio {
        magnetometer@e {
                compatible = "fsl,mag3110";
                reg = <0x0e>;
-               vdd-supply = <&reg_sensors>;
-               vddio-supply = <&reg_sensors>;
+               vdd-supply = <&reg_peri_3v3>;
+               vddio-supply = <&reg_peri_3v3>;
        };
 };
 
        flash0: n25q256a@0 {
                #address-cells = <1>;
                #size-cells = <1>;
-               compatible = "micron,n25q256a";
+               compatible = "micron,n25q256a", "jedec,spi-nor";
                spi-max-frequency = <29000000>;
                spi-rx-bus-width = <4>;
                spi-tx-bus-width = <4>;
                >;
        };
 
-       pinctrl_sensors_reg: sensorsreggrp {
+       pinctrl_peri_3v3: peri3v3grp {
                fsl,pins = <
                        MX6UL_PAD_SNVS_TAMPER2__GPIO5_IO02      0x1b0b0
                >;
index 1fb1ec5..6d16e32 100644 (file)
@@ -49,3 +49,7 @@
                reg = <0x80000000 0x10000000>;
        };
 };
+
+&gpmi {
+       status = "okay";
+};
index d37a192..ab91c98 100644 (file)
                #address-cells = <1>;
                #size-cells = <0>;
 
-               cpu0: cpu@0 {
+               cpu0: cpu@f00 {
                        compatible = "arm,cortex-a7";
                        device_type = "cpu";
-                       reg = <0>;
+                       reg = <0xf00>;
                };
        };
 
index 5a7e3e5..3c534cd 100644 (file)
 &aobus {
        pmu: pmu@e0 {
                compatible = "amlogic,meson8-pmu", "syscon";
-               reg = <0xe0 0x8>;
+               reg = <0xe0 0x18>;
        };
 
        pinctrl_aobus: pinctrl@84 {
index d9762de..6f48082 100644 (file)
 
                        twsi1: i2c@d4011000 {
                                compatible = "mrvl,mmp-twsi";
-                               reg = <0xd4011000 0x1000>;
+                               reg = <0xd4011000 0x70>;
                                interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&soc_clocks MMP2_CLK_TWSI0>;
                                resets = <&soc_clocks MMP2_CLK_TWSI0>;
 
                        twsi2: i2c@d4031000 {
                                compatible = "mrvl,mmp-twsi";
-                               reg = <0xd4031000 0x1000>;
+                               reg = <0xd4031000 0x70>;
                                interrupt-parent = <&twsi_mux>;
                                interrupts = <0>;
                                clocks = <&soc_clocks MMP2_CLK_TWSI1>;
 
                        twsi3: i2c@d4032000 {
                                compatible = "mrvl,mmp-twsi";
-                               reg = <0xd4032000 0x1000>;
+                               reg = <0xd4032000 0x70>;
                                interrupt-parent = <&twsi_mux>;
                                interrupts = <1>;
                                clocks = <&soc_clocks MMP2_CLK_TWSI2>;
 
                        twsi4: i2c@d4033000 {
                                compatible = "mrvl,mmp-twsi";
-                               reg = <0xd4033000 0x1000>;
+                               reg = <0xd4033000 0x70>;
                                interrupt-parent = <&twsi_mux>;
                                interrupts = <2>;
                                clocks = <&soc_clocks MMP2_CLK_TWSI3>;
 
                        twsi5: i2c@d4033800 {
                                compatible = "mrvl,mmp-twsi";
-                               reg = <0xd4033800 0x1000>;
+                               reg = <0xd4033800 0x70>;
                                interrupt-parent = <&twsi_mux>;
                                interrupts = <3>;
                                clocks = <&soc_clocks MMP2_CLK_TWSI4>;
 
                        twsi6: i2c@d4034000 {
                                compatible = "mrvl,mmp-twsi";
-                               reg = <0xd4034000 0x1000>;
+                               reg = <0xd4034000 0x70>;
                                interrupt-parent = <&twsi_mux>;
                                interrupts = <4>;
                                clocks = <&soc_clocks MMP2_CLK_TWSI5>;
index fb92850..d9be511 100644 (file)
                initial-mode = <1>; /* initialize in HUB mode */
                disabled-ports = <1>;
                intn-gpios = <&pio 7 5 GPIO_ACTIVE_HIGH>; /* PH5 */
-               reset-gpios = <&pio 4 16 GPIO_ACTIVE_HIGH>; /* PE16 */
+               reset-gpios = <&pio 4 16 GPIO_ACTIVE_LOW>; /* PE16 */
                connect-gpios = <&pio 4 17 GPIO_ACTIVE_HIGH>; /* PE17 */
                refclk-frequency = <19200000>;
        };
index e7e4bb5..fde84f1 100644 (file)
@@ -350,6 +350,7 @@ CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_SOFTLOCKUP_DETECTOR=y
 # CONFIG_DETECT_HUNG_TASK is not set
index 26d6dee..3608e55 100644 (file)
@@ -462,6 +462,7 @@ CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 CONFIG_PRINTK_TIME=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_PROVE_LOCKING=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
index 8c37cc8..c32c338 100644 (file)
@@ -92,6 +92,7 @@ CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NETFILTER=y
 CONFIG_PHONET=m
+CONFIG_NET_SWITCHDEV=y
 CONFIG_CAN=m
 CONFIG_CAN_C_CAN=m
 CONFIG_CAN_C_CAN_PLATFORM=m
@@ -181,6 +182,7 @@ CONFIG_SMSC911X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_TI_DAVINCI_EMAC=y
 CONFIG_TI_CPSW=y
+CONFIG_TI_CPSW_SWITCHDEV=y
 CONFIG_TI_CPTS=y
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
@@ -554,6 +556,6 @@ CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_INFO_SPLIT=y
 CONFIG_DEBUG_INFO_DWARF4=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_SCHEDSTATS=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
-CONFIG_TI_CPSW_SWITCHDEV=y
index bda57ca..de38304 100644 (file)
@@ -212,4 +212,5 @@ CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_PRINTK_TIME=y
 # CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
index f3f42cf..776ae07 100644 (file)
@@ -38,6 +38,13 @@ void curve25519_arch(u8 out[CURVE25519_KEY_SIZE],
 }
 EXPORT_SYMBOL(curve25519_arch);
 
+void curve25519_base_arch(u8 pub[CURVE25519_KEY_SIZE],
+                         const u8 secret[CURVE25519_KEY_SIZE])
+{
+       return curve25519_arch(pub, secret, curve25519_base_point);
+}
+EXPORT_SYMBOL(curve25519_base_arch);
+
 static int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf,
                                 unsigned int len)
 {
index cea1c27..46e478f 100644 (file)
@@ -226,8 +226,8 @@ void release_thread(struct task_struct *dead_task)
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 
 int
-copy_thread(unsigned long clone_flags, unsigned long stack_start,
-           unsigned long stk_sz, struct task_struct *p)
+copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
+           unsigned long stk_sz, struct task_struct *p, unsigned long tls)
 {
        struct thread_info *thread = task_thread_info(p);
        struct pt_regs *childregs = task_pt_regs(p);
@@ -261,7 +261,7 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
        clear_ptrace_hw_breakpoint(p);
 
        if (clone_flags & CLONE_SETTLS)
-               thread->tp_value[0] = childregs->ARM_r3;
+               thread->tp_value[0] = tls;
        thread->tp_value[1] = get_tpuser();
 
        thread_notify(THREAD_NOTIFY_COPY, thread);
index dbe2967..fa0300d 100644 (file)
@@ -13,6 +13,7 @@ static const char * const bcm2711_compat[] = {
 #ifdef CONFIG_ARCH_MULTI_V7
        "brcm,bcm2711",
 #endif
+       NULL
 };
 
 DT_MACHINE_START(BCM2711, "BCM2711")
index dd427bd..02b180a 100644 (file)
@@ -9,6 +9,7 @@ menuconfig ARCH_DAVINCI
        select PM_GENERIC_DOMAINS if PM
        select PM_GENERIC_DOMAINS_OF if PM && OF
        select REGMAP_MMIO
+       select RESET_CONTROLLER
        select HAVE_IDE
        select PINCTRL_SINGLE
 
index d811803..871f983 100644 (file)
@@ -84,7 +84,7 @@ struct device * __init imx_soc_device_init(void)
        const char *ocotp_compat = NULL;
        struct soc_device *soc_dev;
        struct device_node *root;
-       struct regmap *ocotp;
+       struct regmap *ocotp = NULL;
        const char *soc_id;
        u64 soc_uid = 0;
        u32 val;
@@ -148,11 +148,11 @@ struct device * __init imx_soc_device_init(void)
                soc_id = "i.MX6UL";
                break;
        case MXC_CPU_IMX6ULL:
-               ocotp_compat = "fsl,imx6ul-ocotp";
+               ocotp_compat = "fsl,imx6ull-ocotp";
                soc_id = "i.MX6ULL";
                break;
        case MXC_CPU_IMX6ULZ:
-               ocotp_compat = "fsl,imx6ul-ocotp";
+               ocotp_compat = "fsl,imx6ull-ocotp";
                soc_id = "i.MX6ULZ";
                break;
        case MXC_CPU_IMX6SLL:
@@ -175,7 +175,9 @@ struct device * __init imx_soc_device_init(void)
                ocotp = syscon_regmap_lookup_by_compatible(ocotp_compat);
                if (IS_ERR(ocotp))
                        pr_err("%s: failed to find %s regmap!\n", __func__, ocotp_compat);
+       }
 
+       if (!IS_ERR_OR_NULL(ocotp)) {
                regmap_read(ocotp, OCOTP_UID_H, &val);
                soc_uid = val;
                regmap_read(ocotp, OCOTP_UID_L, &val);
index 0331c58..dff651b 100644 (file)
@@ -17,9 +17,9 @@ extern void pxa168_clear_keypad_wakeup(void);
 #include <linux/platform_data/keypad-pxa27x.h>
 #include <linux/pxa168_eth.h>
 #include <linux/platform_data/mv_usb.h>
+#include <linux/soc/mmp/cputype.h>
 
 #include "devices.h"
-#include "cputype.h"
 
 extern struct pxa_device_desc pxa168_device_uart1;
 extern struct pxa_device_desc pxa168_device_uart2;
index 110dcb3..c65cfc1 100644 (file)
@@ -207,7 +207,7 @@ static int __init mmp_dt_init_timer(struct device_node *np)
                ret = clk_prepare_enable(clk);
                if (ret)
                        return ret;
-               rate = clk_get_rate(clk) / 2;
+               rate = clk_get_rate(clk);
        } else if (cpu_is_pj4()) {
                rate = 6500000;
        } else {
index ad08d47..dca7d06 100644 (file)
@@ -95,6 +95,7 @@ config ARCH_OMAP2PLUS
        bool
        select ARCH_HAS_BANDGAP
        select ARCH_HAS_HOLES_MEMORYMODEL
+       select ARCH_HAS_RESET_CONTROLLER
        select ARCH_OMAP
        select CLKSRC_MMIO
        select GENERIC_IRQ_CHIP
@@ -105,11 +106,11 @@ config ARCH_OMAP2PLUS
        select OMAP_DM_TIMER
        select OMAP_GPMC
        select PINCTRL
+       select RESET_CONTROLLER
        select SOC_BUS
        select TI_SYSC
        select OMAP_IRQCHIP
        select CLKSRC_TI_32K
-       select ARCH_HAS_RESET_CONTROLLER
        help
          Systems based on OMAP2, OMAP3, OMAP4 or OMAP5
 
index ca52271..e95c224 100644 (file)
@@ -306,10 +306,14 @@ static void __init dra7x_evm_mmc_quirk(void)
 
 static struct clockdomain *ti_sysc_find_one_clockdomain(struct clk *clk)
 {
+       struct clk_hw *hw = __clk_get_hw(clk);
        struct clockdomain *clkdm = NULL;
        struct clk_hw_omap *hwclk;
 
-       hwclk = to_clk_hw_omap(__clk_get_hw(clk));
+       hwclk = to_clk_hw_omap(hw);
+       if (!omap2_clk_is_hw_omap(hw))
+               return NULL;
+
        if (hwclk && hwclk->clkdm_name)
                clkdm = clkdm_lookup(hwclk->clkdm_name);
 
index 354e0e7..1da11bd 100644 (file)
@@ -551,8 +551,9 @@ static struct clk *ve_spc_clk_register(struct device *cpu_dev)
 
 static int __init ve_spc_clk_init(void)
 {
-       int cpu;
+       int cpu, cluster;
        struct clk *clk;
+       bool init_opp_table[MAX_CLUSTERS] = { false };
 
        if (!info)
                return 0; /* Continue only if SPC is initialised */
@@ -578,8 +579,17 @@ static int __init ve_spc_clk_init(void)
                        continue;
                }
 
+               cluster = topology_physical_package_id(cpu_dev->id);
+               if (init_opp_table[cluster])
+                       continue;
+
                if (ve_init_opp_table(cpu_dev))
                        pr_warn("failed to initialise cpu%d opp table\n", cpu);
+               else if (dev_pm_opp_set_sharing_cpus(cpu_dev,
+                        topology_core_cpumask(cpu_dev->id)))
+                       pr_warn("failed to mark OPPs shared for cpu%d\n", cpu);
+               else
+                       init_opp_table[cluster] = true;
        }
 
        platform_device_register_simple("vexpress-spc-cpufreq", -1, NULL, 0);
index b1b4476..e688dfa 100644 (file)
@@ -138,6 +138,7 @@ config ARM64
        select HAVE_CMPXCHG_DOUBLE
        select HAVE_CMPXCHG_LOCAL
        select HAVE_CONTEXT_TRACKING
+       select HAVE_COPY_THREAD_TLS
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS
index 96ab022..121e6cc 100644 (file)
@@ -15,7 +15,7 @@
        pinctrl-names = "default";
        pinctrl-0 = <&mmc2_pins>;
        vmmc-supply = <&reg_dcdc1>;
-       vqmmc-supply = <&reg_dcdc1>;
+       vqmmc-supply = <&reg_eldo1>;
        bus-width = <8>;
        non-removable;
        cap-mmc-hw-reset;
index 01a9a52..393c194 100644 (file)
 &mmc1 {
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
-       vmmc-supply = <&reg_aldo2>;
+       vmmc-supply = <&reg_dcdc1>;
        vqmmc-supply = <&reg_dldo4>;
        mmc-pwrseq = <&wifi_pwrseq>;
        bus-width = <4>;
index 144a2c1..d1fc9c2 100644 (file)
 
        pmu {
                compatible = "arm,armv8-pmuv3";
-               interrupts = <0 120 8>,
-                            <0 121 8>,
-                            <0 122 8>,
-                            <0 123 8>;
+               interrupts = <0 170 4>,
+                            <0 171 4>,
+                            <0 172 4>,
+                            <0 173 4>;
                interrupt-affinity = <&cpu0>,
                                     <&cpu1>,
                                     <&cpu2>,
index 5bd0746..a8bb3fa 100644 (file)
        };
 
        gpio-keys {
-               compatible = "gpio-keys-polled";
-               poll-interval = <100>;
+               compatible = "gpio-keys";
 
                key1 {
                        label = "A";
                        linux,code = <BTN_0>;
                        gpios = <&gpio GPIOH_6 GPIO_ACTIVE_LOW>;
+                       interrupt-parent = <&gpio_intc>;
+                       interrupts = <34 IRQ_TYPE_EDGE_BOTH>;
                };
 
                key2 {
                        label = "B";
                        linux,code = <BTN_1>;
                        gpios = <&gpio GPIOH_7 GPIO_ACTIVE_LOW>;
+                       interrupt-parent = <&gpio_intc>;
+                       interrupts = <35 IRQ_TYPE_EDGE_BOTH>;
                };
 
                key3 {
                        label = "C";
                        linux,code = <BTN_2>;
                        gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>;
+                       interrupt-parent = <&gpio_intc>;
+                       interrupts = <2 IRQ_TYPE_EDGE_BOTH>;
+               };
+
+               mic_mute {
+                       label = "MicMute";
+                       linux,code = <SW_MUTE_DEVICE>;
+                       linux,input-type = <EV_SW>;
+                       gpios = <&gpio_ao GPIOE_2 GPIO_ACTIVE_LOW>;
+                       interrupt-parent = <&gpio_intc>;
+                       interrupts = <99 IRQ_TYPE_EDGE_BOTH>;
+               };
+
+               power_key {
+                       label = "PowerKey";
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio_ao GPIOAO_3 GPIO_ACTIVE_LOW>;
+                       interrupt-parent = <&gpio_intc>;
+                       interrupts = <3 IRQ_TYPE_EDGE_BOTH>;
                };
        };
 
 
        bluetooth {
                compatible = "brcm,bcm43438-bt";
+               interrupt-parent = <&gpio_intc>;
+               interrupts = <95 IRQ_TYPE_LEVEL_HIGH>;
                shutdown-gpios = <&gpio GPIOX_17 GPIO_ACTIVE_HIGH>;
                max-speed = <2000000>;
                clocks = <&wifi32k>;
index 8e8a77e..a6f9b77 100644 (file)
@@ -88,7 +88,7 @@
 
        reboot {
                compatible ="syscon-reboot";
-               regmap = <&dcfg>;
+               regmap = <&rst>;
                offset = <0xb0>;
                mask = <0x02>;
        };
                dcfg: syscon@1e00000 {
                        compatible = "fsl,ls1028a-dcfg", "syscon";
                        reg = <0x0 0x1e00000 0x0 0x10000>;
-                       big-endian;
+                       little-endian;
+               };
+
+               rst: syscon@1e60000 {
+                       compatible = "syscon";
+                       reg = <0x0 0x1e60000 0x0 0x10000>;
+                       little-endian;
                };
 
                scfg: syscon@1fc0000 {
                                               0x00010004 0x0000003d
                                               0x00010005 0x00000045
                                               0x00010006 0x0000004d
-                                              0x00010007 0x00000045
+                                              0x00010007 0x00000055
                                               0x00010008 0x0000005e
                                               0x00010009 0x00000066
                                               0x0001000a 0x0000006e
index 6edbdfe..3d95b66 100644 (file)
                                reg = <0x30bd0000 0x10000>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clk IMX8MM_CLK_SDMA1_ROOT>,
-                                        <&clk IMX8MM_CLK_SDMA1_ROOT>;
+                                        <&clk IMX8MM_CLK_AHB>;
                                clock-names = "ipg", "ahb";
                                #dma-cells = <3>;
                                fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin";
index 2a759df..596bc65 100644 (file)
                pinctrl-names = "default";
                pinctrl-0 = <&pinctrl_imu>;
                interrupt-parent = <&gpio3>;
-               interrupts = <19 IRQ_TYPE_LEVEL_LOW>;
+               interrupts = <19 IRQ_TYPE_LEVEL_HIGH>;
                vdd-supply = <&reg_3v3_p>;
                vddio-supply = <&reg_3v3_p>;
        };
index 94090c6..d43e129 100644 (file)
 
        pmu {
                compatible = "arm,armv8-pmuv3";
-               interrupts = <0 120 8>,
-                            <0 121 8>,
-                            <0 122 8>,
-                            <0 123 8>;
+               interrupts = <0 170 4>,
+                            <0 171 4>,
+                            <0 172 4>,
+                            <0 173 4>;
                interrupt-affinity = <&cpu0>,
                                     <&cpu1>,
                                     <&cpu2>,
index 76b49f5..16f1656 100644 (file)
@@ -49,7 +49,8 @@
 
        ir-receiver {
                compatible = "gpio-ir-receiver";
-               gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_HIGH>;
+               gpios = <&gpio2 RK_PA2 GPIO_ACTIVE_LOW>;
+               linux,rc-map-name = "rc-beelink-gs1";
        };
 };
 
index 8dc6c5c..baf52ba 100644 (file)
 #define PAGE_SHARED_EXEC       __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_WRITE)
 #define PAGE_READONLY          __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN)
 #define PAGE_READONLY_EXEC     __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_RDONLY | PTE_NG | PTE_PXN)
-#define PAGE_EXECONLY          __pgprot(_PAGE_DEFAULT | PTE_RDONLY | PTE_NG | PTE_PXN)
 
 #define __P000  PAGE_NONE
 #define __P001  PAGE_READONLY
 #define __P010  PAGE_READONLY
 #define __P011  PAGE_READONLY
-#define __P100  PAGE_EXECONLY
+#define __P100  PAGE_READONLY_EXEC
 #define __P101  PAGE_READONLY_EXEC
 #define __P110  PAGE_READONLY_EXEC
 #define __P111  PAGE_READONLY_EXEC
 #define __S001  PAGE_READONLY
 #define __S010  PAGE_SHARED
 #define __S011  PAGE_SHARED
-#define __S100  PAGE_EXECONLY
+#define __S100  PAGE_READONLY_EXEC
 #define __S101  PAGE_READONLY_EXEC
 #define __S110  PAGE_SHARED_EXEC
 #define __S111  PAGE_SHARED_EXEC
index 5d15b47..cd5de0e 100644 (file)
@@ -96,12 +96,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 #define pte_dirty(pte)         (pte_sw_dirty(pte) || pte_hw_dirty(pte))
 
 #define pte_valid(pte)         (!!(pte_val(pte) & PTE_VALID))
-/*
- * Execute-only user mappings do not have the PTE_USER bit set. All valid
- * kernel mappings have the PTE_UXN bit set.
- */
 #define pte_valid_not_user(pte) \
-       ((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == (PTE_VALID | PTE_UXN))
+       ((pte_val(pte) & (PTE_VALID | PTE_USER)) == PTE_VALID)
 #define pte_valid_young(pte) \
        ((pte_val(pte) & (PTE_VALID | PTE_AF)) == (PTE_VALID | PTE_AF))
 #define pte_valid_user(pte) \
@@ -117,8 +113,8 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 /*
  * p??_access_permitted() is true for valid user mappings (subject to the
- * write permission check) other than user execute-only which do not have the
- * PTE_USER bit set. PROT_NONE mappings do not have the PTE_VALID bit set.
+ * write permission check). PROT_NONE mappings do not have the PTE_VALID bit
+ * set.
  */
 #define pte_access_permitted(pte, write) \
        (pte_valid_user(pte) && (!(write) || pte_write(pte)))
index 2629a68..5af8258 100644 (file)
@@ -42,7 +42,6 @@
 #endif
 
 #define __ARCH_WANT_SYS_CLONE
-#define __ARCH_WANT_SYS_CLONE3
 
 #ifndef __COMPAT_SYSCALL_NR
 #include <uapi/asm/unistd.h>
index 4703d21..f83a70e 100644 (file)
@@ -19,5 +19,6 @@
 #define __ARCH_WANT_NEW_STAT
 #define __ARCH_WANT_SET_GET_RLIMIT
 #define __ARCH_WANT_TIME32_SYSCALLS
+#define __ARCH_WANT_SYS_CLONE3
 
 #include <asm-generic/unistd.h>
index 6a09ca7..85f4bec 100644 (file)
@@ -547,6 +547,7 @@ static const struct midr_range spectre_v2_safe_list[] = {
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A53),
        MIDR_ALL_VERSIONS(MIDR_CORTEX_A55),
        MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
+       MIDR_ALL_VERSIONS(MIDR_HISI_TSV110),
        { /* sentinel */ }
 };
 
index 71f788c..d54586d 100644 (file)
@@ -360,8 +360,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 
 asmlinkage void ret_from_fork(void) asm("ret_from_fork");
 
-int copy_thread(unsigned long clone_flags, unsigned long stack_start,
-               unsigned long stk_sz, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
+               unsigned long stk_sz, struct task_struct *p, unsigned long tls)
 {
        struct pt_regs *childregs = task_pt_regs(p);
 
@@ -394,11 +394,11 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
                }
 
                /*
-                * If a TLS pointer was passed to clone (4th argument), use it
-                * for the new thread.
+                * If a TLS pointer was passed to clone, use it for the new
+                * thread.
                 */
                if (clone_flags & CLONE_SETTLS)
-                       p->thread.uw.tp_value = childregs->regs[3];
+                       p->thread.uw.tp_value = tls;
        } else {
                memset(childregs, 0, sizeof(struct pt_regs));
                childregs->pstate = PSR_MODE_EL1h;
index 46822af..9f21659 100644 (file)
@@ -2098,9 +2098,9 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
                WARN_ON(1);
        }
 
-       kvm_err("Unsupported guest CP%d access at: %08lx [%08lx]\n",
-               cp, *vcpu_pc(vcpu), *vcpu_cpsr(vcpu));
-       print_sys_reg_instr(params);
+       print_sys_reg_msg(params,
+                         "Unsupported guest CP%d access at: %08lx [%08lx]\n",
+                         cp, *vcpu_pc(vcpu), *vcpu_cpsr(vcpu));
        kvm_inject_undefined(vcpu);
 }
 
@@ -2233,6 +2233,12 @@ int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
                                NULL, 0);
 }
 
+static bool is_imp_def_sys_reg(struct sys_reg_params *params)
+{
+       // See ARM DDI 0487E.a, section D12.3.2
+       return params->Op0 == 3 && (params->CRn & 0b1011) == 0b1011;
+}
+
 static int emulate_sys_reg(struct kvm_vcpu *vcpu,
                           struct sys_reg_params *params)
 {
@@ -2248,10 +2254,12 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
 
        if (likely(r)) {
                perform_access(vcpu, params, r);
+       } else if (is_imp_def_sys_reg(params)) {
+               kvm_inject_undefined(vcpu);
        } else {
-               kvm_err("Unsupported guest sys_reg access at: %lx [%08lx]\n",
-                       *vcpu_pc(vcpu), *vcpu_cpsr(vcpu));
-               print_sys_reg_instr(params);
+               print_sys_reg_msg(params,
+                                 "Unsupported guest sys_reg access at: %lx [%08lx]\n",
+                                 *vcpu_pc(vcpu), *vcpu_cpsr(vcpu));
                kvm_inject_undefined(vcpu);
        }
        return 1;
@@ -2360,8 +2368,11 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
        if ((id & KVM_REG_ARM_COPROC_MASK) != KVM_REG_ARM64_SYSREG)
                return NULL;
 
+       if (!index_to_params(id, &params))
+               return NULL;
+
        table = get_target_table(vcpu->arch.target, true, &num);
-       r = find_reg_by_id(id, &params, table, num);
+       r = find_reg(&params, table, num);
        if (!r)
                r = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
 
index 9bca031..5a6fc30 100644 (file)
@@ -62,11 +62,24 @@ struct sys_reg_desc {
 #define REG_HIDDEN_USER                (1 << 0) /* hidden from userspace ioctls */
 #define REG_HIDDEN_GUEST       (1 << 1) /* hidden from guest */
 
-static inline void print_sys_reg_instr(const struct sys_reg_params *p)
+static __printf(2, 3)
+inline void print_sys_reg_msg(const struct sys_reg_params *p,
+                                      char *fmt, ...)
 {
+       va_list va;
+
+       va_start(va, fmt);
        /* Look, we even formatted it for you to paste into the table! */
-       kvm_pr_unimpl(" { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
+       kvm_pr_unimpl("%pV { Op0(%2u), Op1(%2u), CRn(%2u), CRm(%2u), Op2(%2u), func_%s },\n",
+                     &(struct va_format){ fmt, &va },
                      p->Op0, p->Op1, p->CRn, p->CRm, p->Op2, p->is_write ? "write" : "read");
+       va_end(va);
+}
+
+static inline void print_sys_reg_instr(const struct sys_reg_params *p)
+{
+       /* GCC warns on an empty format string */
+       print_sys_reg_msg(p, "%s", "");
 }
 
 static inline bool ignore_write(struct kvm_vcpu *vcpu,
index 077b02a..85566d3 100644 (file)
@@ -445,7 +445,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr,
        const struct fault_info *inf;
        struct mm_struct *mm = current->mm;
        vm_fault_t fault, major = 0;
-       unsigned long vm_flags = VM_READ | VM_WRITE;
+       unsigned long vm_flags = VM_READ | VM_WRITE | VM_EXEC;
        unsigned int mm_flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
 
        if (kprobe_page_fault(regs, esr))
index 5a3b15a..40797cb 100644 (file)
@@ -1070,7 +1070,6 @@ void arch_remove_memory(int nid, u64 start, u64 size,
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
-       struct zone *zone;
 
        /*
         * FIXME: Cleanup page tables (also in arch_add_memory() in case
@@ -1079,7 +1078,6 @@ void arch_remove_memory(int nid, u64 start, u64 size,
         * unplug. ARCH_ENABLE_MEMORY_HOTREMOVE must not be
         * unlocked yet.
         */
-       zone = page_zone(pfn_to_page(start_pfn));
-       __remove_pages(zone, start_pfn, nr_pages, altmap);
+       __remove_pages(start_pfn, nr_pages, altmap);
 }
 #endif
index 12cd923..0231d69 100644 (file)
@@ -91,7 +91,7 @@ static inline void atomic_##op(int i, atomic_t *v)                    \
                "1:     %0 = memw_locked(%1);\n"                        \
                "       %0 = "#op "(%0,%2);\n"                          \
                "       memw_locked(%1,P3)=%0;\n"                       \
-               "       if !P3 jump 1b;\n"                              \
+               "       if (!P3) jump 1b;\n"                            \
                : "=&r" (output)                                        \
                : "r" (&v->counter), "r" (i)                            \
                : "memory", "p3"                                        \
@@ -107,7 +107,7 @@ static inline int atomic_##op##_return(int i, atomic_t *v)          \
                "1:     %0 = memw_locked(%1);\n"                        \
                "       %0 = "#op "(%0,%2);\n"                          \
                "       memw_locked(%1,P3)=%0;\n"                       \
-               "       if !P3 jump 1b;\n"                              \
+               "       if (!P3) jump 1b;\n"                            \
                : "=&r" (output)                                        \
                : "r" (&v->counter), "r" (i)                            \
                : "memory", "p3"                                        \
@@ -124,7 +124,7 @@ static inline int atomic_fetch_##op(int i, atomic_t *v)                     \
                "1:     %0 = memw_locked(%2);\n"                        \
                "       %1 = "#op "(%0,%3);\n"                          \
                "       memw_locked(%2,P3)=%1;\n"                       \
-               "       if !P3 jump 1b;\n"                              \
+               "       if (!P3) jump 1b;\n"                            \
                : "=&r" (output), "=&r" (val)                           \
                : "r" (&v->counter), "r" (i)                            \
                : "memory", "p3"                                        \
@@ -173,7 +173,7 @@ static inline int atomic_fetch_add_unless(atomic_t *v, int a, int u)
                "       }"
                "       memw_locked(%2, p3) = %1;"
                "       {"
-               "               if !p3 jump 1b;"
+               "               if (!p3) jump 1b;"
                "       }"
                "2:"
                : "=&r" (__oldval), "=&r" (tmp)
index 47384b0..71429f7 100644 (file)
@@ -38,7 +38,7 @@ static inline int test_and_clear_bit(int nr, volatile void *addr)
        "1:     R12 = memw_locked(R10);\n"
        "       { P0 = tstbit(R12,R11); R12 = clrbit(R12,R11); }\n"
        "       memw_locked(R10,P1) = R12;\n"
-       "       {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+       "       {if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n"
        : "=&r" (oldval)
        : "r" (addr), "r" (nr)
        : "r10", "r11", "r12", "p0", "p1", "memory"
@@ -62,7 +62,7 @@ static inline int test_and_set_bit(int nr, volatile void *addr)
        "1:     R12 = memw_locked(R10);\n"
        "       { P0 = tstbit(R12,R11); R12 = setbit(R12,R11); }\n"
        "       memw_locked(R10,P1) = R12;\n"
-       "       {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+       "       {if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n"
        : "=&r" (oldval)
        : "r" (addr), "r" (nr)
        : "r10", "r11", "r12", "p0", "p1", "memory"
@@ -88,7 +88,7 @@ static inline int test_and_change_bit(int nr, volatile void *addr)
        "1:     R12 = memw_locked(R10);\n"
        "       { P0 = tstbit(R12,R11); R12 = togglebit(R12,R11); }\n"
        "       memw_locked(R10,P1) = R12;\n"
-       "       {if !P1 jump 1b; %0 = mux(P0,#1,#0);}\n"
+       "       {if (!P1) jump 1b; %0 = mux(P0,#1,#0);}\n"
        : "=&r" (oldval)
        : "r" (addr), "r" (nr)
        : "r10", "r11", "r12", "p0", "p1", "memory"
@@ -223,7 +223,7 @@ static inline int ffs(int x)
        int r;
 
        asm("{ P0 = cmp.eq(%1,#0); %0 = ct0(%1);}\n"
-               "{ if P0 %0 = #0; if !P0 %0 = add(%0,#1);}\n"
+               "{ if (P0) %0 = #0; if (!P0) %0 = add(%0,#1);}\n"
                : "=&r" (r)
                : "r" (x)
                : "p0");
index 6091322..92b8a02 100644 (file)
@@ -30,7 +30,7 @@ static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
        __asm__ __volatile__ (
        "1:     %0 = memw_locked(%1);\n"    /*  load into retval */
        "       memw_locked(%1,P0) = %2;\n" /*  store into memory */
-       "       if !P0 jump 1b;\n"
+       "       if (!P0) jump 1b;\n"
        : "=&r" (retval)
        : "r" (ptr), "r" (x)
        : "memory", "p0"
index cb63521..0191f7c 100644 (file)
@@ -16,7 +16,7 @@
            /* For example: %1 = %4 */ \
            insn \
        "2: memw_locked(%3,p2) = %1;\n" \
-       "   if !p2 jump 1b;\n" \
+       "   if (!p2) jump 1b;\n" \
        "   %1 = #0;\n" \
        "3:\n" \
        ".section .fixup,\"ax\"\n" \
@@ -84,10 +84,10 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval,
        "1: %1 = memw_locked(%3)\n"
        "   {\n"
        "      p2 = cmp.eq(%1,%4)\n"
-       "      if !p2.new jump:NT 3f\n"
+       "      if (!p2.new) jump:NT 3f\n"
        "   }\n"
        "2: memw_locked(%3,p2) = %5\n"
-       "   if !p2 jump 1b\n"
+       "   if (!p2) jump 1b\n"
        "3:\n"
        ".section .fixup,\"ax\"\n"
        "4: %0 = #%6\n"
index 539e3ef..b0dbc34 100644 (file)
@@ -173,6 +173,7 @@ static inline void writel(u32 data, volatile void __iomem *addr)
 
 void __iomem *ioremap(unsigned long phys_addr, unsigned long size);
 #define ioremap_nocache ioremap
+#define ioremap_uc(X, Y) ioremap((X), (Y))
 
 
 #define __raw_writel writel
index bfe07d8..ef103b7 100644 (file)
@@ -30,9 +30,9 @@ static inline void arch_read_lock(arch_rwlock_t *lock)
        __asm__ __volatile__(
                "1:     R6 = memw_locked(%0);\n"
                "       { P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
-               "       { if !P3 jump 1b; }\n"
+               "       { if (!P3) jump 1b; }\n"
                "       memw_locked(%0,P3) = R6;\n"
-               "       { if !P3 jump 1b; }\n"
+               "       { if (!P3) jump 1b; }\n"
                :
                : "r" (&lock->lock)
                : "memory", "r6", "p3"
@@ -46,7 +46,7 @@ static inline void arch_read_unlock(arch_rwlock_t *lock)
                "1:     R6 = memw_locked(%0);\n"
                "       R6 = add(R6,#-1);\n"
                "       memw_locked(%0,P3) = R6\n"
-               "       if !P3 jump 1b;\n"
+               "       if (!P3) jump 1b;\n"
                :
                : "r" (&lock->lock)
                : "memory", "r6", "p3"
@@ -61,7 +61,7 @@ static inline int arch_read_trylock(arch_rwlock_t *lock)
        __asm__ __volatile__(
                "       R6 = memw_locked(%1);\n"
                "       { %0 = #0; P3 = cmp.ge(R6,#0); R6 = add(R6,#1);}\n"
-               "       { if !P3 jump 1f; }\n"
+               "       { if (!P3) jump 1f; }\n"
                "       memw_locked(%1,P3) = R6;\n"
                "       { %0 = P3 }\n"
                "1:\n"
@@ -78,9 +78,9 @@ static inline void arch_write_lock(arch_rwlock_t *lock)
        __asm__ __volatile__(
                "1:     R6 = memw_locked(%0)\n"
                "       { P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
-               "       { if !P3 jump 1b; }\n"
+               "       { if (!P3) jump 1b; }\n"
                "       memw_locked(%0,P3) = R6;\n"
-               "       { if !P3 jump 1b; }\n"
+               "       { if (!P3) jump 1b; }\n"
                :
                : "r" (&lock->lock)
                : "memory", "r6", "p3"
@@ -94,7 +94,7 @@ static inline int arch_write_trylock(arch_rwlock_t *lock)
        __asm__ __volatile__(
                "       R6 = memw_locked(%1)\n"
                "       { %0 = #0; P3 = cmp.eq(R6,#0);  R6 = #-1;}\n"
-               "       { if !P3 jump 1f; }\n"
+               "       { if (!P3) jump 1f; }\n"
                "       memw_locked(%1,P3) = R6;\n"
                "       %0 = P3;\n"
                "1:\n"
@@ -117,9 +117,9 @@ static inline void arch_spin_lock(arch_spinlock_t *lock)
        __asm__ __volatile__(
                "1:     R6 = memw_locked(%0);\n"
                "       P3 = cmp.eq(R6,#0);\n"
-               "       { if !P3 jump 1b; R6 = #1; }\n"
+               "       { if (!P3) jump 1b; R6 = #1; }\n"
                "       memw_locked(%0,P3) = R6;\n"
-               "       { if !P3 jump 1b; }\n"
+               "       { if (!P3) jump 1b; }\n"
                :
                : "r" (&lock->lock)
                : "memory", "r6", "p3"
@@ -139,7 +139,7 @@ static inline unsigned int arch_spin_trylock(arch_spinlock_t *lock)
        __asm__ __volatile__(
                "       R6 = memw_locked(%1);\n"
                "       P3 = cmp.eq(R6,#0);\n"
-               "       { if !P3 jump 1f; R6 = #1; %0 = #0; }\n"
+               "       { if (!P3) jump 1f; R6 = #1; %0 = #0; }\n"
                "       memw_locked(%1,P3) = R6;\n"
                "       %0 = P3;\n"
                "1:\n"
index 35f2942..5ed02f6 100644 (file)
@@ -11,8 +11,6 @@
 #include <linux/thread_info.h>
 #include <linux/module.h>
 
-register unsigned long current_frame_pointer asm("r30");
-
 struct stackframe {
        unsigned long fp;
        unsigned long rets;
@@ -30,7 +28,7 @@ void save_stack_trace(struct stack_trace *trace)
 
        low = (unsigned long)task_stack_page(current);
        high = low + THREAD_SIZE;
-       fp = current_frame_pointer;
+       fp = (unsigned long)__builtin_frame_address(0);
 
        while (fp >= low && fp <= (high - sizeof(*frame))) {
                frame = (struct stackframe *)fp;
index 12242c2..4023fdb 100644 (file)
@@ -369,7 +369,7 @@ ret_from_fork:
                R26.L = #LO(do_work_pending);
                R0 = #VM_INT_DISABLE;
        }
-       if P0 jump check_work_pending
+       if (P0) jump check_work_pending
        {
                R0 = R25;
                callr R24
index 58fd670..b01d68a 100644 (file)
@@ -689,9 +689,7 @@ void arch_remove_memory(int nid, u64 start, u64 size,
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
-       struct zone *zone;
 
-       zone = page_zone(pfn_to_page(start_pfn));
-       __remove_pages(zone, start_pfn, nr_pages, altmap);
+       __remove_pages(start_pfn, nr_pages, altmap);
 }
 #endif
index add3882..ed8e28b 100644 (file)
@@ -47,7 +47,7 @@ config MIPS
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES
        select HAVE_ASM_MODVERSIONS
-       select HAVE_EBPF_JIT if (!CPU_MICROMIPS)
+       select HAVE_EBPF_JIT if 64BIT && !CPU_MICROMIPS && TARGET_ISA_REV >= 2
        select HAVE_CONTEXT_TRACKING
        select HAVE_COPY_THREAD_TLS
        select HAVE_C_RECORDMCOUNT
index 172801e..d859f07 100644 (file)
@@ -29,6 +29,9 @@ KBUILD_AFLAGS := $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
        -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \
        -DKERNEL_ENTRY=$(VMLINUX_ENTRY_ADDRESS)
 
+# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
+KCOV_INSTRUMENT                := n
+
 # decompressor objects (linked with vmlinuz)
 vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o
 
index ba8f82a..e794b2d 100644 (file)
@@ -45,13 +45,6 @@ static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
 /* See header file for descriptions of functions */
 
 /**
- * This macro returns the size of a member of a structure.
- * Logically it is the same as "sizeof(s::field)" in C++, but
- * C lacks the "::" operator.
- */
-#define SIZEOF_FIELD(s, field) sizeof(((s *)NULL)->field)
-
-/**
  * This macro returns a member of the
  * cvmx_bootmem_named_block_desc_t structure. These members can't
  * be directly addressed as they might be in memory not directly
@@ -65,7 +58,7 @@ static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
 #define CVMX_BOOTMEM_NAMED_GET_FIELD(addr, field)                      \
        __cvmx_bootmem_desc_get(addr,                                   \
                offsetof(struct cvmx_bootmem_named_block_desc, field),  \
-               SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field))
+               sizeof_field(struct cvmx_bootmem_named_block_desc, field))
 
 /**
  * This function is the implementation of the get macros defined
index c46c59b..49f0061 100644 (file)
@@ -15,7 +15,8 @@
 static inline int __pure __get_cpu_type(const int cpu_type)
 {
        switch (cpu_type) {
-#if defined(CONFIG_SYS_HAS_CPU_LOONGSON2EF)
+#if defined(CONFIG_SYS_HAS_CPU_LOONGSON2E) || \
+    defined(CONFIG_SYS_HAS_CPU_LOONGSON2F)
        case CPU_LOONGSON2EF:
 #endif
 
index 4993db4..ee26f9a 100644 (file)
@@ -49,8 +49,26 @@ struct thread_info {
        .addr_limit     = KERNEL_DS,            \
 }
 
-/* How to get the thread information struct from C.  */
+/*
+ * A pointer to the struct thread_info for the currently executing thread is
+ * held in register $28/$gp.
+ *
+ * We declare __current_thread_info as a global register variable rather than a
+ * local register variable within current_thread_info() because clang doesn't
+ * support explicit local register variables.
+ *
+ * When building the VDSO we take care not to declare the global register
+ * variable because this causes GCC to not preserve the value of $28/$gp in
+ * functions that change its value (which is common in the PIC VDSO when
+ * accessing the GOT). Since the VDSO shouldn't be accessing
+ * __current_thread_info anyway we declare it extern in order to cause a link
+ * failure if it's referenced.
+ */
+#ifdef __VDSO__
+extern struct thread_info *__current_thread_info;
+#else
 register struct thread_info *__current_thread_info __asm__("$28");
+#endif
 
 static inline struct thread_info *current_thread_info(void)
 {
index b088255..0ae9b4c 100644 (file)
@@ -26,8 +26,6 @@
 
 #define __VDSO_USE_SYSCALL             ULLONG_MAX
 
-#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
-
 static __always_inline long gettimeofday_fallback(
                                struct __kernel_old_timeval *_tv,
                                struct timezone *_tz)
@@ -48,17 +46,6 @@ static __always_inline long gettimeofday_fallback(
        return error ? -ret : ret;
 }
 
-#else
-
-static __always_inline long gettimeofday_fallback(
-                               struct __kernel_old_timeval *_tv,
-                               struct timezone *_tz)
-{
-       return -1;
-}
-
-#endif
-
 static __always_inline long clock_gettime_fallback(
                                        clockid_t _clkid,
                                        struct __kernel_timespec *_ts)
index f777e44..47312c5 100644 (file)
@@ -50,6 +50,25 @@ static int __init_cache_level(unsigned int cpu)
        return 0;
 }
 
+static void fill_cpumask_siblings(int cpu, cpumask_t *cpu_map)
+{
+       int cpu1;
+
+       for_each_possible_cpu(cpu1)
+               if (cpus_are_siblings(cpu, cpu1))
+                       cpumask_set_cpu(cpu1, cpu_map);
+}
+
+static void fill_cpumask_cluster(int cpu, cpumask_t *cpu_map)
+{
+       int cpu1;
+       int cluster = cpu_cluster(&cpu_data[cpu]);
+
+       for_each_possible_cpu(cpu1)
+               if (cpu_cluster(&cpu_data[cpu1]) == cluster)
+                       cpumask_set_cpu(cpu1, cpu_map);
+}
+
 static int __populate_cache_leaves(unsigned int cpu)
 {
        struct cpuinfo_mips *c = &current_cpu_data;
@@ -57,14 +76,20 @@ static int __populate_cache_leaves(unsigned int cpu)
        struct cacheinfo *this_leaf = this_cpu_ci->info_list;
 
        if (c->icache.waysize) {
+               /* L1 caches are per core */
+               fill_cpumask_siblings(cpu, &this_leaf->shared_cpu_map);
                populate_cache(dcache, this_leaf, 1, CACHE_TYPE_DATA);
+               fill_cpumask_siblings(cpu, &this_leaf->shared_cpu_map);
                populate_cache(icache, this_leaf, 1, CACHE_TYPE_INST);
        } else {
                populate_cache(dcache, this_leaf, 1, CACHE_TYPE_UNIFIED);
        }
 
-       if (c->scache.waysize)
+       if (c->scache.waysize) {
+               /* L2 cache is per cluster */
+               fill_cpumask_cluster(cpu, &this_leaf->shared_cpu_map);
                populate_cache(scache, this_leaf, 2, CACHE_TYPE_UNIFIED);
+       }
 
        if (c->tcache.waysize)
                populate_cache(tcache, this_leaf, 3, CACHE_TYPE_UNIFIED);
index 46b7675..561154c 100644 (file)
@@ -604,6 +604,7 @@ static void emit_const_to_reg(struct jit_ctx *ctx, int dst, u64 value)
 static int emit_bpf_tail_call(struct jit_ctx *ctx, int this_idx)
 {
        int off, b_off;
+       int tcc_reg;
 
        ctx->flags |= EBPF_SEEN_TC;
        /*
@@ -616,14 +617,14 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx, int this_idx)
        b_off = b_imm(this_idx + 1, ctx);
        emit_instr(ctx, bne, MIPS_R_AT, MIPS_R_ZERO, b_off);
        /*
-        * if (--TCC < 0)
+        * if (TCC-- < 0)
         *     goto out;
         */
        /* Delay slot */
-       emit_instr(ctx, daddiu, MIPS_R_T5,
-                  (ctx->flags & EBPF_TCC_IN_V1) ? MIPS_R_V1 : MIPS_R_S4, -1);
+       tcc_reg = (ctx->flags & EBPF_TCC_IN_V1) ? MIPS_R_V1 : MIPS_R_S4;
+       emit_instr(ctx, daddiu, MIPS_R_T5, tcc_reg, -1);
        b_off = b_imm(this_idx + 1, ctx);
-       emit_instr(ctx, bltz, MIPS_R_T5, b_off);
+       emit_instr(ctx, bltz, tcc_reg, b_off);
        /*
         * prog = array->ptrs[index];
         * if (prog == NULL)
@@ -1803,7 +1804,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        unsigned int image_size;
        u8 *image_ptr;
 
-       if (!prog->jit_requested || MIPS_ISA_REV < 2)
+       if (!prog->jit_requested)
                return prog;
 
        tmp = bpf_jit_blind_constants(prog);
index 6ebdc37..6b83b63 100644 (file)
@@ -17,12 +17,22 @@ int __vdso_clock_gettime(clockid_t clock,
        return __cvdso_clock_gettime32(clock, ts);
 }
 
+#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+
+/*
+ * This is behind the ifdef so that we don't provide the symbol when there's no
+ * possibility of there being a usable clocksource, because there's nothing we
+ * can do without it. When libc fails the symbol lookup it should fall back on
+ * the standard syscall path.
+ */
 int __vdso_gettimeofday(struct __kernel_old_timeval *tv,
                        struct timezone *tz)
 {
        return __cvdso_gettimeofday(tv, tz);
 }
 
+#endif /* CONFIG_MIPS_CLOCK_VSYSCALL */
+
 int __vdso_clock_getres(clockid_t clock_id,
                        struct old_timespec32 *res)
 {
@@ -43,12 +53,22 @@ int __vdso_clock_gettime(clockid_t clock,
        return __cvdso_clock_gettime(clock, ts);
 }
 
+#ifdef CONFIG_MIPS_CLOCK_VSYSCALL
+
+/*
+ * This is behind the ifdef so that we don't provide the symbol when there's no
+ * possibility of there being a usable clocksource, because there's nothing we
+ * can do without it. When libc fails the symbol lookup it should fall back on
+ * the standard syscall path.
+ */
 int __vdso_gettimeofday(struct __kernel_old_timeval *tv,
                        struct timezone *tz)
 {
        return __cvdso_gettimeofday(tv, tz);
 }
 
+#endif /* CONFIG_MIPS_CLOCK_VSYSCALL */
+
 int __vdso_clock_getres(clockid_t clock_id,
                        struct __kernel_timespec *res)
 {
index d9ac7e6..caddded 100644 (file)
@@ -9,7 +9,11 @@
 #define PG_dcache_dirty PG_arch_1
 
 void flush_icache_range(unsigned long start, unsigned long end);
+#define flush_icache_range flush_icache_range
+
 void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+#define flush_icache_page flush_icache_page
+
 #ifdef CONFIG_CPU_CACHE_ALIASING
 void flush_cache_mm(struct mm_struct *mm);
 void flush_cache_dup_mm(struct mm_struct *mm);
@@ -40,12 +44,11 @@ void invalidate_kernel_vmap_range(void *addr, int size);
 #define flush_dcache_mmap_unlock(mapping) xa_unlock_irq(&(mapping)->i_pages)
 
 #else
-#include <asm-generic/cacheflush.h>
-#undef flush_icache_range
-#undef flush_icache_page
-#undef flush_icache_user_range
 void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
                             unsigned long addr, int len);
+#define flush_icache_user_range flush_icache_user_range
+
+#include <asm-generic/cacheflush.h>
 #endif
 
 #endif /* __NDS32_CACHEFLUSH_H__ */
index 0214e41..6abc58a 100644 (file)
@@ -195,7 +195,7 @@ extern void paging_init(void);
 #define pte_unmap(pte)         do { } while (0)
 #define pte_unmap_nested(pte)  do { } while (0)
 
-#define pmd_off_k(address)     pmd_offset(pgd_offset_k(address), address)
+#define pmd_off_k(address)     pmd_offset(pud_offset(p4d_offset(pgd_offset_k(address), (address)), (address)), (address))
 
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 /*
index b56af75..819bdfc 100644 (file)
@@ -138,6 +138,14 @@ void __iomem *ioremap(unsigned long phys_addr, unsigned long size)
                                return NULL;
        }
 
+       /*
+        * Map uncached objects in the low part of address space to
+        * CONFIG_NIOS2_IO_REGION_BASE
+        */
+       if (IS_MAPPABLE_UNCACHEABLE(phys_addr) &&
+           IS_MAPPABLE_UNCACHEABLE(last_addr))
+               return (void __iomem *)(CONFIG_NIOS2_IO_REGION_BASE + phys_addr);
+
        /* Mappings have to be page-aligned */
        offset = phys_addr & ~PAGE_MASK;
        phys_addr &= PAGE_MASK;
index b16237c..0c29d6c 100644 (file)
@@ -62,6 +62,7 @@ config PARISC
        select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE
        select HAVE_KPROBES_ON_FTRACE
        select HAVE_DYNAMIC_FTRACE_WITH_REGS
+       select HAVE_COPY_THREAD_TLS
 
        help
          The PA-RISC microprocessor is designed by Hewlett-Packard and used
index f627c37..ab5c215 100644 (file)
@@ -44,8 +44,14 @@ __xchg(unsigned long x, __volatile__ void *ptr, int size)
 **             if (((unsigned long)p & 0xf) == 0)
 **                     return __ldcw(p);
 */
-#define xchg(ptr, x) \
-       ((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+#define xchg(ptr, x)                                                   \
+({                                                                     \
+       __typeof__(*(ptr)) __ret;                                       \
+       __typeof__(*(ptr)) _x_ = (x);                                   \
+       __ret = (__typeof__(*(ptr)))                                    \
+               __xchg((unsigned long)_x_, (ptr), sizeof(*(ptr)));      \
+       __ret;                                                          \
+})
 
 /* bug catcher for when unsupported size is used - won't link */
 extern void __cmpxchg_called_with_bad_pointer(void);
index a99ea74..87e1740 100644 (file)
@@ -2,8 +2,6 @@
 #ifndef _ASM_PARISC_KEXEC_H
 #define _ASM_PARISC_KEXEC_H
 
-#ifdef CONFIG_KEXEC
-
 /* Maximum physical address we can use pages from */
 #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
 /* Maximum address we can reach in physical address mode */
@@ -32,6 +30,4 @@ static inline void crash_setup_regs(struct pt_regs *newregs,
 
 #endif /* __ASSEMBLY__ */
 
-#endif /* CONFIG_KEXEC */
-
 #endif /* _ASM_PARISC_KEXEC_H */
index 2663c8f..068d909 100644 (file)
@@ -37,5 +37,5 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER)   += ftrace.o
 obj-$(CONFIG_JUMP_LABEL)               += jump_label.o
 obj-$(CONFIG_KGDB)                     += kgdb.o
 obj-$(CONFIG_KPROBES)                  += kprobes.o
-obj-$(CONFIG_KEXEC)                    += kexec.o relocate_kernel.o
+obj-$(CONFIG_KEXEC_CORE)               += kexec.o relocate_kernel.o
 obj-$(CONFIG_KEXEC_FILE)               += kexec_file.o
index 3b330e5..a5f3e50 100644 (file)
@@ -810,7 +810,7 @@ EXPORT_SYMBOL(device_to_hwpath);
 static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
                             struct device *parent);
 
-static void walk_lower_bus(struct parisc_device *dev)
+static void __init walk_lower_bus(struct parisc_device *dev)
 {
        unsigned long io_io_low, io_io_high;
 
@@ -889,8 +889,8 @@ static void print_parisc_device(struct parisc_device *dev)
        static int count;
 
        print_pa_hwpath(dev, hw_path);
-       pr_info("%d. %s at 0x%px [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
-               ++count, dev->name, (void*) dev->hpa.start, hw_path, dev->id.hw_type,
+       pr_info("%d. %s at %pap [%s] { %d, 0x%x, 0x%.3x, 0x%.5x }",
+               ++count, dev->name, &(dev->hpa.start), hw_path, dev->id.hw_type,
                dev->id.hversion_rev, dev->id.hversion, dev->id.sversion);
 
        if (dev->num_addrs) {
index 36434d4..749c457 100644 (file)
@@ -327,8 +327,7 @@ static int pdt_mainloop(void *unused)
                            ((pde & PDT_ADDR_SINGLE_ERR) == 0))
                                memory_failure(pde >> PAGE_SHIFT, 0);
                        else
-                               soft_offline_page(
-                                       pfn_to_page(pde >> PAGE_SHIFT), 0);
+                               soft_offline_page(pde >> PAGE_SHIFT, 0);
 #else
                        pr_crit("PDT: memory error at 0x%lx ignored.\n"
                                "Rebuild kernel with CONFIG_MEMORY_FAILURE=y "
index ecc5c27..230a642 100644 (file)
@@ -208,8 +208,8 @@ arch_initcall(parisc_idle_init);
  * Copy architecture-specific thread state
  */
 int
-copy_thread(unsigned long clone_flags, unsigned long usp,
-           unsigned long kthread_arg, struct task_struct *p)
+copy_thread_tls(unsigned long clone_flags, unsigned long usp,
+           unsigned long kthread_arg, struct task_struct *p, unsigned long tls)
 {
        struct pt_regs *cregs = &(p->thread.regs);
        void *stack = task_stack_page(p);
@@ -254,9 +254,9 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
                cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;
                cregs->kpc = (unsigned long) &child_return;
 
-               /* Setup thread TLS area from the 4th parameter in clone */
+               /* Setup thread TLS area */
                if (clone_flags & CLONE_SETTLS)
-                       cregs->cr27 = cregs->gr[23];
+                       cregs->cr27 = tls;
        }
 
        return 0;
index ddca828..354cf06 100644 (file)
@@ -401,7 +401,7 @@ static void __init map_pages(unsigned long start_vaddr,
                        pmd = (pmd_t *) __pa(pmd);
                }
 
-               pgd_populate(NULL, pg_dir, __va(pmd));
+               pud_populate(NULL, (pud_t *)pg_dir, __va(pmd));
 #endif
                pg_dir++;
 
index e9a960e..860228e 100644 (file)
@@ -15,6 +15,7 @@
  *
  * (the type definitions are in asm/spinlock_types.h)
  */
+#include <linux/jump_label.h>
 #include <linux/irqflags.h>
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #endif
 
 #ifdef CONFIG_PPC_PSERIES
+DECLARE_STATIC_KEY_FALSE(shared_processor);
+
 #define vcpu_is_preempted vcpu_is_preempted
 static inline bool vcpu_is_preempted(int cpu)
 {
-       if (!firmware_has_feature(FW_FEATURE_SPLPAR))
+       if (!static_branch_unlikely(&shared_processor))
                return false;
        return !!(be32_to_cpu(lppaca_of(cpu).yield_count) & 1);
 }
@@ -110,13 +113,8 @@ static inline void splpar_rw_yield(arch_rwlock_t *lock) {};
 
 static inline bool is_shared_processor(void)
 {
-/*
- * LPPACA is only available on Pseries so guard anything LPPACA related to
- * allow other platforms (which include this common header) to compile.
- */
-#ifdef CONFIG_PPC_PSERIES
-       return (IS_ENABLED(CONFIG_PPC_SPLPAR) &&
-               lppaca_shared_proc(local_paca->lppaca_ptr));
+#ifdef CONFIG_PPC_SPLPAR
+       return static_branch_unlikely(&shared_processor);
 #else
        return false;
 #endif
index 15002b5..c92fe7f 100644 (file)
@@ -401,7 +401,7 @@ copy_to_user_mcsafe(void __user *to, const void *from, unsigned long n)
        return n;
 }
 
-extern unsigned long __clear_user(void __user *addr, unsigned long size);
+unsigned long __arch_clear_user(void __user *addr, unsigned long size);
 
 static inline unsigned long clear_user(void __user *addr, unsigned long size)
 {
@@ -409,12 +409,17 @@ static inline unsigned long clear_user(void __user *addr, unsigned long size)
        might_fault();
        if (likely(access_ok(addr, size))) {
                allow_write_to_user(addr, size);
-               ret = __clear_user(addr, size);
+               ret = __arch_clear_user(addr, size);
                prevent_write_to_user(addr, size);
        }
        return ret;
 }
 
+static inline unsigned long __clear_user(void __user *addr, unsigned long size)
+{
+       return clear_user(addr, size);
+}
+
 extern long strncpy_from_user(char *dst, const char __user *src, long count);
 extern __must_check long strnlen_user(const char __user *str, long n);
 
index 5645bc9..add6749 100644 (file)
@@ -619,8 +619,6 @@ void __do_irq(struct pt_regs *regs)
 
        trace_irq_entry(regs);
 
-       check_stack_overflow();
-
        /*
         * Query the platform PIC for the interrupt & ack it.
         *
@@ -652,6 +650,8 @@ void do_IRQ(struct pt_regs *regs)
        irqsp = hardirq_ctx[raw_smp_processor_id()];
        sirqsp = softirq_ctx[raw_smp_processor_id()];
 
+       check_stack_overflow();
+
        /* Already there ? */
        if (unlikely(cursp == irqsp || cursp == sirqsp)) {
                __do_irq(regs);
index dc53578..6ff3f89 100644 (file)
@@ -4983,7 +4983,8 @@ static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
                if (nesting_enabled(kvm))
                        kvmhv_release_all_nested(kvm);
                kvm->arch.process_table = 0;
-               uv_svm_terminate(kvm->arch.lpid);
+               if (kvm->arch.secure_guest)
+                       uv_svm_terminate(kvm->arch.lpid);
                kvmhv_set_ptbl_entry(kvm->arch.lpid, 0, 0);
        }
 
index 0496e66..c6fbbd2 100644 (file)
@@ -1117,7 +1117,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        ld      r7, VCPU_GPR(R7)(r4)
        bne     ret_to_ultra
 
-       lwz     r0, VCPU_CR(r4)
+       l     r0, VCPU_CR(r4)
        mtcr    r0
 
        ld      r0, VCPU_GPR(R0)(r4)
@@ -1137,7 +1137,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
  *   R3 = UV_RETURN
  */
 ret_to_ultra:
-       lwz     r0, VCPU_CR(r4)
+       l     r0, VCPU_CR(r4)
        mtcr    r0
 
        ld      r0, VCPU_GPR(R3)(r4)
index f69a6aa..1ddb263 100644 (file)
@@ -17,7 +17,7 @@ CACHELINE_BYTES = L1_CACHE_BYTES
 LG_CACHELINE_BYTES = L1_CACHE_SHIFT
 CACHELINE_MASK = (L1_CACHE_BYTES-1)
 
-_GLOBAL(__clear_user)
+_GLOBAL(__arch_clear_user)
 /*
  * Use dcbz on the complete cache lines in the destination
  * to set them to zero.  This requires that the destination
@@ -87,4 +87,4 @@ _GLOBAL(__clear_user)
        EX_TABLE(8b, 91b)
        EX_TABLE(9b, 91b)
 
-EXPORT_SYMBOL(__clear_user)
+EXPORT_SYMBOL(__arch_clear_user)
index 507b18b..169872b 100644 (file)
@@ -17,7 +17,7 @@ PPC64_CACHES:
        .section        ".text"
 
 /**
- * __clear_user: - Zero a block of memory in user space, with less checking.
+ * __arch_clear_user: - Zero a block of memory in user space, with less checking.
  * @to:   Destination address, in user space.
  * @n:    Number of bytes to zero.
  *
@@ -58,7 +58,7 @@ err3; stb     r0,0(r3)
        mr      r3,r4
        blr
 
-_GLOBAL_TOC(__clear_user)
+_GLOBAL_TOC(__arch_clear_user)
        cmpdi   r4,32
        neg     r6,r3
        li      r0,0
@@ -181,4 +181,4 @@ err1;       dcbz    0,r3
        cmpdi   r4,32
        blt     .Lshort_clear
        b       .Lmedium_clear
-EXPORT_SYMBOL(__clear_user)
+EXPORT_SYMBOL(__arch_clear_user)
index 9488b63..f5535ea 100644 (file)
@@ -151,10 +151,9 @@ void __ref arch_remove_memory(int nid, u64 start, u64 size,
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
-       struct page *page = pfn_to_page(start_pfn) + vmem_altmap_offset(altmap);
        int ret;
 
-       __remove_pages(page_zone(page), start_pfn, nr_pages, altmap);
+       __remove_pages(start_pfn, nr_pages, altmap);
 
        /* Remove htab bolted mappings for this section of memory */
        start = (unsigned long)__va(start);
@@ -289,6 +288,14 @@ void __init mem_init(void)
        BUILD_BUG_ON(MMU_PAGE_COUNT > 16);
 
 #ifdef CONFIG_SWIOTLB
+       /*
+        * Some platforms (e.g. 85xx) limit DMA-able memory way below
+        * 4G. We force memblock to bottom-up mode to ensure that the
+        * memory allocated in swiotlb_init() is DMA-able.
+        * As it's the last memblock allocation, no need to reset it
+        * back to to-down.
+        */
+       memblock_set_bottom_up(true);
        swiotlb_init(0);
 #endif
 
index 090af2d..96eb8e4 100644 (file)
@@ -103,7 +103,7 @@ static void mmu_patch_addis(s32 *site, long simm)
        patch_instruction_site(site, instr);
 }
 
-void __init mmu_mapin_ram_chunk(unsigned long offset, unsigned long top, pgprot_t prot)
+static void mmu_mapin_ram_chunk(unsigned long offset, unsigned long top, pgprot_t prot)
 {
        unsigned long s = offset;
        unsigned long v = PAGE_OFFSET + s;
index 42bbcd4..dffe1a4 100644 (file)
@@ -50,7 +50,7 @@ static void slice_print_mask(const char *label, const struct slice_mask *mask) {
 
 #endif
 
-static inline bool slice_addr_is_low(unsigned long addr)
+static inline notrace bool slice_addr_is_low(unsigned long addr)
 {
        u64 tmp = (u64)addr;
 
@@ -659,7 +659,7 @@ unsigned long arch_get_unmapped_area_topdown(struct file *filp,
                                       mm_ctx_user_psize(&current->mm->context), 1);
 }
 
-unsigned int get_slice_psize(struct mm_struct *mm, unsigned long addr)
+unsigned int notrace get_slice_psize(struct mm_struct *mm, unsigned long addr)
 {
        unsigned char *psizes;
        int index, mask_index;
index 6e5a2a4..4ec2a9f 100644 (file)
@@ -97,12 +97,12 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
 #ifdef CONFIG_SMP
 #ifdef CONFIG_PPC64
 #define PPC_BPF_LOAD_CPU(r)            \
-       do { BUILD_BUG_ON(FIELD_SIZEOF(struct paca_struct, paca_index) != 2);   \
+       do { BUILD_BUG_ON(sizeof_field(struct paca_struct, paca_index) != 2);   \
                PPC_LHZ_OFFS(r, 13, offsetof(struct paca_struct, paca_index));  \
        } while (0)
 #else
 #define PPC_BPF_LOAD_CPU(r)     \
-       do { BUILD_BUG_ON(FIELD_SIZEOF(struct task_struct, cpu) != 4);          \
+       do { BUILD_BUG_ON(sizeof_field(struct task_struct, cpu) != 4);          \
                PPC_LHZ_OFFS(r, 2, offsetof(struct task_struct, cpu));          \
        } while(0)
 #endif
index d57b46e..0acc9d5 100644 (file)
@@ -321,7 +321,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                        ctx->seen |= SEEN_XREG | SEEN_MEM | (1<<(K & 0xf));
                        break;
                case BPF_LD | BPF_W | BPF_LEN: /*       A = skb->len; */
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, len) != 4);
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff, len) != 4);
                        PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, len));
                        break;
                case BPF_LDX | BPF_W | BPF_ABS: /* A = *((u32 *)(seccomp_data + K)); */
@@ -333,16 +333,16 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 
                        /*** Ancillary info loads ***/
                case BPF_ANC | SKF_AD_PROTOCOL: /* A = ntohs(skb->protocol); */
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff,
                                                  protocol) != 2);
                        PPC_NTOHS_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                            protocol));
                        break;
                case BPF_ANC | SKF_AD_IFINDEX:
                case BPF_ANC | SKF_AD_HATYPE:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+                       BUILD_BUG_ON(sizeof_field(struct net_device,
                                                ifindex) != 4);
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+                       BUILD_BUG_ON(sizeof_field(struct net_device,
                                                type) != 2);
                        PPC_LL_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
                                                                dev));
@@ -365,17 +365,17 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 
                        break;
                case BPF_ANC | SKF_AD_MARK:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff, mark) != 4);
                        PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          mark));
                        break;
                case BPF_ANC | SKF_AD_RXHASH:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff, hash) != 4);
                        PPC_LWZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          hash));
                        break;
                case BPF_ANC | SKF_AD_VLAN_TAG:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff, vlan_tci) != 2);
 
                        PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          vlan_tci));
@@ -388,7 +388,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
                                PPC_ANDI(r_A, r_A, 1);
                        break;
                case BPF_ANC | SKF_AD_QUEUE:
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
+                       BUILD_BUG_ON(sizeof_field(struct sk_buff,
                                                  queue_mapping) != 2);
                        PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff,
                                                          queue_mapping));
index 9157184..9dba7e8 100644 (file)
@@ -539,6 +539,16 @@ static int cmm_migratepage(struct balloon_dev_info *b_dev_info,
        /* balloon page list reference */
        get_page(newpage);
 
+       /*
+        * When we migrate a page to a different zone, we have to fixup the
+        * count of both involved zones as we adjusted the managed page count
+        * when inflating.
+        */
+       if (page_zone(page) != page_zone(newpage)) {
+               adjust_managed_page_count(page, 1);
+               adjust_managed_page_count(newpage, -1);
+       }
+
        spin_lock_irqsave(&b_dev_info->pages_lock, flags);
        balloon_page_insert(b_dev_info, newpage);
        balloon_page_delete(page);
index 0a40201..0c8421d 100644 (file)
@@ -74,6 +74,9 @@
 #include "pseries.h"
 #include "../../../../drivers/pci/pci.h"
 
+DEFINE_STATIC_KEY_FALSE(shared_processor);
+EXPORT_SYMBOL_GPL(shared_processor);
+
 int CMO_PrPSP = -1;
 int CMO_SecPSP = -1;
 unsigned long CMO_PageSize = (ASM_CONST(1) << IOMMU_PAGE_SHIFT_4K);
@@ -758,6 +761,10 @@ static void __init pSeries_setup_arch(void)
 
        if (firmware_has_feature(FW_FEATURE_LPAR)) {
                vpa_init(boot_cpuid);
+
+               if (lppaca_shared_proc(get_lppaca()))
+                       static_branch_enable(&shared_processor);
+
                ppc_md.power_save = pseries_lpar_idle;
                ppc_md.enable_pmcs = pseries_lpar_enable_pmcs;
 #ifdef CONFIG_PCI_IOV
index 759ffb0..fa7dc03 100644 (file)
@@ -64,6 +64,8 @@ config RISCV
        select SPARSEMEM_STATIC if 32BIT
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
        select HAVE_ARCH_MMAP_RND_BITS if MMU
+       select ARCH_HAS_GCOV_PROFILE_ALL
+       select HAVE_COPY_THREAD_TLS
 
 config ARCH_MMAP_RND_BITS_MIN
        default 18 if 64BIT
@@ -154,7 +156,7 @@ config GENERIC_HWEIGHT
        def_bool y
 
 config FIX_EARLYCON_MEM
-       def_bool CONFIG_MMU
+       def_bool MMU
 
 config PGTABLE_LEVELS
        int
index 634759a..d325b67 100644 (file)
@@ -2,8 +2,8 @@ menu "SoC selection"
 
 config SOC_SIFIVE
        bool "SiFive SoCs"
-       select SERIAL_SIFIVE
-       select SERIAL_SIFIVE_CONSOLE
+       select SERIAL_SIFIVE if TTY
+       select SERIAL_SIFIVE_CONSOLE if TTY
        select CLK_SIFIVE
        select CLK_SIFIVE_FU540_PRCI
        select SIFIVE_PLIC
index a474f98..36db814 100644 (file)
@@ -24,7 +24,7 @@ $(obj)/Image: vmlinux FORCE
 $(obj)/Image.gz: $(obj)/Image FORCE
        $(call if_changed,gzip)
 
-loader.o: $(src)/loader.S $(obj)/Image
+$(obj)/loader.o: $(src)/loader.S $(obj)/Image
 
 $(obj)/loader: $(obj)/loader.o $(obj)/Image $(obj)/loader.lds FORCE
        $(Q)$(LD) -T $(obj)/loader.lds -o $@ $(obj)/loader.o
index 70a1891..a2e3d54 100644 (file)
@@ -54,6 +54,7 @@
                        reg = <1>;
                        riscv,isa = "rv64imafdc";
                        tlb-split;
+                       next-level-cache = <&l2cache>;
                        cpu1_intc: interrupt-controller {
                                #interrupt-cells = <1>;
                                compatible = "riscv,cpu-intc";
@@ -77,6 +78,7 @@
                        reg = <2>;
                        riscv,isa = "rv64imafdc";
                        tlb-split;
+                       next-level-cache = <&l2cache>;
                        cpu2_intc: interrupt-controller {
                                #interrupt-cells = <1>;
                                compatible = "riscv,cpu-intc";
                        reg = <3>;
                        riscv,isa = "rv64imafdc";
                        tlb-split;
+                       next-level-cache = <&l2cache>;
                        cpu3_intc: interrupt-controller {
                                #interrupt-cells = <1>;
                                compatible = "riscv,cpu-intc";
                        reg = <4>;
                        riscv,isa = "rv64imafdc";
                        tlb-split;
+                       next-level-cache = <&l2cache>;
                        cpu4_intc: interrupt-controller {
                                #interrupt-cells = <1>;
                                compatible = "riscv,cpu-intc";
                        #pwm-cells = <3>;
                        status = "disabled";
                };
+               l2cache: cache-controller@2010000 {
+                       compatible = "sifive,fu540-c000-ccache", "cache";
+                       cache-block-size = <64>;
+                       cache-level = <2>;
+                       cache-sets = <1024>;
+                       cache-size = <2097152>;
+                       cache-unified;
+                       interrupt-parent = <&plic0>;
+                       interrupts = <1 2 3>;
+                       reg = <0x0 0x2010000 0x0 0x1000>;
+               };
 
        };
 };
index dd62b69..27e005f 100644 (file)
@@ -5,4 +5,8 @@
 #include <linux/ftrace.h>
 #include <asm-generic/asm-prototypes.h>
 
+long long __lshrti3(long long a, int b);
+long long __ashrti3(long long a, int b);
+long long __ashlti3(long long a, int b);
+
 #endif /* _ASM_RISCV_PROTOTYPES_H */
index 0a62d2d..435b655 100644 (file)
 # define SR_PIE                SR_MPIE
 # define SR_PP         SR_MPP
 
-# define IRQ_SOFT      IRQ_M_SOFT
-# define IRQ_TIMER     IRQ_M_TIMER
-# define IRQ_EXT       IRQ_M_EXT
+# define RV_IRQ_SOFT           IRQ_M_SOFT
+# define RV_IRQ_TIMER  IRQ_M_TIMER
+# define RV_IRQ_EXT            IRQ_M_EXT
 #else /* CONFIG_RISCV_M_MODE */
 # define CSR_STATUS    CSR_SSTATUS
 # define CSR_IE                CSR_SIE
 # define SR_PIE                SR_SPIE
 # define SR_PP         SR_SPP
 
-# define IRQ_SOFT      IRQ_S_SOFT
-# define IRQ_TIMER     IRQ_S_TIMER
-# define IRQ_EXT       IRQ_S_EXT
+# define RV_IRQ_SOFT           IRQ_S_SOFT
+# define RV_IRQ_TIMER  IRQ_S_TIMER
+# define RV_IRQ_EXT            IRQ_S_EXT
 #endif /* CONFIG_RISCV_M_MODE */
 
 /* IE/IP (Supervisor/Machine Interrupt Enable/Pending) flags */
-#define IE_SIE         (_AC(0x1, UL) << IRQ_SOFT)
-#define IE_TIE         (_AC(0x1, UL) << IRQ_TIMER)
-#define IE_EIE         (_AC(0x1, UL) << IRQ_EXT)
+#define IE_SIE         (_AC(0x1, UL) << RV_IRQ_SOFT)
+#define IE_TIE         (_AC(0x1, UL) << RV_IRQ_TIMER)
+#define IE_EIE         (_AC(0x1, UL) << RV_IRQ_EXT)
 
 #ifndef __ASSEMBLY__
 
index 7ff0ed4..36ae017 100644 (file)
@@ -90,6 +90,27 @@ extern pgd_t swapper_pg_dir[];
 #define __S110 PAGE_SHARED_EXEC
 #define __S111 PAGE_SHARED_EXEC
 
+#define VMALLOC_SIZE     (KERN_VIRT_SIZE >> 1)
+#define VMALLOC_END      (PAGE_OFFSET - 1)
+#define VMALLOC_START    (PAGE_OFFSET - VMALLOC_SIZE)
+
+/*
+ * Roughly size the vmemmap space to be large enough to fit enough
+ * struct pages to map half the virtual address space. Then
+ * position vmemmap directly below the VMALLOC region.
+ */
+#define VMEMMAP_SHIFT \
+       (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)
+#define VMEMMAP_SIZE   BIT(VMEMMAP_SHIFT)
+#define VMEMMAP_END    (VMALLOC_START - 1)
+#define VMEMMAP_START  (VMALLOC_START - VMEMMAP_SIZE)
+
+/*
+ * Define vmemmap for pfn_to_page & page_to_pfn calls. Needed if kernel
+ * is configured with CONFIG_SPARSEMEM_VMEMMAP enabled.
+ */
+#define vmemmap                ((struct page *)VMEMMAP_START)
+
 static inline int pmd_present(pmd_t pmd)
 {
        return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
@@ -400,23 +421,6 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
 #define __pte_to_swp_entry(pte)        ((swp_entry_t) { pte_val(pte) })
 #define __swp_entry_to_pte(x)  ((pte_t) { (x).val })
 
-#define VMALLOC_SIZE     (KERN_VIRT_SIZE >> 1)
-#define VMALLOC_END      (PAGE_OFFSET - 1)
-#define VMALLOC_START    (PAGE_OFFSET - VMALLOC_SIZE)
-
-/*
- * Roughly size the vmemmap space to be large enough to fit enough
- * struct pages to map half the virtual address space. Then
- * position vmemmap directly below the VMALLOC region.
- */
-#define VMEMMAP_SHIFT \
-       (CONFIG_VA_BITS - PAGE_SHIFT - 1 + STRUCT_PAGE_MAX_SHIFT)
-#define VMEMMAP_SIZE   BIT(VMEMMAP_SHIFT)
-#define VMEMMAP_END    (VMALLOC_START - 1)
-#define VMEMMAP_START  (VMALLOC_START - VMEMMAP_SIZE)
-
-#define vmemmap                ((struct page *)VMEMMAP_START)
-
 #define PCI_IO_SIZE      SZ_16M
 #define PCI_IO_END       VMEMMAP_START
 #define PCI_IO_START     (PCI_IO_END - PCI_IO_SIZE)
index a1349ca..e163b7b 100644 (file)
@@ -246,6 +246,7 @@ check_syscall_nr:
         */
        li t1, -1
        beq a7, t1, ret_from_syscall_rejected
+       blt a7, t1, 1f
        /* Call syscall */
        la s0, sys_call_table
        slli t0, a7, RISCV_LGPTR
index b94d8db..c40fdcd 100644 (file)
@@ -142,7 +142,7 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
         */
        old = *parent;
 
-       if (function_graph_enter(old, self_addr, frame_pointer, parent))
+       if (!function_graph_enter(old, self_addr, frame_pointer, parent))
                *parent = return_hooker;
 }
 
index 84a6f0a..a4242be 100644 (file)
@@ -80,7 +80,9 @@ _start_kernel:
 
 #ifdef CONFIG_SMP
        li t0, CONFIG_NR_CPUS
-       bgeu a0, t0, .Lsecondary_park
+       blt a0, t0, .Lgood_cores
+       tail .Lsecondary_park
+.Lgood_cores:
 #endif
 
        /* Pick one hart to run the main boot sequence */
@@ -209,11 +211,6 @@ relocate:
        tail smp_callin
 #endif
 
-.align 2
-.Lsecondary_park:
-       /* We lack SMP support or have too many harts, so park this hart */
-       wfi
-       j .Lsecondary_park
 END(_start)
 
 #ifdef CONFIG_RISCV_M_MODE
@@ -246,12 +243,12 @@ ENTRY(reset_regs)
        li      t4, 0
        li      t5, 0
        li      t6, 0
-       csrw    sscratch, 0
+       csrw    CSR_SCRATCH, 0
 
 #ifdef CONFIG_FPU
        csrr    t0, CSR_MISA
        andi    t0, t0, (COMPAT_HWCAP_ISA_F | COMPAT_HWCAP_ISA_D)
-       bnez    t0, .Lreset_regs_done
+       beqz    t0, .Lreset_regs_done
 
        li      t1, SR_FS
        csrs    CSR_STATUS, t1
@@ -295,6 +292,13 @@ ENTRY(reset_regs)
 END(reset_regs)
 #endif /* CONFIG_RISCV_M_MODE */
 
+.section ".text", "ax",@progbits
+.align 2
+.Lsecondary_park:
+       /* We lack SMP support or have too many harts, so park this hart */
+       wfi
+       j .Lsecondary_park
+
 __PAGE_ALIGNED_BSS
        /* Empty zero page */
        .balign PAGE_SIZE
index 3f07a91..345c4f2 100644 (file)
@@ -23,11 +23,11 @@ asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
 
        irq_enter();
        switch (regs->cause & ~CAUSE_IRQ_FLAG) {
-       case IRQ_TIMER:
+       case RV_IRQ_TIMER:
                riscv_timer_interrupt();
                break;
 #ifdef CONFIG_SMP
-       case IRQ_SOFT:
+       case RV_IRQ_SOFT:
                /*
                 * We only use software interrupts to pass IPIs, so if a non-SMP
                 * system gets one, then we don't know what to do.
@@ -35,7 +35,7 @@ asmlinkage __visible void __irq_entry do_IRQ(struct pt_regs *regs)
                riscv_software_interrupt();
                break;
 #endif
-       case IRQ_EXT:
+       case RV_IRQ_EXT:
                handle_arch_irq(regs);
                break;
        default:
index 95a3031..817cf7b 100644 (file)
@@ -99,8 +99,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
        return 0;
 }
 
-int copy_thread(unsigned long clone_flags, unsigned long usp,
-       unsigned long arg, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
+       unsigned long arg, struct task_struct *p, unsigned long tls)
 {
        struct pt_regs *childregs = task_pt_regs(p);
 
@@ -121,7 +121,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
                if (usp) /* User fork */
                        childregs->sp = usp;
                if (clone_flags & CLONE_SETTLS)
-                       childregs->tp = childregs->a5;
+                       childregs->tp = tls;
                childregs->a0 = 0; /* Return value of fork() */
                p->thread.ra = (unsigned long)ret_from_fork;
        }
index 4800cf7..2a02b7e 100644 (file)
@@ -9,8 +9,5 @@
 /*
  * Assembly functions that may be used (directly or indirectly) by modules
  */
-EXPORT_SYMBOL(__clear_user);
-EXPORT_SYMBOL(__asm_copy_to_user);
-EXPORT_SYMBOL(__asm_copy_from_user);
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
index 49a5852..33b16f4 100644 (file)
@@ -58,7 +58,8 @@ quiet_cmd_vdsold = VDSOLD  $@
       cmd_vdsold = $(CC) $(KBUILD_CFLAGS) $(call cc-option, -no-pie) -nostdlib -nostartfiles $(SYSCFLAGS_$(@F)) \
                            -Wl,-T,$(filter-out FORCE,$^) -o $@.tmp && \
                    $(CROSS_COMPILE)objcopy \
-                           $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@
+                           $(patsubst %, -G __vdso_%, $(vdso-syms)) $@.tmp $@ && \
+                   rm $@.tmp
 
 # install commands for the unstripped file
 quiet_cmd_vdso_install = INSTALL $@
index 15f9d54..ef90075 100644 (file)
@@ -4,34 +4,73 @@
  */
 
 #include <linux/linkage.h>
+#include <asm-generic/export.h>
 
-ENTRY(__lshrti3)
+SYM_FUNC_START(__lshrti3)
        beqz    a2, .L1
        li      a5,64
        sub     a5,a5,a2
-       addi    sp,sp,-16
        sext.w  a4,a5
        blez    a5, .L2
        sext.w  a2,a2
-       sll     a4,a1,a4
        srl     a0,a0,a2
-       srl     a1,a1,a2
+       sll     a4,a1,a4
+       srl     a2,a1,a2
        or      a0,a0,a4
-       sd      a1,8(sp)
-       sd      a0,0(sp)
-       ld      a0,0(sp)
-       ld      a1,8(sp)
-       addi    sp,sp,16
-       ret
+       mv      a1,a2
 .L1:
        ret
 .L2:
-       negw    a4,a4
-       srl     a1,a1,a4
-       sd      a1,0(sp)
-       sd      zero,8(sp)
-       ld      a0,0(sp)
-       ld      a1,8(sp)
-       addi    sp,sp,16
+       negw    a0,a4
+       li      a2,0
+       srl     a0,a1,a0
+       mv      a1,a2
+       ret
+SYM_FUNC_END(__lshrti3)
+EXPORT_SYMBOL(__lshrti3)
+
+SYM_FUNC_START(__ashrti3)
+       beqz    a2, .L3
+       li      a5,64
+       sub     a5,a5,a2
+       sext.w  a4,a5
+       blez    a5, .L4
+       sext.w  a2,a2
+       srl     a0,a0,a2
+       sll     a4,a1,a4
+       sra     a2,a1,a2
+       or      a0,a0,a4
+       mv      a1,a2
+.L3:
+       ret
+.L4:
+       negw    a0,a4
+       srai    a2,a1,0x3f
+       sra     a0,a1,a0
+       mv      a1,a2
+       ret
+SYM_FUNC_END(__ashrti3)
+EXPORT_SYMBOL(__ashrti3)
+
+SYM_FUNC_START(__ashlti3)
+       beqz    a2, .L5
+       li      a5,64
+       sub     a5,a5,a2
+       sext.w  a4,a5
+       blez    a5, .L6
+       sext.w  a2,a2
+       sll     a1,a1,a2
+       srl     a4,a0,a4
+       sll     a2,a0,a2
+       or      a1,a1,a4
+       mv      a0,a2
+.L5:
+       ret
+.L6:
+       negw    a1,a4
+       li      a2,0
+       sll     a1,a0,a1
+       mv      a0,a2
        ret
-ENDPROC(__lshrti3)
+SYM_FUNC_END(__ashlti3)
+EXPORT_SYMBOL(__ashlti3)
index fecd656..f29d2ba 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/linkage.h>
+#include <asm-generic/export.h>
 #include <asm/asm.h>
 #include <asm/csr.h>
 
@@ -66,6 +67,8 @@ ENTRY(__asm_copy_from_user)
        j 3b
 ENDPROC(__asm_copy_to_user)
 ENDPROC(__asm_copy_from_user)
+EXPORT_SYMBOL(__asm_copy_to_user)
+EXPORT_SYMBOL(__asm_copy_from_user)
 
 
 ENTRY(__clear_user)
@@ -108,6 +111,7 @@ ENTRY(__clear_user)
        bltu a0, a3, 5b
        j 3b
 ENDPROC(__clear_user)
+EXPORT_SYMBOL(__clear_user)
 
        .section .fixup,"ax"
        .balign 4
index 3c8b332..a1bd95c 100644 (file)
@@ -10,7 +10,6 @@ obj-y += extable.o
 obj-$(CONFIG_MMU) += fault.o
 obj-y += cacheflush.o
 obj-y += context.o
-obj-y += sifive_l2_cache.o
 
 ifeq ($(CONFIG_MMU),y)
 obj-$(CONFIG_SMP) += tlbflush.o
index 8f19006..8930ab7 100644 (file)
@@ -22,6 +22,7 @@ void flush_icache_all(void)
        else
                on_each_cpu(ipi_remote_fence_i, NULL, 1);
 }
+EXPORT_SYMBOL(flush_icache_all);
 
 /*
  * Performs an icache flush for the given MM context.  RISC-V has no direct
index 69f6678..965a8cf 100644 (file)
@@ -99,13 +99,13 @@ static void __init setup_initrd(void)
                pr_info("initrd not found or empty");
                goto disable;
        }
-       if (__pa(initrd_end) > PFN_PHYS(max_low_pfn)) {
+       if (__pa_symbol(initrd_end) > PFN_PHYS(max_low_pfn)) {
                pr_err("initrd extends beyond end of memory");
                goto disable;
        }
 
        size = initrd_end - initrd_start;
-       memblock_reserve(__pa(initrd_start), size);
+       memblock_reserve(__pa_symbol(initrd_start), size);
        initrd_below_start_ok = 1;
 
        pr_info("Initial ramdisk at: 0x%p (%lu bytes)\n",
@@ -124,8 +124,8 @@ void __init setup_bootmem(void)
 {
        struct memblock_region *reg;
        phys_addr_t mem_size = 0;
-       phys_addr_t vmlinux_end = __pa(&_end);
-       phys_addr_t vmlinux_start = __pa(&_start);
+       phys_addr_t vmlinux_end = __pa_symbol(&_end);
+       phys_addr_t vmlinux_start = __pa_symbol(&_start);
 
        /* Find the memory region containing the kernel */
        for_each_memblock(memory, reg) {
@@ -445,7 +445,7 @@ static void __init setup_vm_final(void)
 
        /* Setup swapper PGD for fixmap */
        create_pgd_mapping(swapper_pg_dir, FIXADDR_START,
-                          __pa(fixmap_pgd_next),
+                          __pa_symbol(fixmap_pgd_next),
                           PGDIR_SIZE, PAGE_TABLE);
 
        /* Map all memory banks */
@@ -474,7 +474,7 @@ static void __init setup_vm_final(void)
        clear_fixmap(FIX_PMD);
 
        /* Move to swapper page table */
-       csr_write(CSR_SATP, PFN_DOWN(__pa(swapper_pg_dir)) | SATP_MODE);
+       csr_write(CSR_SATP, PFN_DOWN(__pa_symbol(swapper_pg_dir)) | SATP_MODE);
        local_flush_tlb_all();
 }
 #else
index 5451ef3..7fbf56a 100644 (file)
@@ -631,14 +631,14 @@ static int emit_bpf_tail_call(int insn, struct rv_jit_context *ctx)
                return -1;
        emit(rv_bgeu(RV_REG_A2, RV_REG_T1, off >> 1), ctx);
 
-       /* if (--TCC < 0)
+       /* if (TCC-- < 0)
         *     goto out;
         */
        emit(rv_addi(RV_REG_T1, tcc, -1), ctx);
        off = (tc_ninsn - (ctx->ninsns - start_insn)) << 2;
        if (is_13b_check(off, insn))
                return -1;
-       emit(rv_blt(RV_REG_T1, RV_REG_ZERO, off >> 1), ctx);
+       emit(rv_blt(tcc, RV_REG_ZERO, off >> 1), ctx);
 
        /* prog = array->ptrs[index];
         * if (!prog)
index d4051e8..bc88841 100644 (file)
@@ -124,6 +124,7 @@ config S390
        select HAVE_ARCH_JUMP_LABEL
        select HAVE_ARCH_JUMP_LABEL_RELATIVE
        select HAVE_ARCH_KASAN
+       select HAVE_ARCH_KASAN_VMALLOC
        select CPU_NO_EFFICIENT_FFS if !HAVE_MARCH_Z9_109_FEATURES
        select HAVE_ARCH_SECCOMP_FILTER
        select HAVE_ARCH_SOFT_DIRTY
index 6dc6c4f..69289e9 100644 (file)
@@ -27,7 +27,6 @@
 #define MACHINE_FLAG_DIAG9C    BIT(3)
 #define MACHINE_FLAG_ESOP      BIT(4)
 #define MACHINE_FLAG_IDTE      BIT(5)
-#define MACHINE_FLAG_DIAG44    BIT(6)
 #define MACHINE_FLAG_EDAT1     BIT(7)
 #define MACHINE_FLAG_EDAT2     BIT(8)
 #define MACHINE_FLAG_TOPOLOGY  BIT(10)
@@ -94,7 +93,6 @@ extern unsigned long __swsusp_reset_dma;
 #define MACHINE_HAS_DIAG9C     (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG9C)
 #define MACHINE_HAS_ESOP       (S390_lowcore.machine_flags & MACHINE_FLAG_ESOP)
 #define MACHINE_HAS_IDTE       (S390_lowcore.machine_flags & MACHINE_FLAG_IDTE)
-#define MACHINE_HAS_DIAG44     (S390_lowcore.machine_flags & MACHINE_FLAG_DIAG44)
 #define MACHINE_HAS_EDAT1      (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT1)
 #define MACHINE_HAS_EDAT2      (S390_lowcore.machine_flags & MACHINE_FLAG_EDAT2)
 #define MACHINE_HAS_TOPOLOGY   (S390_lowcore.machine_flags & MACHINE_FLAG_TOPOLOGY)
index 6da8885..670f14a 100644 (file)
@@ -194,9 +194,9 @@ static inline unsigned long long get_tod_clock_monotonic(void)
 {
        unsigned long long tod;
 
-       preempt_disable();
+       preempt_disable_notrace();
        tod = get_tod_clock() - *(unsigned long long *) &tod_clock_base[1];
-       preempt_enable();
+       preempt_enable_notrace();
        return tod;
 }
 
index ef3c00b..4093a28 100644 (file)
@@ -86,7 +86,7 @@ static inline int share(unsigned long addr, u16 cmd)
        };
 
        if (!is_prot_virt_guest())
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        /*
         * Sharing is page wise, if we encounter addresses that are
         * not page aligned, we assume something went wrong. If
index db32a55..cd241ee 100644 (file)
@@ -204,21 +204,6 @@ static __init void detect_diag9c(void)
                S390_lowcore.machine_flags |= MACHINE_FLAG_DIAG9C;
 }
 
-static __init void detect_diag44(void)
-{
-       int rc;
-
-       diag_stat_inc(DIAG_STAT_X044);
-       asm volatile(
-               "       diag    0,0,0x44\n"
-               "0:     la      %0,0\n"
-               "1:\n"
-               EX_TABLE(0b,1b)
-               : "=d" (rc) : "0" (-EOPNOTSUPP) : "cc");
-       if (!rc)
-               S390_lowcore.machine_flags |= MACHINE_FLAG_DIAG44;
-}
-
 static __init void detect_machine_facilities(void)
 {
        if (test_facility(8)) {
@@ -331,7 +316,6 @@ void __init startup_init(void)
        setup_arch_string();
        setup_boot_command_line();
        detect_diag9c();
-       detect_diag44();
        detect_machine_facilities();
        save_vector_registers();
        setup_topology();
index 9e1660a..c3597d2 100644 (file)
@@ -35,6 +35,7 @@ EXPORT_SYMBOL(_mcount)
 ENTRY(ftrace_caller)
        .globl  ftrace_regs_caller
        .set    ftrace_regs_caller,ftrace_caller
+       stg     %r14,(__SF_GPRS+8*8)(%r15)      # save traced function caller
        lgr     %r1,%r15
 #if !(defined(CC_USING_HOTPATCH) || defined(CC_USING_NOP_MCOUNT))
        aghi    %r0,MCOUNT_RETURN_FIXUP
index c07fdcd..77d93c5 100644 (file)
@@ -1303,18 +1303,28 @@ static void hw_perf_event_update(struct perf_event *event, int flush_all)
                 */
                if (flush_all && done)
                        break;
-
-               /* If an event overflow happened, discard samples by
-                * processing any remaining sample-data-blocks.
-                */
-               if (event_overflow)
-                       flush_all = 1;
        }
 
        /* Account sample overflows in the event hardware structure */
        if (sampl_overflow)
                OVERFLOW_REG(hwc) = DIV_ROUND_UP(OVERFLOW_REG(hwc) +
                                                 sampl_overflow, 1 + num_sdb);
+
+       /* Perf_event_overflow() and perf_event_account_interrupt() limit
+        * the interrupt rate to an upper limit. Roughly 1000 samples per
+        * task tick.
+        * Hitting this limit results in a large number
+        * of throttled REF_REPORT_THROTTLE entries and the samples
+        * are dropped.
+        * Slightly increase the interval to avoid hitting this limit.
+        */
+       if (event_overflow) {
+               SAMPL_RATE(hwc) += DIV_ROUND_UP(SAMPL_RATE(hwc), 10);
+               debug_sprintf_event(sfdbg, 1, "%s: rate adjustment %ld\n",
+                                   __func__,
+                                   DIV_ROUND_UP(SAMPL_RATE(hwc), 10));
+       }
+
        if (sampl_overflow || event_overflow)
                debug_sprintf_event(sfdbg, 4, "%s: "
                                    "overflows: sample %llu event %llu"
index 9cbf490..d5fbd75 100644 (file)
@@ -1052,7 +1052,7 @@ static void __init log_component_list(void)
 
        if (!early_ipl_comp_list_addr)
                return;
-       if (ipl_block.hdr.flags & IPL_PL_FLAG_IPLSR)
+       if (ipl_block.hdr.flags & IPL_PL_FLAG_SIPL)
                pr_info("Linux is running with Secure-IPL enabled\n");
        else
                pr_info("Linux is running with Secure-IPL disabled\n");
index 2794cad..a08bd25 100644 (file)
@@ -413,14 +413,11 @@ EXPORT_SYMBOL(arch_vcpu_is_preempted);
 
 void smp_yield_cpu(int cpu)
 {
-       if (MACHINE_HAS_DIAG9C) {
-               diag_stat_inc_norecursion(DIAG_STAT_X09C);
-               asm volatile("diag %0,0,0x9c"
-                            : : "d" (pcpu_devices[cpu].address));
-       } else if (MACHINE_HAS_DIAG44 && !smp_cpu_mtid) {
-               diag_stat_inc_norecursion(DIAG_STAT_X044);
-               asm volatile("diag 0,0,0x44");
-       }
+       if (!MACHINE_HAS_DIAG9C)
+               return;
+       diag_stat_inc_norecursion(DIAG_STAT_X09C);
+       asm volatile("diag %0,0,0x9c"
+                    : : "d" (pcpu_devices[cpu].address));
 }
 
 /*
index da2d4d4..707fd99 100644 (file)
@@ -36,10 +36,17 @@ static bool update_stack_info(struct unwind_state *state, unsigned long sp)
        return true;
 }
 
-static inline bool is_task_pt_regs(struct unwind_state *state,
-                                  struct pt_regs *regs)
+static inline bool is_final_pt_regs(struct unwind_state *state,
+                                   struct pt_regs *regs)
 {
-       return task_pt_regs(state->task) == regs;
+       /* user mode or kernel thread pt_regs at the bottom of task stack */
+       if (task_pt_regs(state->task) == regs)
+               return true;
+
+       /* user mode pt_regs at the bottom of irq stack */
+       return state->stack_info.type == STACK_TYPE_IRQ &&
+              state->stack_info.end - sizeof(struct pt_regs) == (unsigned long)regs &&
+              READ_ONCE_NOCHECK(regs->psw.mask) & PSW_MASK_PSTATE;
 }
 
 bool unwind_next_frame(struct unwind_state *state)
@@ -80,7 +87,7 @@ bool unwind_next_frame(struct unwind_state *state)
                        if (!on_stack(info, sp, sizeof(struct pt_regs)))
                                goto out_err;
                        regs = (struct pt_regs *) sp;
-                       if (is_task_pt_regs(state, regs))
+                       if (is_final_pt_regs(state, regs))
                                goto out_stop;
                        ip = READ_ONCE_NOCHECK(regs->psw.addr);
                        sp = READ_ONCE_NOCHECK(regs->gprs[15]);
index ce1e4bb..9b2dab5 100644 (file)
@@ -242,7 +242,6 @@ static inline void arch_spin_lock_classic(arch_spinlock_t *lp)
 
 void arch_spin_lock_wait(arch_spinlock_t *lp)
 {
-       /* Use classic spinlocks + niai if the steal time is >= 10% */
        if (test_cpu_flag(CIF_DEDICATED_CPU))
                arch_spin_lock_queued(lp);
        else
index bda7ac0..32b7a30 100644 (file)
@@ -238,7 +238,7 @@ static int test_unwind_irq(struct unwindme *u)
 {
        preempt_disable();
        if (register_external_irq(EXT_IRQ_CLK_COMP, unwindme_irq_handler)) {
-               pr_info("Couldn't reqister external interrupt handler");
+               pr_info("Couldn't register external interrupt handler");
                return -1;
        }
        u->task = current;
index f0ce222..ac44bd7 100644 (file)
@@ -292,10 +292,8 @@ void arch_remove_memory(int nid, u64 start, u64 size,
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
-       struct zone *zone;
 
-       zone = page_zone(pfn_to_page(start_pfn));
-       __remove_pages(zone, start_pfn, nr_pages, altmap);
+       __remove_pages(start_pfn, nr_pages, altmap);
        vmem_remove_mapping(start, size);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
index 460f255..0634561 100644 (file)
@@ -82,7 +82,8 @@ static pte_t * __init kasan_early_pte_alloc(void)
 enum populate_mode {
        POPULATE_ONE2ONE,
        POPULATE_MAP,
-       POPULATE_ZERO_SHADOW
+       POPULATE_ZERO_SHADOW,
+       POPULATE_SHALLOW
 };
 static void __init kasan_early_vmemmap_populate(unsigned long address,
                                                unsigned long end,
@@ -116,6 +117,12 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                        pgd_populate(&init_mm, pg_dir, p4_dir);
                }
 
+               if (IS_ENABLED(CONFIG_KASAN_S390_4_LEVEL_PAGING) &&
+                   mode == POPULATE_SHALLOW) {
+                       address = (address + P4D_SIZE) & P4D_MASK;
+                       continue;
+               }
+
                p4_dir = p4d_offset(pg_dir, address);
                if (p4d_none(*p4_dir)) {
                        if (mode == POPULATE_ZERO_SHADOW &&
@@ -130,6 +137,12 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                        p4d_populate(&init_mm, p4_dir, pu_dir);
                }
 
+               if (!IS_ENABLED(CONFIG_KASAN_S390_4_LEVEL_PAGING) &&
+                   mode == POPULATE_SHALLOW) {
+                       address = (address + PUD_SIZE) & PUD_MASK;
+                       continue;
+               }
+
                pu_dir = pud_offset(p4_dir, address);
                if (pud_none(*pu_dir)) {
                        if (mode == POPULATE_ZERO_SHADOW &&
@@ -195,6 +208,9 @@ static void __init kasan_early_vmemmap_populate(unsigned long address,
                                page = kasan_early_shadow_page;
                                pte_val(*pt_dir) = __pa(page) | pgt_prot_zero;
                                break;
+                       case POPULATE_SHALLOW:
+                               /* should never happen */
+                               break;
                        }
                }
                address += PAGE_SIZE;
@@ -313,22 +329,50 @@ void __init kasan_early_init(void)
        init_mm.pgd = early_pg_dir;
        /*
         * Current memory layout:
-        * +- 0 -------------+   +- shadow start -+
-        * | 1:1 ram mapping |  /| 1/8 ram        |
-        * +- end of ram ----+ / +----------------+
-        * | ... gap ...     |/  |      kasan     |
-        * +- shadow start --+   |      zero      |
-        * | 1/8 addr space  |   |      page      |
-        * +- shadow end    -+   |      mapping   |
-        * | ... gap ...     |\  |    (untracked) |
-        * +- modules vaddr -+ \ +----------------+
-        * | 2Gb             |  \|      unmapped  | allocated per module
-        * +-----------------+   +- shadow end ---+
+        * +- 0 -------------+     +- shadow start -+
+        * | 1:1 ram mapping |    /| 1/8 ram        |
+        * |                 |   / |                |
+        * +- end of ram ----+  /  +----------------+
+        * | ... gap ...     | /   |                |
+        * |                 |/    |    kasan       |
+        * +- shadow start --+     |    zero        |
+        * | 1/8 addr space  |     |    page        |
+        * +- shadow end    -+     |    mapping     |
+        * | ... gap ...     |\    |  (untracked)   |
+        * +- vmalloc area  -+ \   |                |
+        * | vmalloc_size    |  \  |                |
+        * +- modules vaddr -+   \ +----------------+
+        * | 2Gb             |    \|      unmapped  | allocated per module
+        * +-----------------+     +- shadow end ---+
+        *
+        * Current memory layout (KASAN_VMALLOC):
+        * +- 0 -------------+     +- shadow start -+
+        * | 1:1 ram mapping |    /| 1/8 ram        |
+        * |                 |   / |                |
+        * +- end of ram ----+  /  +----------------+
+        * | ... gap ...     | /   |    kasan       |
+        * |                 |/    |    zero        |
+        * +- shadow start --+     |    page        |
+        * | 1/8 addr space  |     |    mapping     |
+        * +- shadow end    -+     |  (untracked)   |
+        * | ... gap ...     |\    |                |
+        * +- vmalloc area  -+ \   +- vmalloc area -+
+        * | vmalloc_size    |  \  |shallow populate|
+        * +- modules vaddr -+   \ +- modules area -+
+        * | 2Gb             |    \|shallow populate|
+        * +-----------------+     +- shadow end ---+
         */
        /* populate kasan shadow (for identity mapping and zero page mapping) */
        kasan_early_vmemmap_populate(__sha(0), __sha(memsize), POPULATE_MAP);
        if (IS_ENABLED(CONFIG_MODULES))
                untracked_mem_end = vmax - MODULES_LEN;
+       if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
+               untracked_mem_end = vmax - vmalloc_size - MODULES_LEN;
+               /* shallowly populate kasan shadow for vmalloc and modules */
+               kasan_early_vmemmap_populate(__sha(untracked_mem_end),
+                                            __sha(vmax), POPULATE_SHALLOW);
+       }
+       /* populate kasan shadow for untracked memory */
        kasan_early_vmemmap_populate(__sha(max_physmem_end),
                                     __sha(untracked_mem_end),
                                     POPULATE_ZERO_SHADOW);
index 04a0343..c82157f 100644 (file)
@@ -1,3 +1,4 @@
 purgatory
+purgatory.chk
 purgatory.lds
 purgatory.ro
index bc0d7a0..c57f8c4 100644 (file)
@@ -4,7 +4,7 @@ OBJECT_FILES_NON_STANDARD := y
 
 purgatory-y := head.o purgatory.o string.o sha256.o mem.o
 
-targets += $(purgatory-y) purgatory.lds purgatory purgatory.ro
+targets += $(purgatory-y) purgatory.lds purgatory purgatory.chk purgatory.ro
 PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y))
 
 $(obj)/sha256.o: $(srctree)/lib/crypto/sha256.c FORCE
@@ -15,8 +15,10 @@ CFLAGS_sha256.o := -D__DISABLE_EXPORTS
 $(obj)/mem.o: $(srctree)/arch/s390/lib/mem.S FORCE
        $(call if_changed_rule,as_o_S)
 
-$(obj)/string.o: $(srctree)/arch/s390/lib/string.c FORCE
-       $(call if_changed_rule,cc_o_c)
+KCOV_INSTRUMENT := n
+GCOV_PROFILE := n
+UBSAN_SANITIZE := n
+KASAN_SANITIZE := n
 
 KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes
 KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare
@@ -26,15 +28,22 @@ KBUILD_CFLAGS += $(CLANG_FLAGS)
 KBUILD_CFLAGS += $(call cc-option,-fno-PIE)
 KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS))
 
-LDFLAGS_purgatory := -r --no-undefined -nostdlib -z nodefaultlib -T
+# Since we link purgatory with -r unresolved symbols are not checked, so we
+# also link a purgatory.chk binary without -r to check for unresolved symbols.
+PURGATORY_LDFLAGS := -nostdlib -z nodefaultlib
+LDFLAGS_purgatory := -r $(PURGATORY_LDFLAGS) -T
+LDFLAGS_purgatory.chk := -e purgatory_start $(PURGATORY_LDFLAGS)
 $(obj)/purgatory: $(obj)/purgatory.lds $(PURGATORY_OBJS) FORCE
                $(call if_changed,ld)
 
+$(obj)/purgatory.chk: $(obj)/purgatory FORCE
+               $(call if_changed,ld)
+
 OBJCOPYFLAGS_purgatory.ro := -O elf64-s390
 OBJCOPYFLAGS_purgatory.ro += --remove-section='*debug*'
 OBJCOPYFLAGS_purgatory.ro += --remove-section='.comment'
 OBJCOPYFLAGS_purgatory.ro += --remove-section='.note.*'
-$(obj)/purgatory.ro: $(obj)/purgatory FORCE
+$(obj)/purgatory.ro: $(obj)/purgatory $(obj)/purgatory.chk FORCE
                $(call if_changed,objcopy)
 
 $(obj)/kexec-purgatory.o: $(obj)/kexec-purgatory.S $(obj)/purgatory.ro FORCE
diff --git a/arch/s390/purgatory/string.c b/arch/s390/purgatory/string.c
new file mode 100644 (file)
index 0000000..c98c22a
--- /dev/null
@@ -0,0 +1,3 @@
+// SPDX-License-Identifier: GPL-2.0
+#define __HAVE_ARCH_MEMCMP     /* arch function */
+#include "../lib/string.c"
index f6d1484..f3dc3f2 100644 (file)
@@ -325,9 +325,9 @@ int __init sh_early_platform_driver_probe(char *class_str,
 }
 
 /**
- * sh_early_platform_cleanup - clean up early platform code
+ * early_platform_cleanup - clean up early platform code
  */
-static int __init sh_early_platform_cleanup(void)
+void __init early_platform_cleanup(void)
 {
        struct platform_device *pd, *pd2;
 
@@ -337,11 +337,4 @@ static int __init sh_early_platform_cleanup(void)
                list_del(&pd->dev.devres_head);
                memset(&pd->dev.devres_head, 0, sizeof(pd->dev.devres_head));
        }
-
-       return 0;
 }
-/*
- * This must happen once after all early devices are probed but before probing
- * real platform devices.
- */
-subsys_initcall(sh_early_platform_cleanup);
index 6d61f8c..0d5f3c9 100644 (file)
@@ -266,6 +266,7 @@ int kgdb_arch_handle_exception(int e_vector, int signo, int err_code,
                ptr = &remcomInBuffer[1];
                if (kgdb_hex2long(&ptr, &addr))
                        linux_regs->pc = addr;
+               /* fallthrough */
        case 'D':
        case 'k':
                atomic_set(&kgdb_cpu_doing_single_step, -1);
index dfdbaa5..d1b1ff2 100644 (file)
@@ -434,9 +434,7 @@ void arch_remove_memory(int nid, u64 start, u64 size,
 {
        unsigned long start_pfn = PFN_DOWN(start);
        unsigned long nr_pages = size >> PAGE_SHIFT;
-       struct zone *zone;
 
-       zone = page_zone(pfn_to_page(start_pfn));
-       __remove_pages(zone, start_pfn, nr_pages, altmap);
+       __remove_pages(start_pfn, nr_pages, altmap);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
index 84cc8f7..c8eabb9 100644 (file)
@@ -180,19 +180,19 @@ do {                                                                      \
 
 #define emit_loadptr(BASE, STRUCT, FIELD, DEST)                                \
 do {   unsigned int _off = offsetof(STRUCT, FIELD);                    \
-       BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(void *));    \
+       BUILD_BUG_ON(sizeof_field(STRUCT, FIELD) != sizeof(void *));    \
        *prog++ = LDPTRI | RS1(BASE) | S13(_off) | RD(DEST);            \
 } while (0)
 
 #define emit_load32(BASE, STRUCT, FIELD, DEST)                         \
 do {   unsigned int _off = offsetof(STRUCT, FIELD);                    \
-       BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u32));       \
+       BUILD_BUG_ON(sizeof_field(STRUCT, FIELD) != sizeof(u32));       \
        *prog++ = LD32I | RS1(BASE) | S13(_off) | RD(DEST);             \
 } while (0)
 
 #define emit_load16(BASE, STRUCT, FIELD, DEST)                         \
 do {   unsigned int _off = offsetof(STRUCT, FIELD);                    \
-       BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u16));       \
+       BUILD_BUG_ON(sizeof_field(STRUCT, FIELD) != sizeof(u16));       \
        *prog++ = LD16I | RS1(BASE) | S13(_off) | RD(DEST);             \
 } while (0)
 
@@ -202,7 +202,7 @@ do {        unsigned int _off = offsetof(STRUCT, FIELD);                    \
 } while (0)
 
 #define emit_load8(BASE, STRUCT, FIELD, DEST)                          \
-do {   BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8));        \
+do {   BUILD_BUG_ON(sizeof_field(STRUCT, FIELD) != sizeof(u8));        \
        __emit_load8(BASE, STRUCT, FIELD, DEST);                        \
 } while (0)
 
index 2a6d04f..6f0edd0 100644 (file)
@@ -14,6 +14,7 @@ config UML
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DEBUG_BUGVERBOSE
+       select HAVE_COPY_THREAD_TLS
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
        select GENERIC_CLOCKEVENTS
index 81c647e..adf91ef 100644 (file)
@@ -36,7 +36,7 @@ extern long subarch_ptrace(struct task_struct *child, long request,
 extern unsigned long getreg(struct task_struct *child, int regno);
 extern int putreg(struct task_struct *child, int regno, unsigned long value);
 
-extern int arch_copy_tls(struct task_struct *new);
+extern int arch_set_tls(struct task_struct *new, unsigned long tls);
 extern void clear_flushed_tls(struct task_struct *task);
 extern int syscall_trace_enter(struct pt_regs *regs);
 extern void syscall_trace_leave(struct pt_regs *regs);
index 263a8f0..17045e7 100644 (file)
@@ -153,8 +153,8 @@ void fork_handler(void)
        userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
 }
 
-int copy_thread(unsigned long clone_flags, unsigned long sp,
-               unsigned long arg, struct task_struct * p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long sp,
+               unsigned long arg, struct task_struct * p, unsigned long tls)
 {
        void (*handler)(void);
        int kthread = current->flags & PF_KTHREAD;
@@ -188,7 +188,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
                 * Set a new TLS for the child thread?
                 */
                if (clone_flags & CLONE_SETTLS)
-                       ret = arch_copy_tls(p);
+                       ret = arch_set_tls(p, tls);
        }
 
        return ret;
index aa976ad..1dac210 100644 (file)
@@ -103,7 +103,7 @@ vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
 quiet_cmd_check_data_rel = DATAREL $@
 define cmd_check_data_rel
        for obj in $(filter %.o,$^); do \
-               ${CROSS_COMPILE}readelf -S $$obj | grep -qF .rel.local && { \
+               $(READELF) -S $$obj | grep -qF .rel.local && { \
                        echo "error: $$obj has data relocations!" >&2; \
                        exit 1; \
                } || true; \
index 58a512e..ee60b81 100644 (file)
@@ -244,6 +244,11 @@ SYM_FUNC_START(efi32_stub_entry)
        leal    efi32_config(%ebp), %eax
        movl    %eax, efi_config(%ebp)
 
+       /* Disable paging */
+       movl    %cr0, %eax
+       btrl    $X86_CR0_PG_BIT, %eax
+       movl    %eax, %cr0
+
        jmp     startup_32
 SYM_FUNC_END(efi32_stub_entry)
 #endif
index 9a89d98..f118af9 100644 (file)
@@ -376,7 +376,7 @@ int x86_add_exclusive(unsigned int what)
         * LBR and BTS are still mutually exclusive.
         */
        if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
-               return 0;
+               goto out;
 
        if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
                mutex_lock(&pmc_reserve_mutex);
@@ -388,6 +388,7 @@ int x86_add_exclusive(unsigned int what)
                mutex_unlock(&pmc_reserve_mutex);
        }
 
+out:
        atomic_inc(&active_events);
        return 0;
 
@@ -398,11 +399,15 @@ fail_unlock:
 
 void x86_del_exclusive(unsigned int what)
 {
+       atomic_dec(&active_events);
+
+       /*
+        * See the comment in x86_add_exclusive().
+        */
        if (x86_pmu.lbr_pt_coexist && what == x86_lbr_exclusive_pt)
                return;
 
        atomic_dec(&x86_pmu.lbr_exclusive[what]);
-       atomic_dec(&active_events);
 }
 
 int x86_setup_perfctr(struct perf_event *event)
@@ -1642,9 +1647,12 @@ static struct attribute_group x86_pmu_format_group __ro_after_init = {
 
 ssize_t events_sysfs_show(struct device *dev, struct device_attribute *attr, char *page)
 {
-       struct perf_pmu_events_attr *pmu_attr = \
+       struct perf_pmu_events_attr *pmu_attr =
                container_of(attr, struct perf_pmu_events_attr, attr);
-       u64 config = x86_pmu.event_map(pmu_attr->id);
+       u64 config = 0;
+
+       if (pmu_attr->id < x86_pmu.max_events)
+               config = x86_pmu.event_map(pmu_attr->id);
 
        /* string trumps id */
        if (pmu_attr->event_str)
@@ -1713,6 +1721,9 @@ is_visible(struct kobject *kobj, struct attribute *attr, int idx)
 {
        struct perf_pmu_events_attr *pmu_attr;
 
+       if (idx >= x86_pmu.max_events)
+               return 0;
+
        pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr.attr);
        /* str trumps id */
        return pmu_attr->event_str || x86_pmu.event_map(idx) ? attr->mode : 0;
index 38de4a7..6a3b599 100644 (file)
@@ -63,9 +63,17 @@ struct bts_buffer {
 
 static struct pmu bts_pmu;
 
+static int buf_nr_pages(struct page *page)
+{
+       if (!PagePrivate(page))
+               return 1;
+
+       return 1 << page_private(page);
+}
+
 static size_t buf_size(struct page *page)
 {
-       return 1 << (PAGE_SHIFT + page_private(page));
+       return buf_nr_pages(page) * PAGE_SIZE;
 }
 
 static void *
@@ -83,9 +91,7 @@ bts_buffer_setup_aux(struct perf_event *event, void **pages,
        /* count all the high order buffers */
        for (pg = 0, nbuf = 0; pg < nr_pages;) {
                page = virt_to_page(pages[pg]);
-               if (WARN_ON_ONCE(!PagePrivate(page) && nr_pages > 1))
-                       return NULL;
-               pg += 1 << page_private(page);
+               pg += buf_nr_pages(page);
                nbuf++;
        }
 
@@ -109,7 +115,7 @@ bts_buffer_setup_aux(struct perf_event *event, void **pages,
                unsigned int __nr_pages;
 
                page = virt_to_page(pages[pg]);
-               __nr_pages = PagePrivate(page) ? 1 << page_private(page) : 1;
+               __nr_pages = buf_nr_pages(page);
                buf->buf[nbuf].page = page;
                buf->buf[nbuf].offset = offset;
                buf->buf[nbuf].displacement = (pad ? BTS_RECORD_SIZE - pad : 0);
index dbaa1b0..c37cb12 100644 (file)
@@ -15,6 +15,7 @@
 #define PCI_DEVICE_ID_INTEL_SKL_HQ_IMC         0x1910
 #define PCI_DEVICE_ID_INTEL_SKL_SD_IMC         0x190f
 #define PCI_DEVICE_ID_INTEL_SKL_SQ_IMC         0x191f
+#define PCI_DEVICE_ID_INTEL_SKL_E3_IMC         0x1918
 #define PCI_DEVICE_ID_INTEL_KBL_Y_IMC          0x590c
 #define PCI_DEVICE_ID_INTEL_KBL_U_IMC          0x5904
 #define PCI_DEVICE_ID_INTEL_KBL_UQ_IMC         0x5914
@@ -658,6 +659,10 @@ static const struct pci_device_id skl_uncore_pci_ids[] = {
                .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
        },
        { /* IMC */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SKL_E3_IMC),
+               .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
+       },
+       { /* IMC */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_KBL_Y_IMC),
                .driver_data = UNCORE_PCI_DEV_DATA(SNB_PCI_UNCORE_IMC, 0),
        },
@@ -826,6 +831,7 @@ static const struct imc_uncore_pci_dev desktop_imc_pci_ids[] = {
        IMC_DEV(SKL_HQ_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core H Quad Core */
        IMC_DEV(SKL_SD_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core S Dual Core */
        IMC_DEV(SKL_SQ_IMC, &skl_uncore_pci_driver),  /* 6th Gen Core S Quad Core */
+       IMC_DEV(SKL_E3_IMC, &skl_uncore_pci_driver),  /* Xeon E3 V5 Gen Core processor */
        IMC_DEV(KBL_Y_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core Y */
        IMC_DEV(KBL_U_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core U */
        IMC_DEV(KBL_UQ_IMC, &skl_uncore_pci_driver),  /* 7th Gen Core U Quad Core */
index b10a5ec..ad20220 100644 (file)
 #define SNR_M2M_PCI_PMON_BOX_CTL               0x438
 #define SNR_M2M_PCI_PMON_UMASK_EXT             0xff
 
-/* SNR PCIE3 */
-#define SNR_PCIE3_PCI_PMON_CTL0                        0x508
-#define SNR_PCIE3_PCI_PMON_CTR0                        0x4e8
-#define SNR_PCIE3_PCI_PMON_BOX_CTL             0x4e4
-
 /* SNR IMC */
 #define SNR_IMC_MMIO_PMON_FIXED_CTL            0x54
 #define SNR_IMC_MMIO_PMON_FIXED_CTR            0x38
@@ -4328,27 +4323,12 @@ static struct intel_uncore_type snr_uncore_m2m = {
        .format_group   = &snr_m2m_uncore_format_group,
 };
 
-static struct intel_uncore_type snr_uncore_pcie3 = {
-       .name           = "pcie3",
-       .num_counters   = 4,
-       .num_boxes      = 1,
-       .perf_ctr_bits  = 48,
-       .perf_ctr       = SNR_PCIE3_PCI_PMON_CTR0,
-       .event_ctl      = SNR_PCIE3_PCI_PMON_CTL0,
-       .event_mask     = SNBEP_PMON_RAW_EVENT_MASK,
-       .box_ctl        = SNR_PCIE3_PCI_PMON_BOX_CTL,
-       .ops            = &ivbep_uncore_pci_ops,
-       .format_group   = &ivbep_uncore_format_group,
-};
-
 enum {
        SNR_PCI_UNCORE_M2M,
-       SNR_PCI_UNCORE_PCIE3,
 };
 
 static struct intel_uncore_type *snr_pci_uncores[] = {
        [SNR_PCI_UNCORE_M2M]            = &snr_uncore_m2m,
-       [SNR_PCI_UNCORE_PCIE3]          = &snr_uncore_pcie3,
        NULL,
 };
 
@@ -4357,10 +4337,6 @@ static const struct pci_device_id snr_uncore_pci_ids[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x344a),
                .driver_data = UNCORE_PCI_DEV_FULL_DATA(12, 0, SNR_PCI_UNCORE_M2M, 0),
        },
-       { /* PCIe3 */
-               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x334a),
-               .driver_data = UNCORE_PCI_DEV_FULL_DATA(4, 0, SNR_PCI_UNCORE_PCIE3, 0),
-       },
        { /* end: all zeroes */ }
 };
 
@@ -4536,6 +4512,7 @@ static struct uncore_event_desc snr_uncore_imc_freerunning_events[] = {
        INTEL_UNCORE_EVENT_DESC(write,          "event=0xff,umask=0x21"),
        INTEL_UNCORE_EVENT_DESC(write.scale,    "3.814697266e-6"),
        INTEL_UNCORE_EVENT_DESC(write.unit,     "MiB"),
+       { /* end: all zeroes */ },
 };
 
 static struct intel_uncore_ops snr_uncore_imc_freerunning_ops = {
index 90f75e5..62c3027 100644 (file)
@@ -615,9 +615,9 @@ static void early_detect_mem_encrypt(struct cpuinfo_x86 *c)
                return;
 
 clear_all:
-               clear_cpu_cap(c, X86_FEATURE_SME);
+               setup_clear_cpu_cap(X86_FEATURE_SME);
 clear_sev:
-               clear_cpu_cap(c, X86_FEATURE_SEV);
+               setup_clear_cpu_cap(X86_FEATURE_SEV);
        }
 }
 
index 5167bd2..d6cf5c1 100644 (file)
@@ -266,10 +266,10 @@ static void smca_configure(unsigned int bank, unsigned int cpu)
        smca_set_misc_banks_map(bank, cpu);
 
        /* Return early if this bank was already initialized. */
-       if (smca_banks[bank].hwid)
+       if (smca_banks[bank].hwid && smca_banks[bank].hwid->hwid_mcatype != 0)
                return;
 
-       if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) {
+       if (rdmsr_safe(MSR_AMD64_SMCA_MCx_IPID(bank), &low, &high)) {
                pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
                return;
        }
index 5f42f25..2e2a421 100644 (file)
@@ -819,8 +819,8 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
                if (quirk_no_way_out)
                        quirk_no_way_out(i, m, regs);
 
+               m->bank = i;
                if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
-                       m->bank = i;
                        mce_read_aux(m, i);
                        *msg = tmp;
                        return 1;
index b38010b..6c3e1c9 100644 (file)
@@ -467,6 +467,7 @@ static int thermal_throttle_online(unsigned int cpu)
 {
        struct thermal_state *state = &per_cpu(thermal_state, cpu);
        struct device *dev = get_cpu_device(cpu);
+       u32 l;
 
        state->package_throttle.level = PACKAGE_LEVEL;
        state->core_throttle.level = CORE_LEVEL;
@@ -474,6 +475,10 @@ static int thermal_throttle_online(unsigned int cpu)
        INIT_DELAYED_WORK(&state->package_throttle.therm_work, throttle_active_work);
        INIT_DELAYED_WORK(&state->core_throttle.therm_work, throttle_active_work);
 
+       /* Unmask the thermal vector after the above workqueues are initialized. */
+       l = apic_read(APIC_LVTTHMR);
+       apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
+
        return thermal_throttle_add_dev(dev, cpu);
 }
 
@@ -722,10 +727,6 @@ void intel_init_thermal(struct cpuinfo_x86 *c)
        rdmsr(MSR_IA32_MISC_ENABLE, l, h);
        wrmsr(MSR_IA32_MISC_ENABLE, l | MSR_IA32_MISC_ENABLE_TM1, h);
 
-       /* Unmask the thermal vector: */
-       l = apic_read(APIC_LVTTHMR);
-       apic_write(APIC_LVTTHMR, l & ~APIC_LVT_MASKED);
-
        pr_info_once("CPU0: Thermal monitoring enabled (%s)\n",
                      tm2 ? "TM2" : "TM1");
 
index 03eb90d..89049b3 100644 (file)
@@ -618,7 +618,7 @@ static void domain_remove_cpu(int cpu, struct rdt_resource *r)
                if (static_branch_unlikely(&rdt_mon_enable_key))
                        rmdir_mondata_subdir_allrdtgrp(r, d->id);
                list_del(&d->list);
-               if (is_mbm_enabled())
+               if (r->mon_capable && is_mbm_enabled())
                        cancel_delayed_work(&d->mbm_over);
                if (is_llc_occupancy_enabled() &&  has_busy_rmid(r, d)) {
                        /*
index 2e3b06d..dac7209 100644 (file)
@@ -1741,9 +1741,6 @@ static int set_cache_qos_cfg(int level, bool enable)
        struct rdt_domain *d;
        int cpu;
 
-       if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
-               return -ENOMEM;
-
        if (level == RDT_RESOURCE_L3)
                update = l3_qos_cfg_update;
        else if (level == RDT_RESOURCE_L2)
@@ -1751,6 +1748,9 @@ static int set_cache_qos_cfg(int level, bool enable)
        else
                return -EINVAL;
 
+       if (!zalloc_cpumask_var(&cpu_mask, GFP_KERNEL))
+               return -ENOMEM;
+
        r_l = &rdt_resources_all[level];
        list_for_each_entry(d, &r_l->domains, list) {
                /* Pick one CPU from each domain instance to update MSR */
index 4cba91e..2f9ec14 100644 (file)
@@ -710,8 +710,12 @@ static struct chipset early_qrk[] __initdata = {
         */
        { PCI_VENDOR_ID_INTEL, 0x0f00,
                PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
+       { PCI_VENDOR_ID_INTEL, 0x3e20,
+               PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
        { PCI_VENDOR_ID_INTEL, 0x3ec4,
                PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
+       { PCI_VENDOR_ID_INTEL, 0x8a12,
+               PCI_CLASS_BRIDGE_HOST, PCI_ANY_ID, 0, force_disable_hpet},
        { PCI_VENDOR_ID_BROADCOM, 0x4331,
          PCI_CLASS_NETWORK_OTHER, PCI_ANY_ID, 0, apple_airport_reset},
        {}
index 319be93..fa31470 100644 (file)
@@ -259,7 +259,7 @@ static void __init setup_xstate_features(void)
                                                   xmm_space);
 
        xstate_offsets[XFEATURE_SSE]    = xstate_sizes[XFEATURE_FP];
-       xstate_sizes[XFEATURE_SSE]      = FIELD_SIZEOF(struct fxregs_state,
+       xstate_sizes[XFEATURE_SSE]      = sizeof_field(struct fxregs_state,
                                                       xmm_space);
 
        for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
index 060a361..024c305 100644 (file)
@@ -1043,20 +1043,6 @@ void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
                return;
 
        /*
-        * If the return location is actually pointing directly to
-        * the start of a direct trampoline (if we trace the trampoline
-        * it will still be offset by MCOUNT_INSN_SIZE), then the
-        * return address is actually off by one word, and we
-        * need to adjust for that.
-        */
-       if (ftrace_direct_func_count) {
-               if (ftrace_find_direct_func(self_addr + MCOUNT_INSN_SIZE)) {
-                       self_addr = *parent;
-                       parent++;
-               }
-       }
-
-       /*
         * Protect against fault, even if it shouldn't
         * happen. This tool is too much intrusive to
         * ignore such a protection.
index cfafa32..cf55629 100644 (file)
@@ -402,7 +402,8 @@ static inline void do_cpuid_7_mask(struct kvm_cpuid_entry2 *entry, int index)
                        entry->edx |= F(SPEC_CTRL);
                if (boot_cpu_has(X86_FEATURE_STIBP))
                        entry->edx |= F(INTEL_STIBP);
-               if (boot_cpu_has(X86_FEATURE_SSBD))
+               if (boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+                   boot_cpu_has(X86_FEATURE_AMD_SSBD))
                        entry->edx |= F(SPEC_CTRL_SSBD);
                /*
                 * We emulate ARCH_CAPABILITIES in software even
@@ -759,7 +760,8 @@ static inline int __do_cpuid_func(struct kvm_cpuid_entry2 *entry, u32 function,
                        entry->ebx |= F(AMD_IBRS);
                if (boot_cpu_has(X86_FEATURE_STIBP))
                        entry->ebx |= F(AMD_STIBP);
-               if (boot_cpu_has(X86_FEATURE_SSBD))
+               if (boot_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) ||
+                   boot_cpu_has(X86_FEATURE_AMD_SSBD))
                        entry->ebx |= F(AMD_SSBD);
                if (!boot_cpu_has_bug(X86_BUG_SPEC_STORE_BYPASS))
                        entry->ebx |= F(AMD_SSB_NO);
index 930edeb..0a74407 100644 (file)
@@ -865,10 +865,8 @@ void arch_remove_memory(int nid, u64 start, u64 size,
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
-       struct zone *zone;
 
-       zone = page_zone(pfn_to_page(start_pfn));
-       __remove_pages(zone, start_pfn, nr_pages, altmap);
+       __remove_pages(start_pfn, nr_pages, altmap);
 }
 #endif
 
index dcb9bc9..bcfede4 100644 (file)
@@ -1212,10 +1212,8 @@ void __ref arch_remove_memory(int nid, u64 start, u64 size,
 {
        unsigned long start_pfn = start >> PAGE_SHIFT;
        unsigned long nr_pages = size >> PAGE_SHIFT;
-       struct page *page = pfn_to_page(start_pfn) + vmem_altmap_offset(altmap);
-       struct zone *zone = page_zone(page);
 
-       __remove_pages(zone, start_pfn, nr_pages, altmap);
+       __remove_pages(start_pfn, nr_pages, altmap);
        kernel_physical_mapping_remove(start, start + size);
 }
 #endif /* CONFIG_MEMORY_HOTPLUG */
index 7675cf7..f8f0220 100644 (file)
@@ -260,10 +260,6 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
                return;
        }
 
-       /* No need to reserve regions that will never be freed. */
-       if (md.attribute & EFI_MEMORY_RUNTIME)
-               return;
-
        size += addr % EFI_PAGE_SIZE;
        size = round_up(size, EFI_PAGE_SIZE);
        addr = round_down(addr, EFI_PAGE_SIZE);
@@ -293,6 +289,8 @@ void __init efi_arch_mem_reserve(phys_addr_t addr, u64 size)
        early_memunmap(new, new_size);
 
        efi_memmap_install(new_phys, num_entries);
+       e820__range_update(addr, size, E820_TYPE_RAM, E820_TYPE_RESERVED);
+       e820__update_table(e820_table);
 }
 
 /*
index 5bd949d..ac8eee0 100644 (file)
@@ -215,14 +215,12 @@ static int set_tls_entry(struct task_struct* task, struct user_desc *info,
        return 0;
 }
 
-int arch_copy_tls(struct task_struct *new)
+int arch_set_tls(struct task_struct *new, unsigned long tls)
 {
        struct user_desc info;
        int idx, ret = -EFAULT;
 
-       if (copy_from_user(&info,
-                          (void __user *) UPT_SI(&new->thread.regs.regs),
-                          sizeof(info)))
+       if (copy_from_user(&info, (void __user *) tls, sizeof(info)))
                goto out;
 
        ret = -EINVAL;
index 3a621e0..ebd3855 100644 (file)
@@ -6,14 +6,13 @@ void clear_flushed_tls(struct task_struct *task)
 {
 }
 
-int arch_copy_tls(struct task_struct *t)
+int arch_set_tls(struct task_struct *t, unsigned long tls)
 {
        /*
         * If CLONE_SETTLS is set, we need to save the thread id
-        * (which is argument 5, child_tid, of clone) so it can be set
-        * during context switches.
+        * so it can be set during context switches.
         */
-       t->thread.arch.fs = t->thread.regs.regs.gp[R8 / sizeof(long)];
+       t->thread.arch.fs = tls;
 
        return 0;
 }
index 4a3fa29..296c532 100644 (file)
@@ -24,6 +24,7 @@ config XTENSA
        select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL
        select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL
        select HAVE_ARCH_TRACEHOOK
+       select HAVE_COPY_THREAD_TLS
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS
        select HAVE_EXIT_THREAD
index 9e1c491..3edecc4 100644 (file)
@@ -202,8 +202,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
  * involved.  Much simpler to just not copy those live frames across.
  */
 
-int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
-               unsigned long thread_fn_arg, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp_thread_fn,
+               unsigned long thread_fn_arg, struct task_struct *p,
+               unsigned long tls)
 {
        struct pt_regs *childregs = task_pt_regs(p);
 
@@ -266,9 +267,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
 
                childregs->syscall = regs->syscall;
 
-               /* The thread pointer is passed in the '4th argument' (= a5) */
                if (clone_flags & CLONE_SETTLS)
-                       childregs->threadptr = childregs->areg[5];
+                       childregs->threadptr = tls;
        } else {
                p->thread.ra = MAKE_RA_FOR_CALL(
                                (unsigned long)ret_from_kernel_thread, 1);
index 9d54aa3..94d6972 100644 (file)
@@ -539,6 +539,55 @@ void zero_fill_bio_iter(struct bio *bio, struct bvec_iter start)
 EXPORT_SYMBOL(zero_fill_bio_iter);
 
 /**
+ * bio_truncate - truncate the bio to small size of @new_size
+ * @bio:       the bio to be truncated
+ * @new_size:  new size for truncating the bio
+ *
+ * Description:
+ *   Truncate the bio to new size of @new_size. If bio_op(bio) is
+ *   REQ_OP_READ, zero the truncated part. This function should only
+ *   be used for handling corner cases, such as bio eod.
+ */
+void bio_truncate(struct bio *bio, unsigned new_size)
+{
+       struct bio_vec bv;
+       struct bvec_iter iter;
+       unsigned int done = 0;
+       bool truncated = false;
+
+       if (new_size >= bio->bi_iter.bi_size)
+               return;
+
+       if (bio_op(bio) != REQ_OP_READ)
+               goto exit;
+
+       bio_for_each_segment(bv, bio, iter) {
+               if (done + bv.bv_len > new_size) {
+                       unsigned offset;
+
+                       if (!truncated)
+                               offset = new_size - done;
+                       else
+                               offset = 0;
+                       zero_user(bv.bv_page, offset, bv.bv_len - offset);
+                       truncated = true;
+               }
+               done += bv.bv_len;
+       }
+
+ exit:
+       /*
+        * Don't touch bvec table here and make it really immutable, since
+        * fs bio user has to retrieve all pages via bio_for_each_segment_all
+        * in its .end_bio() callback.
+        *
+        * It is enough to truncate bio by updating .bi_size since we can make
+        * correct bvec with the updated .bi_size for drivers.
+        */
+       bio->bi_iter.bi_size = new_size;
+}
+
+/**
  * bio_put - release a reference to a bio
  * @bio:   bio to release reference to
  *
@@ -754,10 +803,12 @@ bool __bio_try_merge_page(struct bio *bio, struct page *page,
        if (WARN_ON_ONCE(bio_flagged(bio, BIO_CLONED)))
                return false;
 
-       if (bio->bi_vcnt > 0 && !bio_full(bio, len)) {
+       if (bio->bi_vcnt > 0) {
                struct bio_vec *bv = &bio->bi_io_vec[bio->bi_vcnt - 1];
 
                if (page_is_mergeable(bv, page, len, off, same_page)) {
+                       if (bio->bi_iter.bi_size > UINT_MAX - len)
+                               return false;
                        bv->bv_len += len;
                        bio->bi_iter.bi_size += len;
                        return true;
index 708dea9..a229b94 100644 (file)
@@ -1062,26 +1062,6 @@ err_unlock:
 }
 
 /**
- * blkcg_drain_queue - drain blkcg part of request_queue
- * @q: request_queue to drain
- *
- * Called from blk_drain_queue().  Responsible for draining blkcg part.
- */
-void blkcg_drain_queue(struct request_queue *q)
-{
-       lockdep_assert_held(&q->queue_lock);
-
-       /*
-        * @q could be exiting and already have destroyed all blkgs as
-        * indicated by NULL root_blkg.  If so, don't confuse policies.
-        */
-       if (!q->root_blkg)
-               return;
-
-       blk_throtl_drain(q);
-}
-
-/**
  * blkcg_exit_queue - exit and release blkcg part of request_queue
  * @q: request_queue being released
  *
index a1e2287..089e890 100644 (file)
@@ -885,11 +885,14 @@ generic_make_request_checks(struct bio *bio)
        }
 
        /*
-        * For a REQ_NOWAIT based request, return -EOPNOTSUPP
-        * if queue is not a request based queue.
+        * Non-mq queues do not honor REQ_NOWAIT, so complete a bio
+        * with BLK_STS_AGAIN status in order to catch -EAGAIN and
+        * to give a chance to the caller to repeat request gracefully.
         */
-       if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_mq(q))
-               goto not_supported;
+       if ((bio->bi_opf & REQ_NOWAIT) && !queue_is_mq(q)) {
+               status = BLK_STS_AGAIN;
+               goto end_io;
+       }
 
        if (should_fail_bio(bio))
                goto end_io;
@@ -1310,7 +1313,7 @@ EXPORT_SYMBOL_GPL(blk_rq_err_bytes);
 
 void blk_account_io_completion(struct request *req, unsigned int bytes)
 {
-       if (blk_do_io_stat(req)) {
+       if (req->part && blk_do_io_stat(req)) {
                const int sgrp = op_stat_group(req_op(req));
                struct hd_struct *part;
 
@@ -1328,7 +1331,8 @@ void blk_account_io_done(struct request *req, u64 now)
         * normal IO on queueing nor completion.  Accounting the
         * containing request is enough.
         */
-       if (blk_do_io_stat(req) && !(req->rq_flags & RQF_FLUSH_SEQ)) {
+       if (req->part && blk_do_io_stat(req) &&
+           !(req->rq_flags & RQF_FLUSH_SEQ)) {
                const int sgrp = op_stat_group(req_op(req));
                struct hd_struct *part;
 
@@ -1792,9 +1796,9 @@ int __init blk_dev_init(void)
 {
        BUILD_BUG_ON(REQ_OP_LAST >= (1 << REQ_OP_BITS));
        BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
-                       FIELD_SIZEOF(struct request, cmd_flags));
+                       sizeof_field(struct request, cmd_flags));
        BUILD_BUG_ON(REQ_OP_BITS + REQ_FLAG_BITS > 8 *
-                       FIELD_SIZEOF(struct bio, bi_opf));
+                       sizeof_field(struct bio, bi_opf));
 
        /* used for unplugging and affects IO latency/throughput - HIGHPRI */
        kblockd_workqueue = alloc_workqueue("kblockd",
index 1777346..3f977c5 100644 (file)
@@ -69,6 +69,7 @@
 #include <linux/blkdev.h>
 #include <linux/gfp.h>
 #include <linux/blk-mq.h>
+#include <linux/lockdep.h>
 
 #include "blk.h"
 #include "blk-mq.h"
@@ -505,6 +506,9 @@ struct blk_flush_queue *blk_alloc_flush_queue(struct request_queue *q,
        INIT_LIST_HEAD(&fq->flush_queue[1]);
        INIT_LIST_HEAD(&fq->flush_data_in_flight);
 
+       lockdep_register_key(&fq->key);
+       lockdep_set_class(&fq->mq_flush_lock, &fq->key);
+
        return fq;
 
  fail_rq:
@@ -519,6 +523,7 @@ void blk_free_flush_queue(struct blk_flush_queue *fq)
        if (!fq)
                return;
 
+       lockdep_unregister_key(&fq->key);
        kfree(fq->flush_rq);
        kfree(fq);
 }
index e01267f..27ca686 100644 (file)
@@ -1212,7 +1212,7 @@ static enum hrtimer_restart iocg_waitq_timer_fn(struct hrtimer *timer)
        return HRTIMER_NORESTART;
 }
 
-static void iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
+static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
 {
        struct ioc *ioc = iocg->ioc;
        struct blkcg_gq *blkg = iocg_to_blkg(iocg);
@@ -1229,11 +1229,11 @@ static void iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
        /* clear or maintain depending on the overage */
        if (time_before_eq64(vtime, now->vnow)) {
                blkcg_clear_delay(blkg);
-               return;
+               return false;
        }
        if (!atomic_read(&blkg->use_delay) &&
            time_before_eq64(vtime, now->vnow + vmargin))
-               return;
+               return false;
 
        /* use delay */
        if (cost) {
@@ -1250,10 +1250,11 @@ static void iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now, u64 cost)
        oexpires = ktime_to_ns(hrtimer_get_softexpires(&iocg->delay_timer));
        if (hrtimer_is_queued(&iocg->delay_timer) &&
            abs(oexpires - expires) <= margin_ns / 4)
-               return;
+               return true;
 
        hrtimer_start_range_ns(&iocg->delay_timer, ns_to_ktime(expires),
                               margin_ns / 4, HRTIMER_MODE_ABS);
+       return true;
 }
 
 static enum hrtimer_restart iocg_delay_timer_fn(struct hrtimer *timer)
@@ -1739,7 +1740,9 @@ static void ioc_rqos_throttle(struct rq_qos *rqos, struct bio *bio)
         */
        if (bio_issue_as_root_blkg(bio) || fatal_signal_pending(current)) {
                atomic64_add(abs_cost, &iocg->abs_vdebt);
-               iocg_kick_delay(iocg, &now, cost);
+               if (iocg_kick_delay(iocg, &now, cost))
+                       blkcg_schedule_throttle(rqos->q,
+                                       (bio->bi_opf & REQ_SWAP) == REQ_SWAP);
                return;
        }
 
index 3a62e47..b079026 100644 (file)
@@ -151,7 +151,7 @@ int blk_rq_map_user_iov(struct request_queue *q, struct request *rq,
        return 0;
 
 unmap_rq:
-       __blk_rq_unmap_user(bio);
+       blk_rq_unmap_user(bio);
 fail:
        rq->bio = NULL;
        return ret;
index d783bdc..1534ed7 100644 (file)
@@ -157,17 +157,20 @@ static inline unsigned get_max_io_size(struct request_queue *q,
        return sectors & (lbs - 1);
 }
 
-static unsigned get_max_segment_size(const struct request_queue *q,
-                                    unsigned offset)
+static inline unsigned get_max_segment_size(const struct request_queue *q,
+                                           struct page *start_page,
+                                           unsigned long offset)
 {
        unsigned long mask = queue_segment_boundary(q);
 
-       /* default segment boundary mask means no boundary limit */
-       if (mask == BLK_SEG_BOUNDARY_MASK)
-               return queue_max_segment_size(q);
+       offset = mask & (page_to_phys(start_page) + offset);
 
-       return min_t(unsigned long, mask - (mask & offset) + 1,
-                    queue_max_segment_size(q));
+       /*
+        * overflow may be triggered in case of zero page physical address
+        * on 32bit arch, use queue's max segment size when that happens.
+        */
+       return min_not_zero(mask - offset + 1,
+                       (unsigned long)queue_max_segment_size(q));
 }
 
 /**
@@ -201,7 +204,8 @@ static bool bvec_split_segs(const struct request_queue *q,
        unsigned seg_size = 0;
 
        while (len && *nsegs < max_segs) {
-               seg_size = get_max_segment_size(q, bv->bv_offset + total_len);
+               seg_size = get_max_segment_size(q, bv->bv_page,
+                                               bv->bv_offset + total_len);
                seg_size = min(seg_size, len);
 
                (*nsegs)++;
@@ -419,7 +423,8 @@ static unsigned blk_bvec_map_sg(struct request_queue *q,
 
        while (nbytes > 0) {
                unsigned offset = bvec->bv_offset + total;
-               unsigned len = min(get_max_segment_size(q, offset), nbytes);
+               unsigned len = min(get_max_segment_size(q, bvec->bv_page,
+                                       offset), nbytes);
                struct page *page = bvec->bv_page;
 
                /*
index 5f6dcc7..c8eda2e 100644 (file)
@@ -328,7 +328,7 @@ EXPORT_SYMBOL(blk_queue_max_segment_size);
  *   storage device can address.  The default of 512 covers most
  *   hardware.
  **/
-void blk_queue_logical_block_size(struct request_queue *q, unsigned short size)
+void blk_queue_logical_block_size(struct request_queue *q, unsigned int size)
 {
        q->limits.logical_block_size = size;
 
index 6842f28..0b88843 100644 (file)
@@ -30,6 +30,7 @@ struct blk_flush_queue {
         * at the same time
         */
        struct request          *orig_rq;
+       struct lock_class_key   key;
        spinlock_t              mq_flush_lock;
 };
 
index 347dda1..6cbb792 100644 (file)
@@ -266,7 +266,7 @@ static blk_status_t bsg_queue_rq(struct blk_mq_hw_ctx *hctx,
        struct request *req = bd->rq;
        struct bsg_set *bset =
                container_of(q->tag_set, struct bsg_set, tag_set);
-       int sts = BLK_STS_IOERR;
+       blk_status_t sts = BLK_STS_IOERR;
        int ret;
 
        blk_mq_start_request(req);
index 6ca015f..3ed7a0f 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/compat.h>
 #include <linux/elevator.h>
 #include <linux/hdreg.h>
+#include <linux/pr.h>
 #include <linux/slab.h>
 #include <linux/syscalls.h>
 #include <linux/types.h>
@@ -354,6 +355,13 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
         * but we call blkdev_ioctl, which gets the lock for us
         */
        case BLKRRPART:
+       case BLKREPORTZONE:
+       case BLKRESETZONE:
+       case BLKOPENZONE:
+       case BLKCLOSEZONE:
+       case BLKFINISHZONE:
+       case BLKGETZONESZ:
+       case BLKGETNRZONES:
                return blkdev_ioctl(bdev, mode, cmd,
                                (unsigned long)compat_ptr(arg));
        case BLKBSZSET_32:
@@ -401,6 +409,14 @@ long compat_blkdev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
        case BLKTRACETEARDOWN: /* compatible */
                ret = blk_trace_ioctl(bdev, cmd, compat_ptr(arg));
                return ret;
+       case IOC_PR_REGISTER:
+       case IOC_PR_RESERVE:
+       case IOC_PR_RELEASE:
+       case IOC_PR_PREEMPT:
+       case IOC_PR_PREEMPT_ABORT:
+       case IOC_PR_CLEAR:
+               return blkdev_ioctl(bdev, mode, cmd,
+                               (unsigned long)compat_ptr(arg));
        default:
                if (disk->fops->compat_ioctl)
                        ret = disk->fops->compat_ioctl(bdev, mode, cmd, arg);
index aded260..9dc53cf 100644 (file)
@@ -436,10 +436,10 @@ static int adiantum_init_tfm(struct crypto_skcipher *tfm)
 
        BUILD_BUG_ON(offsetofend(struct adiantum_request_ctx, u) !=
                     sizeof(struct adiantum_request_ctx));
-       subreq_size = max(FIELD_SIZEOF(struct adiantum_request_ctx,
+       subreq_size = max(sizeof_field(struct adiantum_request_ctx,
                                       u.hash_desc) +
                          crypto_shash_descsize(hash),
-                         FIELD_SIZEOF(struct adiantum_request_ctx,
+                         sizeof_field(struct adiantum_request_ctx,
                                       u.streamcipher_req) +
                          crypto_skcipher_reqsize(streamcipher));
 
index d16d893..378b18b 100644 (file)
@@ -470,6 +470,7 @@ static int tpm_key_encrypt(struct tpm_key *tk,
        if (ret < 0)
                goto error_free_tfm;
 
+       ret = -ENOMEM;
        req = akcipher_request_alloc(tfm, GFP_KERNEL);
        if (!req)
                goto error_free_tfm;
index 364b9df..d7f43d4 100644 (file)
@@ -184,6 +184,7 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
        if (IS_ERR(tfm))
                return PTR_ERR(tfm);
 
+       ret = -ENOMEM;
        req = akcipher_request_alloc(tfm, GFP_KERNEL);
        if (!req)
                goto error_free_tfm;
index 808f2b3..495a2d1 100644 (file)
@@ -347,7 +347,7 @@ static int essiv_aead_init_tfm(struct crypto_aead *tfm)
        if (IS_ERR(aead))
                return PTR_ERR(aead);
 
-       subreq_size = FIELD_SIZEOF(struct essiv_aead_request_ctx, aead_req) +
+       subreq_size = sizeof_field(struct essiv_aead_request_ctx, aead_req) +
                      crypto_aead_reqsize(aead);
 
        tctx->ivoffset = offsetof(struct essiv_aead_request_ctx, aead_req) +
index 08bb9f2..5e4a886 100644 (file)
@@ -1314,9 +1314,19 @@ static void acpi_dev_pm_detach(struct device *dev, bool power_off)
  */
 int acpi_dev_pm_attach(struct device *dev, bool power_on)
 {
+       /*
+        * Skip devices whose ACPI companions match the device IDs below,
+        * because they require special power management handling incompatible
+        * with the generic ACPI PM domain.
+        */
+       static const struct acpi_device_id special_pm_ids[] = {
+               {"PNP0C0B", }, /* Generic ACPI fan */
+               {"INT3404", }, /* Fan */
+               {}
+       };
        struct acpi_device *adev = ACPI_COMPANION(dev);
 
-       if (!adev)
+       if (!adev || !acpi_match_device_ids(adev, special_pm_ids))
                return 0;
 
        /*
index e9bc9fc..b2dad43 100644 (file)
@@ -3310,7 +3310,7 @@ static void binder_transaction(struct binder_proc *proc,
                        binder_size_t parent_offset;
                        struct binder_fd_array_object *fda =
                                to_binder_fd_array_object(hdr);
-                       size_t num_valid = (buffer_offset - off_start_offset) *
+                       size_t num_valid = (buffer_offset - off_start_offset) /
                                                sizeof(binder_size_t);
                        struct binder_buffer_object *parent =
                                binder_validate_ptr(target_proc, t->buffer,
@@ -3384,7 +3384,7 @@ static void binder_transaction(struct binder_proc *proc,
                                t->buffer->user_data + sg_buf_offset;
                        sg_buf_offset += ALIGN(bp->length, sizeof(u64));
 
-                       num_valid = (buffer_offset - off_start_offset) *
+                       num_valid = (buffer_offset - off_start_offset) /
                                        sizeof(binder_size_t);
                        ret = binder_fixup_parent(t, thread, bp,
                                                  off_start_offset,
index f41744b..66a570d 100644 (file)
@@ -76,8 +76,7 @@ enum brcm_ahci_version {
 };
 
 enum brcm_ahci_quirks {
-       BRCM_AHCI_QUIRK_NO_NCQ          = BIT(0),
-       BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(1),
+       BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE = BIT(0),
 };
 
 struct brcm_ahci_priv {
@@ -213,19 +212,12 @@ static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)
                        brcm_sata_phy_disable(priv, i);
 }
 
-static u32 brcm_ahci_get_portmask(struct platform_device *pdev,
+static u32 brcm_ahci_get_portmask(struct ahci_host_priv *hpriv,
                                  struct brcm_ahci_priv *priv)
 {
-       void __iomem *ahci;
-       struct resource *res;
        u32 impl;
 
-       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci");
-       ahci = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(ahci))
-               return 0;
-
-       impl = readl(ahci + HOST_PORTS_IMPL);
+       impl = readl(hpriv->mmio + HOST_PORTS_IMPL);
 
        if (fls(impl) > SATA_TOP_MAX_PHYS)
                dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",
@@ -233,9 +225,6 @@ static u32 brcm_ahci_get_portmask(struct platform_device *pdev,
        else if (!impl)
                dev_info(priv->dev, "no ports found\n");
 
-       devm_iounmap(&pdev->dev, ahci);
-       devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
-
        return impl;
 }
 
@@ -285,6 +274,13 @@ static unsigned int brcm_ahci_read_id(struct ata_device *dev,
        /* Perform the SATA PHY reset sequence */
        brcm_sata_phy_disable(priv, ap->port_no);
 
+       /* Reset the SATA clock */
+       ahci_platform_disable_clks(hpriv);
+       msleep(10);
+
+       ahci_platform_enable_clks(hpriv);
+       msleep(10);
+
        /* Bring the PHY back on */
        brcm_sata_phy_enable(priv, ap->port_no);
 
@@ -347,11 +343,10 @@ static int brcm_ahci_suspend(struct device *dev)
        struct ata_host *host = dev_get_drvdata(dev);
        struct ahci_host_priv *hpriv = host->private_data;
        struct brcm_ahci_priv *priv = hpriv->plat_data;
-       int ret;
 
-       ret = ahci_platform_suspend(dev);
        brcm_sata_phys_disable(priv);
-       return ret;
+
+       return ahci_platform_suspend(dev);
 }
 
 static int brcm_ahci_resume(struct device *dev)
@@ -359,11 +354,44 @@ static int brcm_ahci_resume(struct device *dev)
        struct ata_host *host = dev_get_drvdata(dev);
        struct ahci_host_priv *hpriv = host->private_data;
        struct brcm_ahci_priv *priv = hpriv->plat_data;
+       int ret;
+
+       /* Make sure clocks are turned on before re-configuration */
+       ret = ahci_platform_enable_clks(hpriv);
+       if (ret)
+               return ret;
 
        brcm_sata_init(priv);
        brcm_sata_phys_enable(priv);
        brcm_sata_alpm_init(hpriv);
-       return ahci_platform_resume(dev);
+
+       /* Since we had to enable clocks earlier on, we cannot use
+        * ahci_platform_resume() as-is since a second call to
+        * ahci_platform_enable_resources() would bump up the resources
+        * (regulators, clocks, PHYs) count artificially so we copy the part
+        * after ahci_platform_enable_resources().
+        */
+       ret = ahci_platform_enable_phys(hpriv);
+       if (ret)
+               goto out_disable_phys;
+
+       ret = ahci_platform_resume_host(dev);
+       if (ret)
+               goto out_disable_platform_phys;
+
+       /* We resumed so update PM runtime state */
+       pm_runtime_disable(dev);
+       pm_runtime_set_active(dev);
+       pm_runtime_enable(dev);
+
+       return 0;
+
+out_disable_platform_phys:
+       ahci_platform_disable_phys(hpriv);
+out_disable_phys:
+       brcm_sata_phys_disable(priv);
+       ahci_platform_disable_clks(hpriv);
+       return ret;
 }
 #endif
 
@@ -410,44 +438,71 @@ static int brcm_ahci_probe(struct platform_device *pdev)
        if (!IS_ERR_OR_NULL(priv->rcdev))
                reset_control_deassert(priv->rcdev);
 
-       if ((priv->version == BRCM_SATA_BCM7425) ||
-               (priv->version == BRCM_SATA_NSP)) {
-               priv->quirks |= BRCM_AHCI_QUIRK_NO_NCQ;
+       hpriv = ahci_platform_get_resources(pdev, 0);
+       if (IS_ERR(hpriv)) {
+               ret = PTR_ERR(hpriv);
+               goto out_reset;
+       }
+
+       hpriv->plat_data = priv;
+       hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP | AHCI_HFLAG_NO_WRITE_TO_RO;
+
+       switch (priv->version) {
+       case BRCM_SATA_BCM7425:
+               hpriv->flags |= AHCI_HFLAG_DELAY_ENGINE;
+               /* fall through */
+       case BRCM_SATA_NSP:
+               hpriv->flags |= AHCI_HFLAG_NO_NCQ;
                priv->quirks |= BRCM_AHCI_QUIRK_SKIP_PHY_ENABLE;
+               break;
+       default:
+               break;
        }
 
+       ret = ahci_platform_enable_clks(hpriv);
+       if (ret)
+               goto out_reset;
+
+       /* Must be first so as to configure endianness including that
+        * of the standard AHCI register space.
+        */
        brcm_sata_init(priv);
 
-       priv->port_mask = brcm_ahci_get_portmask(pdev, priv);
-       if (!priv->port_mask)
-               return -ENODEV;
+       /* Initializes priv->port_mask which is used below */
+       priv->port_mask = brcm_ahci_get_portmask(hpriv, priv);
+       if (!priv->port_mask) {
+               ret = -ENODEV;
+               goto out_disable_clks;
+       }
 
+       /* Must be done before ahci_platform_enable_phys() */
        brcm_sata_phys_enable(priv);
 
-       hpriv = ahci_platform_get_resources(pdev, 0);
-       if (IS_ERR(hpriv))
-               return PTR_ERR(hpriv);
-       hpriv->plat_data = priv;
-       hpriv->flags = AHCI_HFLAG_WAKE_BEFORE_STOP;
-
        brcm_sata_alpm_init(hpriv);
 
-       ret = ahci_platform_enable_resources(hpriv);
+       ret = ahci_platform_enable_phys(hpriv);
        if (ret)
-               return ret;
-
-       if (priv->quirks & BRCM_AHCI_QUIRK_NO_NCQ)
-               hpriv->flags |= AHCI_HFLAG_NO_NCQ;
-       hpriv->flags |= AHCI_HFLAG_NO_WRITE_TO_RO;
+               goto out_disable_phys;
 
        ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
                                      &ahci_platform_sht);
        if (ret)
-               return ret;
+               goto out_disable_platform_phys;
 
        dev_info(dev, "Broadcom AHCI SATA3 registered\n");
 
        return 0;
+
+out_disable_platform_phys:
+       ahci_platform_disable_phys(hpriv);
+out_disable_phys:
+       brcm_sata_phys_disable(priv);
+out_disable_clks:
+       ahci_platform_disable_clks(hpriv);
+out_reset:
+       if (!IS_ERR_OR_NULL(priv->rcdev))
+               reset_control_assert(priv->rcdev);
+       return ret;
 }
 
 static int brcm_ahci_remove(struct platform_device *pdev)
@@ -457,12 +512,12 @@ static int brcm_ahci_remove(struct platform_device *pdev)
        struct brcm_ahci_priv *priv = hpriv->plat_data;
        int ret;
 
+       brcm_sata_phys_disable(priv);
+
        ret = ata_platform_remove_one(pdev);
        if (ret)
                return ret;
 
-       brcm_sata_phys_disable(priv);
-
        return 0;
 }
 
index 8befce0..129556f 100644 (file)
@@ -43,7 +43,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_ops);
  * RETURNS:
  * 0 on success otherwise a negative error code
  */
-static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
+int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
 {
        int rc, i;
 
@@ -74,6 +74,7 @@ disable_phys:
        }
        return rc;
 }
+EXPORT_SYMBOL_GPL(ahci_platform_enable_phys);
 
 /**
  * ahci_platform_disable_phys - Disable PHYs
@@ -81,7 +82,7 @@ disable_phys:
  *
  * This function disables all PHYs found in hpriv->phys.
  */
-static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
+void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
 {
        int i;
 
@@ -90,6 +91,7 @@ static void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)
                phy_exit(hpriv->phys[i]);
        }
 }
+EXPORT_SYMBOL_GPL(ahci_platform_disable_phys);
 
 /**
  * ahci_platform_enable_clks - Enable platform clocks
index e9017c5..6f4ab5c 100644 (file)
@@ -5329,6 +5329,30 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
 }
 
 /**
+ *     ata_qc_get_active - get bitmask of active qcs
+ *     @ap: port in question
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ *     RETURNS:
+ *     Bitmask of active qcs
+ */
+u64 ata_qc_get_active(struct ata_port *ap)
+{
+       u64 qc_active = ap->qc_active;
+
+       /* ATA_TAG_INTERNAL is sent to hw as tag 0 */
+       if (qc_active & (1ULL << ATA_TAG_INTERNAL)) {
+               qc_active |= (1 << 0);
+               qc_active &= ~(1ULL << ATA_TAG_INTERNAL);
+       }
+
+       return qc_active;
+}
+EXPORT_SYMBOL_GPL(ata_qc_get_active);
+
+/**
  *     ata_qc_complete_multiple - Complete multiple qcs successfully
  *     @ap: port in question
  *     @qc_active: new qc_active mask
index 9239615..d55ee24 100644 (file)
@@ -1280,7 +1280,7 @@ static void sata_fsl_host_intr(struct ata_port *ap)
                                     i, ioread32(hcr_base + CC),
                                     ioread32(hcr_base + CA));
                }
-               ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+               ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
                return;
 
        } else if ((ap->qc_active & (1ULL << ATA_TAG_INTERNAL))) {
index 277f119..d7228f8 100644 (file)
@@ -2829,7 +2829,7 @@ static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp
        }
 
        if (work_done) {
-               ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+               ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
 
                /* Update the software queue position index in hardware */
                writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) |
index f3e62f5..eb9dc14 100644 (file)
@@ -984,7 +984,7 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
                                        check_commands = 0;
                                check_commands &= ~(1 << pos);
                        }
-                       ata_qc_complete_multiple(ap, ap->qc_active ^ done_mask);
+                       ata_qc_complete_multiple(ap, ata_qc_get_active(ap) ^ done_mask);
                }
        }
 
index b23d1e4..9d0d65e 100644 (file)
@@ -374,7 +374,7 @@ static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb,
                here = (eni_vcc->descr+skip) & (eni_vcc->words-1);
                dma[j++] = (here << MID_DMA_COUNT_SHIFT) | (vcc->vci
                    << MID_DMA_VCI_SHIFT) | MID_DT_JK;
-               j++;
+               dma[j++] = 0;
        }
        here = (eni_vcc->descr+size+skip) & (eni_vcc->words-1);
        if (!eff) size += skip;
@@ -447,7 +447,7 @@ static int do_rx_dma(struct atm_vcc *vcc,struct sk_buff *skb,
        if (size != eff) {
                dma[j++] = (here << MID_DMA_COUNT_SHIFT) |
                    (vcc->vci << MID_DMA_VCI_SHIFT) | MID_DT_JK;
-               j++;
+               dma[j++] = 0;
        }
        if (!j || j > 2*RX_DMA_BUF) {
                printk(KERN_CRIT DEV_LABEL "!j or j too big!!!\n");
index 30d0523..6cdbf15 100644 (file)
@@ -359,7 +359,7 @@ static int handle_remove(const char *nodename, struct device *dev)
  * If configured, or requested by the commandline, devtmpfs will be
  * auto-mounted after the kernel mounted the root filesystem.
  */
-int devtmpfs_mount(const char *mntdir)
+int devtmpfs_mount(void)
 {
        int err;
 
@@ -369,7 +369,7 @@ int devtmpfs_mount(const char *mntdir)
        if (!thread)
                return 0;
 
-       err = ksys_mount("devtmpfs", mntdir, "devtmpfs", MS_SILENT, NULL);
+       err = do_mount("devtmpfs", "dev", "devtmpfs", MS_SILENT, NULL);
        if (err)
                printk(KERN_INFO "devtmpfs: error mounting %i\n", err);
        else
@@ -394,7 +394,7 @@ static int devtmpfsd(void *p)
        *err = ksys_unshare(CLONE_NEWNS);
        if (*err)
                goto out;
-       *err = ksys_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
+       *err = do_mount("devtmpfs", "/", "devtmpfs", MS_SILENT, NULL);
        if (*err)
                goto out;
        ksys_chdir("/.."); /* will traverse into overmounted root */
index 4a66888..5fa7ce3 100644 (file)
@@ -17,7 +17,7 @@ PROGBITS  = $(if $(CONFIG_ARM),%,@)progbits
 filechk_fwbin = \
        echo "/* Generated by $(src)/Makefile */"               ;\
        echo "    .section .rodata"                             ;\
-       echo "    .p2align $(ASM_ALIGN)"                        ;\
+       echo "    .p2align 4"                                   ;\
        echo "_fw_$(FWSTR)_bin:"                                ;\
        echo "    .incbin \"$(fwdir)/$(FWNAME)\""               ;\
        echo "_fw_end:"                                         ;\
index 7c53254..cf6b6b7 100644 (file)
@@ -1325,10 +1325,14 @@ struct device *platform_find_device_by_driver(struct device *start,
 }
 EXPORT_SYMBOL_GPL(platform_find_device_by_driver);
 
+void __weak __init early_platform_cleanup(void) { }
+
 int __init platform_bus_init(void)
 {
        int error;
 
+       early_platform_cleanup();
+
        error = device_register(&platform_bus);
        if (error) {
                put_device(&platform_bus);
index 5753246..b4607dd 100644 (file)
@@ -1296,10 +1296,10 @@ static int nbd_start_device_ioctl(struct nbd_device *nbd, struct block_device *b
        mutex_unlock(&nbd->config_lock);
        ret = wait_event_interruptible(config->recv_wq,
                                         atomic_read(&config->recv_threads) == 0);
-       if (ret) {
+       if (ret)
                sock_shutdown(nbd);
-               flush_workqueue(nbd->recv_workq);
-       }
+       flush_workqueue(nbd->recv_workq);
+
        mutex_lock(&nbd->config_lock);
        nbd_bdev_reset(bdev);
        /* user requested, ignore socket errors */
index d4d88b5..ed34785 100644 (file)
@@ -129,11 +129,13 @@ static blk_status_t null_zone_write(struct nullb_cmd *cmd, sector_t sector,
                return BLK_STS_IOERR;
        case BLK_ZONE_COND_EMPTY:
        case BLK_ZONE_COND_IMP_OPEN:
+       case BLK_ZONE_COND_EXP_OPEN:
+       case BLK_ZONE_COND_CLOSED:
                /* Writes must be at the write pointer position */
                if (sector != zone->wp)
                        return BLK_STS_IOERR;
 
-               if (zone->cond == BLK_ZONE_COND_EMPTY)
+               if (zone->cond != BLK_ZONE_COND_EXP_OPEN)
                        zone->cond = BLK_ZONE_COND_IMP_OPEN;
 
                zone->wp += nr_sectors;
@@ -186,7 +188,10 @@ static blk_status_t null_zone_mgmt(struct nullb_cmd *cmd, enum req_opf op,
                if (zone->cond == BLK_ZONE_COND_FULL)
                        return BLK_STS_IOERR;
 
-               zone->cond = BLK_ZONE_COND_CLOSED;
+               if (zone->wp == zone->start)
+                       zone->cond = BLK_ZONE_COND_EMPTY;
+               else
+                       zone->cond = BLK_ZONE_COND_CLOSED;
                break;
        case REQ_OP_ZONE_FINISH:
                if (zone->type == BLK_ZONE_TYPE_CONVENTIONAL)
index ee67bf9..861fc65 100644 (file)
@@ -2707,7 +2707,7 @@ static const struct block_device_operations pktcdvd_ops = {
        .release =              pkt_close,
        .ioctl =                pkt_ioctl,
 #ifdef CONFIG_COMPAT
-       .ioctl =                pkt_compat_ioctl,
+       .compat_ioctl =         pkt_compat_ioctl,
 #endif
        .check_events =         pkt_check_events,
 };
index e8c5c54..4c5d99f 100644 (file)
@@ -171,6 +171,15 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)
        blkif->domid = domid;
        atomic_set(&blkif->refcnt, 1);
        init_completion(&blkif->drain_complete);
+
+       /*
+        * Because freeing back to the cache may be deferred, it is not
+        * safe to unload the module (and hence destroy the cache) until
+        * this has completed. To prevent premature unloading, take an
+        * extra module reference here and release only when the object
+        * has been freed back to the cache.
+        */
+       __module_get(THIS_MODULE);
        INIT_WORK(&blkif->free_work, xen_blkif_deferred_free);
 
        return blkif;
@@ -181,6 +190,9 @@ static int xen_blkif_map(struct xen_blkif_ring *ring, grant_ref_t *gref,
 {
        int err;
        struct xen_blkif *blkif = ring->blkif;
+       const struct blkif_common_sring *sring_common;
+       RING_IDX rsp_prod, req_prod;
+       unsigned int size;
 
        /* Already connected through? */
        if (ring->irq)
@@ -191,46 +203,62 @@ static int xen_blkif_map(struct xen_blkif_ring *ring, grant_ref_t *gref,
        if (err < 0)
                return err;
 
+       sring_common = (struct blkif_common_sring *)ring->blk_ring;
+       rsp_prod = READ_ONCE(sring_common->rsp_prod);
+       req_prod = READ_ONCE(sring_common->req_prod);
+
        switch (blkif->blk_protocol) {
        case BLKIF_PROTOCOL_NATIVE:
        {
-               struct blkif_sring *sring;
-               sring = (struct blkif_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.native, sring,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_sring *sring_native =
+                       (struct blkif_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.native, sring_native,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_native, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        case BLKIF_PROTOCOL_X86_32:
        {
-               struct blkif_x86_32_sring *sring_x86_32;
-               sring_x86_32 = (struct blkif_x86_32_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.x86_32, sring_x86_32,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_x86_32_sring *sring_x86_32 =
+                       (struct blkif_x86_32_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.x86_32, sring_x86_32,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_x86_32, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        case BLKIF_PROTOCOL_X86_64:
        {
-               struct blkif_x86_64_sring *sring_x86_64;
-               sring_x86_64 = (struct blkif_x86_64_sring *)ring->blk_ring;
-               BACK_RING_INIT(&ring->blk_rings.x86_64, sring_x86_64,
-                              XEN_PAGE_SIZE * nr_grefs);
+               struct blkif_x86_64_sring *sring_x86_64 =
+                       (struct blkif_x86_64_sring *)ring->blk_ring;
+
+               BACK_RING_ATTACH(&ring->blk_rings.x86_64, sring_x86_64,
+                                rsp_prod, XEN_PAGE_SIZE * nr_grefs);
+               size = __RING_SIZE(sring_x86_64, XEN_PAGE_SIZE * nr_grefs);
                break;
        }
        default:
                BUG();
        }
 
+       err = -EIO;
+       if (req_prod - rsp_prod > size)
+               goto fail;
+
        err = bind_interdomain_evtchn_to_irqhandler(blkif->domid, evtchn,
                                                    xen_blkif_be_int, 0,
                                                    "blkif-backend", ring);
-       if (err < 0) {
-               xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
-               ring->blk_rings.common.sring = NULL;
-               return err;
-       }
+       if (err < 0)
+               goto fail;
        ring->irq = err;
 
        return 0;
+
+fail:
+       xenbus_unmap_ring_vfree(blkif->be->dev, ring->blk_ring);
+       ring->blk_rings.common.sring = NULL;
+       return err;
 }
 
 static int xen_blkif_disconnect(struct xen_blkif *blkif)
@@ -320,6 +348,7 @@ static void xen_blkif_free(struct xen_blkif *blkif)
 
        /* Make sure everything is drained before shutting down */
        kmem_cache_free(xen_blkif_cachep, blkif);
+       module_put(THIS_MODULE);
 }
 
 int __init xen_blkif_interface_init(void)
@@ -1121,7 +1150,8 @@ static struct xenbus_driver xen_blkbk_driver = {
        .ids  = xen_blkbk_ids,
        .probe = xen_blkbk_probe,
        .remove = xen_blkbk_remove,
-       .otherend_changed = frontend_changed
+       .otherend_changed = frontend_changed,
+       .allow_rebind = true,
 };
 
 int xen_blkif_xenbus_init(void)
index a74d039..c02be06 100644 (file)
@@ -1113,8 +1113,8 @@ static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
        if (!VDEV_IS_EXTENDED(info->vdevice)) {
                err = xen_translate_vdev(info->vdevice, &minor, &offset);
                if (err)
-                       return err;             
-               nr_parts = PARTS_PER_DISK;
+                       return err;
+               nr_parts = PARTS_PER_DISK;
        } else {
                minor = BLKIF_MINOR_EXT(info->vdevice);
                nr_parts = PARTS_PER_EXT_DISK;
index 56887c6..ccb44fe 100644 (file)
@@ -343,6 +343,12 @@ static int sysc_get_clocks(struct sysc *ddata)
                return -EINVAL;
        }
 
+       /* Always add a slot for main clocks fck and ick even if unused */
+       if (!nr_fck)
+               ddata->nr_clocks++;
+       if (!nr_ick)
+               ddata->nr_clocks++;
+
        ddata->clocks = devm_kcalloc(ddata->dev,
                                     ddata->nr_clocks, sizeof(*ddata->clocks),
                                     GFP_KERNEL);
@@ -421,7 +427,7 @@ static int sysc_enable_opt_clocks(struct sysc *ddata)
        struct clk *clock;
        int i, error;
 
-       if (!ddata->clocks)
+       if (!ddata->clocks || ddata->nr_clocks < SYSC_OPTFCK0 + 1)
                return 0;
 
        for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
@@ -455,7 +461,7 @@ static void sysc_disable_opt_clocks(struct sysc *ddata)
        struct clk *clock;
        int i;
 
-       if (!ddata->clocks)
+       if (!ddata->clocks || ddata->nr_clocks < SYSC_OPTFCK0 + 1)
                return;
 
        for (i = SYSC_OPTFCK0; i < SYSC_MAX_CLOCKS; i++) {
@@ -981,7 +987,8 @@ static int sysc_disable_module(struct device *dev)
                return ret;
        }
 
-       if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_MSTANDBY)
+       if (ddata->cfg.quirks & (SYSC_QUIRK_SWSUP_MSTANDBY) ||
+           ddata->cfg.quirks & (SYSC_QUIRK_FORCE_MSTANDBY))
                best_mode = SYSC_IDLE_FORCE;
 
        reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);
@@ -1583,6 +1590,10 @@ static int sysc_reset(struct sysc *ddata)
        sysc_val |= sysc_mask;
        sysc_write(ddata, sysc_offset, sysc_val);
 
+       if (ddata->cfg.srst_udelay)
+               usleep_range(ddata->cfg.srst_udelay,
+                            ddata->cfg.srst_udelay * 2);
+
        if (ddata->clk_enable_quirk)
                ddata->clk_enable_quirk(ddata);
 
index 31c374b..7ecf20a 100644 (file)
@@ -84,7 +84,6 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
        unsigned int cdev = 0;
        u32 mnistat, tnistat, tstatus, mcmd;
        u16 tnicmd, mnicmd;
-       u8 mcapndx;
        u32 tot_bw = 0, tot_n = 0, tot_rq = 0, y_max, rq_isoch, rq_async;
        u32 step, rem, rem_isoch, rem_async;
        int ret = 0;
@@ -138,8 +137,6 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
                cur = list_entry(pos, struct agp_3_5_dev, list);
                dev = cur->dev;
 
-               mcapndx = cur->capndx;
-
                pci_read_config_dword(dev, cur->capndx+AGPNISTAT, &mnistat);
 
                master[cdev].maxbw = (mnistat >> 16) & 0xff;
@@ -251,8 +248,6 @@ static int agp_3_5_isochronous_node_enable(struct agp_bridge_data *bridge,
                cur = master[cdev].dev;
                dev = cur->dev;
 
-               mcapndx = cur->capndx;
-
                master[cdev].rq += (cdev == ndevs - 1)
                              ? (rem_async + rem_isoch) : step;
 
@@ -319,7 +314,7 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
 {
        struct pci_dev *td = bridge->dev, *dev = NULL;
        u8 mcapndx;
-       u32 isoch, arqsz;
+       u32 isoch;
        u32 tstatus, mstatus, ncapid;
        u32 mmajor;
        u16 mpstat;
@@ -334,8 +329,6 @@ int agp_3_5_enable(struct agp_bridge_data *bridge)
        if (isoch == 0) /* isoch xfers not available, bail out. */
                return -ENODEV;
 
-       arqsz     = (tstatus >> 13) & 0x7;
-
        /*
         * Allocate a head for our AGP 3.5 device list
         * (multiple AGP v3 devices are allowed behind a single bridge).
index 909e0c3..cda1293 100644 (file)
@@ -2175,6 +2175,7 @@ const struct file_operations urandom_fops = {
        .read  = urandom_read,
        .write = random_write,
        .unlocked_ioctl = random_ioctl,
+       .compat_ioctl = compat_ptr_ioctl,
        .fasync = random_fasync,
        .llseek = noop_llseek,
 };
index 2ec47a6..87f4493 100644 (file)
@@ -61,6 +61,12 @@ static void tpm_dev_async_work(struct work_struct *work)
 
        mutex_lock(&priv->buffer_mutex);
        priv->command_enqueued = false;
+       ret = tpm_try_get_ops(priv->chip);
+       if (ret) {
+               priv->response_length = ret;
+               goto out;
+       }
+
        ret = tpm_dev_transmit(priv->chip, priv->space, priv->data_buffer,
                               sizeof(priv->data_buffer));
        tpm_put_ops(priv->chip);
@@ -68,6 +74,7 @@ static void tpm_dev_async_work(struct work_struct *work)
                priv->response_length = ret;
                mod_timer(&priv->user_read_timer, jiffies + (120 * HZ));
        }
+out:
        mutex_unlock(&priv->buffer_mutex);
        wake_up_interruptible(&priv->async_wait);
 }
@@ -123,7 +130,7 @@ ssize_t tpm_common_read(struct file *file, char __user *buf,
                priv->response_read = true;
 
                ret_size = min_t(ssize_t, size, priv->response_length);
-               if (!ret_size) {
+               if (ret_size <= 0) {
                        priv->response_length = 0;
                        goto out;
                }
@@ -204,6 +211,7 @@ ssize_t tpm_common_write(struct file *file, const char __user *buf,
        if (file->f_flags & O_NONBLOCK) {
                priv->command_enqueued = true;
                queue_work(tpm_dev_wq, &priv->async_work);
+               tpm_put_ops(priv->chip);
                mutex_unlock(&priv->buffer_mutex);
                return size;
        }
index 1089fc0..f3742bc 100644 (file)
@@ -14,7 +14,7 @@ struct file_priv {
        struct work_struct timeout_work;
        struct work_struct async_work;
        wait_queue_head_t async_wait;
-       size_t response_length;
+       ssize_t response_length;
        bool response_read;
        bool command_enqueued;
 
index b9e1547..5620747 100644 (file)
@@ -218,7 +218,6 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx,
 int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
                    struct tpm_digest *digests);
 int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max);
-void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
 ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
                        u32 *value, const char *desc);
 
index fdb4577..13696de 100644 (file)
@@ -362,6 +362,7 @@ void tpm2_flush_context(struct tpm_chip *chip, u32 handle)
        tpm_transmit_cmd(chip, &buf, 0, "flushing context");
        tpm_buf_destroy(&buf);
 }
+EXPORT_SYMBOL_GPL(tpm2_flush_context);
 
 struct tpm2_get_cap_out {
        u8 more_data;
index 6640a14..22bf553 100644 (file)
@@ -32,7 +32,7 @@ static const uuid_t ftpm_ta_uuid =
                  0x82, 0xCB, 0x34, 0x3F, 0xB7, 0xF3, 0x78, 0x96);
 
 /**
- * ftpm_tee_tpm_op_recv - retrieve fTPM response.
+ * ftpm_tee_tpm_op_recv() - retrieve fTPM response.
  * @chip:      the tpm_chip description as specified in driver/char/tpm/tpm.h.
  * @buf:       the buffer to store data.
  * @count:     the number of bytes to read.
@@ -61,7 +61,7 @@ static int ftpm_tee_tpm_op_recv(struct tpm_chip *chip, u8 *buf, size_t count)
 }
 
 /**
- * ftpm_tee_tpm_op_send - send TPM commands through the TEE shared memory.
+ * ftpm_tee_tpm_op_send() - send TPM commands through the TEE shared memory.
  * @chip:      the tpm_chip description as specified in driver/char/tpm/tpm.h
  * @buf:       the buffer to send.
  * @len:       the number of bytes to send.
@@ -208,7 +208,7 @@ static int ftpm_tee_match(struct tee_ioctl_version_data *ver, const void *data)
 }
 
 /**
- * ftpm_tee_probe - initialize the fTPM
+ * ftpm_tee_probe() - initialize the fTPM
  * @pdev: the platform_device description.
  *
  * Return:
@@ -298,7 +298,7 @@ out_tee_session:
 }
 
 /**
- * ftpm_tee_remove - remove the TPM device
+ * ftpm_tee_remove() - remove the TPM device
  * @pdev: the platform_device description.
  *
  * Return:
@@ -328,6 +328,19 @@ static int ftpm_tee_remove(struct platform_device *pdev)
        return 0;
 }
 
+/**
+ * ftpm_tee_shutdown() - shutdown the TPM device
+ * @pdev: the platform_device description.
+ */
+static void ftpm_tee_shutdown(struct platform_device *pdev)
+{
+       struct ftpm_tee_private *pvt_data = dev_get_drvdata(&pdev->dev);
+
+       tee_shm_free(pvt_data->shm);
+       tee_client_close_session(pvt_data->ctx, pvt_data->session);
+       tee_client_close_context(pvt_data->ctx);
+}
+
 static const struct of_device_id of_ftpm_tee_ids[] = {
        { .compatible = "microsoft,ftpm" },
        { }
@@ -341,6 +354,7 @@ static struct platform_driver ftpm_tee_driver = {
        },
        .probe = ftpm_tee_probe,
        .remove = ftpm_tee_remove,
+       .shutdown = ftpm_tee_shutdown,
 };
 
 module_platform_driver(ftpm_tee_driver);
index 8af2cee..27c6ca0 100644 (file)
@@ -1059,8 +1059,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                        goto out_err;
                }
 
-               tpm_chip_start(chip);
-               chip->flags |= TPM_CHIP_FLAG_IRQ;
                if (irq) {
                        tpm_tis_probe_irq_single(chip, intmask, IRQF_SHARED,
                                                 irq);
@@ -1070,7 +1068,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
                } else {
                        tpm_tis_probe_irq(chip, intmask);
                }
-               tpm_chip_stop(chip);
        }
 
        rc = tpm_chip_register(chip);
index 0aabe49..a9d4234 100644 (file)
@@ -348,7 +348,7 @@ static void __init at91sam926x_pmc_setup(struct device_node *np,
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index 0ac34cd..77fe83a 100644 (file)
@@ -83,7 +83,7 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np)
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index 0855f3a..086cf0b 100644 (file)
@@ -146,7 +146,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index 0b03cfa..b71515a 100644 (file)
@@ -275,7 +275,7 @@ static int __init pmc_register_ops(void)
 
        np = of_find_matching_node(NULL, sama5d2_pmc_dt_ids);
 
-       pmcreg = syscon_node_to_regmap(np);
+       pmcreg = device_node_to_regmap(np);
        if (IS_ERR(pmcreg))
                return PTR_ERR(pmcreg);
 
index 0de1108..ff7e3f7 100644 (file)
@@ -162,7 +162,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index 25b156d..a6dee4a 100644 (file)
@@ -136,7 +136,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
                return;
        mainxtal_name = of_clk_get_parent_name(np, i);
 
-       regmap = syscon_node_to_regmap(np);
+       regmap = device_node_to_regmap(np);
        if (IS_ERR(regmap))
                return;
 
index b68e200..772258d 100644 (file)
@@ -3249,6 +3249,34 @@ static inline void clk_debug_unregister(struct clk_core *core)
 }
 #endif
 
+static void clk_core_reparent_orphans_nolock(void)
+{
+       struct clk_core *orphan;
+       struct hlist_node *tmp2;
+
+       /*
+        * walk the list of orphan clocks and reparent any that newly finds a
+        * parent.
+        */
+       hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
+               struct clk_core *parent = __clk_init_parent(orphan);
+
+               /*
+                * We need to use __clk_set_parent_before() and _after() to
+                * to properly migrate any prepare/enable count of the orphan
+                * clock. This is important for CLK_IS_CRITICAL clocks, which
+                * are enabled during init but might not have a parent yet.
+                */
+               if (parent) {
+                       /* update the clk tree topology */
+                       __clk_set_parent_before(orphan, parent);
+                       __clk_set_parent_after(orphan, parent, NULL);
+                       __clk_recalc_accuracies(orphan);
+                       __clk_recalc_rates(orphan, 0);
+               }
+       }
+}
+
 /**
  * __clk_core_init - initialize the data structures in a struct clk_core
  * @core:      clk_core being initialized
@@ -3259,8 +3287,6 @@ static inline void clk_debug_unregister(struct clk_core *core)
 static int __clk_core_init(struct clk_core *core)
 {
        int ret;
-       struct clk_core *orphan;
-       struct hlist_node *tmp2;
        unsigned long rate;
 
        if (!core)
@@ -3400,34 +3426,21 @@ static int __clk_core_init(struct clk_core *core)
        if (core->flags & CLK_IS_CRITICAL) {
                unsigned long flags;
 
-               clk_core_prepare(core);
+               ret = clk_core_prepare(core);
+               if (ret)
+                       goto out;
 
                flags = clk_enable_lock();
-               clk_core_enable(core);
+               ret = clk_core_enable(core);
                clk_enable_unlock(flags);
+               if (ret) {
+                       clk_core_unprepare(core);
+                       goto out;
+               }
        }
 
-       /*
-        * walk the list of orphan clocks and reparent any that newly finds a
-        * parent.
-        */
-       hlist_for_each_entry_safe(orphan, tmp2, &clk_orphan_list, child_node) {
-               struct clk_core *parent = __clk_init_parent(orphan);
+       clk_core_reparent_orphans_nolock();
 
-               /*
-                * We need to use __clk_set_parent_before() and _after() to
-                * to properly migrate any prepare/enable count of the orphan
-                * clock. This is important for CLK_IS_CRITICAL clocks, which
-                * are enabled during init but might not have a parent yet.
-                */
-               if (parent) {
-                       /* update the clk tree topology */
-                       __clk_set_parent_before(orphan, parent);
-                       __clk_set_parent_after(orphan, parent, NULL);
-                       __clk_recalc_accuracies(orphan);
-                       __clk_recalc_rates(orphan, 0);
-               }
-       }
 
        kref_init(&core->ref);
 out:
@@ -4179,6 +4192,13 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
 EXPORT_SYMBOL_GPL(clk_notifier_unregister);
 
 #ifdef CONFIG_OF
+static void clk_core_reparent_orphans(void)
+{
+       clk_prepare_lock();
+       clk_core_reparent_orphans_nolock();
+       clk_prepare_unlock();
+}
+
 /**
  * struct of_clk_provider - Clock provider registration structure
  * @link: Entry in global list of clock providers
@@ -4274,6 +4294,8 @@ int of_clk_add_provider(struct device_node *np,
        mutex_unlock(&of_clk_mutex);
        pr_debug("Added clock from %pOF\n", np);
 
+       clk_core_reparent_orphans();
+
        ret = of_clk_set_defaults(np, true);
        if (ret < 0)
                of_clk_del_provider(np);
@@ -4309,6 +4331,8 @@ int of_clk_add_hw_provider(struct device_node *np,
        mutex_unlock(&of_clk_mutex);
        pr_debug("Added clk_hw provider from %pOF\n", np);
 
+       clk_core_reparent_orphans();
+
        ret = of_clk_set_defaults(np, true);
        if (ret < 0)
                of_clk_del_provider(np);
index 388bdb9..d3486ee 100644 (file)
@@ -142,6 +142,7 @@ struct clk *imx8m_clk_composite_flags(const char *name,
        mux->reg = reg;
        mux->shift = PCG_PCS_SHIFT;
        mux->mask = PCG_PCS_MASK;
+       mux->lock = &imx_ccm_lock;
 
        div = kzalloc(sizeof(*div), GFP_KERNEL);
        if (!div)
@@ -161,6 +162,7 @@ struct clk *imx8m_clk_composite_flags(const char *name,
        gate_hw = &gate->hw;
        gate->reg = reg;
        gate->bit_idx = PCG_CGC_SHIFT;
+       gate->lock = &imx_ccm_lock;
 
        hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
                        mux_hw, &clk_mux_ops, div_hw,
index 3fdf3d4..281191b 100644 (file)
@@ -40,6 +40,7 @@ static const struct clk_div_table ulp_div_table[] = {
        { .val = 5, .div = 16, },
        { .val = 6, .div = 32, },
        { .val = 7, .div = 64, },
+       { /* sentinel */ },
 };
 
 static const int pcc2_uart_clk_ids[] __initconst = {
index 5c45819..3636c80 100644 (file)
@@ -159,7 +159,7 @@ static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
 {
        u32 val;
 
-       return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US, 0,
+       return readl_poll_timeout(pll->base, val, val & LOCK_STATUS, 0,
                        LOCK_TIMEOUT_US);
 }
 
index a60a1be..b4a95cb 100644 (file)
@@ -134,7 +134,7 @@ static DEFINE_SPINLOCK(ssp3_lock);
 static const char *ssp_parent_names[] = {"vctcxo_4", "vctcxo_2", "vctcxo", "pll1_16"};
 
 static DEFINE_SPINLOCK(timer_lock);
-static const char *timer_parent_names[] = {"clk32", "vctcxo_2", "vctcxo_4", "vctcxo"};
+static const char *timer_parent_names[] = {"clk32", "vctcxo_4", "vctcxo_2", "vctcxo"};
 
 static DEFINE_SPINLOCK(reset_lock);
 
index 38424e6..7f59fb8 100644 (file)
@@ -2186,7 +2186,8 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = {
        .pd = {
                .name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc",
        },
-       .pwrsts = PWRSTS_OFF_ON | VOTABLE,
+       .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
@@ -2194,7 +2195,8 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
        .pd = {
                .name = "hlos1_vote_mmnoc_mmu_tbu_sf_gdsc",
        },
-       .pwrsts = PWRSTS_OFF_ON | VOTABLE,
+       .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc *gcc_sc7180_gdscs[] = {
index f7b370f..f6ce888 100644 (file)
@@ -3255,6 +3255,7 @@ static struct gdsc hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc = {
                .name = "hlos1_vote_aggre_noc_mmu_audio_tbu_gdsc",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc = {
@@ -3263,6 +3264,7 @@ static struct gdsc hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc = {
                .name = "hlos1_vote_aggre_noc_mmu_pcie_tbu_gdsc",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_aggre_noc_mmu_tbu1_gdsc = {
@@ -3271,6 +3273,7 @@ static struct gdsc hlos1_vote_aggre_noc_mmu_tbu1_gdsc = {
                .name = "hlos1_vote_aggre_noc_mmu_tbu1_gdsc",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_aggre_noc_mmu_tbu2_gdsc = {
@@ -3279,6 +3282,7 @@ static struct gdsc hlos1_vote_aggre_noc_mmu_tbu2_gdsc = {
                .name = "hlos1_vote_aggre_noc_mmu_tbu2_gdsc",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = {
@@ -3287,6 +3291,7 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc = {
                .name = "hlos1_vote_mmnoc_mmu_tbu_hf0_gdsc",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc = {
@@ -3295,6 +3300,7 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc = {
                .name = "hlos1_vote_mmnoc_mmu_tbu_hf1_gdsc",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
@@ -3303,6 +3309,7 @@ static struct gdsc hlos1_vote_mmnoc_mmu_tbu_sf_gdsc = {
                .name = "hlos1_vote_mmnoc_mmu_tbu_sf_gdsc",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct clk_regmap *gcc_sdm845_clocks[] = {
index e5e2492..9b3923a 100644 (file)
@@ -242,10 +242,12 @@ static struct clk_branch gfx3d_isense_clk = {
 
 static struct gdsc gpu_cx_gdsc = {
        .gdscr = 0x1004,
+       .gds_hw_ctrl = 0x1008,
        .pd = {
                .name = "gpu_cx",
        },
        .pwrsts = PWRSTS_OFF_ON,
+       .flags = VOTABLE,
 };
 
 static struct gdsc gpu_gx_gdsc = {
index 3a991ca..c9e5a1f 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/clk-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/clk.h>
 
 #include "clk.h"
 #include "clk-cpu.h"
@@ -1646,6 +1647,13 @@ static void __init exynos5x_clk_init(struct device_node *np,
                                     exynos5x_subcmus);
        }
 
+       /*
+        * Keep top part of G3D clock path enabled permanently to ensure
+        * that the internal busses get their clock regardless of the
+        * main G3D clock enablement status.
+        */
+       clk_prepare_enable(__clk_lookup("mout_sw_aclk_g3d"));
+
        samsung_clk_of_add_provider(np, ctx);
 }
 
index 45a1ed3..50f8d1b 100644 (file)
@@ -23,9 +23,9 @@
  */
 
 static const char * const ar100_r_apb2_parents[] = { "osc24M", "osc32k",
-                                            "pll-periph0", "iosc" };
+                                                    "iosc", "pll-periph0" };
 static const struct ccu_mux_var_prediv ar100_r_apb2_predivs[] = {
-       { .index = 2, .shift = 0, .width = 5 },
+       { .index = 3, .shift = 0, .width = 5 },
 };
 
 static struct ccu_div ar100_clk = {
@@ -51,17 +51,7 @@ static struct ccu_div ar100_clk = {
 
 static CLK_FIXED_FACTOR_HW(r_ahb_clk, "r-ahb", &ar100_clk.common.hw, 1, 1, 0);
 
-static struct ccu_div r_apb1_clk = {
-       .div            = _SUNXI_CCU_DIV(0, 2),
-
-       .common         = {
-               .reg            = 0x00c,
-               .hw.init        = CLK_HW_INIT("r-apb1",
-                                             "r-ahb",
-                                             &ccu_div_ops,
-                                             0),
-       },
-};
+static SUNXI_CCU_M(r_apb1_clk, "r-apb1", "r-ahb", 0x00c, 0, 2, 0);
 
 static struct ccu_div r_apb2_clk = {
        .div            = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO),
index 4646fdc..4c8c491 100644 (file)
@@ -51,19 +51,7 @@ static struct ccu_div ar100_clk = {
 
 static CLK_FIXED_FACTOR_HW(ahb0_clk, "ahb0", &ar100_clk.common.hw, 1, 1, 0);
 
-static struct ccu_div apb0_clk = {
-       .div            = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
-
-       .common         = {
-               .reg            = 0x0c,
-               .hw.init        = CLK_HW_INIT_HW("apb0",
-                                                &ahb0_clk.hw,
-                                                &ccu_div_ops,
-                                                0),
-       },
-};
-
-static SUNXI_CCU_M(a83t_apb0_clk, "apb0", "ahb0", 0x0c, 0, 2, 0);
+static SUNXI_CCU_M(apb0_clk, "apb0", "ahb0", 0x0c, 0, 2, 0);
 
 /*
  * Define the parent as an array that can be reused to save space
@@ -127,7 +115,7 @@ static struct ccu_mp a83t_ir_clk = {
 
 static struct ccu_common *sun8i_a83t_r_ccu_clks[] = {
        &ar100_clk.common,
-       &a83t_apb0_clk.common,
+       &apb0_clk.common,
        &apb0_pio_clk.common,
        &apb0_ir_clk.common,
        &apb0_timer_clk.common,
@@ -167,7 +155,7 @@ static struct clk_hw_onecell_data sun8i_a83t_r_hw_clks = {
        .hws    = {
                [CLK_AR100]             = &ar100_clk.common.hw,
                [CLK_AHB0]              = &ahb0_clk.hw,
-               [CLK_APB0]              = &a83t_apb0_clk.common.hw,
+               [CLK_APB0]              = &apb0_clk.common.hw,
                [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
                [CLK_APB0_IR]           = &apb0_ir_clk.common.hw,
                [CLK_APB0_TIMER]        = &apb0_timer_clk.common.hw,
@@ -282,9 +270,6 @@ static void __init sunxi_r_ccu_init(struct device_node *node,
 
 static void __init sun8i_a83t_r_ccu_setup(struct device_node *node)
 {
-       /* Fix apb0 bus gate parents here */
-       apb0_gate_parent[0] = &a83t_apb0_clk.common.hw;
-
        sunxi_r_ccu_init(node, &sun8i_a83t_r_ccu_desc);
 }
 CLK_OF_DECLARE(sun8i_a83t_r_ccu, "allwinner,sun8i-a83t-r-ccu",
index 8974908..23bfe1d 100644 (file)
@@ -761,7 +761,8 @@ static struct ccu_mp outa_clk = {
                .reg            = 0x1f0,
                .features       = CCU_FEATURE_FIXED_PREDIV,
                .hw.init        = CLK_HW_INIT_PARENTS("outa", out_parents,
-                                                     &ccu_mp_ops, 0),
+                                                     &ccu_mp_ops,
+                                                     CLK_SET_RATE_PARENT),
        }
 };
 
@@ -779,7 +780,8 @@ static struct ccu_mp outb_clk = {
                .reg            = 0x1f4,
                .features       = CCU_FEATURE_FIXED_PREDIV,
                .hw.init        = CLK_HW_INIT_PARENTS("outb", out_parents,
-                                                     &ccu_mp_ops, 0),
+                                                     &ccu_mp_ops,
+                                                     CLK_SET_RATE_PARENT),
        }
 };
 
index 5c779ee..0e36ca3 100644 (file)
@@ -618,7 +618,7 @@ static struct clk_hw_onecell_data sun8i_v3s_hw_clks = {
                [CLK_MBUS]              = &mbus_clk.common.hw,
                [CLK_MIPI_CSI]          = &mipi_csi_clk.common.hw,
        },
-       .num    = CLK_NUMBER,
+       .num    = CLK_PLL_DDR1 + 1,
 };
 
 static struct clk_hw_onecell_data sun8i_v3_hw_clks = {
@@ -700,7 +700,7 @@ static struct clk_hw_onecell_data sun8i_v3_hw_clks = {
                [CLK_MBUS]              = &mbus_clk.common.hw,
                [CLK_MIPI_CSI]          = &mipi_csi_clk.common.hw,
        },
-       .num    = CLK_NUMBER,
+       .num    = CLK_I2S0 + 1,
 };
 
 static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
index b0160d3..108eeee 100644 (file)
@@ -51,6 +51,4 @@
 
 #define CLK_PLL_DDR1           74
 
-#define CLK_NUMBER             (CLK_I2S0 + 1)
-
 #endif /* _CCU_SUN8I_H3_H_ */
index e6bd6d1..f6cdce4 100644 (file)
@@ -231,8 +231,10 @@ struct clk ** __init tegra_clk_init(void __iomem *regs, int num, int banks)
        periph_banks = banks;
 
        clks = kcalloc(num, sizeof(struct clk *), GFP_KERNEL);
-       if (!clks)
+       if (!clks) {
                kfree(periph_clk_enb_refcnt);
+               return NULL;
+       }
 
        clk_num = num;
 
index f65e16c..8d4c08b 100644 (file)
@@ -233,7 +233,6 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev)
        cinfo->iobase = of_iomap(node, 0);
        cinfo->dev = &pdev->dev;
        pm_runtime_enable(cinfo->dev);
-       pm_runtime_irq_safe(cinfo->dev);
 
        pm_runtime_get_sync(cinfo->dev);
        atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX);
index 4e54856..c4f15c4 100644 (file)
@@ -56,7 +56,7 @@ static unsigned long long riscv_clocksource_rdtime(struct clocksource *cs)
        return get_cycles64();
 }
 
-static u64 riscv_sched_clock(void)
+static u64 notrace riscv_sched_clock(void)
 {
        return get_cycles64();
 }
index f1d170d..aba591d 100644 (file)
@@ -121,6 +121,8 @@ static const struct of_device_id blacklist[] __initconst = {
        { .compatible = "mediatek,mt8176", },
        { .compatible = "mediatek,mt8183", },
 
+       { .compatible = "nvidia,tegra20", },
+       { .compatible = "nvidia,tegra30", },
        { .compatible = "nvidia,tegra124", },
        { .compatible = "nvidia,tegra210", },
 
index 506e3f2..83c85d3 100644 (file)
@@ -434,7 +434,7 @@ static int ve_spc_cpufreq_init(struct cpufreq_policy *policy)
        if (cur_cluster < MAX_CLUSTERS) {
                int cpu;
 
-               cpumask_copy(policy->cpus, topology_core_cpumask(policy->cpu));
+               dev_pm_opp_get_sharing_cpus(cpu_dev, policy->cpus);
 
                for_each_cpu(cpu, policy->cpus)
                        per_cpu(physical_cluster, cpu) = cur_cluster;
index 0005be5..33d19c8 100644 (file)
@@ -381,7 +381,8 @@ u64 cpuidle_poll_time(struct cpuidle_driver *drv,
                if (dev->states_usage[i].disable)
                        continue;
 
-               limit_ns = (u64)drv->states[i].target_residency_ns;
+               limit_ns = drv->states[i].target_residency_ns;
+               break;
        }
 
        dev->poll_limit_ns = limit_ns;
index c76423a..ce6a5f8 100644 (file)
@@ -403,6 +403,13 @@ void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,
 
        mutex_lock(&cpuidle_lock);
 
+       spin_lock(&cpuidle_driver_lock);
+
+       if (!drv->cpumask) {
+               drv->states[idx].flags |= CPUIDLE_FLAG_UNUSABLE;
+               goto unlock;
+       }
+
        for_each_cpu(cpu, drv->cpumask) {
                struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
 
@@ -415,5 +422,8 @@ void cpuidle_driver_state_disabled(struct cpuidle_driver *drv, int idx,
                        dev->states_usage[idx].disable &= ~CPUIDLE_STATE_DISABLED_BY_DRIVER;
        }
 
+unlock:
+       spin_unlock(&cpuidle_driver_lock);
+
        mutex_unlock(&cpuidle_lock);
 }
index de7e706..6deaaf5 100644 (file)
@@ -198,7 +198,7 @@ static void teo_update(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         * pattern detection.
         */
        cpu_data->intervals[cpu_data->interval_idx++] = measured_ns;
-       if (cpu_data->interval_idx > INTERVALS)
+       if (cpu_data->interval_idx >= INTERVALS)
                cpu_data->interval_idx = 0;
 }
 
index 26754d0..b846d73 100644 (file)
@@ -40,7 +40,7 @@ struct sec_req {
        int req_id;
 
        /* Status of the SEC request */
-       int fake_busy;
+       atomic_t fake_busy;
 };
 
 /**
@@ -132,8 +132,8 @@ struct sec_debug_file {
 };
 
 struct sec_dfx {
-       u64 send_cnt;
-       u64 recv_cnt;
+       atomic64_t send_cnt;
+       atomic64_t recv_cnt;
 };
 
 struct sec_debug {
index 62b04e1..0a5391f 100644 (file)
@@ -120,7 +120,7 @@ static void sec_req_cb(struct hisi_qp *qp, void *resp)
                return;
        }
 
-       __sync_add_and_fetch(&req->ctx->sec->debug.dfx.recv_cnt, 1);
+       atomic64_inc(&req->ctx->sec->debug.dfx.recv_cnt);
 
        req->ctx->req_op->buf_unmap(req->ctx, req);
 
@@ -135,13 +135,13 @@ static int sec_bd_send(struct sec_ctx *ctx, struct sec_req *req)
        mutex_lock(&qp_ctx->req_lock);
        ret = hisi_qp_send(qp_ctx->qp, &req->sec_sqe);
        mutex_unlock(&qp_ctx->req_lock);
-       __sync_add_and_fetch(&ctx->sec->debug.dfx.send_cnt, 1);
+       atomic64_inc(&ctx->sec->debug.dfx.send_cnt);
 
        if (ret == -EBUSY)
                return -ENOBUFS;
 
        if (!ret) {
-               if (req->fake_busy)
+               if (atomic_read(&req->fake_busy))
                        ret = -EBUSY;
                else
                        ret = -EINPROGRESS;
@@ -641,7 +641,7 @@ static void sec_skcipher_callback(struct sec_ctx *ctx, struct sec_req *req)
        if (ctx->c_ctx.c_mode == SEC_CMODE_CBC && req->c_req.encrypt)
                sec_update_iv(req);
 
-       if (__sync_bool_compare_and_swap(&req->fake_busy, 1, 0))
+       if (atomic_cmpxchg(&req->fake_busy, 1, 0) != 1)
                sk_req->base.complete(&sk_req->base, -EINPROGRESS);
 
        sk_req->base.complete(&sk_req->base, req->err_type);
@@ -672,9 +672,9 @@ static int sec_request_init(struct sec_ctx *ctx, struct sec_req *req)
        }
 
        if (ctx->fake_req_limit <= atomic_inc_return(&qp_ctx->pending_reqs))
-               req->fake_busy = 1;
+               atomic_set(&req->fake_busy, 1);
        else
-               req->fake_busy = 0;
+               atomic_set(&req->fake_busy, 0);
 
        ret = ctx->req_op->get_res(ctx, req);
        if (ret) {
index 74f0654..ab742df 100644 (file)
@@ -608,6 +608,14 @@ static const struct file_operations sec_dbg_fops = {
        .write = sec_debug_write,
 };
 
+static int debugfs_atomic64_t_get(void *data, u64 *val)
+{
+        *val = atomic64_read((atomic64_t *)data);
+        return 0;
+}
+DEFINE_DEBUGFS_ATTRIBUTE(fops_atomic64_t_ro, debugfs_atomic64_t_get, NULL,
+                        "%lld\n");
+
 static int sec_core_debug_init(struct sec_dev *sec)
 {
        struct hisi_qm *qm = &sec->qm;
@@ -628,9 +636,11 @@ static int sec_core_debug_init(struct sec_dev *sec)
 
        debugfs_create_regset32("regs", 0444, tmp_d, regset);
 
-       debugfs_create_u64("send_cnt", 0444, tmp_d, &dfx->send_cnt);
+       debugfs_create_file("send_cnt", 0444, tmp_d, &dfx->send_cnt,
+                           &fops_atomic64_t_ro);
 
-       debugfs_create_u64("recv_cnt", 0444, tmp_d, &dfx->recv_cnt);
+       debugfs_create_file("recv_cnt", 0444, tmp_d, &dfx->recv_cnt,
+                           &fops_atomic64_t_ro);
 
        return 0;
 }
index defe1d4..3553583 100644 (file)
@@ -83,7 +83,6 @@ config ARM_EXYNOS_BUS_DEVFREQ
        select DEVFREQ_GOV_PASSIVE
        select DEVFREQ_EVENT_EXYNOS_PPMU
        select PM_DEVFREQ_EVENT
-       select PM_OPP
        help
          This adds the common DEVFREQ driver for Exynos Memory bus. Exynos
          Memory bus has one more group of memory bus (e.g, MIF and INT block).
@@ -98,7 +97,7 @@ config ARM_TEGRA_DEVFREQ
                ARCH_TEGRA_132_SOC || ARCH_TEGRA_124_SOC || \
                ARCH_TEGRA_210_SOC || \
                COMPILE_TEST
-       select PM_OPP
+       depends on COMMON_CLK
        help
          This adds the DEVFREQ driver for the Tegra family of SoCs.
          It reads ACTMON counters of memory controllers and adjusts the
@@ -109,7 +108,6 @@ config ARM_TEGRA20_DEVFREQ
        depends on (TEGRA_MC && TEGRA20_EMC) || COMPILE_TEST
        depends on COMMON_CLK
        select DEVFREQ_GOV_SIMPLE_ONDEMAND
-       select PM_OPP
        help
          This adds the DEVFREQ driver for the Tegra20 family of SoCs.
          It reads Memory Controller counters and adjusts the operating
@@ -121,7 +119,6 @@ config ARM_RK3399_DMC_DEVFREQ
        select DEVFREQ_EVENT_ROCKCHIP_DFI
        select DEVFREQ_GOV_SIMPLE_ONDEMAND
        select PM_DEVFREQ_EVENT
-       select PM_OPP
        help
           This adds the DEVFREQ driver for the RK3399 DMC(Dynamic Memory Controller).
           It sets the frequency for the memory controller and reads the usage counts
index 425149e..57f6944 100644 (file)
 #include <linux/printk.h>
 #include <linux/hrtimer.h>
 #include <linux/of.h>
+#include <linux/pm_qos.h>
 #include "governor.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/devfreq.h>
 
+#define HZ_PER_KHZ     1000
+
 static struct class *devfreq_class;
 
 /*
@@ -99,6 +102,54 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
 }
 
 /**
+ * get_freq_range() - Get the current freq range
+ * @devfreq:   the devfreq instance
+ * @min_freq:  the min frequency
+ * @max_freq:  the max frequency
+ *
+ * This takes into consideration all constraints.
+ */
+static void get_freq_range(struct devfreq *devfreq,
+                          unsigned long *min_freq,
+                          unsigned long *max_freq)
+{
+       unsigned long *freq_table = devfreq->profile->freq_table;
+       s32 qos_min_freq, qos_max_freq;
+
+       lockdep_assert_held(&devfreq->lock);
+
+       /*
+        * Initialize minimum/maximum frequency from freq table.
+        * The devfreq drivers can initialize this in either ascending or
+        * descending order and devfreq core supports both.
+        */
+       if (freq_table[0] < freq_table[devfreq->profile->max_state - 1]) {
+               *min_freq = freq_table[0];
+               *max_freq = freq_table[devfreq->profile->max_state - 1];
+       } else {
+               *min_freq = freq_table[devfreq->profile->max_state - 1];
+               *max_freq = freq_table[0];
+       }
+
+       /* Apply constraints from PM QoS */
+       qos_min_freq = dev_pm_qos_read_value(devfreq->dev.parent,
+                                            DEV_PM_QOS_MIN_FREQUENCY);
+       qos_max_freq = dev_pm_qos_read_value(devfreq->dev.parent,
+                                            DEV_PM_QOS_MAX_FREQUENCY);
+       *min_freq = max(*min_freq, (unsigned long)HZ_PER_KHZ * qos_min_freq);
+       if (qos_max_freq != PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE)
+               *max_freq = min(*max_freq,
+                               (unsigned long)HZ_PER_KHZ * qos_max_freq);
+
+       /* Apply constraints from OPP interface */
+       *min_freq = max(*min_freq, devfreq->scaling_min_freq);
+       *max_freq = min(*max_freq, devfreq->scaling_max_freq);
+
+       if (*min_freq > *max_freq)
+               *min_freq = *max_freq;
+}
+
+/**
  * devfreq_get_freq_level() - Lookup freq_table for the frequency
  * @devfreq:   the devfreq instance
  * @freq:      the target frequency
@@ -351,16 +402,7 @@ int update_devfreq(struct devfreq *devfreq)
        err = devfreq->governor->get_target_freq(devfreq, &freq);
        if (err)
                return err;
-
-       /*
-        * Adjust the frequency with user freq, QoS and available freq.
-        *
-        * List from the highest priority
-        * max_freq
-        * min_freq
-        */
-       max_freq = min(devfreq->scaling_max_freq, devfreq->max_freq);
-       min_freq = max(devfreq->scaling_min_freq, devfreq->min_freq);
+       get_freq_range(devfreq, &min_freq, &max_freq);
 
        if (freq < min_freq) {
                freq = min_freq;
@@ -568,26 +610,69 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
                                 void *devp)
 {
        struct devfreq *devfreq = container_of(nb, struct devfreq, nb);
-       int ret;
+       int err = -EINVAL;
 
        mutex_lock(&devfreq->lock);
 
        devfreq->scaling_min_freq = find_available_min_freq(devfreq);
-       if (!devfreq->scaling_min_freq) {
-               mutex_unlock(&devfreq->lock);
-               return -EINVAL;
-       }
+       if (!devfreq->scaling_min_freq)
+               goto out;
 
        devfreq->scaling_max_freq = find_available_max_freq(devfreq);
        if (!devfreq->scaling_max_freq) {
-               mutex_unlock(&devfreq->lock);
-               return -EINVAL;
+               devfreq->scaling_max_freq = ULONG_MAX;
+               goto out;
        }
 
-       ret = update_devfreq(devfreq);
+       err = update_devfreq(devfreq);
+
+out:
        mutex_unlock(&devfreq->lock);
+       if (err)
+               dev_err(devfreq->dev.parent,
+                       "failed to update frequency from OPP notifier (%d)\n",
+                       err);
 
-       return ret;
+       return NOTIFY_OK;
+}
+
+/**
+ * qos_notifier_call() - Common handler for QoS constraints.
+ * @devfreq:    the devfreq instance.
+ */
+static int qos_notifier_call(struct devfreq *devfreq)
+{
+       int err;
+
+       mutex_lock(&devfreq->lock);
+       err = update_devfreq(devfreq);
+       mutex_unlock(&devfreq->lock);
+       if (err)
+               dev_err(devfreq->dev.parent,
+                       "failed to update frequency from PM QoS (%d)\n",
+                       err);
+
+       return NOTIFY_OK;
+}
+
+/**
+ * qos_min_notifier_call() - Callback for QoS min_freq changes.
+ * @nb:                Should be devfreq->nb_min
+ */
+static int qos_min_notifier_call(struct notifier_block *nb,
+                                        unsigned long val, void *ptr)
+{
+       return qos_notifier_call(container_of(nb, struct devfreq, nb_min));
+}
+
+/**
+ * qos_max_notifier_call() - Callback for QoS max_freq changes.
+ * @nb:                Should be devfreq->nb_max
+ */
+static int qos_max_notifier_call(struct notifier_block *nb,
+                                        unsigned long val, void *ptr)
+{
+       return qos_notifier_call(container_of(nb, struct devfreq, nb_max));
 }
 
 /**
@@ -599,16 +684,36 @@ static int devfreq_notifier_call(struct notifier_block *nb, unsigned long type,
 static void devfreq_dev_release(struct device *dev)
 {
        struct devfreq *devfreq = to_devfreq(dev);
+       int err;
 
        mutex_lock(&devfreq_list_lock);
-       if (IS_ERR(find_device_devfreq(devfreq->dev.parent))) {
-               mutex_unlock(&devfreq_list_lock);
-               dev_warn(&devfreq->dev, "releasing devfreq which doesn't exist\n");
-               return;
-       }
        list_del(&devfreq->node);
        mutex_unlock(&devfreq_list_lock);
 
+       err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_max,
+                                        DEV_PM_QOS_MAX_FREQUENCY);
+       if (err && err != -ENOENT)
+               dev_warn(dev->parent,
+                       "Failed to remove max_freq notifier: %d\n", err);
+       err = dev_pm_qos_remove_notifier(devfreq->dev.parent, &devfreq->nb_min,
+                                        DEV_PM_QOS_MIN_FREQUENCY);
+       if (err && err != -ENOENT)
+               dev_warn(dev->parent,
+                       "Failed to remove min_freq notifier: %d\n", err);
+
+       if (dev_pm_qos_request_active(&devfreq->user_max_freq_req)) {
+               err = dev_pm_qos_remove_request(&devfreq->user_max_freq_req);
+               if (err)
+                       dev_warn(dev->parent,
+                               "Failed to remove max_freq request: %d\n", err);
+       }
+       if (dev_pm_qos_request_active(&devfreq->user_min_freq_req)) {
+               err = dev_pm_qos_remove_request(&devfreq->user_min_freq_req);
+               if (err)
+                       dev_warn(dev->parent,
+                               "Failed to remove min_freq request: %d\n", err);
+       }
+
        if (devfreq->profile->exit)
                devfreq->profile->exit(devfreq->dev.parent);
 
@@ -660,6 +765,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
        devfreq->dev.parent = dev;
        devfreq->dev.class = devfreq_class;
        devfreq->dev.release = devfreq_dev_release;
+       INIT_LIST_HEAD(&devfreq->node);
        devfreq->profile = profile;
        strncpy(devfreq->governor_name, governor_name, DEVFREQ_NAME_LEN);
        devfreq->previous_freq = profile->initial_freq;
@@ -681,7 +787,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
                err = -EINVAL;
                goto err_dev;
        }
-       devfreq->min_freq = devfreq->scaling_min_freq;
 
        devfreq->scaling_max_freq = find_available_max_freq(devfreq);
        if (!devfreq->scaling_max_freq) {
@@ -689,7 +794,6 @@ struct devfreq *devfreq_add_device(struct device *dev,
                err = -EINVAL;
                goto err_dev;
        }
-       devfreq->max_freq = devfreq->scaling_max_freq;
 
        devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
        atomic_set(&devfreq->suspend_count, 0);
@@ -730,6 +834,28 @@ struct devfreq *devfreq_add_device(struct device *dev,
 
        mutex_unlock(&devfreq->lock);
 
+       err = dev_pm_qos_add_request(dev, &devfreq->user_min_freq_req,
+                                    DEV_PM_QOS_MIN_FREQUENCY, 0);
+       if (err < 0)
+               goto err_devfreq;
+       err = dev_pm_qos_add_request(dev, &devfreq->user_max_freq_req,
+                                    DEV_PM_QOS_MAX_FREQUENCY,
+                                    PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
+       if (err < 0)
+               goto err_devfreq;
+
+       devfreq->nb_min.notifier_call = qos_min_notifier_call;
+       err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_min,
+                                     DEV_PM_QOS_MIN_FREQUENCY);
+       if (err)
+               goto err_devfreq;
+
+       devfreq->nb_max.notifier_call = qos_max_notifier_call;
+       err = dev_pm_qos_add_notifier(devfreq->dev.parent, &devfreq->nb_max,
+                                     DEV_PM_QOS_MAX_FREQUENCY);
+       if (err)
+               goto err_devfreq;
+
        mutex_lock(&devfreq_list_lock);
 
        governor = try_then_request_governor(devfreq->governor_name);
@@ -1303,41 +1429,37 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
        unsigned long value;
        int ret;
 
+       /*
+        * Protect against theoretical sysfs writes between
+        * device_add and dev_pm_qos_add_request
+        */
+       if (!dev_pm_qos_request_active(&df->user_min_freq_req))
+               return -EAGAIN;
+
        ret = sscanf(buf, "%lu", &value);
        if (ret != 1)
                return -EINVAL;
 
-       mutex_lock(&df->lock);
-
-       if (value) {
-               if (value > df->max_freq) {
-                       ret = -EINVAL;
-                       goto unlock;
-               }
-       } else {
-               unsigned long *freq_table = df->profile->freq_table;
-
-               /* Get minimum frequency according to sorting order */
-               if (freq_table[0] < freq_table[df->profile->max_state - 1])
-                       value = freq_table[0];
-               else
-                       value = freq_table[df->profile->max_state - 1];
-       }
+       /* Round down to kHz for PM QoS */
+       ret = dev_pm_qos_update_request(&df->user_min_freq_req,
+                                       value / HZ_PER_KHZ);
+       if (ret < 0)
+               return ret;
 
-       df->min_freq = value;
-       update_devfreq(df);
-       ret = count;
-unlock:
-       mutex_unlock(&df->lock);
-       return ret;
+       return count;
 }
 
 static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        struct devfreq *df = to_devfreq(dev);
+       unsigned long min_freq, max_freq;
 
-       return sprintf(buf, "%lu\n", max(df->scaling_min_freq, df->min_freq));
+       mutex_lock(&df->lock);
+       get_freq_range(df, &min_freq, &max_freq);
+       mutex_unlock(&df->lock);
+
+       return sprintf(buf, "%lu\n", min_freq);
 }
 
 static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
@@ -1347,33 +1469,37 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
        unsigned long value;
        int ret;
 
+       /*
+        * Protect against theoretical sysfs writes between
+        * device_add and dev_pm_qos_add_request
+        */
+       if (!dev_pm_qos_request_active(&df->user_max_freq_req))
+               return -EINVAL;
+
        ret = sscanf(buf, "%lu", &value);
        if (ret != 1)
                return -EINVAL;
 
-       mutex_lock(&df->lock);
-
-       if (value) {
-               if (value < df->min_freq) {
-                       ret = -EINVAL;
-                       goto unlock;
-               }
-       } else {
-               unsigned long *freq_table = df->profile->freq_table;
+       /*
+        * PM QoS frequencies are in kHz so we need to convert. Convert by
+        * rounding upwards so that the acceptable interval never shrinks.
+        *
+        * For example if the user writes "666666666" to sysfs this value will
+        * be converted to 666667 kHz and back to 666667000 Hz before an OPP
+        * lookup, this ensures that an OPP of 666666666Hz is still accepted.
+        *
+        * A value of zero means "no limit".
+        */
+       if (value)
+               value = DIV_ROUND_UP(value, HZ_PER_KHZ);
+       else
+               value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
 
-               /* Get maximum frequency according to sorting order */
-               if (freq_table[0] < freq_table[df->profile->max_state - 1])
-                       value = freq_table[df->profile->max_state - 1];
-               else
-                       value = freq_table[0];
-       }
+       ret = dev_pm_qos_update_request(&df->user_max_freq_req, value);
+       if (ret < 0)
+               return ret;
 
-       df->max_freq = value;
-       update_devfreq(df);
-       ret = count;
-unlock:
-       mutex_unlock(&df->lock);
-       return ret;
+       return count;
 }
 static DEVICE_ATTR_RW(min_freq);
 
@@ -1381,8 +1507,13 @@ static ssize_t max_freq_show(struct device *dev, struct device_attribute *attr,
                             char *buf)
 {
        struct devfreq *df = to_devfreq(dev);
+       unsigned long min_freq, max_freq;
+
+       mutex_lock(&df->lock);
+       get_freq_range(df, &min_freq, &max_freq);
+       mutex_unlock(&df->lock);
 
-       return sprintf(buf, "%lu\n", min(df->scaling_max_freq, df->max_freq));
+       return sprintf(buf, "%lu\n", max_freq);
 }
 static DEVICE_ATTR_RW(max_freq);
 
index 76fb072..5a5a1da 100644 (file)
@@ -221,7 +221,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
        a_fences = get_fences(a, &a_num_fences);
        b_fences = get_fences(b, &b_num_fences);
        if (a_num_fences > INT_MAX - b_num_fences)
-               return NULL;
+               goto err;
 
        num_fences = a_num_fences + b_num_fences;
 
index fa626ac..44af435 100644 (file)
@@ -999,7 +999,8 @@ static const struct jz4780_dma_soc_data jz4740_dma_soc_data = {
 static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
        .nb_channels = 6,
        .transfer_ord_max = 5,
-       .flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC,
+       .flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC |
+                JZ_SOC_DATA_BREAK_LINKS,
 };
 
 static const struct jz4780_dma_soc_data jz4770_dma_soc_data = {
index 1a422a8..18c011e 100644 (file)
@@ -377,10 +377,11 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags)
 
                descs->virt = dma_alloc_coherent(to_dev(ioat_chan),
                                                 SZ_2M, &descs->hw, flags);
-               if (!descs->virt && (i > 0)) {
+               if (!descs->virt) {
                        int idx;
 
                        for (idx = 0; idx < i; idx++) {
+                               descs = &ioat_chan->descs[idx];
                                dma_free_coherent(to_dev(ioat_chan), SZ_2M,
                                                  descs->virt, descs->hw);
                                descs->virt = NULL;
index adecea5..c5c1aa0 100644 (file)
@@ -229,9 +229,11 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
                        c = p->vchan;
                        if (c && (tc1 & BIT(i))) {
                                spin_lock_irqsave(&c->vc.lock, flags);
-                               vchan_cookie_complete(&p->ds_run->vd);
-                               p->ds_done = p->ds_run;
-                               p->ds_run = NULL;
+                               if (p->ds_run != NULL) {
+                                       vchan_cookie_complete(&p->ds_run->vd);
+                                       p->ds_done = p->ds_run;
+                                       p->ds_run = NULL;
+                               }
                                spin_unlock_irqrestore(&c->vc.lock, flags);
                        }
                        if (c && (tc2 & BIT(i))) {
@@ -271,6 +273,10 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
        if (BIT(c->phy->idx) & k3_dma_get_chan_stat(d))
                return -EAGAIN;
 
+       /* Avoid losing track of  ds_run if a transaction is in flight */
+       if (c->phy->ds_run)
+               return -EAGAIN;
+
        if (vd) {
                struct k3_dma_desc_sw *ds =
                        container_of(vd, struct k3_dma_desc_sw, vd);
index ec4adf4..256fc66 100644 (file)
@@ -104,9 +104,8 @@ static void vchan_complete(unsigned long arg)
                dmaengine_desc_get_callback(&vd->tx, &cb);
 
                list_del(&vd->node);
-               vchan_vdesc_fini(vd);
-
                dmaengine_desc_callback_invoke(&cb, &vd->tx_result);
+               vchan_vdesc_fini(vd);
        }
 }
 
index 417dad6..5c82723 100644 (file)
@@ -462,7 +462,7 @@ config EDAC_ALTERA_SDMMC
 
 config EDAC_SIFIVE
        bool "Sifive platform EDAC driver"
-       depends on EDAC=y && RISCV
+       depends on EDAC=y && SIFIVE_L2
        help
          Support for error detection and correction on the SiFive SoCs.
 
index 413cdb4..c0cc72a 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/edac.h>
 #include <linux/platform_device.h>
 #include "edac_module.h"
-#include <asm/sifive_l2_cache.h>
+#include <soc/sifive/sifive_l2_cache.h>
 
 #define DRVNAME "sifive_edac"
 
index 5b7ef89..ed10da5 100644 (file)
@@ -215,7 +215,6 @@ static int tee_bnxt_fw_probe(struct device *dev)
        fw_shm_pool = tee_shm_alloc(pvt_data.ctx, MAX_SHM_MEM_SZ,
                                    TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
        if (IS_ERR(fw_shm_pool)) {
-               tee_client_close_context(pvt_data.ctx);
                dev_err(pvt_data.dev, "tee_shm_alloc failed\n");
                err = PTR_ERR(fw_shm_pool);
                goto out_sess;
index c9a0efc..5d4f847 100644 (file)
 
 #include <asm/early_ioremap.h>
 
+static const struct console *earlycon_console __initdata;
 static const struct font_desc *font;
 static u32 efi_x, efi_y;
 static u64 fb_base;
-static pgprot_t fb_prot;
+static bool fb_wb;
+static void *efi_fb;
+
+/*
+ * EFI earlycon needs to use early_memremap() to map the framebuffer.
+ * But early_memremap() is not usable for 'earlycon=efifb keep_bootcon',
+ * memremap() should be used instead. memremap() will be available after
+ * paging_init() which is earlier than initcall callbacks. Thus adding this
+ * early initcall function early_efi_map_fb() to map the whole EFI framebuffer.
+ */
+static int __init efi_earlycon_remap_fb(void)
+{
+       /* bail if there is no bootconsole or it has been disabled already */
+       if (!earlycon_console || !(earlycon_console->flags & CON_ENABLED))
+               return 0;
+
+       efi_fb = memremap(fb_base, screen_info.lfb_size,
+                         fb_wb ? MEMREMAP_WB : MEMREMAP_WC);
+
+       return efi_fb ? 0 : -ENOMEM;
+}
+early_initcall(efi_earlycon_remap_fb);
+
+static int __init efi_earlycon_unmap_fb(void)
+{
+       /* unmap the bootconsole fb unless keep_bootcon has left it enabled */
+       if (efi_fb && !(earlycon_console->flags & CON_ENABLED))
+               memunmap(efi_fb);
+       return 0;
+}
+late_initcall(efi_earlycon_unmap_fb);
 
 static __ref void *efi_earlycon_map(unsigned long start, unsigned long len)
 {
+       pgprot_t fb_prot;
+
+       if (efi_fb)
+               return efi_fb + start;
+
+       fb_prot = fb_wb ? PAGE_KERNEL : pgprot_writecombine(PAGE_KERNEL);
        return early_memremap_prot(fb_base + start, len, pgprot_val(fb_prot));
 }
 
 static __ref void efi_earlycon_unmap(void *addr, unsigned long len)
 {
+       if (efi_fb)
+               return;
+
        early_memunmap(addr, len);
 }
 
@@ -176,10 +216,7 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
        if (screen_info.capabilities & VIDEO_CAPABILITY_64BIT_BASE)
                fb_base |= (u64)screen_info.ext_lfb_base << 32;
 
-       if (opt && !strcmp(opt, "ram"))
-               fb_prot = PAGE_KERNEL;
-       else
-               fb_prot = pgprot_writecombine(PAGE_KERNEL);
+       fb_wb = opt && !strcmp(opt, "ram");
 
        si = &screen_info;
        xres = si->lfb_width;
@@ -201,6 +238,7 @@ static int __init efi_earlycon_setup(struct earlycon_device *device,
                efi_earlycon_scroll_up();
 
        device->con->write = efi_earlycon_write;
+       earlycon_console = device->con;
        return 0;
 }
 EARLYCON_DECLARE(efifb, efi_earlycon_setup);
index d101f07..2b02cb1 100644 (file)
@@ -681,7 +681,7 @@ device_initcall(efi_load_efivars);
                { name },                                  \
                { prop },                                  \
                offsetof(struct efi_fdt_params, field),    \
-               FIELD_SIZEOF(struct efi_fdt_params, field) \
+               sizeof_field(struct efi_fdt_params, field) \
        }
 
 struct params {
@@ -979,6 +979,24 @@ static int __init efi_memreserve_map_root(void)
        return 0;
 }
 
+static int efi_mem_reserve_iomem(phys_addr_t addr, u64 size)
+{
+       struct resource *res, *parent;
+
+       res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
+       if (!res)
+               return -ENOMEM;
+
+       res->name       = "reserved";
+       res->flags      = IORESOURCE_MEM;
+       res->start      = addr;
+       res->end        = addr + size - 1;
+
+       /* we expect a conflict with a 'System RAM' region */
+       parent = request_resource_conflict(&iomem_resource, res);
+       return parent ? request_resource(parent, res) : 0;
+}
+
 int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
 {
        struct linux_efi_memreserve *rsv;
@@ -1003,7 +1021,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
                        rsv->entry[index].size = size;
 
                        memunmap(rsv);
-                       return 0;
+                       return efi_mem_reserve_iomem(addr, size);
                }
                memunmap(rsv);
        }
@@ -1013,6 +1031,12 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
        if (!rsv)
                return -ENOMEM;
 
+       rc = efi_mem_reserve_iomem(__pa(rsv), SZ_4K);
+       if (rc) {
+               free_page((unsigned long)rsv);
+               return rc;
+       }
+
        /*
         * The memremap() call above assumes that a linux_efi_memreserve entry
         * never crosses a page boundary, so let's ensure that this remains true
@@ -1029,7 +1053,7 @@ int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size)
        efi_memreserve_root->next = __pa(rsv);
        spin_unlock(&efi_mem_reserve_persistent_lock);
 
-       return 0;
+       return efi_mem_reserve_iomem(addr, size);
 }
 
 static int __init efi_memreserve_root_init(void)
index 0101ca4..b7bf1e9 100644 (file)
@@ -84,30 +84,6 @@ setup_pixel_info(struct screen_info *si, u32 pixels_per_scan_line,
 }
 
 static efi_status_t
-__gop_query32(efi_system_table_t *sys_table_arg,
-             struct efi_graphics_output_protocol_32 *gop32,
-             struct efi_graphics_output_mode_info **info,
-             unsigned long *size, u64 *fb_base)
-{
-       struct efi_graphics_output_protocol_mode_32 *mode;
-       efi_graphics_output_protocol_query_mode query_mode;
-       efi_status_t status;
-       unsigned long m;
-
-       m = gop32->mode;
-       mode = (struct efi_graphics_output_protocol_mode_32 *)m;
-       query_mode = (void *)(unsigned long)gop32->query_mode;
-
-       status = __efi_call_early(query_mode, (void *)gop32, mode->mode, size,
-                                 info);
-       if (status != EFI_SUCCESS)
-               return status;
-
-       *fb_base = mode->frame_buffer_base;
-       return status;
-}
-
-static efi_status_t
 setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
             efi_guid_t *proto, unsigned long size, void **gop_handle)
 {
@@ -119,7 +95,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
        u64 fb_base;
        struct efi_pixel_bitmask pixel_info;
        int pixel_format;
-       efi_status_t status = EFI_NOT_FOUND;
+       efi_status_t status;
        u32 *handles = (u32 *)(unsigned long)gop_handle;
        int i;
 
@@ -128,6 +104,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
        nr_gops = size / sizeof(u32);
        for (i = 0; i < nr_gops; i++) {
+               struct efi_graphics_output_protocol_mode_32 *mode;
                struct efi_graphics_output_mode_info *info = NULL;
                efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
                bool conout_found = false;
@@ -145,9 +122,11 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
                if (status == EFI_SUCCESS)
                        conout_found = true;
 
-               status = __gop_query32(sys_table_arg, gop32, &info, &size,
-                                      &current_fb_base);
-               if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+               mode = (void *)(unsigned long)gop32->mode;
+               info = (void *)(unsigned long)mode->info;
+               current_fb_base = mode->frame_buffer_base;
+
+               if ((!first_gop || conout_found) &&
                    info->pixel_format != PIXEL_BLT_ONLY) {
                        /*
                         * Systems that use the UEFI Console Splitter may
@@ -175,7 +154,7 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
        /* Did we find any GOPs? */
        if (!first_gop)
-               goto out;
+               return EFI_NOT_FOUND;
 
        /* EFI framebuffer */
        si->orig_video_isVGA = VIDEO_TYPE_EFI;
@@ -197,32 +176,8 @@ setup_gop32(efi_system_table_t *sys_table_arg, struct screen_info *si,
        si->lfb_size = si->lfb_linelength * si->lfb_height;
 
        si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
-out:
-       return status;
-}
-
-static efi_status_t
-__gop_query64(efi_system_table_t *sys_table_arg,
-             struct efi_graphics_output_protocol_64 *gop64,
-             struct efi_graphics_output_mode_info **info,
-             unsigned long *size, u64 *fb_base)
-{
-       struct efi_graphics_output_protocol_mode_64 *mode;
-       efi_graphics_output_protocol_query_mode query_mode;
-       efi_status_t status;
-       unsigned long m;
-
-       m = gop64->mode;
-       mode = (struct efi_graphics_output_protocol_mode_64 *)m;
-       query_mode = (void *)(unsigned long)gop64->query_mode;
-
-       status = __efi_call_early(query_mode, (void *)gop64, mode->mode, size,
-                                 info);
-       if (status != EFI_SUCCESS)
-               return status;
 
-       *fb_base = mode->frame_buffer_base;
-       return status;
+       return EFI_SUCCESS;
 }
 
 static efi_status_t
@@ -237,7 +192,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
        u64 fb_base;
        struct efi_pixel_bitmask pixel_info;
        int pixel_format;
-       efi_status_t status = EFI_NOT_FOUND;
+       efi_status_t status;
        u64 *handles = (u64 *)(unsigned long)gop_handle;
        int i;
 
@@ -246,6 +201,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
        nr_gops = size / sizeof(u64);
        for (i = 0; i < nr_gops; i++) {
+               struct efi_graphics_output_protocol_mode_64 *mode;
                struct efi_graphics_output_mode_info *info = NULL;
                efi_guid_t conout_proto = EFI_CONSOLE_OUT_DEVICE_GUID;
                bool conout_found = false;
@@ -263,9 +219,11 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
                if (status == EFI_SUCCESS)
                        conout_found = true;
 
-               status = __gop_query64(sys_table_arg, gop64, &info, &size,
-                                      &current_fb_base);
-               if (status == EFI_SUCCESS && (!first_gop || conout_found) &&
+               mode = (void *)(unsigned long)gop64->mode;
+               info = (void *)(unsigned long)mode->info;
+               current_fb_base = mode->frame_buffer_base;
+
+               if ((!first_gop || conout_found) &&
                    info->pixel_format != PIXEL_BLT_ONLY) {
                        /*
                         * Systems that use the UEFI Console Splitter may
@@ -293,7 +251,7 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
 
        /* Did we find any GOPs? */
        if (!first_gop)
-               goto out;
+               return EFI_NOT_FOUND;
 
        /* EFI framebuffer */
        si->orig_video_isVGA = VIDEO_TYPE_EFI;
@@ -315,8 +273,8 @@ setup_gop64(efi_system_table_t *sys_table_arg, struct screen_info *si,
        si->lfb_size = si->lfb_linelength * si->lfb_height;
 
        si->capabilities |= VIDEO_CAPABILITY_SKIP_QUIRKS;
-out:
-       return status;
+
+       return EFI_SUCCESS;
 }
 
 /*
index 35edd7c..97378cf 100644 (file)
@@ -33,7 +33,7 @@ efi_status_t efi_get_random_bytes(efi_system_table_t *sys_table_arg,
 {
        efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
        efi_status_t status;
-       struct efi_rng_protocol *rng;
+       struct efi_rng_protocol *rng = NULL;
 
        status = efi_call_early(locate_protocol, &rng_proto, NULL,
                                (void **)&rng);
@@ -162,8 +162,8 @@ efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
        efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
        efi_guid_t rng_algo_raw = EFI_RNG_ALGORITHM_RAW;
        efi_guid_t rng_table_guid = LINUX_EFI_RANDOM_SEED_TABLE_GUID;
-       struct efi_rng_protocol *rng;
-       struct linux_efi_random_seed *seed;
+       struct efi_rng_protocol *rng = NULL;
+       struct linux_efi_random_seed *seed = NULL;
        efi_status_t status;
 
        status = efi_call_early(locate_protocol, &rng_proto, NULL,
index 76b0c35..de1a9a1 100644 (file)
@@ -81,6 +81,9 @@ static int __init efi_rci2_sysfs_init(void)
        struct kobject *tables_kobj;
        int ret = -ENOMEM;
 
+       if (rci2_table_phys == EFI_INVALID_TABLE_ADDR)
+               return 0;
+
        rci2_base = memremap(rci2_table_phys,
                             sizeof(struct rci2_table_global_hdr),
                             MEMREMAP_WB);
index 8adffd4..4b6d2ef 100644 (file)
@@ -553,8 +553,8 @@ config GPIO_TEGRA
 
 config GPIO_TEGRA186
        tristate "NVIDIA Tegra186 GPIO support"
-       default ARCH_TEGRA_186_SOC
-       depends on ARCH_TEGRA_186_SOC || COMPILE_TEST
+       default ARCH_TEGRA_186_SOC || ARCH_TEGRA_194_SOC
+       depends on ARCH_TEGRA_186_SOC || ARCH_TEGRA_194_SOC || COMPILE_TEST
        depends on OF_GPIO
        select GPIOLIB_IRQCHIP
        select IRQ_DOMAIN_HIERARCHY
@@ -573,7 +573,6 @@ config GPIO_THUNDERX
        tristate "Cavium ThunderX/OCTEON-TX GPIO"
        depends on ARCH_THUNDER || (64BIT && COMPILE_TEST)
        depends on PCI_MSI
-       select GPIOLIB_IRQCHIP
        select IRQ_DOMAIN_HIERARCHY
        select IRQ_FASTEOI_HIERARCHY_HANDLERS
        help
@@ -1148,6 +1147,7 @@ config GPIO_MADERA
 config GPIO_MAX77620
        tristate "GPIO support for PMIC MAX77620 and MAX20024"
        depends on MFD_MAX77620
+       select GPIOLIB_IRQCHIP
        help
          GPIO driver for MAX77620 and MAX20024 PMIC from Maxim Semiconductor.
          MAX77620 PMIC has 8 pins that can be configured as GPIOs. The
index 7e99860..8319812 100644 (file)
@@ -107,7 +107,7 @@ static void __iomem *bank_reg(struct aspeed_sgpio *gpio,
                return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
        default:
                /* acturally if code runs to here, it's an error case */
-               BUG_ON(1);
+               BUG();
        }
 }
 
index 56d647a..94b8d3a 100644 (file)
@@ -156,7 +156,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
        mutex_lock(&chip->lock);
 
        if (test_bit(FLAG_REQUESTED, &desc->flags) &&
-               !test_bit(FLAG_IS_OUT, &desc->flags)) {
+           !test_bit(FLAG_IS_OUT, &desc->flags)) {
                curr = __gpio_mockup_get(chip, offset);
                if (curr == value)
                        goto out;
@@ -165,7 +165,7 @@ static int gpio_mockup_apply_pull(struct gpio_mockup_chip *chip,
                irq_type = irq_get_trigger_type(irq);
 
                if ((value == 1 && (irq_type & IRQ_TYPE_EDGE_RISING)) ||
-                       (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
+                   (value == 0 && (irq_type & IRQ_TYPE_EDGE_FALLING)))
                        irq_sim_fire(sim, offset);
        }
 
@@ -226,7 +226,7 @@ static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)
        int direction;
 
        mutex_lock(&chip->lock);
-       direction = !chip->lines[offset].dir;
+       direction = chip->lines[offset].dir;
        mutex_unlock(&chip->lock);
 
        return direction;
@@ -395,7 +395,7 @@ static int gpio_mockup_probe(struct platform_device *pdev)
        struct gpio_chip *gc;
        struct device *dev;
        const char *name;
-       int rv, base;
+       int rv, base, i;
        u16 ngpio;
 
        dev = &pdev->dev;
@@ -447,6 +447,9 @@ static int gpio_mockup_probe(struct platform_device *pdev)
        if (!chip->lines)
                return -ENOMEM;
 
+       for (i = 0; i < gc->ngpio; i++)
+               chip->lines[i].dir = GPIO_LINE_DIRECTION_IN;
+
        if (device_property_read_bool(dev, "named-gpio-lines")) {
                rv = gpio_mockup_name_lines(dev, chip);
                if (rv)
index f1e164c..5ae30de 100644 (file)
@@ -346,6 +346,7 @@ static int mpc8xxx_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        gc = &mpc8xxx_gc->gc;
+       gc->parent = &pdev->dev;
 
        if (of_property_read_bool(np, "little-endian")) {
                ret = bgpio_init(gc, &pdev->dev, 4,
index 6652bee..9853547 100644 (file)
@@ -568,16 +568,18 @@ static void pca953x_irq_mask(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct pca953x_chip *chip = gpiochip_get_data(gc);
+       irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       chip->irq_mask[d->hwirq / BANK_SZ] &= ~BIT(d->hwirq % BANK_SZ);
+       clear_bit(hwirq, chip->irq_mask);
 }
 
 static void pca953x_irq_unmask(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct pca953x_chip *chip = gpiochip_get_data(gc);
+       irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       chip->irq_mask[d->hwirq / BANK_SZ] |= BIT(d->hwirq % BANK_SZ);
+       set_bit(hwirq, chip->irq_mask);
 }
 
 static int pca953x_irq_set_wake(struct irq_data *d, unsigned int on)
@@ -635,8 +637,7 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct pca953x_chip *chip = gpiochip_get_data(gc);
-       int bank_nb = d->hwirq / BANK_SZ;
-       u8 mask = BIT(d->hwirq % BANK_SZ);
+       irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
        if (!(type & IRQ_TYPE_EDGE_BOTH)) {
                dev_err(&chip->client->dev, "irq %d: unsupported type %d\n",
@@ -644,15 +645,8 @@ static int pca953x_irq_set_type(struct irq_data *d, unsigned int type)
                return -EINVAL;
        }
 
-       if (type & IRQ_TYPE_EDGE_FALLING)
-               chip->irq_trig_fall[bank_nb] |= mask;
-       else
-               chip->irq_trig_fall[bank_nb] &= ~mask;
-
-       if (type & IRQ_TYPE_EDGE_RISING)
-               chip->irq_trig_raise[bank_nb] |= mask;
-       else
-               chip->irq_trig_raise[bank_nb] &= ~mask;
+       assign_bit(hwirq, chip->irq_trig_fall, type & IRQ_TYPE_EDGE_FALLING);
+       assign_bit(hwirq, chip->irq_trig_raise, type & IRQ_TYPE_EDGE_RISING);
 
        return 0;
 }
@@ -661,10 +655,10 @@ static void pca953x_irq_shutdown(struct irq_data *d)
 {
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct pca953x_chip *chip = gpiochip_get_data(gc);
-       u8 mask = BIT(d->hwirq % BANK_SZ);
+       irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       chip->irq_trig_raise[d->hwirq / BANK_SZ] &= ~mask;
-       chip->irq_trig_fall[d->hwirq / BANK_SZ] &= ~mask;
+       clear_bit(hwirq, chip->irq_trig_raise);
+       clear_bit(hwirq, chip->irq_trig_fall);
 }
 
 static bool pca953x_irq_pending(struct pca953x_chip *chip, unsigned long *pending)
index d08d86a..4627704 100644 (file)
@@ -53,6 +53,7 @@ struct thunderx_line {
 struct thunderx_gpio {
        struct gpio_chip        chip;
        u8 __iomem              *register_base;
+       struct irq_domain       *irqd;
        struct msix_entry       *msix_entries;  /* per line MSI-X */
        struct thunderx_line    *line_entries;  /* per line irq info */
        raw_spinlock_t          lock;
@@ -285,60 +286,54 @@ static void thunderx_gpio_set_multiple(struct gpio_chip *chip,
        }
 }
 
-static void thunderx_gpio_irq_ack(struct irq_data *d)
+static void thunderx_gpio_irq_ack(struct irq_data *data)
 {
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+       struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
 
        writeq(GPIO_INTR_INTR,
-              txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
+              txline->txgpio->register_base + intr_reg(txline->line));
 }
 
-static void thunderx_gpio_irq_mask(struct irq_data *d)
+static void thunderx_gpio_irq_mask(struct irq_data *data)
 {
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+       struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
 
        writeq(GPIO_INTR_ENA_W1C,
-              txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
+              txline->txgpio->register_base + intr_reg(txline->line));
 }
 
-static void thunderx_gpio_irq_mask_ack(struct irq_data *d)
+static void thunderx_gpio_irq_mask_ack(struct irq_data *data)
 {
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+       struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
 
        writeq(GPIO_INTR_ENA_W1C | GPIO_INTR_INTR,
-              txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
+              txline->txgpio->register_base + intr_reg(txline->line));
 }
 
-static void thunderx_gpio_irq_unmask(struct irq_data *d)
+static void thunderx_gpio_irq_unmask(struct irq_data *data)
 {
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
+       struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
 
        writeq(GPIO_INTR_ENA_W1S,
-              txgpio->register_base + intr_reg(irqd_to_hwirq(d)));
+              txline->txgpio->register_base + intr_reg(txline->line));
 }
 
-static int thunderx_gpio_irq_set_type(struct irq_data *d,
+static int thunderx_gpio_irq_set_type(struct irq_data *data,
                                      unsigned int flow_type)
 {
-       struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
-       struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
-       struct thunderx_line *txline =
-               &txgpio->line_entries[irqd_to_hwirq(d)];
+       struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+       struct thunderx_gpio *txgpio = txline->txgpio;
        u64 bit_cfg;
 
-       irqd_set_trigger_type(d, flow_type);
+       irqd_set_trigger_type(data, flow_type);
 
        bit_cfg = txline->fil_bits | GPIO_BIT_CFG_INT_EN;
 
        if (flow_type & IRQ_TYPE_EDGE_BOTH) {
-               irq_set_handler_locked(d, handle_fasteoi_ack_irq);
+               irq_set_handler_locked(data, handle_fasteoi_ack_irq);
                bit_cfg |= GPIO_BIT_CFG_INT_TYPE;
        } else {
-               irq_set_handler_locked(d, handle_fasteoi_mask_irq);
+               irq_set_handler_locked(data, handle_fasteoi_mask_irq);
        }
 
        raw_spin_lock(&txgpio->lock);
@@ -367,6 +362,33 @@ static void thunderx_gpio_irq_disable(struct irq_data *data)
        irq_chip_disable_parent(data);
 }
 
+static int thunderx_gpio_irq_request_resources(struct irq_data *data)
+{
+       struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+       struct thunderx_gpio *txgpio = txline->txgpio;
+       int r;
+
+       r = gpiochip_lock_as_irq(&txgpio->chip, txline->line);
+       if (r)
+               return r;
+
+       r = irq_chip_request_resources_parent(data);
+       if (r)
+               gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
+
+       return r;
+}
+
+static void thunderx_gpio_irq_release_resources(struct irq_data *data)
+{
+       struct thunderx_line *txline = irq_data_get_irq_chip_data(data);
+       struct thunderx_gpio *txgpio = txline->txgpio;
+
+       irq_chip_release_resources_parent(data);
+
+       gpiochip_unlock_as_irq(&txgpio->chip, txline->line);
+}
+
 /*
  * Interrupts are chained from underlying MSI-X vectors.  We have
  * these irq_chip functions to be able to handle level triggering
@@ -383,24 +405,50 @@ static struct irq_chip thunderx_gpio_irq_chip = {
        .irq_unmask             = thunderx_gpio_irq_unmask,
        .irq_eoi                = irq_chip_eoi_parent,
        .irq_set_affinity       = irq_chip_set_affinity_parent,
+       .irq_request_resources  = thunderx_gpio_irq_request_resources,
+       .irq_release_resources  = thunderx_gpio_irq_release_resources,
        .irq_set_type           = thunderx_gpio_irq_set_type,
 
        .flags                  = IRQCHIP_SET_TYPE_MASKED
 };
 
-static int thunderx_gpio_child_to_parent_hwirq(struct gpio_chip *gc,
-                                              unsigned int child,
-                                              unsigned int child_type,
-                                              unsigned int *parent,
-                                              unsigned int *parent_type)
+static int thunderx_gpio_irq_translate(struct irq_domain *d,
+                                      struct irq_fwspec *fwspec,
+                                      irq_hw_number_t *hwirq,
+                                      unsigned int *type)
 {
-       struct thunderx_gpio *txgpio = gpiochip_get_data(gc);
-
-       *parent = txgpio->base_msi + (2 * child);
-       *parent_type = IRQ_TYPE_LEVEL_HIGH;
+       struct thunderx_gpio *txgpio = d->host_data;
+
+       if (WARN_ON(fwspec->param_count < 2))
+               return -EINVAL;
+       if (fwspec->param[0] >= txgpio->chip.ngpio)
+               return -EINVAL;
+       *hwirq = fwspec->param[0];
+       *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
        return 0;
 }
 
+static int thunderx_gpio_irq_alloc(struct irq_domain *d, unsigned int virq,
+                                  unsigned int nr_irqs, void *arg)
+{
+       struct thunderx_line *txline = arg;
+
+       return irq_domain_set_hwirq_and_chip(d, virq, txline->line,
+                                            &thunderx_gpio_irq_chip, txline);
+}
+
+static const struct irq_domain_ops thunderx_gpio_irqd_ops = {
+       .alloc          = thunderx_gpio_irq_alloc,
+       .translate      = thunderx_gpio_irq_translate
+};
+
+static int thunderx_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+       struct thunderx_gpio *txgpio = gpiochip_get_data(chip);
+
+       return irq_find_mapping(txgpio->irqd, offset);
+}
+
 static int thunderx_gpio_probe(struct pci_dev *pdev,
                               const struct pci_device_id *id)
 {
@@ -408,7 +456,6 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
        struct device *dev = &pdev->dev;
        struct thunderx_gpio *txgpio;
        struct gpio_chip *chip;
-       struct gpio_irq_chip *girq;
        int ngpio, i;
        int err = 0;
 
@@ -453,8 +500,8 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
        }
 
        txgpio->msix_entries = devm_kcalloc(dev,
-                                           ngpio, sizeof(struct msix_entry),
-                                           GFP_KERNEL);
+                                         ngpio, sizeof(struct msix_entry),
+                                         GFP_KERNEL);
        if (!txgpio->msix_entries) {
                err = -ENOMEM;
                goto out;
@@ -495,6 +542,27 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
        if (err < 0)
                goto out;
 
+       /*
+        * Push GPIO specific irqdomain on hierarchy created as a side
+        * effect of the pci_enable_msix()
+        */
+       txgpio->irqd = irq_domain_create_hierarchy(irq_get_irq_data(txgpio->msix_entries[0].vector)->domain,
+                                                  0, 0, of_node_to_fwnode(dev->of_node),
+                                                  &thunderx_gpio_irqd_ops, txgpio);
+       if (!txgpio->irqd) {
+               err = -ENOMEM;
+               goto out;
+       }
+
+       /* Push on irq_data and the domain for each line. */
+       for (i = 0; i < ngpio; i++) {
+               err = irq_domain_push_irq(txgpio->irqd,
+                                         txgpio->msix_entries[i].vector,
+                                         &txgpio->line_entries[i]);
+               if (err < 0)
+                       dev_err(dev, "irq_domain_push_irq: %d\n", err);
+       }
+
        chip->label = KBUILD_MODNAME;
        chip->parent = dev;
        chip->owner = THIS_MODULE;
@@ -509,28 +577,11 @@ static int thunderx_gpio_probe(struct pci_dev *pdev,
        chip->set = thunderx_gpio_set;
        chip->set_multiple = thunderx_gpio_set_multiple;
        chip->set_config = thunderx_gpio_set_config;
-       girq = &chip->irq;
-       girq->chip = &thunderx_gpio_irq_chip;
-       girq->fwnode = of_node_to_fwnode(dev->of_node);
-       girq->parent_domain =
-               irq_get_irq_data(txgpio->msix_entries[0].vector)->domain;
-       girq->child_to_parent_hwirq = thunderx_gpio_child_to_parent_hwirq;
-       girq->handler = handle_bad_irq;
-       girq->default_type = IRQ_TYPE_NONE;
-
+       chip->to_irq = thunderx_gpio_to_irq;
        err = devm_gpiochip_add_data(dev, chip, txgpio);
        if (err)
                goto out;
 
-       /* Push on irq_data and the domain for each line. */
-       for (i = 0; i < ngpio; i++) {
-               err = irq_domain_push_irq(chip->irq.domain,
-                                         txgpio->msix_entries[i].vector,
-                                         chip);
-               if (err < 0)
-                       dev_err(dev, "irq_domain_push_irq: %d\n", err);
-       }
-
        dev_info(dev, "ThunderX GPIO: %d lines with base %d.\n",
                 ngpio, chip->base);
        return 0;
@@ -545,10 +596,10 @@ static void thunderx_gpio_remove(struct pci_dev *pdev)
        struct thunderx_gpio *txgpio = pci_get_drvdata(pdev);
 
        for (i = 0; i < txgpio->chip.ngpio; i++)
-               irq_domain_pop_irq(txgpio->chip.irq.domain,
+               irq_domain_pop_irq(txgpio->irqd,
                                   txgpio->msix_entries[i].vector);
 
-       irq_domain_remove(txgpio->chip.irq.domain);
+       irq_domain_remove(txgpio->irqd);
 
        pci_set_drvdata(pdev, NULL);
 }
index 773e5c2..b21c2e4 100644 (file)
@@ -280,7 +280,7 @@ static int iproc_gpio_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __exit iproc_gpio_remove(struct platform_device *pdev)
+static int iproc_gpio_remove(struct platform_device *pdev)
 {
        struct iproc_gpio_chip *chip;
 
index 08d7c3b..c8af34a 100644 (file)
@@ -44,15 +44,14 @@ static inline unsigned long enable_cp(unsigned long *cpenable)
        unsigned long flags;
 
        local_irq_save(flags);
-       RSR_CPENABLE(*cpenable);
-       WSR_CPENABLE(*cpenable | BIT(XCHAL_CP_ID_XTIOP));
-
+       *cpenable = xtensa_get_sr(cpenable);
+       xtensa_set_sr(*cpenable | BIT(XCHAL_CP_ID_XTIOP), cpenable);
        return flags;
 }
 
 static inline void disable_cp(unsigned long flags, unsigned long cpenable)
 {
-       WSR_CPENABLE(cpenable);
+       xtensa_set_sr(cpenable, cpenable);
        local_irq_restore(flags);
 }
 
index 4c3f637..05ba16f 100644 (file)
@@ -684,6 +684,8 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
        unsigned int bank_num;
 
        for (bank_num = 0; bank_num < gpio->p_data->max_bank; bank_num++) {
+               writel_relaxed(ZYNQ_GPIO_IXR_DISABLE_ALL, gpio->base_addr +
+                               ZYNQ_GPIO_INTDIS_OFFSET(bank_num));
                writel_relaxed(gpio->context.datalsw[bank_num],
                               gpio->base_addr +
                               ZYNQ_GPIO_DATA_LSW_OFFSET(bank_num));
@@ -693,9 +695,6 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
                writel_relaxed(gpio->context.dirm[bank_num],
                               gpio->base_addr +
                               ZYNQ_GPIO_DIRM_OFFSET(bank_num));
-               writel_relaxed(gpio->context.int_en[bank_num],
-                              gpio->base_addr +
-                              ZYNQ_GPIO_INTEN_OFFSET(bank_num));
                writel_relaxed(gpio->context.int_type[bank_num],
                               gpio->base_addr +
                               ZYNQ_GPIO_INTTYPE_OFFSET(bank_num));
@@ -705,6 +704,9 @@ static void zynq_gpio_restore_context(struct zynq_gpio *gpio)
                writel_relaxed(gpio->context.int_any[bank_num],
                               gpio->base_addr +
                               ZYNQ_GPIO_INTANY_OFFSET(bank_num));
+               writel_relaxed(~(gpio->context.int_en[bank_num]),
+                              gpio->base_addr +
+                              ZYNQ_GPIO_INTEN_OFFSET(bank_num));
        }
 }
 
index d30e57d..31fee5e 100644 (file)
 #include "gpiolib.h"
 #include "gpiolib-acpi.h"
 
+#define QUIRK_NO_EDGE_EVENTS_ON_BOOT           0x01l
+#define QUIRK_NO_WAKEUP                                0x02l
+
 static int run_edge_events_on_boot = -1;
 module_param(run_edge_events_on_boot, int, 0444);
 MODULE_PARM_DESC(run_edge_events_on_boot,
                 "Run edge _AEI event-handlers at boot: 0=no, 1=yes, -1=auto");
 
+static int honor_wakeup = -1;
+module_param(honor_wakeup, int, 0444);
+MODULE_PARM_DESC(honor_wakeup,
+                "Honor the ACPI wake-capable flag: 0=no, 1=yes, -1=auto");
+
 /**
  * struct acpi_gpio_event - ACPI GPIO event handler data
  *
@@ -281,7 +289,7 @@ static acpi_status acpi_gpiochip_alloc_event(struct acpi_resource *ares,
        event->handle = evt_handle;
        event->handler = handler;
        event->irq = irq;
-       event->irq_is_wake = agpio->wake_capable == ACPI_WAKE_CAPABLE;
+       event->irq_is_wake = honor_wakeup && agpio->wake_capable == ACPI_WAKE_CAPABLE;
        event->pin = pin;
        event->desc = desc;
 
@@ -1309,7 +1317,7 @@ static int acpi_gpio_handle_deferred_request_irqs(void)
 /* We must use _sync so that this runs after the first deferred_probe run */
 late_initcall_sync(acpi_gpio_handle_deferred_request_irqs);
 
-static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
+static const struct dmi_system_id gpiolib_acpi_quirks[] = {
        {
                /*
                 * The Minix Neo Z83-4 has a micro-USB-B id-pin handler for
@@ -1319,7 +1327,8 @@ static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "MINIX"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Z83-4"),
-               }
+               },
+               .driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT,
        },
        {
                /*
@@ -1331,20 +1340,52 @@ static const struct dmi_system_id run_edge_events_on_boot_blacklist[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Wortmann_AG"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "TERRA_PAD_1061"),
-               }
+               },
+               .driver_data = (void *)QUIRK_NO_EDGE_EVENTS_ON_BOOT,
+       },
+       {
+               /*
+                * Various HP X2 10 Cherry Trail models use an external
+                * embedded-controller connected via I2C + an ACPI GPIO
+                * event handler. The embedded controller generates various
+                * spurious wakeup events when suspended. So disable wakeup
+                * for its handler (it uses the only ACPI GPIO event handler).
+                * This breaks wakeup when opening the lid, the user needs
+                * to press the power-button to wakeup the system. The
+                * alternative is suspend simply not working, which is worse.
+                */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP x2 Detachable 10-p0XX"),
+               },
+               .driver_data = (void *)QUIRK_NO_WAKEUP,
        },
        {} /* Terminating entry */
 };
 
 static int acpi_gpio_setup_params(void)
 {
+       const struct dmi_system_id *id;
+       long quirks = 0;
+
+       id = dmi_first_match(gpiolib_acpi_quirks);
+       if (id)
+               quirks = (long)id->driver_data;
+
        if (run_edge_events_on_boot < 0) {
-               if (dmi_check_system(run_edge_events_on_boot_blacklist))
+               if (quirks & QUIRK_NO_EDGE_EVENTS_ON_BOOT)
                        run_edge_events_on_boot = 0;
                else
                        run_edge_events_on_boot = 1;
        }
 
+       if (honor_wakeup < 0) {
+               if (quirks & QUIRK_NO_WAKEUP)
+                       honor_wakeup = 0;
+               else
+                       honor_wakeup = 1;
+       }
+
        return 0;
 }
 
index dc27b1a..b696e45 100644 (file)
 #include "gpiolib.h"
 #include "gpiolib-of.h"
 
+/**
+ * of_gpio_spi_cs_get_count() - special GPIO counting for SPI
+ * Some elder GPIO controllers need special quirks. Currently we handle
+ * the Freescale GPIO controller with bindings that doesn't use the
+ * established "cs-gpios" for chip selects but instead rely on
+ * "gpios" for the chip select lines. If we detect this, we redirect
+ * the counting of "cs-gpios" to count "gpios" transparent to the
+ * driver.
+ */
+static int of_gpio_spi_cs_get_count(struct device *dev, const char *con_id)
+{
+       struct device_node *np = dev->of_node;
+
+       if (!IS_ENABLED(CONFIG_SPI_MASTER))
+               return 0;
+       if (!con_id || strcmp(con_id, "cs"))
+               return 0;
+       if (!of_device_is_compatible(np, "fsl,spi") &&
+           !of_device_is_compatible(np, "aeroflexgaisler,spictrl"))
+               return 0;
+       return of_gpio_named_count(np, "gpios");
+}
+
 /*
  * This is used by external users of of_gpio_count() from <linux/of_gpio.h>
  *
@@ -35,6 +58,10 @@ int of_gpio_get_count(struct device *dev, const char *con_id)
        char propname[32];
        unsigned int i;
 
+       ret = of_gpio_spi_cs_get_count(dev, con_id);
+       if (ret > 0)
+               return ret;
+
        for (i = 0; i < ARRAY_SIZE(gpio_suffixes); i++) {
                if (con_id)
                        snprintf(propname, sizeof(propname), "%s-%s",
index 9913886..78a16e4 100644 (file)
@@ -220,6 +220,14 @@ int gpiod_get_direction(struct gpio_desc *desc)
        chip = gpiod_to_chip(desc);
        offset = gpio_chip_hwgpio(desc);
 
+       /*
+        * Open drain emulation using input mode may incorrectly report
+        * input here, fix that up.
+        */
+       if (test_bit(FLAG_OPEN_DRAIN, &desc->flags) &&
+           test_bit(FLAG_IS_OUT, &desc->flags))
+               return 0;
+
        if (!chip->get_direction)
                return -ENOTSUPP;
 
@@ -4472,8 +4480,9 @@ static struct gpio_desc *gpiod_find(struct device *dev, const char *con_id,
 
                if (chip->ngpio <= p->chip_hwnum) {
                        dev_err(dev,
-                               "requested GPIO %d is out of range [0..%d] for chip %s\n",
-                               idx, chip->ngpio, chip->label);
+                               "requested GPIO %u (%u) is out of range [0..%u] for chip %s\n",
+                               idx, p->chip_hwnum, chip->ngpio - 1,
+                               chip->label);
                        return ERR_PTR(-EINVAL);
                }
 
index d968c24..0d12ebf 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 menu "ACP (Audio CoProcessor) Configuration"
 
 config DRM_AMD_ACP
index 2e98c01..9375e7f 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 config DRM_AMDGPU_SI
        bool "Enable amdgpu support for SI parts"
        depends on DRM_AMDGPU
index a97fb75..3e35a8f 100644 (file)
@@ -613,7 +613,17 @@ static bool amdgpu_atpx_detect(void)
        bool d3_supported = false;
        struct pci_dev *parent_pdev;
 
-       while ((pdev = pci_get_class(PCI_BASE_CLASS_DISPLAY << 16, pdev)) != NULL) {
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+               vga_count++;
+
+               has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true);
+
+               parent_pdev = pci_upstream_bridge(pdev);
+               d3_supported |= parent_pdev && parent_pdev->bridge_d3;
+               amdgpu_atpx_get_quirks(pdev);
+       }
+
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
                vga_count++;
 
                has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true);
index 2cdaf3b..6614d8a 100644 (file)
@@ -604,11 +604,8 @@ void amdgpu_ctx_mgr_entity_fini(struct amdgpu_ctx_mgr *mgr)
                        continue;
                }
 
-               for (i = 0; i < num_entities; i++) {
-                       mutex_lock(&ctx->adev->lock_reset);
+               for (i = 0; i < num_entities; i++)
                        drm_sched_entity_fini(&ctx->entities[0][i].entity);
-                       mutex_unlock(&ctx->adev->lock_reset);
-               }
        }
 }
 
index 0ffc944..01a793a 100644 (file)
@@ -142,7 +142,7 @@ int amdgpu_async_gfx_ring = 1;
 int amdgpu_mcbp = 0;
 int amdgpu_discovery = -1;
 int amdgpu_mes = 0;
-int amdgpu_noretry = 1;
+int amdgpu_noretry;
 int amdgpu_force_asic_type = -1;
 
 struct amdgpu_mgpu_info mgpu_info = {
@@ -588,7 +588,7 @@ MODULE_PARM_DESC(mes,
 module_param_named(mes, amdgpu_mes, int, 0444);
 
 MODULE_PARM_DESC(noretry,
-       "Disable retry faults (0 = retry enabled, 1 = retry disabled (default))");
+       "Disable retry faults (0 = retry enabled (default), 1 = retry disabled)");
 module_param_named(noretry, amdgpu_noretry, int, 0644);
 
 /**
@@ -1359,7 +1359,8 @@ static struct drm_driver kms_driver = {
        .driver_features =
            DRIVER_USE_AGP | DRIVER_ATOMIC |
            DRIVER_GEM |
-           DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ,
+           DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ |
+           DRIVER_SYNCOBJ_TIMELINE,
        .load = amdgpu_driver_load_kms,
        .open = amdgpu_driver_open_kms,
        .postclose = amdgpu_driver_postclose_kms,
index 44be3a4..e1b8d8d 100644 (file)
@@ -1488,7 +1488,7 @@ out:
 
                /* Start rlc autoload after psp recieved all the gfx firmware */
                if (psp->autoload_supported && ucode->ucode_id == (amdgpu_sriov_vf(adev) ?
-                   AMDGPU_UCODE_ID_CP_MEC2 : AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM)) {
+                   AMDGPU_UCODE_ID_CP_MEC2 : AMDGPU_UCODE_ID_RLC_G)) {
                        ret = psp_rlc_autoload(psp);
                        if (ret) {
                                DRM_ERROR("Failed to start rlc autoload\n");
index 410587b..914acec 100644 (file)
@@ -292,10 +292,10 @@ enum AMDGPU_UCODE_ID {
        AMDGPU_UCODE_ID_CP_MEC2_JT,
        AMDGPU_UCODE_ID_CP_MES,
        AMDGPU_UCODE_ID_CP_MES_DATA,
-       AMDGPU_UCODE_ID_RLC_G,
        AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL,
        AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM,
        AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM,
+       AMDGPU_UCODE_ID_RLC_G,
        AMDGPU_UCODE_ID_STORAGE,
        AMDGPU_UCODE_ID_SMC,
        AMDGPU_UCODE_ID_UVD,
index 16fbd2b..4043ebc 100644 (file)
@@ -268,23 +268,29 @@ static void df_v3_6_update_medium_grain_clock_gating(struct amdgpu_device *adev,
 {
        u32 tmp;
 
-       /* Put DF on broadcast mode */
-       adev->df_funcs->enable_broadcast_mode(adev, true);
-
-       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG)) {
-               tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
-               tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
-               tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
-               WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
-       } else {
-               tmp = RREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater);
-               tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
-               tmp |= DF_V3_6_MGCG_DISABLE;
-               WREG32_SOC15(DF, 0, mmDF_PIE_AON0_DfGlobalClkGater, tmp);
-       }
+       if (adev->cg_flags & AMD_CG_SUPPORT_DF_MGCG) {
+               /* Put DF on broadcast mode */
+               adev->df_funcs->enable_broadcast_mode(adev, true);
+
+               if (enable) {
+                       tmp = RREG32_SOC15(DF, 0,
+                                       mmDF_PIE_AON0_DfGlobalClkGater);
+                       tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
+                       tmp |= DF_V3_6_MGCG_ENABLE_15_CYCLE_DELAY;
+                       WREG32_SOC15(DF, 0,
+                                       mmDF_PIE_AON0_DfGlobalClkGater, tmp);
+               } else {
+                       tmp = RREG32_SOC15(DF, 0,
+                                       mmDF_PIE_AON0_DfGlobalClkGater);
+                       tmp &= ~DF_PIE_AON0_DfGlobalClkGater__MGCGMode_MASK;
+                       tmp |= DF_V3_6_MGCG_DISABLE;
+                       WREG32_SOC15(DF, 0,
+                                       mmDF_PIE_AON0_DfGlobalClkGater, tmp);
+               }
 
-       /* Exit broadcast mode */
-       adev->df_funcs->enable_broadcast_mode(adev, false);
+               /* Exit broadcast mode */
+               adev->df_funcs->enable_broadcast_mode(adev, false);
+       }
 }
 
 static void df_v3_6_get_clockgating_state(struct amdgpu_device *adev,
index f2c1b02..ba9e53a 100644 (file)
@@ -117,10 +117,13 @@ static const struct soc15_reg_golden golden_settings_gc_10_1[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0x10000000, 0x10000100),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xffffffff, 0x1402002f),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xffff9fff, 0x00001188),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_TIMEOUT_COUNTER, 0xffffffff, 0x00000800),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x3fffffff, 0x08000009),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_1, 0x00400000, 0x04440000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0x00000800, 0x00000820),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL, 0x001f0000, 0x00070104),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000100, 0x00000130),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
@@ -162,10 +165,13 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_1[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CGTT_SCLK_CTRL, 0xffff0fff, 0x10000100),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL2, 0xffffffff, 0x1402002f),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL2C_CTRL3, 0xffffbfff, 0x00000188),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_BINNER_TIMEOUT_COUNTER, 0xffffffff, 0x00000800),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE, 0x3fffffff, 0x08000009),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_1, 0x00400000, 0x04440000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0x00000800, 0x00000820),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL, 0x001f0000, 0x00070105),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000133, 0x00000130),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
index 983db77..52a647d 100644 (file)
@@ -6146,7 +6146,23 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr,
        bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
        bool int_sel = flags & AMDGPU_FENCE_FLAG_INT;
 
-       /* EVENT_WRITE_EOP - flush caches, send int */
+       /* Workaround for cache flush problems. First send a dummy EOP
+        * event down the pipe with seq one below.
+        */
+       amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
+       amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
+                                EOP_TC_ACTION_EN |
+                                EOP_TC_WB_ACTION_EN |
+                                EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) |
+                                EVENT_INDEX(5)));
+       amdgpu_ring_write(ring, addr & 0xfffffffc);
+       amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) |
+                               DATA_SEL(1) | INT_SEL(0));
+       amdgpu_ring_write(ring, lower_32_bits(seq - 1));
+       amdgpu_ring_write(ring, upper_32_bits(seq - 1));
+
+       /* Then send the real EOP event down the pipe:
+        * EVENT_WRITE_EOP - flush caches, send int */
        amdgpu_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4));
        amdgpu_ring_write(ring, (EOP_TCL1_ACTION_EN |
                                 EOP_TC_ACTION_EN |
@@ -6888,7 +6904,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
                5 +  /* COND_EXEC */
                7 +  /* PIPELINE_SYNC */
                VI_FLUSH_GPU_TLB_NUM_WREG * 5 + 9 + /* VM_FLUSH */
-               8 +  /* FENCE for VM_FLUSH */
+               12 +  /* FENCE for VM_FLUSH */
                20 + /* GDS switch */
                4 + /* double SWITCH_BUFFER,
                       the first COND_EXEC jump to the place just
@@ -6900,7 +6916,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_gfx = {
                31 + /* DE_META */
                3 + /* CNTX_CTRL */
                5 + /* HDP_INVL */
-               8 + 8 + /* FENCE x2 */
+               12 + 12 + /* FENCE x2 */
                2, /* SWITCH_BUFFER */
        .emit_ib_size = 4, /* gfx_v8_0_ring_emit_ib_gfx */
        .emit_ib = gfx_v8_0_ring_emit_ib_gfx,
index 66328ff..97105a5 100644 (file)
@@ -1052,17 +1052,10 @@ static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
        case CHIP_VEGA20:
                break;
        case CHIP_RAVEN:
-               /* Disable GFXOFF on original raven.  There are combinations
-                * of sbios and platforms that are not stable.
-                */
-               if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8))
-                       adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
-               else if (!(adev->rev_id >= 0x8 || adev->pdev->device == 0x15d8)
-                        &&((adev->gfx.rlc_fw_version != 106 &&
-                            adev->gfx.rlc_fw_version < 531) ||
-                           (adev->gfx.rlc_fw_version == 53815) ||
-                           (adev->gfx.rlc_feature_version < 1) ||
-                           !adev->gfx.rlc.is_rlc_v2_1))
+               if (!(adev->rev_id >= 0x8 ||
+                     adev->pdev->device == 0x15d8) &&
+                   (adev->pm.fw_version < 0x41e2b || /* not raven1 fresh */
+                    !adev->gfx.rlc.is_rlc_v2_1)) /* without rlc save restore ucodes */
                        adev->pm.pp_feature &= ~PP_GFXOFF_MASK;
 
                if (adev->pm.pp_feature & PP_GFXOFF_MASK)
index 2324695..f572533 100644 (file)
@@ -219,6 +219,21 @@ static uint32_t gmc_v10_0_get_invalidate_req(unsigned int vmid,
        return req;
 }
 
+/**
+ * gmc_v10_0_use_invalidate_semaphore - judge whether to use semaphore
+ *
+ * @adev: amdgpu_device pointer
+ * @vmhub: vmhub type
+ *
+ */
+static bool gmc_v10_0_use_invalidate_semaphore(struct amdgpu_device *adev,
+                                      uint32_t vmhub)
+{
+       return ((vmhub == AMDGPU_MMHUB_0 ||
+                vmhub == AMDGPU_MMHUB_1) &&
+               (!amdgpu_sriov_vf(adev)));
+}
+
 /*
  * GART
  * VMID 0 is the physical GPU addresses as used by the kernel.
@@ -229,6 +244,7 @@ static uint32_t gmc_v10_0_get_invalidate_req(unsigned int vmid,
 static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
                                   unsigned int vmhub, uint32_t flush_type)
 {
+       bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(adev, vmhub);
        struct amdgpu_vmhub *hub = &adev->vmhub[vmhub];
        u32 tmp = gmc_v10_0_get_invalidate_req(vmid, flush_type);
        /* Use register 17 for GART */
@@ -244,8 +260,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
         */
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (vmhub == AMDGPU_MMHUB_0 ||
-           vmhub == AMDGPU_MMHUB_1) {
+       if (use_semaphore) {
                for (i = 0; i < adev->usec_timeout; i++) {
                        /* a read return value of 1 means semaphore acuqire */
                        tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
@@ -278,8 +293,7 @@ static void gmc_v10_0_flush_vm_hub(struct amdgpu_device *adev, uint32_t vmid,
        }
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (vmhub == AMDGPU_MMHUB_0 ||
-           vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /*
                 * add semaphore release after invalidation,
                 * write with 0 means semaphore release
@@ -369,6 +383,7 @@ error_alloc:
 static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
                                             unsigned vmid, uint64_t pd_addr)
 {
+       bool use_semaphore = gmc_v10_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub);
        struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
        uint32_t req = gmc_v10_0_get_invalidate_req(vmid, 0);
        unsigned eng = ring->vm_inv_eng;
@@ -381,8 +396,7 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
         */
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
-           ring->funcs->vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /* a read return value of 1 means semaphore acuqire */
                amdgpu_ring_emit_reg_wait(ring,
                                          hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
@@ -398,8 +412,7 @@ static uint64_t gmc_v10_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
                                            req, 1 << vmid);
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
-           ring->funcs->vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /*
                 * add semaphore release after invalidation,
                 * write with 0 means semaphore release
index 3c355fb..a5b68b5 100644 (file)
@@ -416,6 +416,24 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
        return req;
 }
 
+/**
+ * gmc_v9_0_use_invalidate_semaphore - judge whether to use semaphore
+ *
+ * @adev: amdgpu_device pointer
+ * @vmhub: vmhub type
+ *
+ */
+static bool gmc_v9_0_use_invalidate_semaphore(struct amdgpu_device *adev,
+                                      uint32_t vmhub)
+{
+       return ((vmhub == AMDGPU_MMHUB_0 ||
+                vmhub == AMDGPU_MMHUB_1) &&
+               (!amdgpu_sriov_vf(adev)) &&
+               (!(adev->asic_type == CHIP_RAVEN &&
+                  adev->rev_id < 0x8 &&
+                  adev->pdev->device == 0x15d8)));
+}
+
 /*
  * GART
  * VMID 0 is the physical GPU addresses as used by the kernel.
@@ -435,6 +453,7 @@ static uint32_t gmc_v9_0_get_invalidate_req(unsigned int vmid,
 static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
                                        uint32_t vmhub, uint32_t flush_type)
 {
+       bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(adev, vmhub);
        const unsigned eng = 17;
        u32 j, tmp;
        struct amdgpu_vmhub *hub;
@@ -468,8 +487,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
         */
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (vmhub == AMDGPU_MMHUB_0 ||
-           vmhub == AMDGPU_MMHUB_1) {
+       if (use_semaphore) {
                for (j = 0; j < adev->usec_timeout; j++) {
                        /* a read return value of 1 means semaphore acuqire */
                        tmp = RREG32_NO_KIQ(hub->vm_inv_eng0_sem + eng);
@@ -499,8 +517,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
        }
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (vmhub == AMDGPU_MMHUB_0 ||
-           vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /*
                 * add semaphore release after invalidation,
                 * write with 0 means semaphore release
@@ -518,6 +535,7 @@ static void gmc_v9_0_flush_gpu_tlb(struct amdgpu_device *adev, uint32_t vmid,
 static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
                                            unsigned vmid, uint64_t pd_addr)
 {
+       bool use_semaphore = gmc_v9_0_use_invalidate_semaphore(ring->adev, ring->funcs->vmhub);
        struct amdgpu_device *adev = ring->adev;
        struct amdgpu_vmhub *hub = &adev->vmhub[ring->funcs->vmhub];
        uint32_t req = gmc_v9_0_get_invalidate_req(vmid, 0);
@@ -531,8 +549,7 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
         */
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
-           ring->funcs->vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /* a read return value of 1 means semaphore acuqire */
                amdgpu_ring_emit_reg_wait(ring,
                                          hub->vm_inv_eng0_sem + eng, 0x1, 0x1);
@@ -548,8 +565,7 @@ static uint64_t gmc_v9_0_emit_flush_gpu_tlb(struct amdgpu_ring *ring,
                                            req, 1 << vmid);
 
        /* TODO: It needs to continue working on debugging with semaphore for GFXHUB as well. */
-       if (ring->funcs->vmhub == AMDGPU_MMHUB_0 ||
-           ring->funcs->vmhub == AMDGPU_MMHUB_1)
+       if (use_semaphore)
                /*
                 * add semaphore release after invalidation,
                 * write with 0 means semaphore release
index 4ef4d31..2f52b7f 100644 (file)
@@ -254,7 +254,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_3[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
-       SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000)
+       SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x03fbe1fe)
 };
 
 static u32 sdma_v4_0_get_reg_offset(struct amdgpu_device *adev,
index ba0e680..b3672d1 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 #
 # Heterogenous system architecture configuration
 #
index 313183b..ae161fe 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-License-Identifier: GPL-2.0-only
+# SPDX-License-Identifier: MIT
 menu "Display Engine Configuration"
        depends on DRM && DRM_AMDGPU
 
index 7aac956..803e59d 100644 (file)
@@ -3356,27 +3356,21 @@ get_output_color_space(const struct dc_crtc_timing *dc_crtc_timing)
        return color_space;
 }
 
-static void reduce_mode_colour_depth(struct dc_crtc_timing *timing_out)
-{
-       if (timing_out->display_color_depth <= COLOR_DEPTH_888)
-               return;
-
-       timing_out->display_color_depth--;
-}
-
-static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_out,
-                                               const struct drm_display_info *info)
+static bool adjust_colour_depth_from_display_info(
+       struct dc_crtc_timing *timing_out,
+       const struct drm_display_info *info)
 {
+       enum dc_color_depth depth = timing_out->display_color_depth;
        int normalized_clk;
-       if (timing_out->display_color_depth <= COLOR_DEPTH_888)
-               return;
        do {
                normalized_clk = timing_out->pix_clk_100hz / 10;
                /* YCbCr 4:2:0 requires additional adjustment of 1/2 */
                if (timing_out->pixel_encoding == PIXEL_ENCODING_YCBCR420)
                        normalized_clk /= 2;
                /* Adjusting pix clock following on HDMI spec based on colour depth */
-               switch (timing_out->display_color_depth) {
+               switch (depth) {
+               case COLOR_DEPTH_888:
+                       break;
                case COLOR_DEPTH_101010:
                        normalized_clk = (normalized_clk * 30) / 24;
                        break;
@@ -3387,14 +3381,15 @@ static void adjust_colour_depth_from_display_info(struct dc_crtc_timing *timing_
                        normalized_clk = (normalized_clk * 48) / 24;
                        break;
                default:
-                       return;
+                       /* The above depths are the only ones valid for HDMI. */
+                       return false;
                }
-               if (normalized_clk <= info->max_tmds_clock)
-                       return;
-               reduce_mode_colour_depth(timing_out);
-
-       } while (timing_out->display_color_depth > COLOR_DEPTH_888);
-
+               if (normalized_clk <= info->max_tmds_clock) {
+                       timing_out->display_color_depth = depth;
+                       return true;
+               }
+       } while (--depth > COLOR_DEPTH_666);
+       return false;
 }
 
 static void fill_stream_properties_from_drm_display_mode(
@@ -3474,8 +3469,14 @@ static void fill_stream_properties_from_drm_display_mode(
 
        stream->out_transfer_func->type = TF_TYPE_PREDEFINED;
        stream->out_transfer_func->tf = TRANSFER_FUNCTION_SRGB;
-       if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
-               adjust_colour_depth_from_display_info(timing_out, info);
+       if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A) {
+               if (!adjust_colour_depth_from_display_info(timing_out, info) &&
+                   drm_mode_is_420_also(info, mode_in) &&
+                   timing_out->pixel_encoding != PIXEL_ENCODING_YCBCR420) {
+                       timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
+                       adjust_colour_depth_from_display_info(timing_out, info);
+               }
+       }
 }
 
 static void fill_audio_info(struct audio_info *audio_info,
index 7873abe..5c3fcaa 100644 (file)
@@ -1625,6 +1625,7 @@ static enum bp_result construct_integrated_info(
                /* Don't need to check major revision as they are all 1 */
                switch (revision.minor) {
                case 11:
+               case 12:
                        result = get_integrated_info_v11(bp, info);
                        break;
                default:
index 790a2d2..35c55e5 100644 (file)
@@ -471,12 +471,28 @@ static void rn_notify_wm_ranges(struct clk_mgr *clk_mgr_base)
 
 }
 
+static bool rn_are_clock_states_equal(struct dc_clocks *a,
+               struct dc_clocks *b)
+{
+       if (a->dispclk_khz != b->dispclk_khz)
+               return false;
+       else if (a->dppclk_khz != b->dppclk_khz)
+               return false;
+       else if (a->dcfclk_khz != b->dcfclk_khz)
+               return false;
+       else if (a->dcfclk_deep_sleep_khz != b->dcfclk_deep_sleep_khz)
+               return false;
+
+       return true;
+}
+
+
 static struct clk_mgr_funcs dcn21_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = rn_update_clocks,
        .init_clocks = rn_init_clocks,
        .enable_pme_wa = rn_enable_pme_wa,
-       /* .dump_clk_registers = rn_dump_clk_registers, */
+       .are_clock_states_equal = rn_are_clock_states_equal,
        .notify_wm_ranges = rn_notify_wm_ranges
 };
 
@@ -518,36 +534,83 @@ struct clk_bw_params rn_bw_params = {
                .num_entries = 4,
        },
 
-       .wm_table = {
-               .entries = {
-                       {
-                               .wm_inst = WM_A,
-                               .wm_type = WM_TYPE_PSTATE_CHG,
-                               .pstate_latency_us = 23.84,
-                               .valid = true,
-                       },
-                       {
-                               .wm_inst = WM_B,
-                               .wm_type = WM_TYPE_PSTATE_CHG,
-                               .pstate_latency_us = 23.84,
-                               .valid = true,
-                       },
-                       {
-                               .wm_inst = WM_C,
-                               .wm_type = WM_TYPE_PSTATE_CHG,
-                               .pstate_latency_us = 23.84,
-                               .valid = true,
-                       },
-                       {
-                               .wm_inst = WM_D,
-                               .wm_type = WM_TYPE_PSTATE_CHG,
-                               .pstate_latency_us = 23.84,
-                               .valid = true,
-                       },
+};
+
+struct wm_table ddr4_wm_table = {
+       .entries = {
+               {
+                       .wm_inst = WM_A,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 6.09,
+                       .sr_enter_plus_exit_time_us = 7.14,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_B,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 10.12,
+                       .sr_enter_plus_exit_time_us = 11.48,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_C,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 10.12,
+                       .sr_enter_plus_exit_time_us = 11.48,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_D,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 11.72,
+                       .sr_exit_time_us = 10.12,
+                       .sr_enter_plus_exit_time_us = 11.48,
+                       .valid = true,
                },
        }
 };
 
+struct wm_table lpddr4_wm_table = {
+       .entries = {
+               {
+                       .wm_inst = WM_A,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 23.84,
+                       .sr_exit_time_us = 12.5,
+                       .sr_enter_plus_exit_time_us = 17.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_B,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 23.84,
+                       .sr_exit_time_us = 12.5,
+                       .sr_enter_plus_exit_time_us = 17.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_C,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 23.84,
+                       .sr_exit_time_us = 12.5,
+                       .sr_enter_plus_exit_time_us = 17.0,
+                       .valid = true,
+               },
+               {
+                       .wm_inst = WM_D,
+                       .wm_type = WM_TYPE_PSTATE_CHG,
+                       .pstate_latency_us = 23.84,
+                       .sr_exit_time_us = 12.5,
+                       .sr_enter_plus_exit_time_us = 17.0,
+                       .valid = true,
+               },
+       }
+};
+
+
 static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsigned int voltage)
 {
        int i;
@@ -561,7 +624,7 @@ static unsigned int find_dcfclk_for_voltage(struct dpm_clocks *clock_table, unsi
        return 0;
 }
 
-static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct hw_asic_id *asic_id)
+static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params, struct dpm_clocks *clock_table, struct integrated_info *bios_info)
 {
        int i, j = 0;
 
@@ -593,8 +656,8 @@ static void rn_clk_mgr_helper_populate_bw_params(struct clk_bw_params *bw_params
                bw_params->clk_table.entries[i].dcfclk_mhz = find_dcfclk_for_voltage(clock_table, clock_table->FClocks[j].Vol);
        }
 
-       bw_params->vram_type = asic_id->vram_type;
-       bw_params->num_channels = asic_id->vram_width / DDR4_DRAM_WIDTH;
+       bw_params->vram_type = bios_info->memory_type;
+       bw_params->num_channels = bios_info->ma_channel_number;
 
        for (i = 0; i < WM_SET_COUNT; i++) {
                bw_params->wm_table.entries[i].wm_inst = i;
@@ -669,15 +732,24 @@ void rn_clk_mgr_construct(
                        ASSERT(clk_mgr->base.dprefclk_khz == 600000);
                        clk_mgr->base.dprefclk_khz = 600000;
                }
+
+               if (ctx->dc_bios->integrated_info->memory_type == LpDdr4MemType) {
+                       rn_bw_params.wm_table = lpddr4_wm_table;
+               } else {
+                       rn_bw_params.wm_table = ddr4_wm_table;
+               }
        }
 
        dce_clock_read_ss_info(clk_mgr);
 
+
        clk_mgr->base.bw_params = &rn_bw_params;
 
        if (pp_smu && pp_smu->rn_funcs.get_dpm_clock_table) {
                pp_smu->rn_funcs.get_dpm_clock_table(&pp_smu->rn_funcs.pp_smu, &clock_table);
-               rn_clk_mgr_helper_populate_bw_params(clk_mgr->base.bw_params, &clock_table, &ctx->asic_id);
+               if (ctx->dc_bios && ctx->dc_bios->integrated_info) {
+                       rn_clk_mgr_helper_populate_bw_params (clk_mgr->base.bw_params, &clock_table, ctx->dc_bios->integrated_info);
+               }
        }
 
        if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment) && clk_mgr->smu_ver >= 0x00371500) {
index 12ba6fd..4619f94 100644 (file)
@@ -372,7 +372,7 @@ bool dc_link_is_dp_sink_present(struct dc_link *link)
 
        if (GPIO_RESULT_OK != dal_ddc_open(
                ddc, GPIO_MODE_INPUT, GPIO_DDC_CONFIG_TYPE_MODE_I2C)) {
-               dal_gpio_destroy_ddc(&ddc);
+               dal_ddc_close(ddc);
 
                return present;
        }
@@ -817,8 +817,8 @@ static bool dc_link_detect_helper(struct dc_link *link,
                }
 
                case SIGNAL_TYPE_EDP: {
-                       read_current_link_settings_on_detect(link);
                        detect_edp_sink_caps(link);
+                       read_current_link_settings_on_detect(link);
                        sink_caps.transaction_type = DDC_TRANSACTION_TYPE_I2C_OVER_AUX;
                        sink_caps.signal = SIGNAL_TYPE_EDP;
                        break;
index 7f904d5..8178919 100644 (file)
@@ -586,7 +586,7 @@ bool dal_ddc_service_query_ddc_data(
 bool dal_ddc_submit_aux_command(struct ddc_service *ddc,
                struct aux_payload *payload)
 {
-       uint8_t retrieved = 0;
+       uint32_t retrieved = 0;
        bool ret = 0;
 
        if (!ddc)
index 0f59b68..504055f 100644 (file)
@@ -3522,7 +3522,14 @@ void dp_set_fec_enable(struct dc_link *link, bool enable)
        if (link_enc->funcs->fec_set_enable &&
                        link->dpcd_caps.fec_cap.bits.FEC_CAPABLE) {
                if (link->fec_state == dc_link_fec_ready && enable) {
-                       msleep(1);
+                       /* Accord to DP spec, FEC enable sequence can first
+                        * be transmitted anytime after 1000 LL codes have
+                        * been transmitted on the link after link training
+                        * completion. Using 1 lane RBR should have the maximum
+                        * time for transmitting 1000 LL codes which is 6.173 us.
+                        * So use 7 microseconds delay instead.
+                        */
+                       udelay(7);
                        link_enc->funcs->fec_set_enable(link_enc, true);
                        link->fec_state = dc_link_fec_enabled;
                } else if (link->fec_state == dc_link_fec_enabled && !enable) {
index e472608..793c0ce 100644 (file)
@@ -583,6 +583,8 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
        uint8_t reply;
        bool payload_reply = true;
        enum aux_channel_operation_result operation_result;
+       bool retry_on_defer = false;
+
        int aux_ack_retries = 0,
                aux_defer_retries = 0,
                aux_i2c_defer_retries = 0,
@@ -613,8 +615,10 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
                        break;
 
                        case AUX_TRANSACTION_REPLY_AUX_DEFER:
-                       case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
                        case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_DEFER:
+                               retry_on_defer = true;
+                               /* fall through */
+                       case AUX_TRANSACTION_REPLY_I2C_OVER_AUX_NACK:
                                if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES) {
                                        goto fail;
                                } else {
@@ -647,15 +651,24 @@ bool dce_aux_transfer_with_retries(struct ddc_service *ddc,
                        break;
 
                case AUX_CHANNEL_OPERATION_FAILED_TIMEOUT:
-                       if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
-                               goto fail;
-                       else {
-                               /*
-                                * DP 1.4, 2.8.2:  AUX Transaction Response/Reply Timeouts
-                                * According to the DP spec there should be 3 retries total
-                                * with a 400us wait inbetween each. Hardware already waits
-                                * for 550us therefore no wait is required here.
-                                */
+                       // Check whether a DEFER had occurred before the timeout.
+                       // If so, treat timeout as a DEFER.
+                       if (retry_on_defer) {
+                               if (++aux_defer_retries >= AUX_MAX_DEFER_RETRIES)
+                                       goto fail;
+                               else if (payload->defer_delay > 0)
+                                       msleep(payload->defer_delay);
+                       } else {
+                               if (++aux_timeout_retries >= AUX_MAX_TIMEOUT_RETRIES)
+                                       goto fail;
+                               else {
+                                       /*
+                                        * DP 1.4, 2.8.2:  AUX Transaction Response/Reply Timeouts
+                                        * According to the DP spec there should be 3 retries total
+                                        * with a 400us wait inbetween each. Hardware already waits
+                                        * for 550us therefore no wait is required here.
+                                        */
+                               }
                        }
                        break;
 
index 0979333..23ff2f1 100644 (file)
@@ -923,7 +923,9 @@ static const struct resource_caps res_cap_nv14 = {
                .num_dwb = 1,
                .num_ddc = 5,
                .num_vmid = 16,
+#ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
                .num_dsc = 5,
+#endif
 };
 
 static const struct dc_debug_options debug_defaults_drv = {
@@ -1536,13 +1538,20 @@ enum dc_status dcn20_build_mapped_resource(const struct dc *dc, struct dc_state
 
 static void acquire_dsc(struct resource_context *res_ctx,
                        const struct resource_pool *pool,
-                       struct display_stream_compressor **dsc)
+                       struct display_stream_compressor **dsc,
+                       int pipe_idx)
 {
        int i;
 
        ASSERT(*dsc == NULL);
        *dsc = NULL;
 
+       if (pool->res_cap->num_dsc == pool->res_cap->num_opp) {
+               *dsc = pool->dscs[pipe_idx];
+               res_ctx->is_dsc_acquired[pipe_idx] = true;
+               return;
+       }
+
        /* Find first free DSC */
        for (i = 0; i < pool->res_cap->num_dsc; i++)
                if (!res_ctx->is_dsc_acquired[i]) {
@@ -1585,7 +1594,7 @@ static enum dc_status add_dsc_to_stream_resource(struct dc *dc,
                if (pipe_ctx->stream != dc_stream)
                        continue;
 
-               acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc);
+               acquire_dsc(&dc_ctx->res_ctx, pool, &pipe_ctx->stream_res.dsc, i);
 
                /* The number of DSCs can be less than the number of pipes */
                if (!pipe_ctx->stream_res.dsc) {
@@ -1785,7 +1794,7 @@ bool dcn20_split_stream_for_odm(
        next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
 #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT
        if (next_odm_pipe->stream->timing.flags.DSC == 1) {
-               acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc);
+               acquire_dsc(res_ctx, pool, &next_odm_pipe->stream_res.dsc, next_odm_pipe->pipe_idx);
                ASSERT(next_odm_pipe->stream_res.dsc);
                if (next_odm_pipe->stream_res.dsc == NULL)
                        return false;
index 4b34016..fcb3877 100644 (file)
@@ -492,15 +492,23 @@ void enc2_stream_encoder_dp_unblank(
                                DP_VID_N_MUL, n_multiply);
        }
 
-       /* set DIG_START to 0x1 to reset FIFO */
+       /* make sure stream is disabled before resetting steer fifo */
+       REG_UPDATE(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, false);
+       REG_WAIT(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, 0, 10, 5000);
 
+       /* set DIG_START to 0x1 to reset FIFO */
        REG_UPDATE(DIG_FE_CNTL, DIG_START, 1);
+       udelay(1);
 
        /* write 0 to take the FIFO out of reset */
 
        REG_UPDATE(DIG_FE_CNTL, DIG_START, 0);
 
-       /* switch DP encoder to CRTC data */
+       /* switch DP encoder to CRTC data, but reset it the fifo first. It may happen
+        * that it overflows during mode transition, and sometimes doesn't recover.
+        */
+       REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 1);
+       udelay(10);
 
        REG_UPDATE(DP_STEER_FIFO, DP_STEER_FIFO_RESET, 0);
 
index 459bd9a..b29b2c9 100644 (file)
@@ -23,6 +23,8 @@
  *
  */
 
+#include <linux/slab.h>
+
 #include "dm_services.h"
 #include "dc.h"
 
@@ -257,7 +259,7 @@ struct _vcs_dpi_soc_bounding_box_st dcn2_1_soc = {
        .vmm_page_size_bytes = 4096,
        .dram_clock_change_latency_us = 23.84,
        .return_bus_width_bytes = 64,
-       .dispclk_dppclk_vco_speed_mhz = 3550,
+       .dispclk_dppclk_vco_speed_mhz = 3600,
        .xfc_bus_transport_time_us = 4,
        .xfc_xbuf_latency_tolerance_us = 4,
        .use_urgent_burst_bw = 1,
@@ -1000,6 +1002,8 @@ static void calculate_wm_set_for_vlevel(
        pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
 
        dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
+       dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
+       dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
 
        wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
        wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
@@ -1017,14 +1021,21 @@ static void calculate_wm_set_for_vlevel(
 
 static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_st *bb)
 {
+       int i;
+
        kernel_fpu_begin();
        if (dc->bb_overrides.sr_exit_time_ns) {
-               bb->sr_exit_time_us = dc->bb_overrides.sr_exit_time_ns / 1000.0;
+               for (i = 0; i < WM_SET_COUNT; i++) {
+                         dc->clk_mgr->bw_params->wm_table.entries[i].sr_exit_time_us =
+                                         dc->bb_overrides.sr_exit_time_ns / 1000.0;
+               }
        }
 
        if (dc->bb_overrides.sr_enter_plus_exit_time_ns) {
-               bb->sr_enter_plus_exit_time_us =
-                               dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
+               for (i = 0; i < WM_SET_COUNT; i++) {
+                         dc->clk_mgr->bw_params->wm_table.entries[i].sr_enter_plus_exit_time_us =
+                                         dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0;
+               }
        }
 
        if (dc->bb_overrides.urgent_latency_ns) {
@@ -1032,9 +1043,12 @@ static void patch_bounding_box(struct dc *dc, struct _vcs_dpi_soc_bounding_box_s
        }
 
        if (dc->bb_overrides.dram_clock_change_latency_ns) {
-               bb->dram_clock_change_latency_us =
+               for (i = 0; i < WM_SET_COUNT; i++) {
+                       dc->clk_mgr->bw_params->wm_table.entries[i].pstate_latency_us =
                                dc->bb_overrides.dram_clock_change_latency_ns / 1000.0;
+               }
        }
+
        kernel_fpu_end();
 }
 
index 9707372..641ffb7 100644 (file)
@@ -1,3 +1,4 @@
+# SPDX-License-Identifier: MIT
 #
 # Makefile for the 'dsc' sub-component of DAL.
 
index 4e18e77..026e6a2 100644 (file)
@@ -69,6 +69,8 @@ struct wm_range_table_entry {
        unsigned int wm_inst;
        unsigned int wm_type;
        double pstate_latency_us;
+       double sr_exit_time_us;
+       double sr_enter_plus_exit_time_us;
        bool valid;
 };
 
index bb012cb..c7fbb9c 100644 (file)
@@ -42,7 +42,7 @@ struct aux_payload {
        bool write;
        bool mot;
        uint32_t address;
-       uint8_t length;
+       uint32_t length;
        uint8_t *data;
        /*
         * used to return the reply type of the transaction
index 16e69bb..5437b50 100644 (file)
@@ -37,8 +37,8 @@
 #define STATIC_SCREEN_RAMP_DELTA_REFRESH_RATE_PER_FRAME ((1000 / 60) * 65)
 /* Number of elements in the render times cache array */
 #define RENDER_TIMES_MAX_COUNT 10
-/* Threshold to exit/exit BTR (to avoid frequent enter-exits at the lower limit) */
-#define BTR_MAX_MARGIN 2500
+/* Threshold to exit BTR (to avoid frequent enter-exits at the lower limit) */
+#define BTR_EXIT_MARGIN 2000
 /* Threshold to change BTR multiplier (to avoid frequent changes) */
 #define BTR_DRIFT_MARGIN 2000
 /*Threshold to exit fixed refresh rate*/
@@ -254,22 +254,24 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
        unsigned int delta_from_mid_point_in_us_1 = 0xFFFFFFFF;
        unsigned int delta_from_mid_point_in_us_2 = 0xFFFFFFFF;
        unsigned int frames_to_insert = 0;
+       unsigned int min_frame_duration_in_ns = 0;
+       unsigned int max_render_time_in_us = in_out_vrr->max_duration_in_us;
        unsigned int delta_from_mid_point_delta_in_us;
-       unsigned int max_render_time_in_us =
-                       in_out_vrr->max_duration_in_us - in_out_vrr->btr.margin_in_us;
+
+       min_frame_duration_in_ns = ((unsigned int) (div64_u64(
+               (1000000000ULL * 1000000),
+               in_out_vrr->max_refresh_in_uhz)));
 
        /* Program BTR */
-       if ((last_render_time_in_us + in_out_vrr->btr.margin_in_us / 2) < max_render_time_in_us) {
+       if (last_render_time_in_us + BTR_EXIT_MARGIN < max_render_time_in_us) {
                /* Exit Below the Range */
                if (in_out_vrr->btr.btr_active) {
                        in_out_vrr->btr.frame_counter = 0;
                        in_out_vrr->btr.btr_active = false;
                }
-       } else if (last_render_time_in_us > (max_render_time_in_us + in_out_vrr->btr.margin_in_us / 2)) {
+       } else if (last_render_time_in_us > max_render_time_in_us) {
                /* Enter Below the Range */
-               if (!in_out_vrr->btr.btr_active) {
-                       in_out_vrr->btr.btr_active = true;
-               }
+               in_out_vrr->btr.btr_active = true;
        }
 
        /* BTR set to "not active" so disengage */
@@ -325,9 +327,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
                /* Choose number of frames to insert based on how close it
                 * can get to the mid point of the variable range.
                 */
-               if ((frame_time_in_us / mid_point_frames_ceil) > in_out_vrr->min_duration_in_us &&
-                               (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2 ||
-                                               mid_point_frames_floor < 2)) {
+               if (delta_from_mid_point_in_us_1 < delta_from_mid_point_in_us_2) {
                        frames_to_insert = mid_point_frames_ceil;
                        delta_from_mid_point_delta_in_us = delta_from_mid_point_in_us_2 -
                                        delta_from_mid_point_in_us_1;
@@ -343,7 +343,7 @@ static void apply_below_the_range(struct core_freesync *core_freesync,
                if (in_out_vrr->btr.frames_to_insert != 0 &&
                                delta_from_mid_point_delta_in_us < BTR_DRIFT_MARGIN) {
                        if (((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) <
-                                       max_render_time_in_us) &&
+                                       in_out_vrr->max_duration_in_us) &&
                                ((last_render_time_in_us / in_out_vrr->btr.frames_to_insert) >
                                        in_out_vrr->min_duration_in_us))
                                frames_to_insert = in_out_vrr->btr.frames_to_insert;
@@ -796,11 +796,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
                refresh_range = in_out_vrr->max_refresh_in_uhz -
                                in_out_vrr->min_refresh_in_uhz;
 
-               in_out_vrr->btr.margin_in_us = in_out_vrr->max_duration_in_us -
-                               2 * in_out_vrr->min_duration_in_us;
-               if (in_out_vrr->btr.margin_in_us > BTR_MAX_MARGIN)
-                       in_out_vrr->btr.margin_in_us = BTR_MAX_MARGIN;
-
                in_out_vrr->supported = true;
        }
 
@@ -816,7 +811,6 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
        in_out_vrr->btr.inserted_duration_in_us = 0;
        in_out_vrr->btr.frames_to_insert = 0;
        in_out_vrr->btr.frame_counter = 0;
-
        in_out_vrr->btr.mid_point_in_us =
                                (in_out_vrr->min_duration_in_us +
                                 in_out_vrr->max_duration_in_us) / 2;
index dbe7835..dc18784 100644 (file)
@@ -92,7 +92,6 @@ struct mod_vrr_params_btr {
        uint32_t inserted_duration_in_us;
        uint32_t frames_to_insert;
        uint32_t frame_counter;
-       uint32_t margin_in_us;
 };
 
 struct mod_vrr_params_fixed_refresh {
index 5ff7cce..a23729d 100644 (file)
@@ -866,6 +866,7 @@ static int smu_sw_init(void *handle)
        smu->smu_baco.platform_support = false;
 
        mutex_init(&smu->sensor_lock);
+       mutex_init(&smu->metrics_lock);
 
        smu->watermarks_bitmap = 0;
        smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
index ce3566c..472e9fe 100644 (file)
@@ -862,18 +862,21 @@ static int arcturus_get_metrics_table(struct smu_context *smu,
        struct smu_table_context *smu_table= &smu->smu_table;
        int ret = 0;
 
+       mutex_lock(&smu->metrics_lock);
        if (!smu_table->metrics_time ||
             time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
                ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
                                (void *)smu_table->metrics_table, false);
                if (ret) {
                        pr_info("Failed to export SMU metrics table!\n");
+                       mutex_unlock(&smu->metrics_lock);
                        return ret;
                }
                smu_table->metrics_time = jiffies;
        }
 
        memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+       mutex_unlock(&smu->metrics_lock);
 
        return ret;
 }
@@ -1313,12 +1316,17 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
                                        "VR",
                                        "COMPUTE",
                                        "CUSTOM"};
+       static const char *title[] = {
+                       "PROFILE_INDEX(NAME)"};
        uint32_t i, size = 0;
        int16_t workload_type = 0;
 
        if (!smu->pm_enabled || !buf)
                return -EINVAL;
 
+       size += sprintf(buf + size, "%16s\n",
+                       title[0]);
+
        for (i = 0; i <= PP_SMC_POWER_PROFILE_CUSTOM; i++) {
                /*
                 * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
index ac97583..41fce75 100644 (file)
@@ -349,6 +349,7 @@ struct smu_context
        const struct pptable_funcs      *ppt_funcs;
        struct mutex                    mutex;
        struct mutex                    sensor_lock;
+       struct mutex                    metrics_lock;
        uint64_t pool_size;
 
        struct smu_table_context        smu_table;
index 4a14fd1..ca62e92 100644 (file)
@@ -562,17 +562,20 @@ static int navi10_get_metrics_table(struct smu_context *smu,
        struct smu_table_context *smu_table= &smu->smu_table;
        int ret = 0;
 
+       mutex_lock(&smu->metrics_lock);
        if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + msecs_to_jiffies(100))) {
                ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
                                (void *)smu_table->metrics_table, false);
                if (ret) {
                        pr_info("Failed to export SMU metrics table!\n");
+                       mutex_unlock(&smu->metrics_lock);
                        return ret;
                }
                smu_table->metrics_time = jiffies;
        }
 
        memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+       mutex_unlock(&smu->metrics_lock);
 
        return ret;
 }
index 60b9ff0..0d3a3b0 100644 (file)
@@ -1678,17 +1678,20 @@ static int vega20_get_metrics_table(struct smu_context *smu,
        struct smu_table_context *smu_table= &smu->smu_table;
        int ret = 0;
 
+       mutex_lock(&smu->metrics_lock);
        if (!smu_table->metrics_time || time_after(jiffies, smu_table->metrics_time + HZ / 1000)) {
                ret = smu_update_table(smu, SMU_TABLE_SMU_METRICS, 0,
                                (void *)smu_table->metrics_table, false);
                if (ret) {
                        pr_info("Failed to export SMU metrics table!\n");
+                       mutex_unlock(&smu->metrics_lock);
                        return ret;
                }
                smu_table->metrics_time = jiffies;
        }
 
        memcpy(metrics_table, smu_table->metrics_table, sizeof(SmuMetrics_t));
+       mutex_unlock(&smu->metrics_lock);
 
        return ret;
 }
index 875a3a9..7d0e7b0 100644 (file)
@@ -56,7 +56,7 @@ malidp_mw_connector_mode_valid(struct drm_connector *connector,
        return MODE_OK;
 }
 
-const struct drm_connector_helper_funcs malidp_mw_connector_helper_funcs = {
+static const struct drm_connector_helper_funcs malidp_mw_connector_helper_funcs = {
        .get_modes = malidp_mw_connector_get_modes,
        .mode_valid = malidp_mw_connector_mode_valid,
 };
index 273dd80..5a61a55 100644 (file)
@@ -393,7 +393,7 @@ drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,
                        memcpy(&buf[idx], req->u.i2c_read.transactions[i].bytes, req->u.i2c_read.transactions[i].num_bytes);
                        idx += req->u.i2c_read.transactions[i].num_bytes;
 
-                       buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 5;
+                       buf[idx] = (req->u.i2c_read.transactions[i].no_stop_bit & 0x1) << 4;
                        buf[idx] |= (req->u.i2c_read.transactions[i].i2c_transaction_delay & 0xf);
                        idx++;
                }
@@ -1190,6 +1190,8 @@ static int drm_dp_mst_wait_tx_reply(struct drm_dp_mst_branch *mstb,
                    txmsg->state == DRM_DP_SIDEBAND_TX_SENT) {
                        mstb->tx_slots[txmsg->seqno] = NULL;
                }
+               mgr->is_waiting_for_dwn_reply = false;
+
        }
 out:
        if (unlikely(ret == -EIO) && drm_debug_enabled(DRM_UT_DP)) {
@@ -1199,6 +1201,7 @@ out:
        }
        mutex_unlock(&mgr->qlock);
 
+       drm_dp_mst_kick_tx(mgr);
        return ret;
 }
 
@@ -2318,7 +2321,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
 {
        struct drm_dp_mst_topology_mgr *mgr = mstb->mgr;
        struct drm_dp_mst_port *port;
-       int old_ddps, ret;
+       int old_ddps, old_input, ret, i;
        u8 new_pdt;
        bool dowork = false, create_connector = false;
 
@@ -2349,6 +2352,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
        }
 
        old_ddps = port->ddps;
+       old_input = port->input;
        port->input = conn_stat->input_port;
        port->mcs = conn_stat->message_capability_status;
        port->ldps = conn_stat->legacy_device_plug_status;
@@ -2373,6 +2377,28 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb,
                dowork = false;
        }
 
+       if (!old_input && old_ddps != port->ddps && !port->ddps) {
+               for (i = 0; i < mgr->max_payloads; i++) {
+                       struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i];
+                       struct drm_dp_mst_port *port_validated;
+
+                       if (!vcpi)
+                               continue;
+
+                       port_validated =
+                               container_of(vcpi, struct drm_dp_mst_port, vcpi);
+                       port_validated =
+                               drm_dp_mst_topology_get_port_validated(mgr, port_validated);
+                       if (!port_validated) {
+                               mutex_lock(&mgr->payload_lock);
+                               vcpi->num_slots = 0;
+                               mutex_unlock(&mgr->payload_lock);
+                       } else {
+                               drm_dp_mst_topology_put_port(port_validated);
+                       }
+               }
+       }
+
        if (port->connector)
                drm_modeset_unlock(&mgr->base.lock);
        else if (create_connector)
@@ -2718,9 +2744,11 @@ static void process_single_down_tx_qlock(struct drm_dp_mst_topology_mgr *mgr)
        ret = process_single_tx_qlock(mgr, txmsg, false);
        if (ret == 1) {
                /* txmsg is sent it should be in the slots now */
+               mgr->is_waiting_for_dwn_reply = true;
                list_del(&txmsg->next);
        } else if (ret) {
                DRM_DEBUG_KMS("failed to send msg in q %d\n", ret);
+               mgr->is_waiting_for_dwn_reply = false;
                list_del(&txmsg->next);
                if (txmsg->seqno != -1)
                        txmsg->dst->tx_slots[txmsg->seqno] = NULL;
@@ -2760,7 +2788,8 @@ static void drm_dp_queue_down_tx(struct drm_dp_mst_topology_mgr *mgr,
                drm_dp_mst_dump_sideband_msg_tx(&p, txmsg);
        }
 
-       if (list_is_singular(&mgr->tx_msg_downq))
+       if (list_is_singular(&mgr->tx_msg_downq) &&
+           !mgr->is_waiting_for_dwn_reply)
                process_single_down_tx_qlock(mgr);
        mutex_unlock(&mgr->qlock);
 }
@@ -3678,6 +3707,7 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
        mutex_lock(&mgr->qlock);
        txmsg->state = DRM_DP_SIDEBAND_TX_RX;
        mstb->tx_slots[slot] = NULL;
+       mgr->is_waiting_for_dwn_reply = false;
        mutex_unlock(&mgr->qlock);
 
        wake_up_all(&mgr->tx_waitq);
@@ -3687,6 +3717,9 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
 no_msg:
        drm_dp_mst_topology_put_mstb(mstb);
 clear_down_rep_recv:
+       mutex_lock(&mgr->qlock);
+       mgr->is_waiting_for_dwn_reply = false;
+       mutex_unlock(&mgr->qlock);
        memset(&mgr->down_rep_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
 
        return 0;
@@ -4497,7 +4530,7 @@ static void drm_dp_tx_work(struct work_struct *work)
        struct drm_dp_mst_topology_mgr *mgr = container_of(work, struct drm_dp_mst_topology_mgr, tx_work);
 
        mutex_lock(&mgr->qlock);
-       if (!list_empty(&mgr->tx_msg_downq))
+       if (!list_empty(&mgr->tx_msg_downq) && !mgr->is_waiting_for_dwn_reply)
                process_single_down_tx_qlock(mgr);
        mutex_unlock(&mgr->qlock);
 }
index 8ebeccd..d8e8f39 100644 (file)
@@ -1283,7 +1283,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
         * Changes struct fb_var_screeninfo are currently not pushed back
         * to KMS, hence fail if different settings are requested.
         */
-       if (var->bits_per_pixel != fb->format->cpp[0] * 8 ||
+       if (var->bits_per_pixel > fb->format->cpp[0] * 8 ||
            var->xres > fb->width || var->yres > fb->height ||
            var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
                DRM_DEBUG("fb requested width/height/bpp can't fit in current fb "
@@ -1309,6 +1309,11 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
        }
 
        /*
+        * Likewise, bits_per_pixel should be rounded up to a supported value.
+        */
+       var->bits_per_pixel = fb->format->cpp[0] * 8;
+
+       /*
         * drm fbdev emulation doesn't support changing the pixel format at all,
         * so reject all pixel format changing requests.
         */
index 7ae087b..88b6fca 100644 (file)
@@ -1313,6 +1313,7 @@ static int gsc_remove(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
 
+       component_del(dev, &gsc_component_ops);
        pm_runtime_dont_use_autosuspend(dev);
        pm_runtime_disable(dev);
 
index 85e6b2b..3a5ac13 100644 (file)
@@ -856,7 +856,7 @@ static unsigned long i915_audio_component_get_power(struct device *kdev)
                }
 
                /* Force CDCLK to 2*BCLK as long as we need audio powered. */
-               if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               if (IS_GEMINILAKE(dev_priv))
                        glk_force_audio_cdclk(dev_priv, true);
 
                if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
@@ -875,7 +875,7 @@ static void i915_audio_component_put_power(struct device *kdev,
 
        /* Stop forcing CDCLK to 2*BCLK if no need for audio to be powered. */
        if (--dev_priv->audio_power_refcount == 0)
-               if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
+               if (IS_GEMINILAKE(dev_priv))
                        glk_force_audio_cdclk(dev_priv, false);
 
        intel_display_power_put(dev_priv, POWER_DOMAIN_AUDIO, cookie);
index c7c2b34..2a27fb5 100644 (file)
@@ -3986,6 +3986,7 @@ static void intel_enable_ddi(struct intel_encoder *encoder,
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED)
                intel_hdcp_enable(to_intel_connector(conn_state->connector),
+                                 crtc_state->cpu_transcoder,
                                  (u8)conn_state->hdcp_content_type);
 }
 
@@ -4089,7 +4090,9 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder,
        if (conn_state->content_protection ==
            DRM_MODE_CONTENT_PROTECTION_DESIRED ||
            content_protection_type_changed)
-               intel_hdcp_enable(connector, (u8)conn_state->hdcp_content_type);
+               intel_hdcp_enable(connector,
+                                 crtc_state->cpu_transcoder,
+                                 (u8)conn_state->hdcp_content_type);
 }
 
 static void
index 6f5e3bd..3018977 100644 (file)
@@ -4515,8 +4515,6 @@ static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_
 {
        struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->base.crtc);
        struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
-       i915_reg_t reg;
-       u32 trans_ddi_func_ctl2_val;
 
        if (old_crtc_state->master_transcoder == INVALID_TRANSCODER)
                return;
@@ -4524,10 +4522,7 @@ static void icl_disable_transcoder_port_sync(const struct intel_crtc_state *old_
        DRM_DEBUG_KMS("Disabling Transcoder Port Sync on Slave Transcoder %s\n",
                      transcoder_name(old_crtc_state->cpu_transcoder));
 
-       reg = TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder);
-       trans_ddi_func_ctl2_val = ~(PORT_SYNC_MODE_ENABLE |
-                                   PORT_SYNC_MODE_MASTER_SELECT_MASK);
-       I915_WRITE(reg, trans_ddi_func_ctl2_val);
+       I915_WRITE(TRANS_DDI_FUNC_CTL2(old_crtc_state->cpu_transcoder), 0);
 }
 
 static void intel_fdi_normal_train(struct intel_crtc *crtc)
@@ -15112,7 +15107,7 @@ intel_prepare_plane_fb(struct drm_plane *plane,
                return ret;
 
        fb_obj_bump_render_priority(obj);
-       intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_DIRTYFB);
+       i915_gem_object_flush_frontbuffer(obj, ORIGIN_DIRTYFB);
 
        if (!new_plane_state->base.fence) { /* implicit fencing */
                struct dma_fence *fence;
index ce1b64f..12ba747 100644 (file)
@@ -3688,6 +3688,151 @@ static const struct i915_power_well_desc icl_power_wells[] = {
        },
 };
 
+static const struct i915_power_well_desc ehl_power_wells[] = {
+       {
+               .name = "always-on",
+               .always_on = true,
+               .domains = POWER_DOMAIN_MASK,
+               .ops = &i9xx_always_on_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+       },
+       {
+               .name = "power well 1",
+               /* Handled by the DMC firmware */
+               .always_on = true,
+               .domains = 0,
+               .ops = &hsw_power_well_ops,
+               .id = SKL_DISP_PW_1,
+               {
+                       .hsw.regs = &hsw_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_PW_1,
+                       .hsw.has_fuses = true,
+               },
+       },
+       {
+               .name = "DC off",
+               .domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS,
+               .ops = &gen9_dc_off_power_well_ops,
+               .id = SKL_DISP_DC_OFF,
+       },
+       {
+               .name = "power well 2",
+               .domains = ICL_PW_2_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = SKL_DISP_PW_2,
+               {
+                       .hsw.regs = &hsw_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_PW_2,
+                       .hsw.has_fuses = true,
+               },
+       },
+       {
+               .name = "power well 3",
+               .domains = ICL_PW_3_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &hsw_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_PW_3,
+                       .hsw.irq_pipe_mask = BIT(PIPE_B),
+                       .hsw.has_vga = true,
+                       .hsw.has_fuses = true,
+               },
+       },
+       {
+               .name = "DDI A IO",
+               .domains = ICL_DDI_IO_A_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_ddi_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_DDI_A,
+               },
+       },
+       {
+               .name = "DDI B IO",
+               .domains = ICL_DDI_IO_B_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_ddi_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_DDI_B,
+               },
+       },
+       {
+               .name = "DDI C IO",
+               .domains = ICL_DDI_IO_C_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_ddi_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_DDI_C,
+               },
+       },
+       {
+               .name = "DDI D IO",
+               .domains = ICL_DDI_IO_D_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_ddi_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_DDI_D,
+               },
+       },
+       {
+               .name = "AUX A",
+               .domains = ICL_AUX_A_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_aux_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_AUX_A,
+               },
+       },
+       {
+               .name = "AUX B",
+               .domains = ICL_AUX_B_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_aux_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_AUX_B,
+               },
+       },
+       {
+               .name = "AUX C",
+               .domains = ICL_AUX_C_TC1_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_aux_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_AUX_C,
+               },
+       },
+       {
+               .name = "AUX D",
+               .domains = ICL_AUX_D_TC2_IO_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &icl_aux_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_AUX_D,
+               },
+       },
+       {
+               .name = "power well 4",
+               .domains = ICL_PW_4_POWER_DOMAINS,
+               .ops = &hsw_power_well_ops,
+               .id = DISP_PW_ID_NONE,
+               {
+                       .hsw.regs = &hsw_power_well_regs,
+                       .hsw.idx = ICL_PW_CTL_IDX_PW_4,
+                       .hsw.has_fuses = true,
+                       .hsw.irq_pipe_mask = BIT(PIPE_C),
+               },
+       },
+};
+
 static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "always-on",
@@ -3832,7 +3977,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX A",
                .domains = TGL_AUX_A_IO_POWER_DOMAINS,
-               .ops = &icl_combo_phy_aux_power_well_ops,
+               .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -3842,7 +3987,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX B",
                .domains = TGL_AUX_B_IO_POWER_DOMAINS,
-               .ops = &icl_combo_phy_aux_power_well_ops,
+               .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -3852,7 +3997,7 @@ static const struct i915_power_well_desc tgl_power_wells[] = {
        {
                .name = "AUX C",
                .domains = TGL_AUX_C_IO_POWER_DOMAINS,
-               .ops = &icl_combo_phy_aux_power_well_ops,
+               .ops = &hsw_power_well_ops,
                .id = DISP_PW_ID_NONE,
                {
                        .hsw.regs = &icl_aux_power_well_regs,
@@ -4162,6 +4307,8 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv)
         */
        if (IS_GEN(dev_priv, 12)) {
                err = set_power_wells(power_domains, tgl_power_wells);
+       } else if (IS_ELKHARTLAKE(dev_priv)) {
+               err = set_power_wells(power_domains, ehl_power_wells);
        } else if (IS_GEN(dev_priv, 11)) {
                err = set_power_wells(power_domains, icl_power_wells);
        } else if (IS_CANNONLAKE(dev_priv)) {
index 050655a..b05b219 100644 (file)
@@ -2414,9 +2414,6 @@ intel_dp_compute_config(struct intel_encoder *encoder,
 
        intel_psr_compute_config(intel_dp, pipe_config);
 
-       intel_hdcp_transcoder_config(intel_connector,
-                                    pipe_config->cpu_transcoder);
-
        return 0;
 }
 
index 3111eca..2061663 100644 (file)
@@ -1284,7 +1284,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv)
                return 0;
 
        /* https://bugs.freedesktop.org/show_bug.cgi?id=108085 */
-       if (IS_GEMINILAKE(dev_priv))
+       if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))
                return 0;
 
        if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9)
index 84b164f..6cb02c9 100644 (file)
@@ -229,11 +229,11 @@ static void frontbuffer_release(struct kref *ref)
                vma->display_alignment = I915_GTT_MIN_ALIGNMENT;
        spin_unlock(&obj->vma.lock);
 
-       obj->frontbuffer = NULL;
+       RCU_INIT_POINTER(obj->frontbuffer, NULL);
        spin_unlock(&to_i915(obj->base.dev)->fb_tracking.lock);
 
        i915_gem_object_put(obj);
-       kfree(front);
+       kfree_rcu(front, rcu);
 }
 
 struct intel_frontbuffer *
@@ -242,11 +242,7 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
        struct drm_i915_private *i915 = to_i915(obj->base.dev);
        struct intel_frontbuffer *front;
 
-       spin_lock(&i915->fb_tracking.lock);
-       front = obj->frontbuffer;
-       if (front)
-               kref_get(&front->ref);
-       spin_unlock(&i915->fb_tracking.lock);
+       front = __intel_frontbuffer_get(obj);
        if (front)
                return front;
 
@@ -262,13 +258,13 @@ intel_frontbuffer_get(struct drm_i915_gem_object *obj)
                         i915_active_may_sleep(frontbuffer_retire));
 
        spin_lock(&i915->fb_tracking.lock);
-       if (obj->frontbuffer) {
+       if (rcu_access_pointer(obj->frontbuffer)) {
                kfree(front);
-               front = obj->frontbuffer;
+               front = rcu_dereference_protected(obj->frontbuffer, true);
                kref_get(&front->ref);
        } else {
                i915_gem_object_get(obj);
-               obj->frontbuffer = front;
+               rcu_assign_pointer(obj->frontbuffer, front);
        }
        spin_unlock(&i915->fb_tracking.lock);
 
index adc64d6..6d41f53 100644 (file)
 #include <linux/atomic.h>
 #include <linux/kref.h>
 
+#include "gem/i915_gem_object_types.h"
 #include "i915_active.h"
 
 struct drm_i915_private;
-struct drm_i915_gem_object;
 
 enum fb_op_origin {
        ORIGIN_GTT,
@@ -45,6 +45,7 @@ struct intel_frontbuffer {
        atomic_t bits;
        struct i915_active write;
        struct drm_i915_gem_object *obj;
+       struct rcu_head rcu;
 };
 
 void intel_frontbuffer_flip_prepare(struct drm_i915_private *i915,
@@ -54,6 +55,35 @@ void intel_frontbuffer_flip_complete(struct drm_i915_private *i915,
 void intel_frontbuffer_flip(struct drm_i915_private *i915,
                            unsigned frontbuffer_bits);
 
+void intel_frontbuffer_put(struct intel_frontbuffer *front);
+
+static inline struct intel_frontbuffer *
+__intel_frontbuffer_get(const struct drm_i915_gem_object *obj)
+{
+       struct intel_frontbuffer *front;
+
+       if (likely(!rcu_access_pointer(obj->frontbuffer)))
+               return NULL;
+
+       rcu_read_lock();
+       do {
+               front = rcu_dereference(obj->frontbuffer);
+               if (!front)
+                       break;
+
+               if (unlikely(!kref_get_unless_zero(&front->ref)))
+                       continue;
+
+               if (likely(front == rcu_access_pointer(obj->frontbuffer)))
+                       break;
+
+               intel_frontbuffer_put(front);
+       } while (1);
+       rcu_read_unlock();
+
+       return front;
+}
+
 struct intel_frontbuffer *
 intel_frontbuffer_get(struct drm_i915_gem_object *obj);
 
@@ -119,6 +149,4 @@ void intel_frontbuffer_track(struct intel_frontbuffer *old,
                             struct intel_frontbuffer *new,
                             unsigned int frontbuffer_bits);
 
-void intel_frontbuffer_put(struct intel_frontbuffer *front);
-
 #endif /* __INTEL_FRONTBUFFER_H__ */
index f1f41ca..a448815 100644 (file)
@@ -1821,23 +1821,6 @@ enum mei_fw_tc intel_get_mei_fw_tc(enum transcoder cpu_transcoder)
        }
 }
 
-void intel_hdcp_transcoder_config(struct intel_connector *connector,
-                                 enum transcoder cpu_transcoder)
-{
-       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
-       struct intel_hdcp *hdcp = &connector->hdcp;
-
-       if (!hdcp->shim)
-               return;
-
-       if (INTEL_GEN(dev_priv) >= 12) {
-               mutex_lock(&hdcp->mutex);
-               hdcp->cpu_transcoder = cpu_transcoder;
-               hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder);
-               mutex_unlock(&hdcp->mutex);
-       }
-}
-
 static inline int initialize_hdcp_port_data(struct intel_connector *connector,
                                            const struct intel_hdcp_shim *shim)
 {
@@ -1959,8 +1942,10 @@ int intel_hdcp_init(struct intel_connector *connector,
        return 0;
 }
 
-int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
+int intel_hdcp_enable(struct intel_connector *connector,
+                     enum transcoder cpu_transcoder, u8 content_type)
 {
+       struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
        struct intel_hdcp *hdcp = &connector->hdcp;
        unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS;
        int ret = -EINVAL;
@@ -1972,6 +1957,11 @@ int intel_hdcp_enable(struct intel_connector *connector, u8 content_type)
        WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED);
        hdcp->content_type = content_type;
 
+       if (INTEL_GEN(dev_priv) >= 12) {
+               hdcp->cpu_transcoder = cpu_transcoder;
+               hdcp->port_data.fw_tc = intel_get_mei_fw_tc(cpu_transcoder);
+       }
+
        /*
         * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup
         * is capable of HDCP2.2, it is preferred to use HDCP2.2.
index 41c1053..f3c3272 100644 (file)
@@ -21,11 +21,10 @@ enum transcoder;
 void intel_hdcp_atomic_check(struct drm_connector *connector,
                             struct drm_connector_state *old_state,
                             struct drm_connector_state *new_state);
-void intel_hdcp_transcoder_config(struct intel_connector *connector,
-                                 enum transcoder cpu_transcoder);
 int intel_hdcp_init(struct intel_connector *connector,
                    const struct intel_hdcp_shim *hdcp_shim);
-int intel_hdcp_enable(struct intel_connector *connector, u8 content_type);
+int intel_hdcp_enable(struct intel_connector *connector,
+                     enum transcoder cpu_transcoder, u8 content_type);
 int intel_hdcp_disable(struct intel_connector *connector);
 bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port);
 bool intel_hdcp_capable(struct intel_connector *connector);
index f6f5312..f56fffc 100644 (file)
@@ -2489,9 +2489,6 @@ int intel_hdmi_compute_config(struct intel_encoder *encoder,
                return -EINVAL;
        }
 
-       intel_hdcp_transcoder_config(intel_hdmi->attached_connector,
-                                    pipe_config->cpu_transcoder);
-
        return 0;
 }
 
index 848ce07..8a98a1a 100644 (file)
@@ -279,12 +279,21 @@ static void intel_overlay_flip_prepare(struct intel_overlay *overlay,
                                       struct i915_vma *vma)
 {
        enum pipe pipe = overlay->crtc->pipe;
+       struct intel_frontbuffer *from = NULL, *to = NULL;
 
        WARN_ON(overlay->old_vma);
 
-       intel_frontbuffer_track(overlay->vma ? overlay->vma->obj->frontbuffer : NULL,
-                               vma ? vma->obj->frontbuffer : NULL,
-                               INTEL_FRONTBUFFER_OVERLAY(pipe));
+       if (overlay->vma)
+               from = intel_frontbuffer_get(overlay->vma->obj);
+       if (vma)
+               to = intel_frontbuffer_get(vma->obj);
+
+       intel_frontbuffer_track(from, to, INTEL_FRONTBUFFER_OVERLAY(pipe));
+
+       if (to)
+               intel_frontbuffer_put(to);
+       if (from)
+               intel_frontbuffer_put(from);
 
        intel_frontbuffer_flip_prepare(overlay->i915,
                                       INTEL_FRONTBUFFER_OVERLAY(pipe));
@@ -766,7 +775,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
                ret = PTR_ERR(vma);
                goto out_pin_section;
        }
-       intel_frontbuffer_flush(new_bo->frontbuffer, ORIGIN_DIRTYFB);
+       i915_gem_object_flush_frontbuffer(new_bo, ORIGIN_DIRTYFB);
 
        if (!overlay->active) {
                u32 oconfig;
index b9f504b..18ee708 100644 (file)
@@ -20,7 +20,8 @@ static void __do_clflush(struct drm_i915_gem_object *obj)
 {
        GEM_BUG_ON(!i915_gem_object_has_pages(obj));
        drm_clflush_sg(obj->mm.pages);
-       intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+
+       i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 }
 
 static int clflush_work(struct dma_fence_work *base)
index 337ba17..4238527 100644 (file)
@@ -2167,8 +2167,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
        ext_data.fpriv = file->driver_priv;
        if (client_is_banned(ext_data.fpriv)) {
                DRM_DEBUG("client %s[%d] banned from creating ctx\n",
-                         current->comm,
-                         pid_nr(get_task_pid(current, PIDTYPE_PID)));
+                         current->comm, task_pid_nr(current));
                return -EIO;
        }
 
index 9937b4c..f86400a 100644 (file)
@@ -664,7 +664,7 @@ i915_gem_set_domain_ioctl(struct drm_device *dev, void *data,
        i915_gem_object_unlock(obj);
 
        if (write_domain)
-               intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+               i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
 out_unpin:
        i915_gem_object_unpin_pages(obj);
@@ -784,7 +784,7 @@ int i915_gem_object_prepare_write(struct drm_i915_gem_object *obj,
        }
 
 out:
-       intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+       i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
        obj->mm.dirty = true;
        /* return with the pages pinned */
        return 0;
index f0998f1..bc3a672 100644 (file)
@@ -2694,6 +2694,7 @@ i915_gem_do_execbuffer(struct drm_device *dev,
        err = eb_submit(&eb);
 err_request:
        add_to_client(eb.request, file);
+       i915_request_get(eb.request);
        i915_request_add(eb.request);
 
        if (fences)
@@ -2709,6 +2710,7 @@ err_request:
                        fput(out_fence->file);
                }
        }
+       i915_request_put(eb.request);
 
 err_batch_unpin:
        if (eb.batch_flags & I915_DISPATCH_SECURE)
index a50296c..a596548 100644 (file)
@@ -280,7 +280,7 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
                for_each_ggtt_vma(vma, obj)
                        intel_gt_flush_ggtt_writes(vma->vm->gt);
 
-               intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+               i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 
                for_each_ggtt_vma(vma, obj) {
                        if (vma->iomap)
@@ -308,6 +308,30 @@ i915_gem_object_flush_write_domain(struct drm_i915_gem_object *obj,
        obj->write_domain = 0;
 }
 
+void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+                                        enum fb_op_origin origin)
+{
+       struct intel_frontbuffer *front;
+
+       front = __intel_frontbuffer_get(obj);
+       if (front) {
+               intel_frontbuffer_flush(front, origin);
+               intel_frontbuffer_put(front);
+       }
+}
+
+void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+                                             enum fb_op_origin origin)
+{
+       struct intel_frontbuffer *front;
+
+       front = __intel_frontbuffer_get(obj);
+       if (front) {
+               intel_frontbuffer_invalidate(front, origin);
+               intel_frontbuffer_put(front);
+       }
+}
+
 void i915_gem_init__objects(struct drm_i915_private *i915)
 {
        INIT_WORK(&i915->mm.free_work, __i915_gem_free_work);
index 458cd51..4b93591 100644 (file)
@@ -13,8 +13,8 @@
 
 #include <drm/i915_drm.h>
 
+#include "display/intel_frontbuffer.h"
 #include "i915_gem_object_types.h"
-
 #include "i915_gem_gtt.h"
 
 void i915_gem_init__objects(struct drm_i915_private *i915);
@@ -463,4 +463,25 @@ int i915_gem_object_wait_priority(struct drm_i915_gem_object *obj,
                                  unsigned int flags,
                                  const struct i915_sched_attr *attr);
 
+void __i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+                                        enum fb_op_origin origin);
+void __i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+                                             enum fb_op_origin origin);
+
+static inline void
+i915_gem_object_flush_frontbuffer(struct drm_i915_gem_object *obj,
+                                 enum fb_op_origin origin)
+{
+       if (unlikely(rcu_access_pointer(obj->frontbuffer)))
+               __i915_gem_object_flush_frontbuffer(obj, origin);
+}
+
+static inline void
+i915_gem_object_invalidate_frontbuffer(struct drm_i915_gem_object *obj,
+                                      enum fb_op_origin origin)
+{
+       if (unlikely(rcu_access_pointer(obj->frontbuffer)))
+               __i915_gem_object_invalidate_frontbuffer(obj, origin);
+}
+
 #endif
index 9600837..e3f3944 100644 (file)
@@ -150,7 +150,7 @@ struct drm_i915_gem_object {
         */
        u16 write_domain;
 
-       struct intel_frontbuffer *frontbuffer;
+       struct intel_frontbuffer __rcu *frontbuffer;
 
        /** Current tiling stride for the object, if it's tiled. */
        unsigned int tiling_and_stride;
index ef7bc41..5b7ff3c 100644 (file)
@@ -123,6 +123,10 @@ static int __context_pin_state(struct i915_vma *vma)
        if (err)
                return err;
 
+       err = i915_active_acquire(&vma->active);
+       if (err)
+               goto err_unpin;
+
        /*
         * And mark it as a globally pinned object to let the shrinker know
         * it cannot reclaim the object until we release it.
@@ -131,14 +135,44 @@ static int __context_pin_state(struct i915_vma *vma)
        vma->obj->mm.dirty = true;
 
        return 0;
+
+err_unpin:
+       i915_vma_unpin(vma);
+       return err;
 }
 
 static void __context_unpin_state(struct i915_vma *vma)
 {
        i915_vma_make_shrinkable(vma);
+       i915_active_release(&vma->active);
        __i915_vma_unpin(vma);
 }
 
+static int __ring_active(struct intel_ring *ring)
+{
+       int err;
+
+       err = i915_active_acquire(&ring->vma->active);
+       if (err)
+               return err;
+
+       err = intel_ring_pin(ring);
+       if (err)
+               goto err_active;
+
+       return 0;
+
+err_active:
+       i915_active_release(&ring->vma->active);
+       return err;
+}
+
+static void __ring_retire(struct intel_ring *ring)
+{
+       intel_ring_unpin(ring);
+       i915_active_release(&ring->vma->active);
+}
+
 __i915_active_call
 static void __intel_context_retire(struct i915_active *active)
 {
@@ -151,7 +185,7 @@ static void __intel_context_retire(struct i915_active *active)
                __context_unpin_state(ce->state);
 
        intel_timeline_unpin(ce->timeline);
-       intel_ring_unpin(ce->ring);
+       __ring_retire(ce->ring);
 
        intel_context_put(ce);
 }
@@ -163,7 +197,7 @@ static int __intel_context_active(struct i915_active *active)
 
        intel_context_get(ce);
 
-       err = intel_ring_pin(ce->ring);
+       err = __ring_active(ce->ring);
        if (err)
                goto err_put;
 
@@ -183,7 +217,7 @@ static int __intel_context_active(struct i915_active *active)
 err_timeline:
        intel_timeline_unpin(ce->timeline);
 err_ring:
-       intel_ring_unpin(ce->ring);
+       __ring_retire(ce->ring);
 err_put:
        intel_context_put(ce);
        return err;
index a459a42..7e64b7d 100644 (file)
@@ -94,8 +94,9 @@ static int __gt_park(struct intel_wakeref *wf)
                intel_uncore_forcewake_put(&i915->uncore, FORCEWAKE_ALL);
        }
 
+       /* Defer dropping the display power well for 100ms, it's slow! */
        GEM_BUG_ON(!wakeref);
-       intel_display_power_put(i915, POWER_DOMAIN_GT_IRQ, wakeref);
+       intel_display_power_put_async(i915, POWER_DOMAIN_GT_IRQ, wakeref);
 
        i915_globals_park();
 
index 9fdefbd..d925a10 100644 (file)
@@ -845,12 +845,6 @@ static const u8 *reg_offsets(const struct intel_engine_cs *engine)
        }
 }
 
-static void unwind_wa_tail(struct i915_request *rq)
-{
-       rq->tail = intel_ring_wrap(rq->ring, rq->wa_tail - WA_TAIL_BYTES);
-       assert_ring_tail_valid(rq->ring, rq->tail);
-}
-
 static struct i915_request *
 __unwind_incomplete_requests(struct intel_engine_cs *engine)
 {
@@ -863,12 +857,10 @@ __unwind_incomplete_requests(struct intel_engine_cs *engine)
        list_for_each_entry_safe_reverse(rq, rn,
                                         &engine->active.requests,
                                         sched.link) {
-
                if (i915_request_completed(rq))
                        continue; /* XXX */
 
                __i915_request_unsubmit(rq);
-               unwind_wa_tail(rq);
 
                /*
                 * Push the request back into the queue for later resubmission.
@@ -1161,13 +1153,29 @@ execlists_schedule_out(struct i915_request *rq)
        i915_request_put(rq);
 }
 
-static u64 execlists_update_context(const struct i915_request *rq)
+static u64 execlists_update_context(struct i915_request *rq)
 {
        struct intel_context *ce = rq->hw_context;
-       u64 desc;
+       u64 desc = ce->lrc_desc;
+       u32 tail;
 
-       ce->lrc_reg_state[CTX_RING_TAIL] =
-               intel_ring_set_tail(rq->ring, rq->tail);
+       /*
+        * WaIdleLiteRestore:bdw,skl
+        *
+        * We should never submit the context with the same RING_TAIL twice
+        * just in case we submit an empty ring, which confuses the HW.
+        *
+        * We append a couple of NOOPs (gen8_emit_wa_tail) after the end of
+        * the normal request to be able to always advance the RING_TAIL on
+        * subsequent resubmissions (for lite restore). Should that fail us,
+        * and we try and submit the same tail again, force the context
+        * reload.
+        */
+       tail = intel_ring_set_tail(rq->ring, rq->tail);
+       if (unlikely(ce->lrc_reg_state[CTX_RING_TAIL] == tail))
+               desc |= CTX_DESC_FORCE_RESTORE;
+       ce->lrc_reg_state[CTX_RING_TAIL] = tail;
+       rq->tail = rq->wa_tail;
 
        /*
         * Make sure the context image is complete before we submit it to HW.
@@ -1186,13 +1194,11 @@ static u64 execlists_update_context(const struct i915_request *rq)
         */
        mb();
 
-       desc = ce->lrc_desc;
-       ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
-
        /* Wa_1607138340:tgl */
        if (IS_TGL_REVID(rq->i915, TGL_REVID_A0, TGL_REVID_A0))
                desc |= CTX_DESC_FORCE_RESTORE;
 
+       ce->lrc_desc &= ~CTX_DESC_FORCE_RESTORE;
        return desc;
 }
 
@@ -1703,16 +1709,6 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
 
                                return;
                        }
-
-                       /*
-                        * WaIdleLiteRestore:bdw,skl
-                        * Apply the wa NOOPs to prevent
-                        * ring:HEAD == rq:TAIL as we resubmit the
-                        * request. See gen8_emit_fini_breadcrumb() for
-                        * where we prepare the padding after the
-                        * end of the request.
-                        */
-                       last->tail = last->wa_tail;
                }
        }
 
@@ -2668,6 +2664,14 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch)
        /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt,glk */
        batch = gen8_emit_flush_coherentl3_wa(engine, batch);
 
+       /* WaClearSlmSpaceAtContextSwitch:skl,bxt,kbl,glk,cfl */
+       batch = gen8_emit_pipe_control(batch,
+                                      PIPE_CONTROL_FLUSH_L3 |
+                                      PIPE_CONTROL_STORE_DATA_INDEX |
+                                      PIPE_CONTROL_CS_STALL |
+                                      PIPE_CONTROL_QW_WRITE,
+                                      LRC_PPHWSP_SCRATCH_ADDR);
+
        batch = emit_lri(batch, lri, ARRAY_SIZE(lri));
 
        /* WaMediaPoolStateCmdInWABB:bxt,glk */
@@ -4120,17 +4124,18 @@ static void virtual_context_destroy(struct kref *kref)
        for (n = 0; n < ve->num_siblings; n++) {
                struct intel_engine_cs *sibling = ve->siblings[n];
                struct rb_node *node = &ve->nodes[sibling->id].rb;
+               unsigned long flags;
 
                if (RB_EMPTY_NODE(node))
                        continue;
 
-               spin_lock_irq(&sibling->active.lock);
+               spin_lock_irqsave(&sibling->active.lock, flags);
 
                /* Detachment is lazily performed in the execlists tasklet */
                if (!RB_EMPTY_NODE(node))
                        rb_erase_cached(node, &sibling->execlists.virtual);
 
-               spin_unlock_irq(&sibling->active.lock);
+               spin_unlock_irqrestore(&sibling->active.lock, flags);
        }
        GEM_BUG_ON(__tasklet_is_scheduled(&ve->base.execlists.tasklet));
 
@@ -4419,9 +4424,11 @@ intel_execlists_create_virtual(struct i915_gem_context *ctx,
        ve->base.gt = siblings[0]->gt;
        ve->base.uncore = siblings[0]->uncore;
        ve->base.id = -1;
+
        ve->base.class = OTHER_CLASS;
        ve->base.uabi_class = I915_ENGINE_CLASS_INVALID;
        ve->base.instance = I915_ENGINE_CLASS_INVALID_VIRTUAL;
+       ve->base.uabi_instance = I915_ENGINE_CLASS_INVALID_VIRTUAL;
 
        /*
         * The decision on whether to submit a request using semaphores
index a47d5a7..9302621 100644 (file)
@@ -1413,14 +1413,6 @@ static inline int mi_set_context(struct i915_request *rq, u32 flags)
        int len;
        u32 *cs;
 
-       flags |= MI_MM_SPACE_GTT;
-       if (IS_HASWELL(i915))
-               /* These flags are for resource streamer on HSW+ */
-               flags |= HSW_MI_RS_SAVE_STATE_EN | HSW_MI_RS_RESTORE_STATE_EN;
-       else
-               /* We need to save the extended state for powersaving modes */
-               flags |= MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN;
-
        len = 4;
        if (IS_GEN(i915, 7))
                len += 2 + (num_engines ? 4 * num_engines + 6 : 0);
@@ -1589,22 +1581,21 @@ static int switch_context(struct i915_request *rq)
        }
 
        if (ce->state) {
-               u32 hw_flags;
+               u32 flags;
 
                GEM_BUG_ON(rq->engine->id != RCS0);
 
-               /*
-                * The kernel context(s) is treated as pure scratch and is not
-                * expected to retain any state (as we sacrifice it during
-                * suspend and on resume it may be corrupted). This is ok,
-                * as nothing actually executes using the kernel context; it
-                * is purely used for flushing user contexts.
-                */
-               hw_flags = 0;
-               if (i915_gem_context_is_kernel(rq->gem_context))
-                       hw_flags = MI_RESTORE_INHIBIT;
+               /* For resource streamer on HSW+ and power context elsewhere */
+               BUILD_BUG_ON(HSW_MI_RS_SAVE_STATE_EN != MI_SAVE_EXT_STATE_EN);
+               BUILD_BUG_ON(HSW_MI_RS_RESTORE_STATE_EN != MI_RESTORE_EXT_STATE_EN);
+
+               flags = MI_SAVE_EXT_STATE_EN | MI_MM_SPACE_GTT;
+               if (!i915_gem_context_is_kernel(rq->gem_context))
+                       flags |= MI_RESTORE_EXT_STATE_EN;
+               else
+                       flags |= MI_RESTORE_INHIBIT;
 
-               ret = mi_set_context(rq, hw_flags);
+               ret = mi_set_context(rq, flags);
                if (ret)
                        return ret;
        }
index e451298..2477a1e 100644 (file)
 
 #define GEN8_DECODE_PTE(pte) (pte & GENMASK_ULL(63, 12))
 
+static int vgpu_pin_dma_address(struct intel_vgpu *vgpu,
+                               unsigned long size,
+                               dma_addr_t dma_addr)
+{
+       int ret = 0;
+
+       if (intel_gvt_hypervisor_dma_pin_guest_page(vgpu, dma_addr))
+               ret = -EINVAL;
+
+       return ret;
+}
+
+static void vgpu_unpin_dma_address(struct intel_vgpu *vgpu,
+                                  dma_addr_t dma_addr)
+{
+       intel_gvt_hypervisor_dma_unmap_guest_page(vgpu, dma_addr);
+}
+
 static int vgpu_gem_get_pages(
                struct drm_i915_gem_object *obj)
 {
        struct drm_i915_private *dev_priv = to_i915(obj->base.dev);
+       struct intel_vgpu *vgpu;
        struct sg_table *st;
        struct scatterlist *sg;
-       int i, ret;
+       int i, j, ret;
        gen8_pte_t __iomem *gtt_entries;
        struct intel_vgpu_fb_info *fb_info;
        u32 page_num;
@@ -51,6 +70,10 @@ static int vgpu_gem_get_pages(
        if (WARN_ON(!fb_info))
                return -ENODEV;
 
+       vgpu = fb_info->obj->vgpu;
+       if (WARN_ON(!vgpu))
+               return -ENODEV;
+
        st = kmalloc(sizeof(*st), GFP_KERNEL);
        if (unlikely(!st))
                return -ENOMEM;
@@ -64,21 +87,53 @@ static int vgpu_gem_get_pages(
        gtt_entries = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm +
                (fb_info->start >> PAGE_SHIFT);
        for_each_sg(st->sgl, sg, page_num, i) {
+               dma_addr_t dma_addr =
+                       GEN8_DECODE_PTE(readq(&gtt_entries[i]));
+               if (vgpu_pin_dma_address(vgpu, PAGE_SIZE, dma_addr)) {
+                       ret = -EINVAL;
+                       goto out;
+               }
+
                sg->offset = 0;
                sg->length = PAGE_SIZE;
-               sg_dma_address(sg) =
-                       GEN8_DECODE_PTE(readq(&gtt_entries[i]));
                sg_dma_len(sg) = PAGE_SIZE;
+               sg_dma_address(sg) = dma_addr;
        }
 
        __i915_gem_object_set_pages(obj, st, PAGE_SIZE);
+out:
+       if (ret) {
+               dma_addr_t dma_addr;
+
+               for_each_sg(st->sgl, sg, i, j) {
+                       dma_addr = sg_dma_address(sg);
+                       if (dma_addr)
+                               vgpu_unpin_dma_address(vgpu, dma_addr);
+               }
+               sg_free_table(st);
+               kfree(st);
+       }
+
+       return ret;
 
-       return 0;
 }
 
 static void vgpu_gem_put_pages(struct drm_i915_gem_object *obj,
                struct sg_table *pages)
 {
+       struct scatterlist *sg;
+
+       if (obj->base.dma_buf) {
+               struct intel_vgpu_fb_info *fb_info = obj->gvt_info;
+               struct intel_vgpu_dmabuf_obj *obj = fb_info->obj;
+               struct intel_vgpu *vgpu = obj->vgpu;
+               int i;
+
+               for_each_sg(pages->sgl, sg, fb_info->size, i)
+                       vgpu_unpin_dma_address(vgpu,
+                                              sg_dma_address(sg));
+       }
+
        sg_free_table(pages);
        kfree(pages);
 }
@@ -163,6 +218,7 @@ static struct drm_i915_gem_object *vgpu_create_gem(struct drm_device *dev,
        drm_gem_private_object_init(dev, &obj->base,
                roundup(info->size, PAGE_SIZE));
        i915_gem_object_init(obj, &intel_vgpu_gem_ops, &lock_class);
+       i915_gem_object_set_readonly(obj);
 
        obj->read_domains = I915_GEM_DOMAIN_GTT;
        obj->write_domain = 0;
index bb9fe6b..1043e6d 100644 (file)
@@ -341,6 +341,10 @@ static int gdrst_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
                        gvt_dbg_mmio("vgpu%d: request VCS2 Reset\n", vgpu->id);
                        engine_mask |= BIT(VCS1);
                }
+               if (data & GEN9_GRDOM_GUC) {
+                       gvt_dbg_mmio("vgpu%d: request GUC Reset\n", vgpu->id);
+                       vgpu_vreg_t(vgpu, GUC_STATUS) |= GS_MIA_IN_RESET;
+               }
                engine_mask &= INTEL_INFO(vgpu->gvt->dev_priv)->engine_mask;
        }
 
@@ -1636,6 +1640,16 @@ static int edp_psr_imr_iir_write(struct intel_vgpu *vgpu,
        return 0;
 }
 
+static int guc_status_read(struct intel_vgpu *vgpu,
+                          unsigned int offset, void *p_data,
+                          unsigned int bytes)
+{
+       /* keep MIA_IN_RESET before clearing */
+       read_vreg(vgpu, offset, p_data, bytes);
+       vgpu_vreg(vgpu, offset) &= ~GS_MIA_IN_RESET;
+       return 0;
+}
+
 static int mmio_read_from_hw(struct intel_vgpu *vgpu,
                unsigned int offset, void *p_data, unsigned int bytes)
 {
@@ -2672,6 +2686,8 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
 
        MMIO_DH(EDP_PSR_IMR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write);
        MMIO_DH(EDP_PSR_IIR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write);
+       MMIO_DH(GUC_STATUS, D_ALL, guc_status_read, NULL);
+
        return 0;
 }
 
index 4862fb1..b19a3b1 100644 (file)
@@ -62,6 +62,8 @@ struct intel_gvt_mpt {
                                  unsigned long size, dma_addr_t *dma_addr);
        void (*dma_unmap_guest_page)(unsigned long handle, dma_addr_t dma_addr);
 
+       int (*dma_pin_guest_page)(unsigned long handle, dma_addr_t dma_addr);
+
        int (*map_gfn_to_mfn)(unsigned long handle, unsigned long gfn,
                              unsigned long mfn, unsigned int nr, bool map);
        int (*set_trap_area)(unsigned long handle, u64 start, u64 end,
index 04a5a0d..3259a1f 100644 (file)
@@ -1916,6 +1916,28 @@ err_unlock:
        return ret;
 }
 
+static int kvmgt_dma_pin_guest_page(unsigned long handle, dma_addr_t dma_addr)
+{
+       struct kvmgt_guest_info *info;
+       struct gvt_dma *entry;
+       int ret = 0;
+
+       if (!handle_valid(handle))
+               return -ENODEV;
+
+       info = (struct kvmgt_guest_info *)handle;
+
+       mutex_lock(&info->vgpu->vdev.cache_lock);
+       entry = __gvt_cache_find_dma_addr(info->vgpu, dma_addr);
+       if (entry)
+               kref_get(&entry->ref);
+       else
+               ret = -ENOMEM;
+       mutex_unlock(&info->vgpu->vdev.cache_lock);
+
+       return ret;
+}
+
 static void __gvt_dma_release(struct kref *ref)
 {
        struct gvt_dma *entry = container_of(ref, typeof(*entry), ref);
@@ -2027,6 +2049,7 @@ static struct intel_gvt_mpt kvmgt_mpt = {
        .gfn_to_mfn = kvmgt_gfn_to_pfn,
        .dma_map_guest_page = kvmgt_dma_map_guest_page,
        .dma_unmap_guest_page = kvmgt_dma_unmap_guest_page,
+       .dma_pin_guest_page = kvmgt_dma_pin_guest_page,
        .set_opregion = kvmgt_set_opregion,
        .set_edid = kvmgt_set_edid,
        .get_vfio_device = kvmgt_get_vfio_device,
index 0f94401..9ad224d 100644 (file)
@@ -255,6 +255,21 @@ static inline void intel_gvt_hypervisor_dma_unmap_guest_page(
 }
 
 /**
+ * intel_gvt_hypervisor_dma_pin_guest_page - pin guest dma buf
+ * @vgpu: a vGPU
+ * @dma_addr: guest dma addr
+ *
+ * Returns:
+ * 0 on success, negative error code if failed.
+ */
+static inline int
+intel_gvt_hypervisor_dma_pin_guest_page(struct intel_vgpu *vgpu,
+                                       dma_addr_t dma_addr)
+{
+       return intel_gvt_host.mpt->dma_pin_guest_page(vgpu->handle, dma_addr);
+}
+
+/**
  * intel_gvt_hypervisor_map_gfn_to_mfn - map a GFN region to MFN
  * @vgpu: a vGPU
  * @gfn: guest PFN
index d5a6e4e..85bd9bf 100644 (file)
@@ -212,9 +212,9 @@ static void intel_gvt_update_vgpu_types(struct intel_gvt *gvt)
  */
 void intel_gvt_activate_vgpu(struct intel_vgpu *vgpu)
 {
-       mutex_lock(&vgpu->gvt->lock);
+       mutex_lock(&vgpu->vgpu_lock);
        vgpu->active = true;
-       mutex_unlock(&vgpu->gvt->lock);
+       mutex_unlock(&vgpu->vgpu_lock);
 }
 
 /**
index e29bc13..21aa08f 100644 (file)
@@ -1660,8 +1660,10 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915,
        (IS_BROADWELL(dev_priv) || IS_GEN(dev_priv, 9))
 
 /* WaRsDisableCoarsePowerGating:skl,cnl */
-#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv) \
-       (IS_CANNONLAKE(dev_priv) || IS_GEN(dev_priv, 9))
+#define NEEDS_WaRsDisableCoarsePowerGating(dev_priv)                   \
+       (IS_CANNONLAKE(dev_priv) ||                                     \
+        IS_SKL_GT3(dev_priv) ||                                        \
+        IS_SKL_GT4(dev_priv))
 
 #define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4)
 #define HAS_GMBUS_BURST_READ(dev_priv) (INTEL_GEN(dev_priv) >= 10 || \
index b9eb6b3..905890e 100644 (file)
@@ -45,6 +45,7 @@
 #include "gem/i915_gem_context.h"
 #include "gem/i915_gem_ioctls.h"
 #include "gem/i915_gem_pm.h"
+#include "gt/intel_context.h"
 #include "gt/intel_engine_user.h"
 #include "gt/intel_gt.h"
 #include "gt/intel_gt_pm.h"
@@ -160,7 +161,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
         * We manually control the domain here and pretend that it
         * remains coherent i.e. in the GTT domain, like shmem_pwrite.
         */
-       intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+       i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
        if (copy_from_user(vaddr, user_data, args->size))
                return -EFAULT;
@@ -168,7 +169,7 @@ i915_gem_phys_pwrite(struct drm_i915_gem_object *obj,
        drm_clflush_virt_range(vaddr, args->size);
        intel_gt_chipset_flush(&to_i915(obj->base.dev)->gt);
 
-       intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+       i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
        return 0;
 }
 
@@ -588,7 +589,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
                goto out_unpin;
        }
 
-       intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CPU);
+       i915_gem_object_invalidate_frontbuffer(obj, ORIGIN_CPU);
 
        user_data = u64_to_user_ptr(args->data_ptr);
        offset = args->offset;
@@ -630,7 +631,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj,
                user_data += page_length;
                offset += page_length;
        }
-       intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+       i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
 
        i915_gem_object_unlock_fence(obj, fence);
 out_unpin:
@@ -720,7 +721,7 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
                offset = 0;
        }
 
-       intel_frontbuffer_flush(obj->frontbuffer, ORIGIN_CPU);
+       i915_gem_object_flush_frontbuffer(obj, ORIGIN_CPU);
        i915_gem_object_unlock_fence(obj, fence);
 
        return ret;
@@ -1053,6 +1054,18 @@ out:
        return err;
 }
 
+static int __intel_context_flush_retire(struct intel_context *ce)
+{
+       struct intel_timeline *tl;
+
+       tl = intel_context_timeline_lock(ce);
+       if (IS_ERR(tl))
+               return PTR_ERR(tl);
+
+       intel_context_timeline_unlock(tl);
+       return 0;
+}
+
 static int __intel_engines_record_defaults(struct intel_gt *gt)
 {
        struct i915_request *requests[I915_NUM_ENGINES] = {};
@@ -1121,13 +1134,20 @@ err_rq:
                if (!rq)
                        continue;
 
-               /* We want to be able to unbind the state from the GGTT */
-               GEM_BUG_ON(intel_context_is_pinned(rq->hw_context));
-
+               GEM_BUG_ON(!test_bit(CONTEXT_ALLOC_BIT,
+                                    &rq->hw_context->flags));
                state = rq->hw_context->state;
                if (!state)
                        continue;
 
+               /* Serialise with retirement on another CPU */
+               err = __intel_context_flush_retire(rq->hw_context);
+               if (err)
+                       goto out;
+
+               /* We want to be able to unbind the state from the GGTT */
+               GEM_BUG_ON(intel_context_is_pinned(rq->hw_context));
+
                /*
                 * As we will hold a reference to the logical state, it will
                 * not be torn down with the context, and importantly the
index 6239a9a..c083f51 100644 (file)
@@ -3304,7 +3304,7 @@ void i915_ggtt_disable_guc(struct i915_ggtt *ggtt)
 
 static void ggtt_restore_mappings(struct i915_ggtt *ggtt)
 {
-       struct i915_vma *vma, *vn;
+       struct i915_vma *vma;
        bool flush = false;
        int open;
 
@@ -3319,15 +3319,12 @@ static void ggtt_restore_mappings(struct i915_ggtt *ggtt)
        open = atomic_xchg(&ggtt->vm.open, 0);
 
        /* clflush objects bound into the GGTT and rebind them. */
-       list_for_each_entry_safe(vma, vn, &ggtt->vm.bound_list, vm_link) {
+       list_for_each_entry(vma, &ggtt->vm.bound_list, vm_link) {
                struct drm_i915_gem_object *obj = vma->obj;
 
                if (!i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND))
                        continue;
 
-               if (!__i915_vma_unbind(vma))
-                       continue;
-
                clear_bit(I915_VMA_GLOBAL_BIND_BIT, __i915_vma_flags(vma));
                WARN_ON(i915_vma_bind(vma,
                                      obj ? obj->cache_level : 0,
index 65d7c2e..2ae14bc 100644 (file)
@@ -2078,20 +2078,12 @@ gen8_update_reg_state_unlocked(const struct intel_context *ce,
        u32 *reg_state = ce->lrc_reg_state;
        int i;
 
-       if (IS_GEN(stream->perf->i915, 12)) {
-               u32 format = stream->oa_buffer.format;
+       reg_state[ctx_oactxctrl + 1] =
+               (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
+               (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
+               GEN8_OA_COUNTER_RESUME;
 
-               reg_state[ctx_oactxctrl + 1] =
-                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
-                       (stream->oa_config ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0);
-       } else {
-               reg_state[ctx_oactxctrl + 1] =
-                       (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
-                       (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
-                       GEN8_OA_COUNTER_RESUME;
-       }
-
-       for (i = 0; !!ctx_flexeu0 && i < ARRAY_SIZE(flex_regs); i++)
+       for (i = 0; i < ARRAY_SIZE(flex_regs); i++)
                reg_state[ctx_flexeu0 + i * 2 + 1] =
                        oa_config_flex_reg(stream->oa_config, flex_regs[i]);
 
@@ -2224,34 +2216,51 @@ static int gen8_configure_context(struct i915_gem_context *ctx,
        return err;
 }
 
-static int gen12_emit_oar_config(struct intel_context *ce, bool enable)
+static int gen12_configure_oar_context(struct i915_perf_stream *stream, bool enable)
 {
-       struct i915_request *rq;
-       u32 *cs;
-       int err = 0;
-
-       rq = i915_request_create(ce);
-       if (IS_ERR(rq))
-               return PTR_ERR(rq);
-
-       cs = intel_ring_begin(rq, 4);
-       if (IS_ERR(cs)) {
-               err = PTR_ERR(cs);
-               goto out;
-       }
-
-       *cs++ = MI_LOAD_REGISTER_IMM(1);
-       *cs++ = i915_mmio_reg_offset(RING_CONTEXT_CONTROL(ce->engine->mmio_base));
-       *cs++ = _MASKED_FIELD(GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE,
-                             enable ? GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE : 0);
-       *cs++ = MI_NOOP;
+       int err;
+       struct intel_context *ce = stream->pinned_ctx;
+       u32 format = stream->oa_buffer.format;
+       struct flex regs_context[] = {
+               {
+                       GEN8_OACTXCONTROL,
+                       stream->perf->ctx_oactxctrl_offset + 1,
+                       enable ? GEN8_OA_COUNTER_RESUME : 0,
+               },
+       };
+       /* Offsets in regs_lri are not used since this configuration is only
+        * applied using LRI. Initialize the correct offsets for posterity.
+        */
+#define GEN12_OAR_OACONTROL_OFFSET 0x5B0
+       struct flex regs_lri[] = {
+               {
+                       GEN12_OAR_OACONTROL,
+                       GEN12_OAR_OACONTROL_OFFSET + 1,
+                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
+                       (enable ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0)
+               },
+               {
+                       RING_CONTEXT_CONTROL(ce->engine->mmio_base),
+                       CTX_CONTEXT_CONTROL,
+                       _MASKED_FIELD(GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE,
+                                     enable ?
+                                     GEN12_CTX_CTRL_OAR_CONTEXT_ENABLE :
+                                     0)
+               },
+       };
 
-       intel_ring_advance(rq, cs);
+       /* Modify the context image of pinned context with regs_context*/
+       err = intel_context_lock_pinned(ce);
+       if (err)
+               return err;
 
-out:
-       i915_request_add(rq);
+       err = gen8_modify_context(ce, regs_context, ARRAY_SIZE(regs_context));
+       intel_context_unlock_pinned(ce);
+       if (err)
+               return err;
 
-       return err;
+       /* Apply regs_lri using LRI with pinned context */
+       return gen8_modify_self(ce, regs_lri, ARRAY_SIZE(regs_lri));
 }
 
 /*
@@ -2277,53 +2286,16 @@ out:
  *   per-context OA state.
  *
  * Note: it's only the RCS/Render context that has any OA state.
+ * Note: the first flex register passed must always be R_PWR_CLK_STATE
  */
-static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
-                                     const struct i915_oa_config *oa_config)
+static int oa_configure_all_contexts(struct i915_perf_stream *stream,
+                                    struct flex *regs,
+                                    size_t num_regs)
 {
        struct drm_i915_private *i915 = stream->perf->i915;
-       /* The MMIO offsets for Flex EU registers aren't contiguous */
-       const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset;
-#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1)
-       struct flex regs[] = {
-               {
-                       GEN8_R_PWR_CLK_STATE,
-                       CTX_R_PWR_CLK_STATE,
-               },
-               {
-                       IS_GEN(i915, 12) ?
-                       GEN12_OAR_OACONTROL : GEN8_OACTXCONTROL,
-                       stream->perf->ctx_oactxctrl_offset + 1,
-               },
-               { EU_PERF_CNTL0, ctx_flexeuN(0) },
-               { EU_PERF_CNTL1, ctx_flexeuN(1) },
-               { EU_PERF_CNTL2, ctx_flexeuN(2) },
-               { EU_PERF_CNTL3, ctx_flexeuN(3) },
-               { EU_PERF_CNTL4, ctx_flexeuN(4) },
-               { EU_PERF_CNTL5, ctx_flexeuN(5) },
-               { EU_PERF_CNTL6, ctx_flexeuN(6) },
-       };
-#undef ctx_flexeuN
        struct intel_engine_cs *engine;
        struct i915_gem_context *ctx, *cn;
-       size_t array_size = IS_GEN(i915, 12) ? 2 : ARRAY_SIZE(regs);
-       int i, err;
-
-       if (IS_GEN(i915, 12)) {
-               u32 format = stream->oa_buffer.format;
-
-               regs[1].value =
-                       (format << GEN12_OAR_OACONTROL_COUNTER_FORMAT_SHIFT) |
-                       (oa_config ? GEN12_OAR_OACONTROL_COUNTER_ENABLE : 0);
-       } else {
-               regs[1].value =
-                       (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
-                       (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
-                       GEN8_OA_COUNTER_RESUME;
-       }
-
-       for (i = 2; !!ctx_flexeu0 && i < array_size; i++)
-               regs[i].value = oa_config_flex_reg(oa_config, regs[i].reg);
+       int err;
 
        lockdep_assert_held(&stream->perf->lock);
 
@@ -2353,7 +2325,7 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
 
                spin_unlock(&i915->gem.contexts.lock);
 
-               err = gen8_configure_context(ctx, regs, array_size);
+               err = gen8_configure_context(ctx, regs, num_regs);
                if (err) {
                        i915_gem_context_put(ctx);
                        return err;
@@ -2378,7 +2350,7 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
 
                regs[0].value = intel_sseu_make_rpcs(i915, &ce->sseu);
 
-               err = gen8_modify_self(ce, regs, array_size);
+               err = gen8_modify_self(ce, regs, num_regs);
                if (err)
                        return err;
        }
@@ -2386,6 +2358,56 @@ static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
        return 0;
 }
 
+static int gen12_configure_all_contexts(struct i915_perf_stream *stream,
+                                       const struct i915_oa_config *oa_config)
+{
+       struct flex regs[] = {
+               {
+                       GEN8_R_PWR_CLK_STATE,
+                       CTX_R_PWR_CLK_STATE,
+               },
+       };
+
+       return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs));
+}
+
+static int lrc_configure_all_contexts(struct i915_perf_stream *stream,
+                                     const struct i915_oa_config *oa_config)
+{
+       /* The MMIO offsets for Flex EU registers aren't contiguous */
+       const u32 ctx_flexeu0 = stream->perf->ctx_flexeu0_offset;
+#define ctx_flexeuN(N) (ctx_flexeu0 + 2 * (N) + 1)
+       struct flex regs[] = {
+               {
+                       GEN8_R_PWR_CLK_STATE,
+                       CTX_R_PWR_CLK_STATE,
+               },
+               {
+                       GEN8_OACTXCONTROL,
+                       stream->perf->ctx_oactxctrl_offset + 1,
+               },
+               { EU_PERF_CNTL0, ctx_flexeuN(0) },
+               { EU_PERF_CNTL1, ctx_flexeuN(1) },
+               { EU_PERF_CNTL2, ctx_flexeuN(2) },
+               { EU_PERF_CNTL3, ctx_flexeuN(3) },
+               { EU_PERF_CNTL4, ctx_flexeuN(4) },
+               { EU_PERF_CNTL5, ctx_flexeuN(5) },
+               { EU_PERF_CNTL6, ctx_flexeuN(6) },
+       };
+#undef ctx_flexeuN
+       int i;
+
+       regs[1].value =
+               (stream->period_exponent << GEN8_OA_TIMER_PERIOD_SHIFT) |
+               (stream->periodic ? GEN8_OA_TIMER_ENABLE : 0) |
+               GEN8_OA_COUNTER_RESUME;
+
+       for (i = 2; i < ARRAY_SIZE(regs); i++)
+               regs[i].value = oa_config_flex_reg(oa_config, regs[i].reg);
+
+       return oa_configure_all_contexts(stream, regs, ARRAY_SIZE(regs));
+}
+
 static int gen8_enable_metric_set(struct i915_perf_stream *stream)
 {
        struct intel_uncore *uncore = stream->uncore;
@@ -2464,7 +2486,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream)
         * to make sure all slices/subslices are ON before writing to NOA
         * registers.
         */
-       ret = lrc_configure_all_contexts(stream, oa_config);
+       ret = gen12_configure_all_contexts(stream, oa_config);
        if (ret)
                return ret;
 
@@ -2474,8 +2496,7 @@ static int gen12_enable_metric_set(struct i915_perf_stream *stream)
         * requested this.
         */
        if (stream->ctx) {
-               ret = gen12_emit_oar_config(stream->pinned_ctx,
-                                           oa_config != NULL);
+               ret = gen12_configure_oar_context(stream, true);
                if (ret)
                        return ret;
        }
@@ -2509,11 +2530,11 @@ static void gen12_disable_metric_set(struct i915_perf_stream *stream)
        struct intel_uncore *uncore = stream->uncore;
 
        /* Reset all contexts' slices/subslices configurations. */
-       lrc_configure_all_contexts(stream, NULL);
+       gen12_configure_all_contexts(stream, NULL);
 
        /* disable the context save/restore or OAR counters */
        if (stream->ctx)
-               gen12_emit_oar_config(stream->pinned_ctx, false);
+               gen12_configure_oar_context(stream, false);
 
        /* Make sure we disable noa to save power. */
        intel_uncore_rmw(uncore, RPM_CONFIG1, GEN10_GT_NOA_ENABLE, 0);
@@ -2713,7 +2734,8 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
                return -EINVAL;
        }
 
-       if (!(props->sample_flags & SAMPLE_OA_REPORT)) {
+       if (!(props->sample_flags & SAMPLE_OA_REPORT) &&
+           (INTEL_GEN(perf->i915) < 12 || !stream->ctx)) {
                DRM_DEBUG("Only OA report sampling supported\n");
                return -EINVAL;
        }
@@ -2745,7 +2767,7 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream,
 
        format_size = perf->oa_formats[props->oa_format].size;
 
-       stream->sample_flags |= SAMPLE_OA_REPORT;
+       stream->sample_flags = props->sample_flags;
        stream->sample_size += format_size;
 
        stream->oa_buffer.format_size = format_size;
@@ -2854,7 +2876,11 @@ void i915_oa_init_reg_state(const struct intel_context *ce,
                return;
 
        stream = engine->i915->perf.exclusive_stream;
-       if (stream)
+       /*
+        * For gen12, only CTX_R_PWR_CLK_STATE needs update, but the caller
+        * is already doing that, so nothing to be done for gen12 here.
+        */
+       if (stream && INTEL_GEN(stream->perf->i915) < 12)
                gen8_update_reg_state_unlocked(ce, stream);
 }
 
index 2814218..d6d2e6f 100644 (file)
@@ -144,61 +144,40 @@ static inline s64 ktime_since(const ktime_t kt)
        return ktime_to_ns(ktime_sub(ktime_get(), kt));
 }
 
-static u64 __pmu_estimate_rc6(struct i915_pmu *pmu)
-{
-       u64 val;
-
-       /*
-        * We think we are runtime suspended.
-        *
-        * Report the delta from when the device was suspended to now,
-        * on top of the last known real value, as the approximated RC6
-        * counter value.
-        */
-       val = ktime_since(pmu->sleep_last);
-       val += pmu->sample[__I915_SAMPLE_RC6].cur;
-
-       pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur = val;
-
-       return val;
-}
-
-static u64 __pmu_update_rc6(struct i915_pmu *pmu, u64 val)
-{
-       /*
-        * If we are coming back from being runtime suspended we must
-        * be careful not to report a larger value than returned
-        * previously.
-        */
-       if (val >= pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur) {
-               pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur = 0;
-               pmu->sample[__I915_SAMPLE_RC6].cur = val;
-       } else {
-               val = pmu->sample[__I915_SAMPLE_RC6_ESTIMATED].cur;
-       }
-
-       return val;
-}
-
 static u64 get_rc6(struct intel_gt *gt)
 {
        struct drm_i915_private *i915 = gt->i915;
        struct i915_pmu *pmu = &i915->pmu;
        unsigned long flags;
+       bool awake = false;
        u64 val;
 
-       val = 0;
        if (intel_gt_pm_get_if_awake(gt)) {
                val = __get_rc6(gt);
                intel_gt_pm_put_async(gt);
+               awake = true;
        }
 
        spin_lock_irqsave(&pmu->lock, flags);
 
-       if (val)
-               val = __pmu_update_rc6(pmu, val);
+       if (awake) {
+               pmu->sample[__I915_SAMPLE_RC6].cur = val;
+       } else {
+               /*
+                * We think we are runtime suspended.
+                *
+                * Report the delta from when the device was suspended to now,
+                * on top of the last known real value, as the approximated RC6
+                * counter value.
+                */
+               val = ktime_since(pmu->sleep_last);
+               val += pmu->sample[__I915_SAMPLE_RC6].cur;
+       }
+
+       if (val < pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur)
+               val = pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur;
        else
-               val = __pmu_estimate_rc6(pmu);
+               pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = val;
 
        spin_unlock_irqrestore(&pmu->lock, flags);
 
@@ -210,20 +189,11 @@ static void park_rc6(struct drm_i915_private *i915)
        struct i915_pmu *pmu = &i915->pmu;
 
        if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY))
-               __pmu_update_rc6(pmu, __get_rc6(&i915->gt));
+               pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
 
        pmu->sleep_last = ktime_get();
 }
 
-static void unpark_rc6(struct drm_i915_private *i915)
-{
-       struct i915_pmu *pmu = &i915->pmu;
-
-       /* Estimate how long we slept and accumulate that into rc6 counters */
-       if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY))
-               __pmu_estimate_rc6(pmu);
-}
-
 #else
 
 static u64 get_rc6(struct intel_gt *gt)
@@ -232,7 +202,6 @@ static u64 get_rc6(struct intel_gt *gt)
 }
 
 static void park_rc6(struct drm_i915_private *i915) {}
-static void unpark_rc6(struct drm_i915_private *i915) {}
 
 #endif
 
@@ -281,8 +250,6 @@ void i915_pmu_gt_unparked(struct drm_i915_private *i915)
         */
        __i915_pmu_maybe_start_timer(pmu);
 
-       unpark_rc6(i915);
-
        spin_unlock_irq(&pmu->lock);
 }
 
@@ -1107,12 +1074,17 @@ void i915_pmu_register(struct drm_i915_private *i915)
        hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pmu->timer.function = i915_sample;
 
-       if (!is_igp(i915))
+       if (!is_igp(i915)) {
                pmu->name = kasprintf(GFP_KERNEL,
-                                     "i915-%s",
+                                     "i915_%s",
                                      dev_name(i915->drm.dev));
-       else
+               if (pmu->name) {
+                       /* tools/perf reserves colons as special. */
+                       strreplace((char *)pmu->name, ':', '_');
+               }
+       } else {
                pmu->name = "i915";
+       }
        if (!pmu->name)
                goto err;
 
index bf52e39..6c1647c 100644 (file)
@@ -18,7 +18,7 @@ enum {
        __I915_SAMPLE_FREQ_ACT = 0,
        __I915_SAMPLE_FREQ_REQ,
        __I915_SAMPLE_RC6,
-       __I915_SAMPLE_RC6_ESTIMATED,
+       __I915_SAMPLE_RC6_LAST_REPORTED,
        __I915_NUM_PMU_SAMPLERS
 };
 
index 73079b5..094011b 100644 (file)
@@ -4177,7 +4177,13 @@ enum {
 #define  CPSSUNIT_CLKGATE_DIS          REG_BIT(9)
 
 #define UNSLICE_UNIT_LEVEL_CLKGATE     _MMIO(0x9434)
-#define  VFUNIT_CLKGATE_DIS            (1 << 20)
+#define   VFUNIT_CLKGATE_DIS           REG_BIT(20)
+#define   HSUNIT_CLKGATE_DIS           REG_BIT(8)
+#define   VSUNIT_CLKGATE_DIS           REG_BIT(3)
+
+#define UNSLICE_UNIT_LEVEL_CLKGATE2    _MMIO(0x94e4)
+#define   VSUNIT_CLKGATE_DIS_TGL       REG_BIT(19)
+#define   PSDUNIT_CLKGATE_DIS          REG_BIT(5)
 
 #define INF_UNIT_LEVEL_CLKGATE         _MMIO(0x9560)
 #define   CGPSF_CLKGATE_DIS            (1 << 3)
@@ -9405,11 +9411,9 @@ enum skl_power_gate {
 #define _ICL_AUX_REG_IDX(pw_idx)       ((pw_idx) - ICL_PW_CTL_IDX_AUX_A)
 #define _ICL_AUX_ANAOVRD1_A            0x162398
 #define _ICL_AUX_ANAOVRD1_B            0x6C398
-#define _TGL_AUX_ANAOVRD1_C            0x160398
 #define ICL_AUX_ANAOVRD1(pw_idx)       _MMIO(_PICK(_ICL_AUX_REG_IDX(pw_idx), \
                                                    _ICL_AUX_ANAOVRD1_A, \
-                                                   _ICL_AUX_ANAOVRD1_B, \
-                                                   _TGL_AUX_ANAOVRD1_C))
+                                                   _ICL_AUX_ANAOVRD1_B))
 #define   ICL_AUX_ANAOVRD1_LDO_BYPASS  (1 << 7)
 #define   ICL_AUX_ANAOVRD1_ENABLE      (1 << 0)
 
@@ -11994,7 +11998,7 @@ enum skl_power_gate {
 /* This register controls the Display State Buffer (DSB) engines. */
 #define _DSBSL_INSTANCE_BASE           0x70B00
 #define DSBSL_INSTANCE(pipe, id)       (_DSBSL_INSTANCE_BASE + \
-                                        (pipe) * 0x1000 + (id) * 100)
+                                        (pipe) * 0x1000 + (id) * 0x100)
 #define DSB_HEAD(pipe, id)             _MMIO(DSBSL_INSTANCE(pipe, id) + 0x0)
 #define DSB_TAIL(pipe, id)             _MMIO(DSBSL_INSTANCE(pipe, id) + 0x4)
 #define DSB_CTRL(pipe, id)             _MMIO(DSBSL_INSTANCE(pipe, id) + 0x8)
index bbd71af..765bec8 100644 (file)
@@ -300,11 +300,11 @@ void i915_request_retire_upto(struct i915_request *rq)
 }
 
 static int
-__i915_request_await_execution(struct i915_request *rq,
-                              struct i915_request *signal,
-                              void (*hook)(struct i915_request *rq,
-                                           struct dma_fence *signal),
-                              gfp_t gfp)
+__await_execution(struct i915_request *rq,
+                 struct i915_request *signal,
+                 void (*hook)(struct i915_request *rq,
+                              struct dma_fence *signal),
+                 gfp_t gfp)
 {
        struct execute_cb *cb;
 
@@ -341,6 +341,8 @@ __i915_request_await_execution(struct i915_request *rq,
        }
        spin_unlock_irq(&signal->lock);
 
+       /* Copy across semaphore status as we need the same behaviour */
+       rq->sched.flags |= signal->sched.flags;
        return 0;
 }
 
@@ -811,31 +813,21 @@ already_busywaiting(struct i915_request *rq)
 }
 
 static int
-emit_semaphore_wait(struct i915_request *to,
-                   struct i915_request *from,
-                   gfp_t gfp)
+__emit_semaphore_wait(struct i915_request *to,
+                     struct i915_request *from,
+                     u32 seqno)
 {
        const int has_token = INTEL_GEN(to->i915) >= 12;
        u32 hwsp_offset;
-       int len;
+       int len, err;
        u32 *cs;
 
        GEM_BUG_ON(INTEL_GEN(to->i915) < 8);
 
-       /* Just emit the first semaphore we see as request space is limited. */
-       if (already_busywaiting(to) & from->engine->mask)
-               goto await_fence;
-
-       if (i915_request_await_start(to, from) < 0)
-               goto await_fence;
-
-       /* Only submit our spinner after the signaler is running! */
-       if (__i915_request_await_execution(to, from, NULL, gfp))
-               goto await_fence;
-
        /* We need to pin the signaler's HWSP until we are finished reading. */
-       if (intel_timeline_read_hwsp(from, to, &hwsp_offset))
-               goto await_fence;
+       err = intel_timeline_read_hwsp(from, to, &hwsp_offset);
+       if (err)
+               return err;
 
        len = 4;
        if (has_token)
@@ -858,7 +850,7 @@ emit_semaphore_wait(struct i915_request *to,
                 MI_SEMAPHORE_POLL |
                 MI_SEMAPHORE_SAD_GTE_SDD) +
                has_token;
-       *cs++ = from->fence.seqno;
+       *cs++ = seqno;
        *cs++ = hwsp_offset;
        *cs++ = 0;
        if (has_token) {
@@ -867,6 +859,28 @@ emit_semaphore_wait(struct i915_request *to,
        }
 
        intel_ring_advance(to, cs);
+       return 0;
+}
+
+static int
+emit_semaphore_wait(struct i915_request *to,
+                   struct i915_request *from,
+                   gfp_t gfp)
+{
+       /* Just emit the first semaphore we see as request space is limited. */
+       if (already_busywaiting(to) & from->engine->mask)
+               goto await_fence;
+
+       if (i915_request_await_start(to, from) < 0)
+               goto await_fence;
+
+       /* Only submit our spinner after the signaler is running! */
+       if (__await_execution(to, from, NULL, gfp))
+               goto await_fence;
+
+       if (__emit_semaphore_wait(to, from, from->fence.seqno))
+               goto await_fence;
+
        to->sched.semaphores |= from->engine->mask;
        to->sched.flags |= I915_SCHED_HAS_SEMAPHORE_CHAIN;
        return 0;
@@ -980,6 +994,57 @@ i915_request_await_dma_fence(struct i915_request *rq, struct dma_fence *fence)
        return 0;
 }
 
+static bool intel_timeline_sync_has_start(struct intel_timeline *tl,
+                                         struct dma_fence *fence)
+{
+       return __intel_timeline_sync_is_later(tl,
+                                             fence->context,
+                                             fence->seqno - 1);
+}
+
+static int intel_timeline_sync_set_start(struct intel_timeline *tl,
+                                        const struct dma_fence *fence)
+{
+       return __intel_timeline_sync_set(tl, fence->context, fence->seqno - 1);
+}
+
+static int
+__i915_request_await_execution(struct i915_request *to,
+                              struct i915_request *from,
+                              void (*hook)(struct i915_request *rq,
+                                           struct dma_fence *signal))
+{
+       int err;
+
+       /* Submit both requests at the same time */
+       err = __await_execution(to, from, hook, I915_FENCE_GFP);
+       if (err)
+               return err;
+
+       /* Squash repeated depenendices to the same timelines */
+       if (intel_timeline_sync_has_start(i915_request_timeline(to),
+                                         &from->fence))
+               return 0;
+
+       /* Ensure both start together [after all semaphores in signal] */
+       if (intel_engine_has_semaphores(to->engine))
+               err = __emit_semaphore_wait(to, from, from->fence.seqno - 1);
+       else
+               err = i915_request_await_start(to, from);
+       if (err < 0)
+               return err;
+
+       /* Couple the dependency tree for PI on this exposed to->fence */
+       if (to->engine->schedule) {
+               err = i915_sched_node_add_dependency(&to->sched, &from->sched);
+               if (err < 0)
+                       return err;
+       }
+
+       return intel_timeline_sync_set_start(i915_request_timeline(to),
+                                            &from->fence);
+}
+
 int
 i915_request_await_execution(struct i915_request *rq,
                             struct dma_fence *fence,
@@ -1013,8 +1078,7 @@ i915_request_await_execution(struct i915_request *rq,
                if (dma_fence_is_i915(fence))
                        ret = __i915_request_await_execution(rq,
                                                             to_request(fence),
-                                                            hook,
-                                                            I915_FENCE_GFP);
+                                                            hook);
                else
                        ret = i915_sw_fence_await_dma_fence(&rq->submit, fence,
                                                            I915_FENCE_TIMEOUT,
index 010d67f..247a967 100644 (file)
@@ -474,7 +474,6 @@ void i915_sched_node_fini(struct i915_sched_node *node)
         * so we may be called out-of-order.
         */
        list_for_each_entry_safe(dep, tmp, &node->signalers_list, signal_link) {
-               GEM_BUG_ON(!node_signaled(dep->signaler));
                GEM_BUG_ON(!list_empty(&dep->dfs_link));
 
                list_del(&dep->wait_link);
index 07552cd..8538ee7 100644 (file)
@@ -78,12 +78,11 @@ static const struct dma_fence_ops fence_ops = {
 void dma_fence_work_init(struct dma_fence_work *f,
                         const struct dma_fence_work_ops *ops)
 {
+       f->ops = ops;
        spin_lock_init(&f->lock);
        dma_fence_init(&f->dma, &fence_ops, &f->lock, 0, 0);
        i915_sw_fence_init(&f->chain, fence_notify);
        INIT_WORK(&f->work, fence_work);
-
-       f->ops = ops;
 }
 
 int dma_fence_work_chain(struct dma_fence_work *f, struct dma_fence *signal)
index e5512f2..01c8222 100644 (file)
@@ -1104,8 +1104,14 @@ int i915_vma_move_to_active(struct i915_vma *vma,
                return err;
 
        if (flags & EXEC_OBJECT_WRITE) {
-               if (intel_frontbuffer_invalidate(obj->frontbuffer, ORIGIN_CS))
-                       i915_active_add_request(&obj->frontbuffer->write, rq);
+               struct intel_frontbuffer *front;
+
+               front = __intel_frontbuffer_get(obj);
+               if (unlikely(front)) {
+                       if (intel_frontbuffer_invalidate(front, ORIGIN_CS))
+                               i915_active_add_request(&front->write, rq);
+                       intel_frontbuffer_put(front);
+               }
 
                dma_resv_add_excl_fence(vma->resv, &rq->fence);
                obj->write_domain = I915_GEM_DOMAIN_RENDER;
index 809bff9..86379ed 100644 (file)
@@ -4291,8 +4291,8 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *crtc_state,
                                &crtc_state->wm.skl.optimal.planes[plane_id];
 
                        if (plane_id == PLANE_CURSOR) {
-                               if (WARN_ON(wm->wm[level].min_ddb_alloc >
-                                           total[PLANE_CURSOR])) {
+                               if (wm->wm[level].min_ddb_alloc > total[PLANE_CURSOR]) {
+                                       WARN_ON(wm->wm[level].min_ddb_alloc != U16_MAX);
                                        blocks = U32_MAX;
                                        break;
                                }
@@ -6565,6 +6565,17 @@ static void icl_init_clock_gating(struct drm_i915_private *dev_priv)
        /* WaEnable32PlaneMode:icl */
        I915_WRITE(GEN9_CSFE_CHICKEN1_RCS,
                   _MASKED_BIT_ENABLE(GEN11_ENABLE_32_PLANE_MODE));
+
+       /*
+        * Wa_1408615072:icl,ehl  (vsunit)
+        * Wa_1407596294:icl,ehl  (hsunit)
+        */
+       intel_uncore_rmw(&dev_priv->uncore, UNSLICE_UNIT_LEVEL_CLKGATE,
+                        0, VSUNIT_CLKGATE_DIS | HSUNIT_CLKGATE_DIS);
+
+       /* Wa_1407352427:icl,ehl */
+       intel_uncore_rmw(&dev_priv->uncore, UNSLICE_UNIT_LEVEL_CLKGATE2,
+                        0, PSDUNIT_CLKGATE_DIS);
 }
 
 static void tgl_init_clock_gating(struct drm_i915_private *dev_priv)
index 35cc69a..05364ec 100644 (file)
@@ -25,6 +25,7 @@
 #ifndef __I915_SELFTESTS_RANDOM_H__
 #define __I915_SELFTESTS_RANDOM_H__
 
+#include <linux/math64.h>
 #include <linux/random.h>
 
 #include "../i915_selftest.h"
index d6214d3..ef4c630 100644 (file)
@@ -935,11 +935,13 @@ static int mcde_dsi_bind(struct device *dev, struct device *master,
        for_each_available_child_of_node(dev->of_node, child) {
                panel = of_drm_find_panel(child);
                if (IS_ERR(panel)) {
-                       dev_err(dev, "failed to find panel try bridge (%lu)\n",
+                       dev_err(dev, "failed to find panel try bridge (%ld)\n",
                                PTR_ERR(panel));
+                       panel = NULL;
+
                        bridge = of_drm_find_bridge(child);
                        if (IS_ERR(bridge)) {
-                               dev_err(dev, "failed to find bridge (%lu)\n",
+                               dev_err(dev, "failed to find bridge (%ld)\n",
                                        PTR_ERR(bridge));
                                return PTR_ERR(bridge);
                        }
index f80a8ba..3305a94 100644 (file)
@@ -215,11 +215,12 @@ struct mtk_ddp_comp *mtk_drm_ddp_comp_for_plane(struct drm_crtc *crtc,
        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
        struct mtk_ddp_comp *comp;
        int i, count = 0;
+       unsigned int local_index = plane - mtk_crtc->planes;
 
        for (i = 0; i < mtk_crtc->ddp_comp_nr; i++) {
                comp = mtk_crtc->ddp_comp[i];
-               if (plane->index < (count + mtk_ddp_comp_layer_nr(comp))) {
-                       *local_layer = plane->index - count;
+               if (local_index < (count + mtk_ddp_comp_layer_nr(comp))) {
+                       *local_layer = local_index - count;
                        return comp;
                }
                count += mtk_ddp_comp_layer_nr(comp);
@@ -310,7 +311,9 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc)
 
                plane_state = to_mtk_plane_state(plane->state);
                comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer);
-               mtk_ddp_comp_layer_config(comp, local_layer, plane_state);
+               if (comp)
+                       mtk_ddp_comp_layer_config(comp, local_layer,
+                                                 plane_state);
        }
 
        return 0;
@@ -386,8 +389,9 @@ static void mtk_crtc_ddp_config(struct drm_crtc *crtc)
                        comp = mtk_drm_ddp_comp_for_plane(crtc, plane,
                                                          &local_layer);
 
-                       mtk_ddp_comp_layer_config(comp, local_layer,
-                                                 plane_state);
+                       if (comp)
+                               mtk_ddp_comp_layer_config(comp, local_layer,
+                                                         plane_state);
                        plane_state->pending.config = false;
                }
                mtk_crtc->pending_planes = false;
@@ -401,7 +405,9 @@ int mtk_drm_crtc_plane_check(struct drm_crtc *crtc, struct drm_plane *plane,
        struct mtk_ddp_comp *comp;
 
        comp = mtk_drm_ddp_comp_for_plane(crtc, plane, &local_layer);
-       return mtk_ddp_comp_layer_check(comp, local_layer, state);
+       if (comp)
+               return mtk_ddp_comp_layer_check(comp, local_layer, state);
+       return 0;
 }
 
 static void mtk_drm_crtc_atomic_enable(struct drm_crtc *crtc,
index e9931bb..d77c9f4 100644 (file)
@@ -230,28 +230,25 @@ static void mtk_dsi_mask(struct mtk_dsi *dsi, u32 offset, u32 mask, u32 data)
 static void mtk_dsi_phy_timconfig(struct mtk_dsi *dsi)
 {
        u32 timcon0, timcon1, timcon2, timcon3;
-       u32 ui, cycle_time;
+       u32 data_rate_mhz = DIV_ROUND_UP(dsi->data_rate, 1000000);
        struct mtk_phy_timing *timing = &dsi->phy_timing;
 
-       ui = DIV_ROUND_UP(1000000000, dsi->data_rate);
-       cycle_time = div_u64(8000000000ULL, dsi->data_rate);
+       timing->lpx = (60 * data_rate_mhz / (8 * 1000)) + 1;
+       timing->da_hs_prepare = (80 * data_rate_mhz + 4 * 1000) / 8000;
+       timing->da_hs_zero = (170 * data_rate_mhz + 10 * 1000) / 8000 + 1 -
+                            timing->da_hs_prepare;
+       timing->da_hs_trail = timing->da_hs_prepare + 1;
 
-       timing->lpx = NS_TO_CYCLE(60, cycle_time);
-       timing->da_hs_prepare = NS_TO_CYCLE(50 + 5 * ui, cycle_time);
-       timing->da_hs_zero = NS_TO_CYCLE(110 + 6 * ui, cycle_time);
-       timing->da_hs_trail = NS_TO_CYCLE(77 + 4 * ui, cycle_time);
+       timing->ta_go = 4 * timing->lpx - 2;
+       timing->ta_sure = timing->lpx + 2;
+       timing->ta_get = 4 * timing->lpx;
+       timing->da_hs_exit = 2 * timing->lpx + 1;
 
-       timing->ta_go = 4 * timing->lpx;
-       timing->ta_sure = 3 * timing->lpx / 2;
-       timing->ta_get = 5 * timing->lpx;
-       timing->da_hs_exit = 2 * timing->lpx;
-
-       timing->clk_hs_zero = NS_TO_CYCLE(336, cycle_time);
-       timing->clk_hs_trail = NS_TO_CYCLE(100, cycle_time) + 10;
-
-       timing->clk_hs_prepare = NS_TO_CYCLE(64, cycle_time);
-       timing->clk_hs_post = NS_TO_CYCLE(80 + 52 * ui, cycle_time);
-       timing->clk_hs_exit = 2 * timing->lpx;
+       timing->clk_hs_prepare = 70 * data_rate_mhz / (8 * 1000);
+       timing->clk_hs_post = timing->clk_hs_prepare + 8;
+       timing->clk_hs_trail = timing->clk_hs_prepare;
+       timing->clk_hs_zero = timing->clk_hs_trail * 4;
+       timing->clk_hs_exit = 2 * timing->clk_hs_trail;
 
        timcon0 = timing->lpx | timing->da_hs_prepare << 8 |
                  timing->da_hs_zero << 16 | timing->da_hs_trail << 24;
@@ -482,27 +479,39 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi)
                        dsi_tmp_buf_bpp - 10);
 
        data_phy_cycles = timing->lpx + timing->da_hs_prepare +
-                                 timing->da_hs_zero + timing->da_hs_exit + 2;
+                         timing->da_hs_zero + timing->da_hs_exit + 3;
 
        if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) {
-               if (vm->hfront_porch * dsi_tmp_buf_bpp >
+               if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp >
                    data_phy_cycles * dsi->lanes + 18) {
-                       horizontal_frontporch_byte = vm->hfront_porch *
-                                                    dsi_tmp_buf_bpp -
-                                                    data_phy_cycles *
-                                                    dsi->lanes - 18;
+                       horizontal_frontporch_byte =
+                               vm->hfront_porch * dsi_tmp_buf_bpp -
+                               (data_phy_cycles * dsi->lanes + 18) *
+                               vm->hfront_porch /
+                               (vm->hfront_porch + vm->hback_porch);
+
+                       horizontal_backporch_byte =
+                               horizontal_backporch_byte -
+                               (data_phy_cycles * dsi->lanes + 18) *
+                               vm->hback_porch /
+                               (vm->hfront_porch + vm->hback_porch);
                } else {
                        DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n");
                        horizontal_frontporch_byte = vm->hfront_porch *
                                                     dsi_tmp_buf_bpp;
                }
        } else {
-               if (vm->hfront_porch * dsi_tmp_buf_bpp >
+               if ((vm->hfront_porch + vm->hback_porch) * dsi_tmp_buf_bpp >
                    data_phy_cycles * dsi->lanes + 12) {
-                       horizontal_frontporch_byte = vm->hfront_porch *
-                                                    dsi_tmp_buf_bpp -
-                                                    data_phy_cycles *
-                                                    dsi->lanes - 12;
+                       horizontal_frontporch_byte =
+                               vm->hfront_porch * dsi_tmp_buf_bpp -
+                               (data_phy_cycles * dsi->lanes + 12) *
+                               vm->hfront_porch /
+                               (vm->hfront_porch + vm->hback_porch);
+                       horizontal_backporch_byte = horizontal_backporch_byte -
+                               (data_phy_cycles * dsi->lanes + 12) *
+                               vm->hback_porch /
+                               (vm->hfront_porch + vm->hback_porch);
                } else {
                        DRM_WARN("HFP less than d-phy, FPS will under 60Hz\n");
                        horizontal_frontporch_byte = vm->hfront_porch *
index 9ab27ae..1bd6b6d 100644 (file)
@@ -64,6 +64,25 @@ struct meson_cvbs_mode meson_cvbs_modes[MESON_CVBS_MODES_COUNT] = {
        },
 };
 
+static const struct meson_cvbs_mode *
+meson_cvbs_get_mode(const struct drm_display_mode *req_mode)
+{
+       int i;
+
+       for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
+               struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+
+               if (drm_mode_match(req_mode, &meson_mode->mode,
+                                  DRM_MODE_MATCH_TIMINGS |
+                                  DRM_MODE_MATCH_CLOCK |
+                                  DRM_MODE_MATCH_FLAGS |
+                                  DRM_MODE_MATCH_3D_FLAGS))
+                       return meson_mode;
+       }
+
+       return NULL;
+}
+
 /* Connector */
 
 static void meson_cvbs_connector_destroy(struct drm_connector *connector)
@@ -136,14 +155,8 @@ static int meson_venc_cvbs_encoder_atomic_check(struct drm_encoder *encoder,
                                        struct drm_crtc_state *crtc_state,
                                        struct drm_connector_state *conn_state)
 {
-       int i;
-
-       for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
-               struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
-
-               if (drm_mode_equal(&crtc_state->mode, &meson_mode->mode))
-                       return 0;
-       }
+       if (meson_cvbs_get_mode(&crtc_state->mode))
+               return 0;
 
        return -EINVAL;
 }
@@ -191,24 +204,17 @@ static void meson_venc_cvbs_encoder_mode_set(struct drm_encoder *encoder,
                                   struct drm_display_mode *mode,
                                   struct drm_display_mode *adjusted_mode)
 {
+       const struct meson_cvbs_mode *meson_mode = meson_cvbs_get_mode(mode);
        struct meson_venc_cvbs *meson_venc_cvbs =
                                        encoder_to_meson_venc_cvbs(encoder);
        struct meson_drm *priv = meson_venc_cvbs->priv;
-       int i;
 
-       for (i = 0; i < MESON_CVBS_MODES_COUNT; ++i) {
-               struct meson_cvbs_mode *meson_mode = &meson_cvbs_modes[i];
+       if (meson_mode) {
+               meson_venci_cvbs_mode_set(priv, meson_mode->enci);
 
-               if (drm_mode_equal(mode, &meson_mode->mode)) {
-                       meson_venci_cvbs_mode_set(priv,
-                                                 meson_mode->enci);
-
-                       /* Setup 27MHz vclk2 for ENCI and VDAC */
-                       meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
-                                        MESON_VCLK_CVBS, MESON_VCLK_CVBS,
-                                        MESON_VCLK_CVBS, true);
-                       break;
-               }
+               /* Setup 27MHz vclk2 for ENCI and VDAC */
+               meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS, MESON_VCLK_CVBS,
+                                MESON_VCLK_CVBS, MESON_VCLK_CVBS, true);
        }
 }
 
index d43951c..b113876 100644 (file)
@@ -30,9 +30,8 @@ module_param_named(modeset, mgag200_modeset, int, 0400);
 static struct drm_driver driver;
 
 static const struct pci_device_id pciidlist[] = {
-       { PCI_VENDOR_ID_MATROX, 0x522, PCI_VENDOR_ID_SUN, 0x4852, 0, 0,
+       { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                G200_SE_A | MGAG200_FLAG_HW_BUG_NO_STARTADD},
-       { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
        { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
        { PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
        { PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },
index 43df86c..24f7700 100644 (file)
@@ -114,6 +114,7 @@ struct nv50_head_atom {
                u8 nhsync:1;
                u8 nvsync:1;
                u8 depth:4;
+               u8 bpc;
        } or;
 
        /* Currently only used for MST */
index 549486f..63425e2 100644 (file)
@@ -326,9 +326,9 @@ nv50_outp_atomic_check_view(struct drm_encoder *encoder,
                         * same size as the native one (e.g. different
                         * refresh rate)
                         */
-                       if (adjusted_mode->hdisplay == native_mode->hdisplay &&
-                           adjusted_mode->vdisplay == native_mode->vdisplay &&
-                           adjusted_mode->type & DRM_MODE_TYPE_DRIVER)
+                       if (mode->hdisplay == native_mode->hdisplay &&
+                           mode->vdisplay == native_mode->vdisplay &&
+                           mode->type & DRM_MODE_TYPE_DRIVER)
                                break;
                        mode = native_mode;
                        asyc->scaler.full = true;
@@ -353,10 +353,20 @@ nv50_outp_atomic_check(struct drm_encoder *encoder,
                       struct drm_crtc_state *crtc_state,
                       struct drm_connector_state *conn_state)
 {
-       struct nouveau_connector *nv_connector =
-               nouveau_connector(conn_state->connector);
-       return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
-                                          nv_connector->native_mode);
+       struct drm_connector *connector = conn_state->connector;
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
+       struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
+       int ret;
+
+       ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+                                         nv_connector->native_mode);
+       if (ret)
+               return ret;
+
+       if (crtc_state->mode_changed || crtc_state->connectors_changed)
+               asyh->or.bpc = connector->display_info.bpc;
+
+       return 0;
 }
 
 /******************************************************************************
@@ -770,32 +780,54 @@ nv50_msto_atomic_check(struct drm_encoder *encoder,
        struct nv50_mstm *mstm = mstc->mstm;
        struct nv50_head_atom *asyh = nv50_head_atom(crtc_state);
        int slots;
+       int ret;
+
+       ret = nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
+                                         mstc->native);
+       if (ret)
+               return ret;
+
+       if (!crtc_state->mode_changed && !crtc_state->connectors_changed)
+               return 0;
+
+       /*
+        * When restoring duplicated states, we need to make sure that the bw
+        * remains the same and avoid recalculating it, as the connector's bpc
+        * may have changed after the state was duplicated
+        */
+       if (!state->duplicated) {
+               const int clock = crtc_state->adjusted_mode.clock;
 
-       if (crtc_state->mode_changed || crtc_state->connectors_changed) {
                /*
-                * When restoring duplicated states, we need to make sure that
-                * the bw remains the same and avoid recalculating it, as the
-                * connector's bpc may have changed after the state was
-                * duplicated
+                * XXX: Since we don't use HDR in userspace quite yet, limit
+                * the bpc to 8 to save bandwidth on the topology. In the
+                * future, we'll want to properly fix this by dynamically
+                * selecting the highest possible bpc that would fit in the
+                * topology
                 */
-               if (!state->duplicated) {
-                       const int bpp = connector->display_info.bpc * 3;
-                       const int clock = crtc_state->adjusted_mode.clock;
+               asyh->or.bpc = min(connector->display_info.bpc, 8U);
+               asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, asyh->or.bpc * 3);
+       }
 
-                       asyh->dp.pbn = drm_dp_calc_pbn_mode(clock, bpp);
-               }
+       slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr, mstc->port,
+                                             asyh->dp.pbn);
+       if (slots < 0)
+               return slots;
 
-               slots = drm_dp_atomic_find_vcpi_slots(state, &mstm->mgr,
-                                                     mstc->port,
-                                                     asyh->dp.pbn);
-               if (slots < 0)
-                       return slots;
+       asyh->dp.tu = slots;
 
-               asyh->dp.tu = slots;
-       }
+       return 0;
+}
 
-       return nv50_outp_atomic_check_view(encoder, crtc_state, conn_state,
-                                          mstc->native);
+static u8
+nv50_dp_bpc_to_depth(unsigned int bpc)
+{
+       switch (bpc) {
+       case  6: return 0x2;
+       case  8: return 0x5;
+       case 10: /* fall-through */
+       default: return 0x6;
+       }
 }
 
 static void
@@ -808,7 +840,7 @@ nv50_msto_enable(struct drm_encoder *encoder)
        struct nv50_mstm *mstm = NULL;
        struct drm_connector *connector;
        struct drm_connector_list_iter conn_iter;
-       u8 proto, depth;
+       u8 proto;
        bool r;
 
        drm_connector_list_iter_begin(encoder->dev, &conn_iter);
@@ -837,14 +869,8 @@ nv50_msto_enable(struct drm_encoder *encoder)
        else
                proto = 0x9;
 
-       switch (mstc->connector.display_info.bpc) {
-       case  6: depth = 0x2; break;
-       case  8: depth = 0x5; break;
-       case 10:
-       default: depth = 0x6; break;
-       }
-
-       mstm->outp->update(mstm->outp, head->base.index, armh, proto, depth);
+       mstm->outp->update(mstm->outp, head->base.index, armh, proto,
+                          nv50_dp_bpc_to_depth(armh->or.bpc));
 
        msto->head = head;
        msto->mstc = mstc;
@@ -1498,20 +1524,14 @@ nv50_sor_enable(struct drm_encoder *encoder)
                                        lvds.lvds.script |= 0x0200;
                        }
 
-                       if (nv_connector->base.display_info.bpc == 8)
+                       if (asyh->or.bpc == 8)
                                lvds.lvds.script |= 0x0200;
                }
 
                nvif_mthd(&disp->disp->object, 0, &lvds, sizeof(lvds));
                break;
        case DCB_OUTPUT_DP:
-               if (nv_connector->base.display_info.bpc == 6)
-                       depth = 0x2;
-               else
-               if (nv_connector->base.display_info.bpc == 8)
-                       depth = 0x5;
-               else
-                       depth = 0x6;
+               depth = nv50_dp_bpc_to_depth(asyh->or.bpc);
 
                if (nv_encoder->link & 1)
                        proto = 0x8;
@@ -1662,7 +1682,7 @@ nv50_pior_enable(struct drm_encoder *encoder)
        nv50_outp_acquire(nv_encoder);
 
        nv_connector = nouveau_encoder_connector_get(nv_encoder);
-       switch (nv_connector->base.display_info.bpc) {
+       switch (asyh->or.bpc) {
        case 10: asyh->or.depth = 0x6; break;
        case  8: asyh->or.depth = 0x5; break;
        case  6: asyh->or.depth = 0x2; break;
index 71c23bf..c9692df 100644 (file)
@@ -81,18 +81,17 @@ nv50_head_atomic_check_dither(struct nv50_head_atom *armh,
                              struct nv50_head_atom *asyh,
                              struct nouveau_conn_atom *asyc)
 {
-       struct drm_connector *connector = asyc->state.connector;
        u32 mode = 0x00;
 
        if (asyc->dither.mode == DITHERING_MODE_AUTO) {
-               if (asyh->base.depth > connector->display_info.bpc * 3)
+               if (asyh->base.depth > asyh->or.bpc * 3)
                        mode = DITHERING_MODE_DYNAMIC2X2;
        } else {
                mode = asyc->dither.mode;
        }
 
        if (asyc->dither.depth == DITHERING_DEPTH_AUTO) {
-               if (connector->display_info.bpc >= 8)
+               if (asyh->or.bpc >= 8)
                        mode |= DITHERING_DEPTH_8BPC;
        } else {
                mode |= asyc->dither.depth;
index 5b41358..9a9a7f5 100644 (file)
@@ -245,14 +245,22 @@ nouveau_conn_atomic_duplicate_state(struct drm_connector *connector)
 void
 nouveau_conn_reset(struct drm_connector *connector)
 {
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_conn_atom *asyc;
 
-       if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
-               return;
+       if (drm_drv_uses_atomic_modeset(connector->dev)) {
+               if (WARN_ON(!(asyc = kzalloc(sizeof(*asyc), GFP_KERNEL))))
+                       return;
+
+               if (connector->state)
+                       nouveau_conn_atomic_destroy_state(connector,
+                                                         connector->state);
+
+               __drm_atomic_helper_connector_reset(connector, &asyc->state);
+       } else {
+               asyc = &nv_connector->properties_state;
+       }
 
-       if (connector->state)
-               nouveau_conn_atomic_destroy_state(connector, connector->state);
-       __drm_atomic_helper_connector_reset(connector, &asyc->state);
        asyc->dither.mode = DITHERING_MODE_AUTO;
        asyc->dither.depth = DITHERING_DEPTH_AUTO;
        asyc->scaler.mode = DRM_MODE_SCALE_NONE;
@@ -276,8 +284,14 @@ void
 nouveau_conn_attach_properties(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
-       struct nouveau_conn_atom *armc = nouveau_conn_atom(connector->state);
        struct nouveau_display *disp = nouveau_display(dev);
+       struct nouveau_connector *nv_connector = nouveau_connector(connector);
+       struct nouveau_conn_atom *armc;
+
+       if (drm_drv_uses_atomic_modeset(connector->dev))
+               armc = nouveau_conn_atom(connector->state);
+       else
+               armc = &nv_connector->properties_state;
 
        /* Init DVI-I specific properties. */
        if (connector->connector_type == DRM_MODE_CONNECTOR_DVII)
@@ -748,9 +762,9 @@ static int
 nouveau_connector_set_property(struct drm_connector *connector,
                               struct drm_property *property, uint64_t value)
 {
-       struct nouveau_conn_atom *asyc = nouveau_conn_atom(connector->state);
        struct nouveau_connector *nv_connector = nouveau_connector(connector);
        struct nouveau_encoder *nv_encoder = nv_connector->detected_encoder;
+       struct nouveau_conn_atom *asyc = &nv_connector->properties_state;
        struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
        int ret;
 
index f43a8d6..de84fb4 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <nvif/notify.h>
 
+#include <drm/drm_crtc.h>
 #include <drm/drm_edid.h>
 #include <drm/drm_encoder.h>
 #include <drm/drm_dp_helper.h>
@@ -44,6 +45,60 @@ struct dcb_output;
 struct nouveau_backlight;
 #endif
 
+#define nouveau_conn_atom(p)                                                   \
+       container_of((p), struct nouveau_conn_atom, state)
+
+struct nouveau_conn_atom {
+       struct drm_connector_state state;
+
+       struct {
+               /* The enum values specifically defined here match nv50/gf119
+                * hw values, and the code relies on this.
+                */
+               enum {
+                       DITHERING_MODE_OFF = 0x00,
+                       DITHERING_MODE_ON = 0x01,
+                       DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
+                       DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
+                       DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
+                       DITHERING_MODE_AUTO
+               } mode;
+               enum {
+                       DITHERING_DEPTH_6BPC = 0x00,
+                       DITHERING_DEPTH_8BPC = 0x02,
+                       DITHERING_DEPTH_AUTO
+               } depth;
+       } dither;
+
+       struct {
+               int mode;       /* DRM_MODE_SCALE_* */
+               struct {
+                       enum {
+                               UNDERSCAN_OFF,
+                               UNDERSCAN_ON,
+                               UNDERSCAN_AUTO,
+                       } mode;
+                       u32 hborder;
+                       u32 vborder;
+               } underscan;
+               bool full;
+       } scaler;
+
+       struct {
+               int color_vibrance;
+               int vibrant_hue;
+       } procamp;
+
+       union {
+               struct {
+                       bool dither:1;
+                       bool scaler:1;
+                       bool procamp:1;
+               };
+               u8 mask;
+       } set;
+};
+
 struct nouveau_connector {
        struct drm_connector base;
        enum dcb_connector_type type;
@@ -63,6 +118,12 @@ struct nouveau_connector {
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
        struct nouveau_backlight *backlight;
 #endif
+       /*
+        * Our connector property code expects a nouveau_conn_atom struct
+        * even on pre-nv50 where we do not support atomic. This embedded
+        * version gets used in the non atomic modeset case.
+        */
+       struct nouveau_conn_atom properties_state;
 };
 
 static inline struct nouveau_connector *nouveau_connector(
@@ -121,61 +182,6 @@ extern int nouveau_ignorelid;
 extern int nouveau_duallink;
 extern int nouveau_hdmimhz;
 
-#include <drm/drm_crtc.h>
-#define nouveau_conn_atom(p)                                                   \
-       container_of((p), struct nouveau_conn_atom, state)
-
-struct nouveau_conn_atom {
-       struct drm_connector_state state;
-
-       struct {
-               /* The enum values specifically defined here match nv50/gf119
-                * hw values, and the code relies on this.
-                */
-               enum {
-                       DITHERING_MODE_OFF = 0x00,
-                       DITHERING_MODE_ON = 0x01,
-                       DITHERING_MODE_DYNAMIC2X2 = 0x10 | DITHERING_MODE_ON,
-                       DITHERING_MODE_STATIC2X2 = 0x18 | DITHERING_MODE_ON,
-                       DITHERING_MODE_TEMPORAL = 0x20 | DITHERING_MODE_ON,
-                       DITHERING_MODE_AUTO
-               } mode;
-               enum {
-                       DITHERING_DEPTH_6BPC = 0x00,
-                       DITHERING_DEPTH_8BPC = 0x02,
-                       DITHERING_DEPTH_AUTO
-               } depth;
-       } dither;
-
-       struct {
-               int mode;       /* DRM_MODE_SCALE_* */
-               struct {
-                       enum {
-                               UNDERSCAN_OFF,
-                               UNDERSCAN_ON,
-                               UNDERSCAN_AUTO,
-                       } mode;
-                       u32 hborder;
-                       u32 vborder;
-               } underscan;
-               bool full;
-       } scaler;
-
-       struct {
-               int color_vibrance;
-               int vibrant_hue;
-       } procamp;
-
-       union {
-               struct {
-                       bool dither:1;
-                       bool scaler:1;
-                       bool procamp:1;
-               };
-               u8 mask;
-       } set;
-};
-
 void nouveau_conn_attach_properties(struct drm_connector *);
 void nouveau_conn_reset(struct drm_connector *);
 struct drm_connector_state *
index 4c4e8a3..536ba93 100644 (file)
@@ -18,15 +18,18 @@ static void panfrost_devfreq_update_utilization(struct panfrost_device *pfdev);
 static int panfrost_devfreq_target(struct device *dev, unsigned long *freq,
                                   u32 flags)
 {
-       struct panfrost_device *pfdev = dev_get_drvdata(dev);
+       struct dev_pm_opp *opp;
        int err;
 
+       opp = devfreq_recommended_opp(dev, freq, flags);
+       if (IS_ERR(opp))
+               return PTR_ERR(opp);
+       dev_pm_opp_put(opp);
+
        err = dev_pm_opp_set_rate(dev, *freq);
        if (err)
                return err;
 
-       *freq = clk_get_rate(pfdev->clock);
-
        return 0;
 }
 
@@ -60,20 +63,10 @@ static int panfrost_devfreq_get_dev_status(struct device *dev,
        return 0;
 }
 
-static int panfrost_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
-{
-       struct panfrost_device *pfdev = platform_get_drvdata(to_platform_device(dev));
-
-       *freq = clk_get_rate(pfdev->clock);
-
-       return 0;
-}
-
 static struct devfreq_dev_profile panfrost_devfreq_profile = {
        .polling_ms = 50, /* ~3 frames */
        .target = panfrost_devfreq_target,
        .get_dev_status = panfrost_devfreq_get_dev_status,
-       .get_cur_freq = panfrost_devfreq_get_cur_freq,
 };
 
 int panfrost_devfreq_init(struct panfrost_device *pfdev)
index 9458dc6..f61364f 100644 (file)
@@ -303,14 +303,17 @@ static int panfrost_ioctl_mmap_bo(struct drm_device *dev, void *data,
        }
 
        /* Don't allow mmapping of heap objects as pages are not pinned. */
-       if (to_panfrost_bo(gem_obj)->is_heap)
-               return -EINVAL;
+       if (to_panfrost_bo(gem_obj)->is_heap) {
+               ret = -EINVAL;
+               goto out;
+       }
 
        ret = drm_gem_create_mmap_offset(gem_obj);
        if (ret == 0)
                args->offset = drm_vma_node_offset_addr(&gem_obj->vma_node);
-       drm_gem_object_put_unlocked(gem_obj);
 
+out:
+       drm_gem_object_put_unlocked(gem_obj);
        return ret;
 }
 
@@ -347,20 +350,19 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data,
                return -ENOENT;
        }
 
+       mutex_lock(&pfdev->shrinker_lock);
        args->retained = drm_gem_shmem_madvise(gem_obj, args->madv);
 
        if (args->retained) {
                struct panfrost_gem_object *bo = to_panfrost_bo(gem_obj);
 
-               mutex_lock(&pfdev->shrinker_lock);
-
                if (args->madv == PANFROST_MADV_DONTNEED)
-                       list_add_tail(&bo->base.madv_list, &pfdev->shrinker_list);
+                       list_add_tail(&bo->base.madv_list,
+                                     &pfdev->shrinker_list);
                else if (args->madv == PANFROST_MADV_WILLNEED)
                        list_del_init(&bo->base.madv_list);
-
-               mutex_unlock(&pfdev->shrinker_lock);
        }
+       mutex_unlock(&pfdev->shrinker_lock);
 
        drm_gem_object_put_unlocked(gem_obj);
        return 0;
@@ -443,7 +445,7 @@ panfrost_postclose(struct drm_device *dev, struct drm_file *file)
 {
        struct panfrost_file_priv *panfrost_priv = file->driver_priv;
 
-       panfrost_perfcnt_close(panfrost_priv);
+       panfrost_perfcnt_close(file);
        panfrost_job_close(panfrost_priv);
 
        panfrost_mmu_pgtable_free(panfrost_priv);
index deca0c3..fd766b1 100644 (file)
@@ -19,6 +19,16 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj)
        struct panfrost_gem_object *bo = to_panfrost_bo(obj);
        struct panfrost_device *pfdev = obj->dev->dev_private;
 
+       /*
+        * Make sure the BO is no longer inserted in the shrinker list before
+        * taking care of the destruction itself. If we don't do that we have a
+        * race condition between this function and what's done in
+        * panfrost_gem_shrinker_scan().
+        */
+       mutex_lock(&pfdev->shrinker_lock);
+       list_del_init(&bo->base.madv_list);
+       mutex_unlock(&pfdev->shrinker_lock);
+
        if (bo->sgts) {
                int i;
                int n_sgt = bo->base.base.size / SZ_2M;
@@ -33,15 +43,10 @@ static void panfrost_gem_free_object(struct drm_gem_object *obj)
                kfree(bo->sgts);
        }
 
-       mutex_lock(&pfdev->shrinker_lock);
-       if (!list_empty(&bo->base.madv_list))
-               list_del(&bo->base.madv_list);
-       mutex_unlock(&pfdev->shrinker_lock);
-
        drm_gem_shmem_free_object(obj);
 }
 
-static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
+int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv)
 {
        int ret;
        size_t size = obj->size;
@@ -80,7 +85,7 @@ static int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_p
        return ret;
 }
 
-static void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
+void panfrost_gem_close(struct drm_gem_object *obj, struct drm_file *file_priv)
 {
        struct panfrost_gem_object *bo = to_panfrost_bo(obj);
        struct panfrost_file_priv *priv = file_priv->driver_priv;
index 5092081..4b17e73 100644 (file)
@@ -45,6 +45,10 @@ panfrost_gem_create_with_handle(struct drm_file *file_priv,
                                u32 flags,
                                uint32_t *handle);
 
+int panfrost_gem_open(struct drm_gem_object *obj, struct drm_file *file_priv);
+void panfrost_gem_close(struct drm_gem_object *obj,
+                       struct drm_file *file_priv);
+
 void panfrost_gem_shrinker_init(struct drm_device *dev);
 void panfrost_gem_shrinker_cleanup(struct drm_device *dev);
 
index 2dba192..2c04e85 100644 (file)
@@ -67,9 +67,10 @@ static int panfrost_perfcnt_dump_locked(struct panfrost_device *pfdev)
 }
 
 static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
-                                         struct panfrost_file_priv *user,
+                                         struct drm_file *file_priv,
                                          unsigned int counterset)
 {
+       struct panfrost_file_priv *user = file_priv->driver_priv;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
        struct drm_gem_shmem_object *bo;
        u32 cfg;
@@ -91,14 +92,14 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
        perfcnt->bo = to_panfrost_bo(&bo->base);
 
        /* Map the perfcnt buf in the address space attached to file_priv. */
-       ret = panfrost_mmu_map(perfcnt->bo);
+       ret = panfrost_gem_open(&perfcnt->bo->base.base, file_priv);
        if (ret)
                goto err_put_bo;
 
        perfcnt->buf = drm_gem_shmem_vmap(&bo->base);
        if (IS_ERR(perfcnt->buf)) {
                ret = PTR_ERR(perfcnt->buf);
-               goto err_put_bo;
+               goto err_close_bo;
        }
 
        /*
@@ -157,14 +158,17 @@ static int panfrost_perfcnt_enable_locked(struct panfrost_device *pfdev,
 
 err_vunmap:
        drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf);
+err_close_bo:
+       panfrost_gem_close(&perfcnt->bo->base.base, file_priv);
 err_put_bo:
        drm_gem_object_put_unlocked(&bo->base);
        return ret;
 }
 
 static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
-                                          struct panfrost_file_priv *user)
+                                          struct drm_file *file_priv)
 {
+       struct panfrost_file_priv *user = file_priv->driver_priv;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
 
        if (user != perfcnt->user)
@@ -180,6 +184,7 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
        perfcnt->user = NULL;
        drm_gem_shmem_vunmap(&perfcnt->bo->base.base, perfcnt->buf);
        perfcnt->buf = NULL;
+       panfrost_gem_close(&perfcnt->bo->base.base, file_priv);
        drm_gem_object_put_unlocked(&perfcnt->bo->base.base);
        perfcnt->bo = NULL;
        pm_runtime_mark_last_busy(pfdev->dev);
@@ -191,7 +196,6 @@ static int panfrost_perfcnt_disable_locked(struct panfrost_device *pfdev,
 int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv)
 {
-       struct panfrost_file_priv *pfile = file_priv->driver_priv;
        struct panfrost_device *pfdev = dev->dev_private;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
        struct drm_panfrost_perfcnt_enable *req = data;
@@ -207,10 +211,10 @@ int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
 
        mutex_lock(&perfcnt->lock);
        if (req->enable)
-               ret = panfrost_perfcnt_enable_locked(pfdev, pfile,
+               ret = panfrost_perfcnt_enable_locked(pfdev, file_priv,
                                                     req->counterset);
        else
-               ret = panfrost_perfcnt_disable_locked(pfdev, pfile);
+               ret = panfrost_perfcnt_disable_locked(pfdev, file_priv);
        mutex_unlock(&perfcnt->lock);
 
        return ret;
@@ -248,15 +252,16 @@ out:
        return ret;
 }
 
-void panfrost_perfcnt_close(struct panfrost_file_priv *pfile)
+void panfrost_perfcnt_close(struct drm_file *file_priv)
 {
+       struct panfrost_file_priv *pfile = file_priv->driver_priv;
        struct panfrost_device *pfdev = pfile->pfdev;
        struct panfrost_perfcnt *perfcnt = pfdev->perfcnt;
 
        pm_runtime_get_sync(pfdev->dev);
        mutex_lock(&perfcnt->lock);
        if (perfcnt->user == pfile)
-               panfrost_perfcnt_disable_locked(pfdev, pfile);
+               panfrost_perfcnt_disable_locked(pfdev, file_priv);
        mutex_unlock(&perfcnt->lock);
        pm_runtime_mark_last_busy(pfdev->dev);
        pm_runtime_put_autosuspend(pfdev->dev);
index 13b8fda..8bbcf5f 100644 (file)
@@ -9,7 +9,7 @@ void panfrost_perfcnt_sample_done(struct panfrost_device *pfdev);
 void panfrost_perfcnt_clean_cache_done(struct panfrost_device *pfdev);
 int panfrost_perfcnt_init(struct panfrost_device *pfdev);
 void panfrost_perfcnt_fini(struct panfrost_device *pfdev);
-void panfrost_perfcnt_close(struct panfrost_file_priv *pfile);
+void panfrost_perfcnt_close(struct drm_file *file_priv);
 int panfrost_ioctl_perfcnt_enable(struct drm_device *dev, void *data,
                                  struct drm_file *file_priv);
 int panfrost_ioctl_perfcnt_dump(struct drm_device *dev, void *data,
index 83c4586..81ac9b6 100644 (file)
@@ -95,7 +95,7 @@ struct cdn_dp_device {
        struct cdn_dp_port *port[MAX_PHY];
        u8 ports;
        u8 max_lanes;
-       u8 max_rate;
+       unsigned int max_rate;
        u8 lanes;
        int active_port;
 
index a7c4654..68d4644 100644 (file)
@@ -685,8 +685,6 @@ static void sun4i_hdmi_unbind(struct device *dev, struct device *master,
        struct sun4i_hdmi *hdmi = dev_get_drvdata(dev);
 
        cec_unregister_adapter(hdmi->cec_adap);
-       drm_connector_cleanup(&hdmi->connector);
-       drm_encoder_cleanup(&hdmi->encoder);
        i2c_del_adapter(hdmi->i2c);
        i2c_put_adapter(hdmi->ddc_i2c);
        clk_disable_unprepare(hdmi->mod_clk);
index 42651d7..c81cdce 100644 (file)
@@ -489,7 +489,7 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
 
        WARN_ON(!tcon->quirks->has_channel_0);
 
-       tcon->dclk_min_div = 1;
+       tcon->dclk_min_div = tcon->quirks->dclk_min_div;
        tcon->dclk_max_div = 127;
        sun4i_tcon0_mode_set_common(tcon, mode);
 
@@ -1426,12 +1426,14 @@ static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
 static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
        .has_channel_0          = true,
        .has_channel_1          = true,
+       .dclk_min_div           = 4,
        .set_mux                = sun4i_a10_tcon_set_mux,
 };
 
 static const struct sun4i_tcon_quirks sun5i_a13_quirks = {
        .has_channel_0          = true,
        .has_channel_1          = true,
+       .dclk_min_div           = 4,
        .set_mux                = sun5i_a13_tcon_set_mux,
 };
 
@@ -1440,6 +1442,7 @@ static const struct sun4i_tcon_quirks sun6i_a31_quirks = {
        .has_channel_1          = true,
        .has_lvds_alt           = true,
        .needs_de_be_mux        = true,
+       .dclk_min_div           = 1,
        .set_mux                = sun6i_tcon_set_mux,
 };
 
@@ -1447,11 +1450,13 @@ static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
        .has_channel_0          = true,
        .has_channel_1          = true,
        .needs_de_be_mux        = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
        .has_channel_0          = true,
        .has_channel_1          = true,
+       .dclk_min_div           = 4,
        /* Same display pipeline structure as A10 */
        .set_mux                = sun4i_a10_tcon_set_mux,
 };
@@ -1459,11 +1464,13 @@ static const struct sun4i_tcon_quirks sun7i_a20_quirks = {
 static const struct sun4i_tcon_quirks sun8i_a33_quirks = {
        .has_channel_0          = true,
        .has_lvds_alt           = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
        .supports_lvds          = true,
        .has_channel_0          = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun8i_a83t_tv_quirks = {
@@ -1477,11 +1484,13 @@ static const struct sun4i_tcon_quirks sun8i_r40_tv_quirks = {
 
 static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
        .has_channel_0          = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun9i_a80_tcon_lcd_quirks = {
-       .has_channel_0  = true,
-       .needs_edp_reset = true,
+       .has_channel_0          = true,
+       .needs_edp_reset        = true,
+       .dclk_min_div           = 1,
 };
 
 static const struct sun4i_tcon_quirks sun9i_a80_tcon_tv_quirks = {
index f9f1fe8..a62ec82 100644 (file)
@@ -224,6 +224,7 @@ struct sun4i_tcon_quirks {
        bool    needs_de_be_mux; /* sun6i needs mux to select backend */
        bool    needs_edp_reset; /* a80 edp reset needed for tcon0 access */
        bool    supports_lvds;   /* Does the TCON support an LVDS output? */
+       u8      dclk_min_div;   /* minimum divider for TCON0 DCLK */
 
        /* callback to handle tcon muxing options */
        int     (*set_mux)(struct sun4i_tcon *, const struct drm_encoder *);
index 3905241..1635a9f 100644 (file)
@@ -232,6 +232,7 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane,
                if (!objs)
                        return;
                virtio_gpu_array_add_obj(objs, vgfb->base.obj[0]);
+               virtio_gpu_array_lock_resv(objs);
                virtio_gpu_cmd_transfer_to_host_2d
                        (vgdev, 0,
                         plane->state->crtc_w,
index 8063b1d..e6e4c84 100644 (file)
@@ -261,7 +261,8 @@ static int asus_event(struct hid_device *hdev, struct hid_field *field,
                      struct hid_usage *usage, __s32 value)
 {
        if ((usage->hid & HID_USAGE_PAGE) == 0xff310000 &&
-           (usage->hid & HID_USAGE) != 0x00 && !usage->type) {
+           (usage->hid & HID_USAGE) != 0x00 &&
+           (usage->hid & HID_USAGE) != 0xff && !usage->type) {
                hid_warn(hdev, "Unmapped Asus vendor usagepage code 0x%02x\n",
                         usage->hid & HID_USAGE);
        }
index e0b241b..851fe54 100644 (file)
@@ -288,6 +288,12 @@ static int hid_add_field(struct hid_parser *parser, unsigned report_type, unsign
        offset = report->size;
        report->size += parser->global.report_size * parser->global.report_count;
 
+       /* Total size check: Allow for possible report index byte */
+       if (report->size > (HID_MAX_BUFFER_SIZE - 1) << 3) {
+               hid_err(parser->device, "report is too long\n");
+               return -1;
+       }
+
        if (!parser->local.usage_index) /* Ignore padding fields */
                return 0;
 
index 7e1689e..3a400ce 100644 (file)
 #define USB_VENDOR_ID_ITE               0x048d
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA   0x8386
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA2  0x8350
+#define I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720   0x837a
 #define USB_DEVICE_ID_ITE_LENOVO_YOGA900       0x8396
 #define USB_DEVICE_ID_ITE8595          0x8595
 
 #define USB_DEVICE_ID_LG_MULTITOUCH    0x0064
 #define USB_DEVICE_ID_LG_MELFAS_MT     0x6007
 #define I2C_DEVICE_ID_LG_8001          0x8001
+#define I2C_DEVICE_ID_LG_7010          0x7010
 
 #define USB_VENDOR_ID_LOGITECH         0x046d
 #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
 #define USB_DEVICE_ID_SYNAPTICS_LTS2   0x1d10
 #define USB_DEVICE_ID_SYNAPTICS_HD     0x0ac3
 #define USB_DEVICE_ID_SYNAPTICS_QUAD_HD        0x1ac3
+#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012       0x2968
 #define USB_DEVICE_ID_SYNAPTICS_TP_V103        0x5710
 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5   0x81a7
 
index 63855f2..dea9cc6 100644 (file)
@@ -1132,9 +1132,15 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
        }
 
 mapped:
-       if (device->driver->input_mapped && device->driver->input_mapped(device,
-                               hidinput, field, usage, &bit, &max) < 0)
-               goto ignore;
+       if (device->driver->input_mapped &&
+           device->driver->input_mapped(device, hidinput, field, usage,
+                                        &bit, &max) < 0) {
+               /*
+                * The driver indicated that no further generic handling
+                * of the usage is desired.
+                */
+               return;
+       }
 
        set_bit(usage->type, input->evbit);
 
@@ -1215,9 +1221,11 @@ mapped:
                set_bit(MSC_SCAN, input->mscbit);
        }
 
-ignore:
        return;
 
+ignore:
+       usage->type = 0;
+       usage->code = 0;
 }
 
 static void hidinput_handle_scroll(struct hid_usage *usage,
index a45f235..c436e12 100644 (file)
@@ -40,6 +40,9 @@ static int ite_event(struct hid_device *hdev, struct hid_field *field,
 static const struct hid_device_id ite_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ITE, USB_DEVICE_ID_ITE8595) },
        { HID_USB_DEVICE(USB_VENDOR_ID_258A, USB_DEVICE_ID_258A_6A88) },
+       /* ITE8595 USB kbd ctlr, with Synaptics touchpad connected to it. */
+       { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS,
+                        USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, ite_devices);
index 3cfeb16..362805d 100644 (file)
@@ -1019,7 +1019,7 @@ static int mt_process_slot(struct mt_device *td, struct input_dev *input,
                tool = MT_TOOL_DIAL;
        else if (unlikely(!confidence_state)) {
                tool = MT_TOOL_PALM;
-               if (!active &&
+               if (!active && mt &&
                    input_mt_is_active(&mt->slots[slotnum])) {
                        /*
                         * The non-confidence was reported for
@@ -1985,6 +1985,9 @@ static const struct hid_device_id mt_devices[] = {
        { .driver_data = MT_CLS_LG,
                HID_USB_DEVICE(USB_VENDOR_ID_LG,
                        USB_DEVICE_ID_LG_MELFAS_MT) },
+       { .driver_data = MT_CLS_LG,
+               HID_DEVICE(BUS_I2C, HID_GROUP_GENERIC,
+                       USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_7010) },
 
        /* MosArt panels */
        { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE,
index d1b39c2..0e7b2d9 100644 (file)
@@ -174,6 +174,7 @@ static const struct hid_device_id hid_quirks[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET), HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD2, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
        { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_QUAD_USB_JOYPAD), HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
+       { HID_USB_DEVICE(USB_VENDOR_ID_XIN_MO, USB_DEVICE_ID_XIN_MO_DUAL_ARCADE), HID_QUIRK_MULTI_INPUT },
 
        { 0 }
 };
index 8dae0f9..6286204 100644 (file)
@@ -768,8 +768,12 @@ static int steam_probe(struct hid_device *hdev,
 
        if (steam->quirks & STEAM_QUIRK_WIRELESS) {
                hid_info(hdev, "Steam wireless receiver connected");
+               /* If using a wireless adaptor ask for connection status */
+               steam->connected = false;
                steam_request_conn_status(steam);
        } else {
+               /* A wired connection is always present */
+               steam->connected = true;
                ret = steam_register(steam);
                if (ret) {
                        hid_err(hdev,
index c3fc0ce..7a75aff 100644 (file)
@@ -249,13 +249,14 @@ out:
 static __poll_t hidraw_poll(struct file *file, poll_table *wait)
 {
        struct hidraw_list *list = file->private_data;
+       __poll_t mask = EPOLLOUT | EPOLLWRNORM; /* hidraw is always writable */
 
        poll_wait(file, &list->hidraw->wait, wait);
        if (list->head != list->tail)
-               return EPOLLIN | EPOLLRDNORM | EPOLLOUT;
+               mask |= EPOLLIN | EPOLLRDNORM;
        if (!list->hidraw->exist)
-               return EPOLLERR | EPOLLHUP;
-       return 0;
+               mask |= EPOLLERR | EPOLLHUP;
+       return mask;
 }
 
 static int hidraw_open(struct inode *inode, struct file *file)
index a358e61..009000c 100644 (file)
@@ -49,6 +49,8 @@
 #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET       BIT(1)
 #define I2C_HID_QUIRK_BOGUS_IRQ                        BIT(4)
 #define I2C_HID_QUIRK_RESET_ON_RESUME          BIT(5)
+#define I2C_HID_QUIRK_BAD_INPUT_SIZE           BIT(6)
+
 
 /* flags */
 #define I2C_HID_STARTED                0
@@ -175,6 +177,8 @@ static const struct i2c_hid_quirks {
                 I2C_HID_QUIRK_BOGUS_IRQ },
        { USB_VENDOR_ID_ALPS_JP, HID_ANY_ID,
                 I2C_HID_QUIRK_RESET_ON_RESUME },
+       { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
+               I2C_HID_QUIRK_BAD_INPUT_SIZE },
        { 0, 0 }
 };
 
@@ -496,9 +500,15 @@ static void i2c_hid_get_input(struct i2c_hid *ihid)
        }
 
        if ((ret_size > size) || (ret_size < 2)) {
-               dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
-                       __func__, size, ret_size);
-               return;
+               if (ihid->quirks & I2C_HID_QUIRK_BAD_INPUT_SIZE) {
+                       ihid->inbuf[0] = size & 0xff;
+                       ihid->inbuf[1] = size >> 8;
+                       ret_size = size;
+               } else {
+                       dev_err(&ihid->client->dev, "%s: incomplete report (%d/%d)\n",
+                               __func__, size, ret_size);
+                       return;
+               }
        }
 
        i2c_hid_dbg(ihid, "input: %*ph\n", ret_size, ihid->inbuf);
index 6c1e611..1fb294c 100644 (file)
@@ -24,7 +24,9 @@
 #define ICL_MOBILE_DEVICE_ID   0x34FC
 #define SPT_H_DEVICE_ID                0xA135
 #define CML_LP_DEVICE_ID       0x02FC
+#define CMP_H_DEVICE_ID                0x06FC
 #define EHL_Ax_DEVICE_ID       0x4BB3
+#define TGL_LP_DEVICE_ID       0xA0FC
 
 #define        REVISION_ID_CHT_A0      0x6
 #define        REVISION_ID_CHT_Ax_SI   0x0
index 784dcc8..f491d8b 100644 (file)
@@ -34,7 +34,9 @@ static const struct pci_device_id ish_pci_tbl[] = {
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, ICL_MOBILE_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, SPT_H_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CML_LP_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, CMP_H_DEVICE_ID)},
        {PCI_DEVICE(PCI_VENDOR_ID_INTEL, EHL_Ax_DEVICE_ID)},
+       {PCI_DEVICE(PCI_VENDOR_ID_INTEL, TGL_LP_DEVICE_ID)},
        {0, }
 };
 MODULE_DEVICE_TABLE(pci, ish_pci_tbl);
index fa0cc08..8fe3efc 100644 (file)
@@ -766,13 +766,14 @@ unlock:
 static __poll_t uhid_char_poll(struct file *file, poll_table *wait)
 {
        struct uhid_device *uhid = file->private_data;
+       __poll_t mask = EPOLLOUT | EPOLLWRNORM; /* uhid is always writable */
 
        poll_wait(file, &uhid->waitq, wait);
 
        if (uhid->head != uhid->tail)
-               return EPOLLIN | EPOLLRDNORM;
+               mask |= EPOLLIN | EPOLLRDNORM;
 
-       return 0;
+       return mask;
 }
 
 static const struct file_operations uhid_fops = {
index e421cdf..a970b80 100644 (file)
@@ -241,12 +241,51 @@ static int hiddev_release(struct inode * inode, struct file * file)
        return 0;
 }
 
+static int __hiddev_open(struct hiddev *hiddev, struct file *file)
+{
+       struct hiddev_list *list;
+       int error;
+
+       lockdep_assert_held(&hiddev->existancelock);
+
+       list = vzalloc(sizeof(*list));
+       if (!list)
+               return -ENOMEM;
+
+       mutex_init(&list->thread_lock);
+       list->hiddev = hiddev;
+
+       if (!hiddev->open++) {
+               error = hid_hw_power(hiddev->hid, PM_HINT_FULLON);
+               if (error < 0)
+                       goto err_drop_count;
+
+               error = hid_hw_open(hiddev->hid);
+               if (error < 0)
+                       goto err_normal_power;
+       }
+
+       spin_lock_irq(&hiddev->list_lock);
+       list_add_tail(&list->node, &hiddev->list);
+       spin_unlock_irq(&hiddev->list_lock);
+
+       file->private_data = list;
+
+       return 0;
+
+err_normal_power:
+       hid_hw_power(hiddev->hid, PM_HINT_NORMAL);
+err_drop_count:
+       hiddev->open--;
+       vfree(list);
+       return error;
+}
+
 /*
  * open file op
  */
 static int hiddev_open(struct inode *inode, struct file *file)
 {
-       struct hiddev_list *list;
        struct usb_interface *intf;
        struct hid_device *hid;
        struct hiddev *hiddev;
@@ -255,66 +294,14 @@ static int hiddev_open(struct inode *inode, struct file *file)
        intf = usbhid_find_interface(iminor(inode));
        if (!intf)
                return -ENODEV;
+
        hid = usb_get_intfdata(intf);
        hiddev = hid->hiddev;
 
-       if (!(list = vzalloc(sizeof(struct hiddev_list))))
-               return -ENOMEM;
-       mutex_init(&list->thread_lock);
-       list->hiddev = hiddev;
-       file->private_data = list;
-
-       /*
-        * no need for locking because the USB major number
-        * is shared which usbcore guards against disconnect
-        */
-       if (list->hiddev->exist) {
-               if (!list->hiddev->open++) {
-                       res = hid_hw_open(hiddev->hid);
-                       if (res < 0)
-                               goto bail;
-               }
-       } else {
-               res = -ENODEV;
-               goto bail;
-       }
-
-       spin_lock_irq(&list->hiddev->list_lock);
-       list_add_tail(&list->node, &hiddev->list);
-       spin_unlock_irq(&list->hiddev->list_lock);
-
        mutex_lock(&hiddev->existancelock);
-       /*
-        * recheck exist with existance lock held to
-        * avoid opening a disconnected device
-        */
-       if (!list->hiddev->exist) {
-               res = -ENODEV;
-               goto bail_unlock;
-       }
-       if (!list->hiddev->open++)
-               if (list->hiddev->exist) {
-                       struct hid_device *hid = hiddev->hid;
-                       res = hid_hw_power(hid, PM_HINT_FULLON);
-                       if (res < 0)
-                               goto bail_unlock;
-                       res = hid_hw_open(hid);
-                       if (res < 0)
-                               goto bail_normal_power;
-               }
-       mutex_unlock(&hiddev->existancelock);
-       return 0;
-bail_normal_power:
-       hid_hw_power(hid, PM_HINT_NORMAL);
-bail_unlock:
+       res = hiddev->exist ? __hiddev_open(hiddev, file) : -ENODEV;
        mutex_unlock(&hiddev->existancelock);
 
-       spin_lock_irq(&list->hiddev->list_lock);
-       list_del(&list->node);
-       spin_unlock_irq(&list->hiddev->list_lock);
-bail:
-       file->private_data = NULL;
-       vfree(list);
        return res;
 }
 
index ccb7452..d99a9d4 100644 (file)
@@ -2096,14 +2096,16 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field
                    (hdev->product == 0x34d || hdev->product == 0x34e ||  /* MobileStudio Pro */
                     hdev->product == 0x357 || hdev->product == 0x358 ||  /* Intuos Pro 2 */
                     hdev->product == 0x392 ||                            /* Intuos Pro 2 */
-                    hdev->product == 0x398 || hdev->product == 0x399)) { /* MobileStudio Pro */
+                    hdev->product == 0x398 || hdev->product == 0x399 ||  /* MobileStudio Pro */
+                    hdev->product == 0x3AA)) {                           /* MobileStudio Pro */
                        value = (field->logical_maximum - value);
 
                        if (hdev->product == 0x357 || hdev->product == 0x358 ||
                            hdev->product == 0x392)
                                value = wacom_offset_rotation(input, usage, value, 3, 16);
                        else if (hdev->product == 0x34d || hdev->product == 0x34e ||
-                                hdev->product == 0x398 || hdev->product == 0x399)
+                                hdev->product == 0x398 || hdev->product == 0x399 ||
+                                hdev->product == 0x3AA)
                                value = wacom_offset_rotation(input, usage, value, 1, 2);
                }
                else {
index dc3f507..a90d757 100644 (file)
@@ -1132,7 +1132,6 @@ static void etm4_init_trace_id(struct etmv4_drvdata *drvdata)
        drvdata->trcid = coresight_get_trace_id(drvdata->cpu);
 }
 
-#ifdef CONFIG_CPU_PM
 static int etm4_cpu_save(struct etmv4_drvdata *drvdata)
 {
        int i, ret = 0;
@@ -1402,17 +1401,17 @@ static struct notifier_block etm4_cpu_pm_nb = {
 
 static int etm4_cpu_pm_register(void)
 {
-       return cpu_pm_register_notifier(&etm4_cpu_pm_nb);
+       if (IS_ENABLED(CONFIG_CPU_PM))
+               return cpu_pm_register_notifier(&etm4_cpu_pm_nb);
+
+       return 0;
 }
 
 static void etm4_cpu_pm_unregister(void)
 {
-       cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
+       if (IS_ENABLED(CONFIG_CPU_PM))
+               cpu_pm_unregister_notifier(&etm4_cpu_pm_nb);
 }
-#else
-static int etm4_cpu_pm_register(void) { return 0; }
-static void etm4_cpu_pm_unregister(void) { }
-#endif
 
 static int etm4_probe(struct amba_device *adev, const struct amba_id *id)
 {
index 0dfd97b..ca232ec 100644 (file)
@@ -834,9 +834,6 @@ static irqreturn_t intel_th_irq(int irq, void *data)
                        ret |= d->irq(th->thdev[i]);
        }
 
-       if (ret == IRQ_NONE)
-               pr_warn_ratelimited("nobody cared for irq\n");
-
        return ret;
 }
 
@@ -887,6 +884,7 @@ intel_th_alloc(struct device *dev, struct intel_th_drvdata *drvdata,
 
                        if (th->irq == -1)
                                th->irq = devres[r].start;
+                       th->num_irqs++;
                        break;
                default:
                        dev_warn(dev, "Unknown resource type %lx\n",
@@ -940,6 +938,9 @@ void intel_th_free(struct intel_th *th)
 
        th->num_thdevs = 0;
 
+       for (i = 0; i < th->num_irqs; i++)
+               devm_free_irq(th->dev, th->irq + i, th);
+
        pm_runtime_get_sync(th->dev);
        pm_runtime_forbid(th->dev);
 
index 0df4800..6f4f548 100644 (file)
@@ -261,6 +261,7 @@ enum th_mmio_idx {
  * @num_thdevs:        number of devices in the @thdev array
  * @num_resources:     number of resources in the @resource array
  * @irq:       irq number
+ * @num_irqs:  number of IRQs is use
  * @id:                this Intel TH controller's device ID in the system
  * @major:     device node major for output devices
  */
@@ -277,6 +278,7 @@ struct intel_th {
        unsigned int            num_thdevs;
        unsigned int            num_resources;
        int                     irq;
+       int                     num_irqs;
 
        int                     id;
        int                     major;
index 6d240df..8e48c74 100644 (file)
@@ -1676,10 +1676,13 @@ static int intel_th_msc_init(struct msc *msc)
        return 0;
 }
 
-static void msc_win_switch(struct msc *msc)
+static int msc_win_switch(struct msc *msc)
 {
        struct msc_window *first;
 
+       if (list_empty(&msc->win_list))
+               return -EINVAL;
+
        first = list_first_entry(&msc->win_list, struct msc_window, entry);
 
        if (msc_is_last_win(msc->cur_win))
@@ -1691,6 +1694,8 @@ static void msc_win_switch(struct msc *msc)
        msc->base_addr = msc_win_base_dma(msc->cur_win);
 
        intel_th_trace_switch(msc->thdev);
+
+       return 0;
 }
 
 /**
@@ -2025,16 +2030,15 @@ win_switch_store(struct device *dev, struct device_attribute *attr,
        if (val != 1)
                return -EINVAL;
 
+       ret = -EINVAL;
        mutex_lock(&msc->buf_mutex);
        /*
         * Window switch can only happen in the "multi" mode.
         * If a external buffer is engaged, they have the full
         * control over window switching.
         */
-       if (msc->mode != MSC_MODE_MULTI || msc->mbuf)
-               ret = -ENOTSUPP;
-       else
-               msc_win_switch(msc);
+       if (msc->mode == MSC_MODE_MULTI && !msc->mbuf)
+               ret = msc_win_switch(msc);
        mutex_unlock(&msc->buf_mutex);
 
        return ret ? ret : size;
index ebf3e30..e9d90b5 100644 (file)
@@ -205,6 +205,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
        {
+               /* Comet Lake PCH-V */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa3a6),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
+       {
                /* Ice Lake NNPI */
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x45c5),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
@@ -229,6 +234,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
                PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4da6),
                .driver_data = (kernel_ulong_t)&intel_th_2x,
        },
+       {
+               /* Elkhart Lake */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x4b26),
+               .driver_data = (kernel_ulong_t)&intel_th_2x,
+       },
        { 0 },
 };
 
index e13af48..5137e62 100644 (file)
@@ -174,7 +174,7 @@ static struct at91_twi_pdata sama5d2_config = {
 
 static struct at91_twi_pdata sam9x60_config = {
        .clk_max_div = 7,
-       .clk_offset = 4,
+       .clk_offset = 3,
        .has_unre_flag = true,
        .has_alt_cmd = true,
        .has_hold_field = true,
index e01b2b5..5ab901a 100644 (file)
@@ -58,6 +58,7 @@ struct bcm2835_i2c_dev {
        struct i2c_adapter adapter;
        struct completion completion;
        struct i2c_msg *curr_msg;
+       struct clk *bus_clk;
        int num_msgs;
        u32 msg_err;
        u8 *msg_buf;
@@ -404,7 +405,6 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
        struct resource *mem, *irq;
        int ret;
        struct i2c_adapter *adap;
-       struct clk *bus_clk;
        struct clk *mclk;
        u32 bus_clk_rate;
 
@@ -427,11 +427,11 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
                return PTR_ERR(mclk);
        }
 
-       bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
+       i2c_dev->bus_clk = bcm2835_i2c_register_div(&pdev->dev, mclk, i2c_dev);
 
-       if (IS_ERR(bus_clk)) {
+       if (IS_ERR(i2c_dev->bus_clk)) {
                dev_err(&pdev->dev, "Could not register clock\n");
-               return PTR_ERR(bus_clk);
+               return PTR_ERR(i2c_dev->bus_clk);
        }
 
        ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
@@ -442,13 +442,13 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
                bus_clk_rate = 100000;
        }
 
-       ret = clk_set_rate_exclusive(bus_clk, bus_clk_rate);
+       ret = clk_set_rate_exclusive(i2c_dev->bus_clk, bus_clk_rate);
        if (ret < 0) {
                dev_err(&pdev->dev, "Could not set clock frequency\n");
                return ret;
        }
 
-       ret = clk_prepare_enable(bus_clk);
+       ret = clk_prepare_enable(i2c_dev->bus_clk);
        if (ret) {
                dev_err(&pdev->dev, "Couldn't prepare clock");
                return ret;
@@ -491,10 +491,9 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
 static int bcm2835_i2c_remove(struct platform_device *pdev)
 {
        struct bcm2835_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
-       struct clk *bus_clk = devm_clk_get(i2c_dev->dev, "div");
 
-       clk_rate_exclusive_put(bus_clk);
-       clk_disable_unprepare(bus_clk);
+       clk_rate_exclusive_put(i2c_dev->bus_clk);
+       clk_disable_unprepare(i2c_dev->bus_clk);
 
        free_irq(i2c_dev->irq, i2c_dev);
        i2c_del_adapter(&i2c_dev->adapter);
index 3855638..2f8b805 100644 (file)
@@ -433,13 +433,17 @@ iop3xx_i2c_probe(struct platform_device *pdev)
        adapter_data->gpio_scl = devm_gpiod_get_optional(&pdev->dev,
                                                         "scl",
                                                         GPIOD_ASIS);
-       if (IS_ERR(adapter_data->gpio_scl))
-               return PTR_ERR(adapter_data->gpio_scl);
+       if (IS_ERR(adapter_data->gpio_scl)) {
+               ret = PTR_ERR(adapter_data->gpio_scl);
+               goto free_both;
+       }
        adapter_data->gpio_sda = devm_gpiod_get_optional(&pdev->dev,
                                                         "sda",
                                                         GPIOD_ASIS);
-       if (IS_ERR(adapter_data->gpio_sda))
-               return PTR_ERR(adapter_data->gpio_sda);
+       if (IS_ERR(adapter_data->gpio_sda)) {
+               ret = PTR_ERR(adapter_data->gpio_sda);
+               goto free_both;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
index a98bf31..61339c6 100644 (file)
@@ -1608,14 +1608,18 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        }
 
        pm_runtime_enable(&pdev->dev);
-       if (!pm_runtime_enabled(&pdev->dev))
+       if (!pm_runtime_enabled(&pdev->dev)) {
                ret = tegra_i2c_runtime_resume(&pdev->dev);
-       else
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "runtime resume failed\n");
+                       goto unprepare_div_clk;
+               }
+       } else {
                ret = pm_runtime_get_sync(i2c_dev->dev);
-
-       if (ret < 0) {
-               dev_err(&pdev->dev, "runtime resume failed\n");
-               goto unprepare_div_clk;
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "runtime resume failed\n");
+                       goto disable_rpm;
+               }
        }
 
        if (i2c_dev->is_multimaster_mode) {
@@ -1623,7 +1627,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
                if (ret < 0) {
                        dev_err(i2c_dev->dev, "div_clk enable failed %d\n",
                                ret);
-                       goto disable_rpm;
+                       goto put_rpm;
                }
        }
 
@@ -1671,11 +1675,16 @@ disable_div_clk:
        if (i2c_dev->is_multimaster_mode)
                clk_disable(i2c_dev->div_clk);
 
-disable_rpm:
-       pm_runtime_disable(&pdev->dev);
-       if (!pm_runtime_status_suspended(&pdev->dev))
+put_rpm:
+       if (pm_runtime_enabled(&pdev->dev))
+               pm_runtime_put_sync(&pdev->dev);
+       else
                tegra_i2c_runtime_suspend(&pdev->dev);
 
+disable_rpm:
+       if (pm_runtime_enabled(&pdev->dev))
+               pm_runtime_disable(&pdev->dev);
+
 unprepare_div_clk:
        clk_unprepare(i2c_dev->div_clk);
 
@@ -1710,9 +1719,14 @@ static int tegra_i2c_remove(struct platform_device *pdev)
 static int __maybe_unused tegra_i2c_suspend(struct device *dev)
 {
        struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev);
+       int err;
 
        i2c_mark_adapter_suspended(&i2c_dev->adapter);
 
+       err = pm_runtime_force_suspend(dev);
+       if (err < 0)
+               return err;
+
        return 0;
 }
 
@@ -1733,6 +1747,10 @@ static int __maybe_unused tegra_i2c_resume(struct device *dev)
        if (err)
                return err;
 
+       err = pm_runtime_force_resume(dev);
+       if (err < 0)
+               return err;
+
        i2c_mark_adapter_resumed(&i2c_dev->adapter);
 
        return 0;
index 9333c86..35b2097 100644 (file)
@@ -186,10 +186,11 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
         * If we can set SDA, we will always create a STOP to ensure additional
         * pulses will do no harm. This is achieved by letting SDA follow SCL
         * half a cycle later. Check the 'incomplete_write_byte' fault injector
-        * for details.
+        * for details. Note that we must honour tsu:sto, 4us, but lets use 5us
+        * here for simplicity.
         */
        bri->set_scl(adap, scl);
-       ndelay(RECOVERY_NDELAY / 2);
+       ndelay(RECOVERY_NDELAY);
        if (bri->set_sda)
                bri->set_sda(adap, scl);
        ndelay(RECOVERY_NDELAY / 2);
@@ -211,7 +212,13 @@ int i2c_generic_scl_recovery(struct i2c_adapter *adap)
                scl = !scl;
                bri->set_scl(adap, scl);
                /* Creating STOP again, see above */
-               ndelay(RECOVERY_NDELAY / 2);
+               if (scl)  {
+                       /* Honour minimum tsu:sto */
+                       ndelay(RECOVERY_NDELAY);
+               } else {
+                       /* Honour minimum tf and thd:dat */
+                       ndelay(RECOVERY_NDELAY / 2);
+               }
                if (bri->set_sda)
                        bri->set_sda(adap, scl);
                ndelay(RECOVERY_NDELAY / 2);
@@ -896,29 +903,6 @@ struct i2c_client *i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address
 }
 EXPORT_SYMBOL_GPL(i2c_new_dummy_device);
 
-/**
- * i2c_new_dummy - return a new i2c device bound to a dummy driver
- * @adapter: the adapter managing the device
- * @address: seven bit address to be used
- * Context: can sleep
- *
- * This deprecated function has the same functionality as @i2c_new_dummy_device,
- * it just returns NULL instead of an ERR_PTR in case of an error for
- * compatibility with current I2C API. It will be removed once all users are
- * converted.
- *
- * This returns the new i2c client, which should be saved for later use with
- * i2c_unregister_device(); or NULL to indicate an error.
- */
-struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address)
-{
-       struct i2c_client *ret;
-
-       ret = i2c_new_dummy_device(adapter, address);
-       return IS_ERR(ret) ? NULL : ret;
-}
-EXPORT_SYMBOL_GPL(i2c_new_dummy);
-
 struct i2c_dummy_devres {
        struct i2c_client *client;
 };
index 7b83764..7320275 100644 (file)
@@ -992,6 +992,7 @@ static const struct iio_trigger_ops st_accel_trigger_ops = {
 #define ST_ACCEL_TRIGGER_OPS NULL
 #endif
 
+#ifdef CONFIG_ACPI
 static const struct iio_mount_matrix *
 get_mount_matrix(const struct iio_dev *indio_dev,
                 const struct iio_chan_spec *chan)
@@ -1012,7 +1013,6 @@ static const struct iio_chan_spec_ext_info mount_matrix_ext_info[] = {
 static int apply_acpi_orientation(struct iio_dev *indio_dev,
                                  struct iio_chan_spec *channels)
 {
-#ifdef CONFIG_ACPI
        struct st_sensor_data *adata = iio_priv(indio_dev);
        struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
        struct acpi_device *adev;
@@ -1140,10 +1140,14 @@ static int apply_acpi_orientation(struct iio_dev *indio_dev,
 out:
        kfree(buffer.pointer);
        return ret;
+}
 #else /* !CONFIG_ACPI */
+static int apply_acpi_orientation(struct iio_dev *indio_dev,
+                                 struct iio_chan_spec *channels)
+{
        return 0;
-#endif
 }
+#endif
 
 /*
  * st_accel_get_settings() - get sensor settings from device name
index edc6f1c..306bf15 100644 (file)
@@ -39,6 +39,8 @@
 #define AD7124_STATUS_POR_FLAG_MSK     BIT(4)
 
 /* AD7124_ADC_CONTROL */
+#define AD7124_ADC_CTRL_REF_EN_MSK     BIT(8)
+#define AD7124_ADC_CTRL_REF_EN(x)      FIELD_PREP(AD7124_ADC_CTRL_REF_EN_MSK, x)
 #define AD7124_ADC_CTRL_PWR_MSK        GENMASK(7, 6)
 #define AD7124_ADC_CTRL_PWR(x)         FIELD_PREP(AD7124_ADC_CTRL_PWR_MSK, x)
 #define AD7124_ADC_CTRL_MODE_MSK       GENMASK(5, 2)
@@ -424,7 +426,10 @@ static int ad7124_init_channel_vref(struct ad7124_state *st,
                break;
        case AD7124_INT_REF:
                st->channel_config[channel_number].vref_mv = 2500;
-               break;
+               st->adc_control &= ~AD7124_ADC_CTRL_REF_EN_MSK;
+               st->adc_control |= AD7124_ADC_CTRL_REF_EN(1);
+               return ad_sd_write_reg(&st->sd, AD7124_ADC_CONTROL,
+                                     2, st->adc_control);
        default:
                dev_err(&st->sd.spi->dev, "Invalid reference %d\n", refsel);
                return -EINVAL;
@@ -489,13 +494,11 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev,
                st->channel_config[channel].buf_negative =
                        of_property_read_bool(child, "adi,buffered-negative");
 
-               *chan = ad7124_channel_template;
-               chan->address = channel;
-               chan->scan_index = channel;
-               chan->channel = ain[0];
-               chan->channel2 = ain[1];
-
-               chan++;
+               chan[channel] = ad7124_channel_template;
+               chan[channel].address = channel;
+               chan[channel].scan_index = channel;
+               chan[channel].channel = ain[0];
+               chan[channel].channel2 = ain[1];
        }
 
        return 0;
index f5ba94c..e4683a6 100644 (file)
@@ -85,7 +85,7 @@ err_unlock:
 
 static int ad7606_read_samples(struct ad7606_state *st)
 {
-       unsigned int num = st->chip_info->num_channels;
+       unsigned int num = st->chip_info->num_channels - 1;
        u16 *data = st->data;
        int ret;
 
index 5c2b344..2c6f60e 100644 (file)
@@ -89,6 +89,7 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
                                   unsigned int channel)
 {
        int ret;
+       int i;
        int bits_per_word = ad7949_adc->resolution;
        int mask = GENMASK(ad7949_adc->resolution, 0);
        struct spi_message msg;
@@ -100,12 +101,23 @@ static int ad7949_spi_read_channel(struct ad7949_adc_chip *ad7949_adc, int *val,
                },
        };
 
-       ret = ad7949_spi_write_cfg(ad7949_adc,
-                                  channel << AD7949_OFFSET_CHANNEL_SEL,
-                                  AD7949_MASK_CHANNEL_SEL);
-       if (ret)
-               return ret;
+       /*
+        * 1: write CFG for sample N and read old data (sample N-2)
+        * 2: if CFG was not changed since sample N-1 then we'll get good data
+        *    at the next xfer, so we bail out now, otherwise we write something
+        *    and we read garbage (sample N-1 configuration).
+        */
+       for (i = 0; i < 2; i++) {
+               ret = ad7949_spi_write_cfg(ad7949_adc,
+                                          channel << AD7949_OFFSET_CHANNEL_SEL,
+                                          AD7949_MASK_CHANNEL_SEL);
+               if (ret)
+                       return ret;
+               if (channel == ad7949_adc->current_channel)
+                       break;
+       }
 
+       /* 3: write something and read actual data */
        ad7949_adc->buffer = 0;
        spi_message_init_with_transfers(&msg, tx, 1);
        ret = spi_sync(ad7949_adc->spi, &msg);
index 67d096f..c35a1be 100644 (file)
@@ -185,7 +185,7 @@ static int mrfld_adc_probe(struct platform_device *pdev)
        int irq;
        int ret;
 
-       indio_dev = devm_iio_device_alloc(dev, sizeof(*indio_dev));
+       indio_dev = devm_iio_device_alloc(dev, sizeof(struct mrfld_adc));
        if (!indio_dev)
                return -ENOMEM;
 
index e171db2..02834ca 100644 (file)
@@ -478,7 +478,13 @@ static int max1027_probe(struct spi_device *spi)
                st->trig->ops = &max1027_trigger_ops;
                st->trig->dev.parent = &spi->dev;
                iio_trigger_set_drvdata(st->trig, indio_dev);
-               iio_trigger_register(st->trig);
+               ret = devm_iio_trigger_register(&indio_dev->dev,
+                                               st->trig);
+               if (ret < 0) {
+                       dev_err(&indio_dev->dev,
+                               "Failed to register iio trigger\n");
+                       return ret;
+               }
 
                ret = devm_request_threaded_irq(&spi->dev, spi->irq,
                                                iio_trigger_generic_data_rdy_poll,
index da073d7..e480529 100644 (file)
 #define MAX9611_TEMP_SCALE_NUM         1000000
 #define MAX9611_TEMP_SCALE_DIV         2083
 
+/*
+ * Conversion time is 2 ms (typically) at Ta=25 degreeC
+ * No maximum value is known, so play it safe.
+ */
+#define MAX9611_CONV_TIME_US_RANGE     3000, 3300
+
 struct max9611_dev {
        struct device *dev;
        struct i2c_client *i2c_client;
@@ -236,11 +242,9 @@ static int max9611_read_single(struct max9611_dev *max9611,
                return ret;
        }
 
-       /*
-        * need a delay here to make register configuration
-        * stabilize. 1 msec at least, from empirical testing.
-        */
-       usleep_range(1000, 2000);
+       /* need a delay here to make register configuration stabilize. */
+
+       usleep_range(MAX9611_CONV_TIME_US_RANGE);
 
        ret = i2c_smbus_read_word_swapped(max9611->i2c_client, reg_addr);
        if (ret < 0) {
@@ -507,7 +511,7 @@ static int max9611_init(struct max9611_dev *max9611)
                        MAX9611_REG_CTRL2, 0);
                return ret;
        }
-       usleep_range(1000, 2000);
+       usleep_range(MAX9611_CONV_TIME_US_RANGE);
 
        return 0;
 }
index fa45860..0b91de4 100644 (file)
@@ -65,6 +65,7 @@ config IAQCORE
 config PMS7003
        tristate "Plantower PMS7003 particulate matter sensor"
        depends on SERIAL_DEV_BUS
+       select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        help
          Say Y here to build support for the Plantower PMS7003 particulate
index 963ff04..7ecd2ff 100644 (file)
@@ -229,7 +229,7 @@ static int hdc100x_read_raw(struct iio_dev *indio_dev,
                        *val2 = 65536;
                        return IIO_VAL_FRACTIONAL;
                } else {
-                       *val = 100;
+                       *val = 100000;
                        *val2 = 65536;
                        return IIO_VAL_FRACTIONAL;
                }
index 45e77b3..0686e41 100644 (file)
@@ -117,6 +117,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
                .fifo_size = 1024,
+               .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU6500_WHOAMI_VALUE,
@@ -124,6 +125,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU6515_WHOAMI_VALUE,
@@ -131,6 +133,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU6000_WHOAMI_VALUE,
@@ -138,6 +141,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
                .fifo_size = 1024,
+               .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU9150_WHOAMI_VALUE,
@@ -145,6 +149,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6050,
                .config = &chip_config_6050,
                .fifo_size = 1024,
+               .temp = {INV_MPU6050_TEMP_OFFSET, INV_MPU6050_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU9250_WHOAMI_VALUE,
@@ -152,6 +157,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
        },
        {
                .whoami = INV_MPU9255_WHOAMI_VALUE,
@@ -159,6 +165,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_MPU6500_TEMP_OFFSET, INV_MPU6500_TEMP_SCALE},
        },
        {
                .whoami = INV_ICM20608_WHOAMI_VALUE,
@@ -166,6 +173,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_6500,
                .config = &chip_config_6050,
                .fifo_size = 512,
+               .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
        },
        {
                .whoami = INV_ICM20602_WHOAMI_VALUE,
@@ -173,6 +181,7 @@ static const struct inv_mpu6050_hw hw_info[] = {
                .reg = &reg_set_icm20602,
                .config = &chip_config_6050,
                .fifo_size = 1008,
+               .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
        },
 };
 
@@ -481,12 +490,8 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
 
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_TEMP:
-                       *val = 0;
-                       if (st->chip_type == INV_ICM20602)
-                               *val2 = INV_ICM20602_TEMP_SCALE;
-                       else
-                               *val2 = INV_MPU6050_TEMP_SCALE;
-
+                       *val = st->hw->temp.scale / 1000000;
+                       *val2 = st->hw->temp.scale % 1000000;
                        return IIO_VAL_INT_PLUS_MICRO;
                case IIO_MAGN:
                        return inv_mpu_magn_get_scale(st, chan, val, val2);
@@ -496,11 +501,7 @@ inv_mpu6050_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_OFFSET:
                switch (chan->type) {
                case IIO_TEMP:
-                       if (st->chip_type == INV_ICM20602)
-                               *val = INV_ICM20602_TEMP_OFFSET;
-                       else
-                               *val = INV_MPU6050_TEMP_OFFSET;
-
+                       *val = st->hw->temp.offset;
                        return IIO_VAL_INT;
                default:
                        return -EINVAL;
index f1fb7b6..b096e01 100644 (file)
@@ -107,6 +107,7 @@ struct inv_mpu6050_chip_config {
  *  @reg:   register map of the chip.
  *  @config:    configuration of the chip.
  *  @fifo_size:        size of the FIFO in bytes.
+ *  @temp:     offset and scale to apply to raw temperature.
  */
 struct inv_mpu6050_hw {
        u8 whoami;
@@ -114,6 +115,10 @@ struct inv_mpu6050_hw {
        const struct inv_mpu6050_reg_map *reg;
        const struct inv_mpu6050_chip_config *config;
        size_t fifo_size;
+       struct {
+               int offset;
+               int scale;
+       } temp;
 };
 
 /*
@@ -279,16 +284,19 @@ struct inv_mpu6050_state {
 #define INV_MPU6050_REG_UP_TIME_MIN          5000
 #define INV_MPU6050_REG_UP_TIME_MAX          10000
 
-#define INV_MPU6050_TEMP_OFFSET                     12421
-#define INV_MPU6050_TEMP_SCALE               2941
+#define INV_MPU6050_TEMP_OFFSET                     12420
+#define INV_MPU6050_TEMP_SCALE               2941176
 #define INV_MPU6050_MAX_GYRO_FS_PARAM        3
 #define INV_MPU6050_MAX_ACCL_FS_PARAM        3
 #define INV_MPU6050_THREE_AXIS               3
 #define INV_MPU6050_GYRO_CONFIG_FSR_SHIFT    3
 #define INV_MPU6050_ACCL_CONFIG_FSR_SHIFT    3
 
-#define INV_ICM20602_TEMP_OFFSET            8170
-#define INV_ICM20602_TEMP_SCALE                     3060
+#define INV_MPU6500_TEMP_OFFSET              7011
+#define INV_MPU6500_TEMP_SCALE               2995178
+
+#define INV_ICM20608_TEMP_OFFSET            8170
+#define INV_ICM20608_TEMP_SCALE                     3059976
 
 /* 6 + 6 + 7 (for MPU9x50) = 19 round up to 24 and plus 8 */
 #define INV_MPU6050_OUTPUT_DATA_SIZE         32
index c605b15..dc55d7d 100644 (file)
@@ -320,7 +320,6 @@ enum st_lsm6dsx_fifo_mode {
  * @odr: Output data rate of the sensor [Hz].
  * @watermark: Sensor watermark level.
  * @sip: Number of samples in a given pattern.
- * @decimator: FIFO decimation factor.
  * @ts_ref: Sensor timestamp reference for hw one.
  * @ext_info: Sensor settings if it is connected to i2c controller
  */
@@ -334,7 +333,6 @@ struct st_lsm6dsx_sensor {
 
        u16 watermark;
        u8 sip;
-       u8 decimator;
        s64 ts_ref;
 
        struct {
@@ -351,9 +349,9 @@ struct st_lsm6dsx_sensor {
  * @fifo_lock: Mutex to prevent concurrent access to the hw FIFO.
  * @conf_lock: Mutex to prevent concurrent FIFO configuration update.
  * @page_lock: Mutex to prevent concurrent memory page configuration.
- * @fifo_mode: FIFO operating mode supported by the device.
  * @suspend_mask: Suspended sensor bitmask.
  * @enable_mask: Enabled sensor bitmask.
+ * @fifo_mask: Enabled hw FIFO bitmask.
  * @ts_gain: Hw timestamp rate after internal calibration.
  * @ts_sip: Total number of timestamp samples in a given pattern.
  * @sip: Total number of samples (acc/gyro/ts) in a given pattern.
@@ -373,9 +371,9 @@ struct st_lsm6dsx_hw {
        struct mutex conf_lock;
        struct mutex page_lock;
 
-       enum st_lsm6dsx_fifo_mode fifo_mode;
        u8 suspend_mask;
        u8 enable_mask;
+       u8 fifo_mask;
        s64 ts_gain;
        u8 ts_sip;
        u8 sip;
index d416990..cb536b8 100644 (file)
@@ -78,14 +78,20 @@ struct st_lsm6dsx_decimator_entry st_lsm6dsx_decimator_table[] = {
        { 32, 0x7 },
 };
 
-static int st_lsm6dsx_get_decimator_val(u8 val)
+static int
+st_lsm6dsx_get_decimator_val(struct st_lsm6dsx_sensor *sensor, u32 max_odr)
 {
        const int max_size = ARRAY_SIZE(st_lsm6dsx_decimator_table);
+       u32 decimator =  max_odr / sensor->odr;
        int i;
 
-       for (i = 0; i < max_size; i++)
-               if (st_lsm6dsx_decimator_table[i].decimator == val)
+       if (decimator > 1)
+               decimator = round_down(decimator, 2);
+
+       for (i = 0; i < max_size; i++) {
+               if (st_lsm6dsx_decimator_table[i].decimator == decimator)
                        break;
+       }
 
        return i == max_size ? 0 : st_lsm6dsx_decimator_table[i].val;
 }
@@ -111,6 +117,13 @@ static void st_lsm6dsx_get_max_min_odr(struct st_lsm6dsx_hw *hw,
        }
 }
 
+static u8 st_lsm6dsx_get_sip(struct st_lsm6dsx_sensor *sensor, u32 min_odr)
+{
+       u8 sip = sensor->odr / min_odr;
+
+       return sip > 1 ? round_down(sip, 2) : sip;
+}
+
 static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
 {
        const struct st_lsm6dsx_reg *ts_dec_reg;
@@ -131,12 +144,10 @@ static int st_lsm6dsx_update_decimators(struct st_lsm6dsx_hw *hw)
                sensor = iio_priv(hw->iio_devs[i]);
                /* update fifo decimators and sample in pattern */
                if (hw->enable_mask & BIT(sensor->id)) {
-                       sensor->sip = sensor->odr / min_odr;
-                       sensor->decimator = max_odr / sensor->odr;
-                       data = st_lsm6dsx_get_decimator_val(sensor->decimator);
+                       sensor->sip = st_lsm6dsx_get_sip(sensor, min_odr);
+                       data = st_lsm6dsx_get_decimator_val(sensor, max_odr);
                } else {
                        sensor->sip = 0;
-                       sensor->decimator = 0;
                        data = 0;
                }
                ts_sip = max_t(u16, ts_sip, sensor->sip);
@@ -176,17 +187,10 @@ int st_lsm6dsx_set_fifo_mode(struct st_lsm6dsx_hw *hw,
                             enum st_lsm6dsx_fifo_mode fifo_mode)
 {
        unsigned int data;
-       int err;
 
        data = FIELD_PREP(ST_LSM6DSX_FIFO_MODE_MASK, fifo_mode);
-       err = st_lsm6dsx_update_bits_locked(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
-                                           ST_LSM6DSX_FIFO_MODE_MASK, data);
-       if (err < 0)
-               return err;
-
-       hw->fifo_mode = fifo_mode;
-
-       return 0;
+       return st_lsm6dsx_update_bits_locked(hw, ST_LSM6DSX_REG_FIFO_MODE_ADDR,
+                                            ST_LSM6DSX_FIFO_MODE_MASK, data);
 }
 
 static int st_lsm6dsx_set_fifo_odr(struct st_lsm6dsx_sensor *sensor,
@@ -608,11 +612,17 @@ int st_lsm6dsx_flush_fifo(struct st_lsm6dsx_hw *hw)
 int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable)
 {
        struct st_lsm6dsx_hw *hw = sensor->hw;
+       u8 fifo_mask;
        int err;
 
        mutex_lock(&hw->conf_lock);
 
-       if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS) {
+       if (enable)
+               fifo_mask = hw->fifo_mask | BIT(sensor->id);
+       else
+               fifo_mask = hw->fifo_mask & ~BIT(sensor->id);
+
+       if (hw->fifo_mask) {
                err = st_lsm6dsx_flush_fifo(hw);
                if (err < 0)
                        goto out;
@@ -642,15 +652,19 @@ int st_lsm6dsx_update_fifo(struct st_lsm6dsx_sensor *sensor, bool enable)
        if (err < 0)
                goto out;
 
-       if (hw->enable_mask) {
+       if (fifo_mask) {
                /* reset hw ts counter */
                err = st_lsm6dsx_reset_hw_ts(hw);
                if (err < 0)
                        goto out;
 
                err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
+               if (err < 0)
+                       goto out;
        }
 
+       hw->fifo_mask = fifo_mask;
+
 out:
        mutex_unlock(&hw->conf_lock);
 
index 11b2c7b..b921dd9 100644 (file)
@@ -1301,7 +1301,8 @@ static int st_lsm6dsx_check_whoami(struct st_lsm6dsx_hw *hw, int id,
 
        for (i = 0; i < ARRAY_SIZE(st_lsm6dsx_sensor_settings); i++) {
                for (j = 0; j < ST_LSM6DSX_MAX_ID; j++) {
-                       if (id == st_lsm6dsx_sensor_settings[i].id[j].hw_id)
+                       if (st_lsm6dsx_sensor_settings[i].id[j].name &&
+                           id == st_lsm6dsx_sensor_settings[i].id[j].hw_id)
                                break;
                }
                if (j < ST_LSM6DSX_MAX_ID)
@@ -1447,8 +1448,9 @@ st_lsm6dsx_set_odr(struct st_lsm6dsx_sensor *sensor, u32 req_odr)
        return st_lsm6dsx_update_bits_locked(hw, reg->addr, reg->mask, data);
 }
 
-int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
-                                bool enable)
+static int
+__st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
+                              bool enable)
 {
        struct st_lsm6dsx_hw *hw = sensor->hw;
        u32 odr = enable ? sensor->odr : 0;
@@ -1466,6 +1468,26 @@ int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
        return 0;
 }
 
+static int
+st_lsm6dsx_check_events(struct st_lsm6dsx_sensor *sensor, bool enable)
+{
+       struct st_lsm6dsx_hw *hw = sensor->hw;
+
+       if (sensor->id == ST_LSM6DSX_ID_GYRO || enable)
+               return 0;
+
+       return hw->enable_event;
+}
+
+int st_lsm6dsx_sensor_set_enable(struct st_lsm6dsx_sensor *sensor,
+                                bool enable)
+{
+       if (st_lsm6dsx_check_events(sensor, enable))
+               return 0;
+
+       return __st_lsm6dsx_sensor_set_enable(sensor, enable);
+}
+
 static int st_lsm6dsx_read_oneshot(struct st_lsm6dsx_sensor *sensor,
                                   u8 addr, int *val)
 {
@@ -1661,7 +1683,7 @@ st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
        struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
        struct st_lsm6dsx_hw *hw = sensor->hw;
        u8 enable_event;
-       int err = 0;
+       int err;
 
        if (type != IIO_EV_TYPE_THRESH)
                return -EINVAL;
@@ -1689,7 +1711,8 @@ st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
                return err;
 
        mutex_lock(&hw->conf_lock);
-       err = st_lsm6dsx_sensor_set_enable(sensor, state);
+       if (enable_event || !(hw->fifo_mask & BIT(sensor->id)))
+               err = __st_lsm6dsx_sensor_set_enable(sensor, state);
        mutex_unlock(&hw->conf_lock);
        if (err < 0)
                return err;
@@ -2300,7 +2323,7 @@ static int __maybe_unused st_lsm6dsx_suspend(struct device *dev)
                hw->suspend_mask |= BIT(sensor->id);
        }
 
-       if (hw->fifo_mode != ST_LSM6DSX_FIFO_BYPASS)
+       if (hw->fifo_mask)
                err = st_lsm6dsx_flush_fifo(hw);
 
        return err;
@@ -2336,7 +2359,7 @@ static int __maybe_unused st_lsm6dsx_resume(struct device *dev)
                hw->suspend_mask &= ~BIT(sensor->id);
        }
 
-       if (hw->enable_mask)
+       if (hw->fifo_mask)
                err = st_lsm6dsx_set_fifo_mode(hw, ST_LSM6DSX_FIFO_CONT);
 
        return err;
index c193d64..112225c 100644 (file)
@@ -566,7 +566,7 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
                                const unsigned long *mask, bool timestamp)
 {
        unsigned bytes = 0;
-       int length, i;
+       int length, i, largest = 0;
 
        /* How much space will the demuxed element take? */
        for_each_set_bit(i, mask,
@@ -574,13 +574,17 @@ static int iio_compute_scan_bytes(struct iio_dev *indio_dev,
                length = iio_storage_bytes_for_si(indio_dev, i);
                bytes = ALIGN(bytes, length);
                bytes += length;
+               largest = max(largest, length);
        }
 
        if (timestamp) {
                length = iio_storage_bytes_for_timestamp(indio_dev);
                bytes = ALIGN(bytes, length);
                bytes += length;
+               largest = max(largest, length);
        }
+
+       bytes = ALIGN(bytes, largest);
        return bytes;
 }
 
index 16dacea..b0e241a 100644 (file)
@@ -163,7 +163,6 @@ static int vcnl4200_init(struct vcnl4000_data *data)
        if (ret < 0)
                return ret;
 
-       data->al_scale = 24000;
        data->vcnl4200_al.reg = VCNL4200_AL_DATA;
        data->vcnl4200_ps.reg = VCNL4200_PS_DATA;
        switch (id) {
@@ -172,11 +171,13 @@ static int vcnl4200_init(struct vcnl4000_data *data)
                /* show 54ms in total. */
                data->vcnl4200_al.sampling_rate = ktime_set(0, 54000 * 1000);
                data->vcnl4200_ps.sampling_rate = ktime_set(0, 4200 * 1000);
+               data->al_scale = 24000;
                break;
        case VCNL4040_PROD_ID:
                /* Integration time is 80ms, add 10ms. */
                data->vcnl4200_al.sampling_rate = ktime_set(0, 100000 * 1000);
                data->vcnl4200_ps.sampling_rate = ktime_set(0, 100000 * 1000);
+               data->al_scale = 120000;
                break;
        }
        data->vcnl4200_al.last_measurement = ktime_set(0, 0);
index ddf4702..d39c0d6 100644 (file)
@@ -444,8 +444,10 @@ static struct ltc2983_custom_sensor *__ltc2983_custom_sensor_new(
                        else
                                temp = __convert_to_raw(temp, resolution);
                } else {
-                       of_property_read_u32_index(np, propname, index,
-                                                  (u32 *)&temp);
+                       u32 t32;
+
+                       of_property_read_u32_index(np, propname, index, &t32);
+                       temp = t32;
                }
 
                for (j = 0; j < n_size; j++)
index 25f2b70..43a6f07 100644 (file)
@@ -4763,6 +4763,7 @@ err_ib:
 err:
        unregister_netdevice_notifier(&cma_nb);
        ib_sa_unregister_client(&sa_client);
+       unregister_pernet_subsys(&cma_pernet_operations);
 err_wq:
        destroy_workqueue(cma_wq);
        return ret;
index 8434ec0..2257d7f 100644 (file)
@@ -286,6 +286,9 @@ int rdma_counter_bind_qp_auto(struct ib_qp *qp, u8 port)
        struct rdma_counter *counter;
        int ret;
 
+       if (!qp->res.valid)
+               return 0;
+
        if (!rdma_is_port_valid(dev, port))
                return -EINVAL;
 
index f509c47..b7cb598 100644 (file)
@@ -238,28 +238,32 @@ void rdma_user_mmap_entry_remove(struct rdma_user_mmap_entry *entry)
 EXPORT_SYMBOL(rdma_user_mmap_entry_remove);
 
 /**
- * rdma_user_mmap_entry_insert() - Insert an entry to the mmap_xa
+ * rdma_user_mmap_entry_insert_range() - Insert an entry to the mmap_xa
+ *                                      in a given range.
  *
  * @ucontext: associated user context.
  * @entry: the entry to insert into the mmap_xa
  * @length: length of the address that will be mmapped
+ * @min_pgoff: minimum pgoff to be returned
+ * @max_pgoff: maximum pgoff to be returned
  *
  * This function should be called by drivers that use the rdma_user_mmap
  * interface for implementing their mmap syscall A database of mmap offsets is
  * handled in the core and helper functions are provided to insert entries
  * into the database and extract entries when the user calls mmap with the
- * given offset.  The function allocates a unique page offset that should be
- * provided to user, the user will use the offset to retrieve information such
- * as address to be mapped and how.
+ * given offset. The function allocates a unique page offset in a given range
+ * that should be provided to user, the user will use the offset to retrieve
+ * information such as address to be mapped and how.
  *
  * Return: 0 on success and -ENOMEM on failure
  */
-int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
-                               struct rdma_user_mmap_entry *entry,
-                               size_t length)
+int rdma_user_mmap_entry_insert_range(struct ib_ucontext *ucontext,
+                                     struct rdma_user_mmap_entry *entry,
+                                     size_t length, u32 min_pgoff,
+                                     u32 max_pgoff)
 {
        struct ib_uverbs_file *ufile = ucontext->ufile;
-       XA_STATE(xas, &ucontext->mmap_xa, 0);
+       XA_STATE(xas, &ucontext->mmap_xa, min_pgoff);
        u32 xa_first, xa_last, npages;
        int err;
        u32 i;
@@ -285,7 +289,7 @@ int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
        entry->npages = npages;
        while (true) {
                /* First find an empty index */
-               xas_find_marked(&xas, U32_MAX, XA_FREE_MARK);
+               xas_find_marked(&xas, max_pgoff, XA_FREE_MARK);
                if (xas.xa_node == XAS_RESTART)
                        goto err_unlock;
 
@@ -332,4 +336,30 @@ err_unlock:
        mutex_unlock(&ufile->umap_lock);
        return -ENOMEM;
 }
+EXPORT_SYMBOL(rdma_user_mmap_entry_insert_range);
+
+/**
+ * rdma_user_mmap_entry_insert() - Insert an entry to the mmap_xa.
+ *
+ * @ucontext: associated user context.
+ * @entry: the entry to insert into the mmap_xa
+ * @length: length of the address that will be mmapped
+ *
+ * This function should be called by drivers that use the rdma_user_mmap
+ * interface for handling user mmapped addresses. The database is handled in
+ * the core and helper functions are provided to insert entries into the
+ * database and extract entries when the user calls mmap with the given offset.
+ * The function allocates a unique page offset that should be provided to user,
+ * the user will use the offset to retrieve information such as address to
+ * be mapped and how.
+ *
+ * Return: 0 on success and -ENOMEM on failure
+ */
+int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
+                               struct rdma_user_mmap_entry *entry,
+                               size_t length)
+{
+       return rdma_user_mmap_entry_insert_range(ucontext, entry, length, 0,
+                                                U32_MAX);
+}
 EXPORT_SYMBOL(rdma_user_mmap_entry_insert);
index 9b6ca15..ad5112a 100644 (file)
@@ -3305,8 +3305,10 @@ int bnxt_re_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
        int rc;
 
        rc = bnxt_qplib_free_mrw(&rdev->qplib_res, &mr->qplib_mr);
-       if (rc)
+       if (rc) {
                dev_err(rdev_to_dev(rdev), "Dereg MR failed: %#x\n", rc);
+               return rc;
+       }
 
        if (mr->pages) {
                rc = bnxt_qplib_free_fast_reg_page_list(&rdev->qplib_res,
index 958c1ff..4d07d22 100644 (file)
@@ -2283,13 +2283,13 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
                        /* Add qp to flush list of the CQ */
                        bnxt_qplib_add_flush_qp(qp);
                } else {
+                       /* Before we complete, do WA 9060 */
+                       if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
+                                     cqe_sq_cons)) {
+                               *lib_qp = qp;
+                               goto out;
+                       }
                        if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) {
-                               /* Before we complete, do WA 9060 */
-                               if (do_wa9060(qp, cq, cq_cons, sw_sq_cons,
-                                             cqe_sq_cons)) {
-                                       *lib_qp = qp;
-                                       goto out;
-                               }
                                cqe->status = CQ_REQ_STATUS_OK;
                                cqe++;
                                (*budget)--;
index c9d294c..50c2257 100644 (file)
@@ -145,7 +145,7 @@ static inline bool is_rdma_read_cap(struct efa_dev *dev)
 }
 
 #define field_avail(x, fld, sz) (offsetof(typeof(x), fld) + \
-                                FIELD_SIZEOF(typeof(x), fld) <= (sz))
+                                sizeof_field(typeof(x), fld) <= (sz))
 
 #define is_reserved_cleared(reserved) \
        !memchr_inv(reserved, 0, sizeof(reserved))
index adb4a1b..5836fe7 100644 (file)
@@ -81,7 +81,9 @@ void iowait_init(struct iowait *wait, u32 tx_limit,
 void iowait_cancel_work(struct iowait *w)
 {
        cancel_work_sync(&iowait_get_ib_work(w)->iowork);
-       cancel_work_sync(&iowait_get_tid_work(w)->iowork);
+       /* Make sure that the iowork for TID RDMA is used */
+       if (iowait_get_tid_work(w)->iowork.func)
+               cancel_work_sync(&iowait_get_tid_work(w)->iowork);
 }
 
 /**
index 5774dfc..a515256 100644 (file)
@@ -848,7 +848,7 @@ static const struct rhashtable_params sdma_rht_params = {
        .nelem_hint = NR_CPUS_HINT,
        .head_offset = offsetof(struct sdma_rht_node, node),
        .key_offset = offsetof(struct sdma_rht_node, cpu_id),
-       .key_len = FIELD_SIZEOF(struct sdma_rht_node, cpu_id),
+       .key_len = sizeof_field(struct sdma_rht_node, cpu_id),
        .max_size = NR_CPUS,
        .min_size = 8,
        .automatic_shrinking = true,
index e53f542..8a2e0d9 100644 (file)
@@ -4633,6 +4633,15 @@ void hfi1_rc_rcv_tid_rdma_ack(struct hfi1_packet *packet)
                         */
                        fpsn = full_flow_psn(flow, flow->flow_state.spsn);
                        req->r_ack_psn = psn;
+                       /*
+                        * If resync_psn points to the last flow PSN for a
+                        * segment and the new segment (likely from a new
+                        * request) starts with a new generation number, we
+                        * need to adjust resync_psn accordingly.
+                        */
+                       if (flow->flow_state.generation !=
+                           (resync_psn >> HFI1_KDETH_BTH_SEQ_SHIFT))
+                               resync_psn = mask_psn(fpsn - 1);
                        flow->resync_npkts +=
                                delta_psn(mask_psn(resync_psn + 1), fpsn);
                        /*
index b0e9bf7..d36e3e1 100644 (file)
@@ -107,9 +107,9 @@ enum {
        HFI1_HAS_GRH = (1 << 0),
 };
 
-#define LRH_16B_BYTES (FIELD_SIZEOF(struct hfi1_16b_header, lrh))
+#define LRH_16B_BYTES (sizeof_field(struct hfi1_16b_header, lrh))
 #define LRH_16B_DWORDS (LRH_16B_BYTES / sizeof(u32))
-#define LRH_9B_BYTES (FIELD_SIZEOF(struct ib_header, lrh))
+#define LRH_9B_BYTES (sizeof_field(struct ib_header, lrh))
 #define LRH_9B_DWORDS (LRH_9B_BYTES / sizeof(u32))
 
 /* 24Bits for qpn, upper 8Bits reserved */
index 8637594..dbd96d0 100644 (file)
@@ -169,8 +169,7 @@ static void i40iw_dealloc_ucontext(struct ib_ucontext *context)
 static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 {
        struct i40iw_ucontext *ucontext;
-       u64 db_addr_offset;
-       u64 push_offset;
+       u64 db_addr_offset, push_offset, pfn;
 
        ucontext = to_ucontext(context);
        if (ucontext->iwdev->sc_dev.is_pf) {
@@ -189,7 +188,6 @@ static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
 
        if (vma->vm_pgoff == (db_addr_offset >> PAGE_SHIFT)) {
                vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-               vma->vm_private_data = ucontext;
        } else {
                if ((vma->vm_pgoff - (push_offset >> PAGE_SHIFT)) % 2)
                        vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
@@ -197,12 +195,12 @@ static int i40iw_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
                        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
        }
 
-       if (io_remap_pfn_range(vma, vma->vm_start,
-                              vma->vm_pgoff + (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >> PAGE_SHIFT),
-                              PAGE_SIZE, vma->vm_page_prot))
-               return -EAGAIN;
+       pfn = vma->vm_pgoff +
+             (pci_resource_start(ucontext->iwdev->ldev->pcidev, 0) >>
+              PAGE_SHIFT);
 
-       return 0;
+       return rdma_user_mmap_io(context, vma, pfn, PAGE_SIZE,
+                                vma->vm_page_prot, NULL);
 }
 
 /**
index 0b5dc1d..34055cb 100644 (file)
@@ -3018,16 +3018,17 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr)
        ibdev->ib_active = false;
        flush_workqueue(wq);
 
-       mlx4_ib_close_sriov(ibdev);
-       mlx4_ib_mad_cleanup(ibdev);
-       ib_unregister_device(&ibdev->ib_dev);
-       mlx4_ib_diag_cleanup(ibdev);
        if (ibdev->iboe.nb.notifier_call) {
                if (unregister_netdevice_notifier(&ibdev->iboe.nb))
                        pr_warn("failure unregistering notifier\n");
                ibdev->iboe.nb.notifier_call = NULL;
        }
 
+       mlx4_ib_close_sriov(ibdev);
+       mlx4_ib_mad_cleanup(ibdev);
+       ib_unregister_device(&ibdev->ib_dev);
+       mlx4_ib_diag_cleanup(ibdev);
+
        mlx4_qp_release_range(dev, ibdev->steer_qpn_base,
                              ibdev->steer_qpn_count);
        kfree(ibdev->ib_uc_qpns_bitmap);
index 4937947..4c26492 100644 (file)
@@ -157,7 +157,7 @@ int mlx5_cmd_alloc_memic(struct mlx5_dm *dm, phys_addr_t *addr,
        return -ENOMEM;
 }
 
-int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
+void mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
 {
        struct mlx5_core_dev *dev = dm->dev;
        u64 hw_start_addr = MLX5_CAP64_DEV_MEM(dev, memic_bar_start_addr);
@@ -175,15 +175,13 @@ int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length)
        MLX5_SET(dealloc_memic_in, in, memic_size, length);
 
        err =  mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+       if (err)
+               return;
 
-       if (!err) {
-               spin_lock(&dm->lock);
-               bitmap_clear(dm->memic_alloc_pages,
-                            start_page_idx, num_pages);
-               spin_unlock(&dm->lock);
-       }
-
-       return err;
+       spin_lock(&dm->lock);
+       bitmap_clear(dm->memic_alloc_pages,
+                    start_page_idx, num_pages);
+       spin_unlock(&dm->lock);
 }
 
 int mlx5_cmd_query_ext_ppcnt_counters(struct mlx5_core_dev *dev, void *out)
index 169cab4..945ebce 100644 (file)
@@ -46,7 +46,7 @@ int mlx5_cmd_modify_cong_params(struct mlx5_core_dev *mdev,
                                void *in, int in_size);
 int mlx5_cmd_alloc_memic(struct mlx5_dm *dm, phys_addr_t *addr,
                         u64 length, u32 alignment);
-int mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length);
+void mlx5_cmd_dealloc_memic(struct mlx5_dm *dm, phys_addr_t addr, u64 length);
 void mlx5_cmd_dealloc_pd(struct mlx5_core_dev *dev, u32 pdn, u16 uid);
 void mlx5_cmd_destroy_tir(struct mlx5_core_dev *dev, u32 tirn, u16 uid);
 void mlx5_cmd_destroy_tis(struct mlx5_core_dev *dev, u32 tisn, u16 uid);
index 5110035..997cbfe 100644 (file)
@@ -2074,6 +2074,24 @@ static int mlx5_ib_mmap_clock_info_page(struct mlx5_ib_dev *dev,
                              virt_to_page(dev->mdev->clock_info));
 }
 
+static void mlx5_ib_mmap_free(struct rdma_user_mmap_entry *entry)
+{
+       struct mlx5_user_mmap_entry *mentry = to_mmmap(entry);
+       struct mlx5_ib_dev *dev = to_mdev(entry->ucontext->device);
+       struct mlx5_ib_dm *mdm;
+
+       switch (mentry->mmap_flag) {
+       case MLX5_IB_MMAP_TYPE_MEMIC:
+               mdm = container_of(mentry, struct mlx5_ib_dm, mentry);
+               mlx5_cmd_dealloc_memic(&dev->dm, mdm->dev_addr,
+                                      mdm->size);
+               kfree(mdm);
+               break;
+       default:
+               WARN_ON(true);
+       }
+}
+
 static int uar_mmap(struct mlx5_ib_dev *dev, enum mlx5_ib_mmap_cmd cmd,
                    struct vm_area_struct *vma,
                    struct mlx5_ib_ucontext *context)
@@ -2186,26 +2204,55 @@ free_bfreg:
        return err;
 }
 
-static int dm_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+static int add_dm_mmap_entry(struct ib_ucontext *context,
+                            struct mlx5_ib_dm *mdm,
+                            u64 address)
+{
+       mdm->mentry.mmap_flag = MLX5_IB_MMAP_TYPE_MEMIC;
+       mdm->mentry.address = address;
+       return rdma_user_mmap_entry_insert_range(
+                       context, &mdm->mentry.rdma_entry,
+                       mdm->size,
+                       MLX5_IB_MMAP_DEVICE_MEM << 16,
+                       (MLX5_IB_MMAP_DEVICE_MEM << 16) + (1UL << 16) - 1);
+}
+
+static unsigned long mlx5_vma_to_pgoff(struct vm_area_struct *vma)
+{
+       unsigned long idx;
+       u8 command;
+
+       command = get_command(vma->vm_pgoff);
+       idx = get_extended_index(vma->vm_pgoff);
+
+       return (command << 16 | idx);
+}
+
+static int mlx5_ib_mmap_offset(struct mlx5_ib_dev *dev,
+                              struct vm_area_struct *vma,
+                              struct ib_ucontext *ucontext)
 {
-       struct mlx5_ib_ucontext *mctx = to_mucontext(context);
-       struct mlx5_ib_dev *dev = to_mdev(context->device);
-       u16 page_idx = get_extended_index(vma->vm_pgoff);
-       size_t map_size = vma->vm_end - vma->vm_start;
-       u32 npages = map_size >> PAGE_SHIFT;
+       struct mlx5_user_mmap_entry *mentry;
+       struct rdma_user_mmap_entry *entry;
+       unsigned long pgoff;
+       pgprot_t prot;
        phys_addr_t pfn;
+       int ret;
 
-       if (find_next_zero_bit(mctx->dm_pages, page_idx + npages, page_idx) !=
-           page_idx + npages)
+       pgoff = mlx5_vma_to_pgoff(vma);
+       entry = rdma_user_mmap_entry_get_pgoff(ucontext, pgoff);
+       if (!entry)
                return -EINVAL;
 
-       pfn = ((dev->mdev->bar_addr +
-             MLX5_CAP64_DEV_MEM(dev->mdev, memic_bar_start_addr)) >>
-             PAGE_SHIFT) +
-             page_idx;
-       return rdma_user_mmap_io(context, vma, pfn, map_size,
-                                pgprot_writecombine(vma->vm_page_prot),
-                                NULL);
+       mentry = to_mmmap(entry);
+       pfn = (mentry->address >> PAGE_SHIFT);
+       prot = pgprot_writecombine(vma->vm_page_prot);
+       ret = rdma_user_mmap_io(ucontext, vma, pfn,
+                               entry->npages * PAGE_SIZE,
+                               prot,
+                               entry);
+       rdma_user_mmap_entry_put(&mentry->rdma_entry);
+       return ret;
 }
 
 static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vma)
@@ -2248,11 +2295,8 @@ static int mlx5_ib_mmap(struct ib_ucontext *ibcontext, struct vm_area_struct *vm
        case MLX5_IB_MMAP_CLOCK_INFO:
                return mlx5_ib_mmap_clock_info_page(dev, vma, context);
 
-       case MLX5_IB_MMAP_DEVICE_MEM:
-               return dm_mmap(ibcontext, vma);
-
        default:
-               return -EINVAL;
+               return mlx5_ib_mmap_offset(dev, vma, ibcontext);
        }
 
        return 0;
@@ -2288,8 +2332,9 @@ static int handle_alloc_dm_memic(struct ib_ucontext *ctx,
 {
        struct mlx5_dm *dm_db = &to_mdev(ctx->device)->dm;
        u64 start_offset;
-       u32 page_idx;
+       u16 page_idx;
        int err;
+       u64 address;
 
        dm->size = roundup(attr->length, MLX5_MEMIC_BASE_SIZE);
 
@@ -2298,28 +2343,30 @@ static int handle_alloc_dm_memic(struct ib_ucontext *ctx,
        if (err)
                return err;
 
-       page_idx = (dm->dev_addr - pci_resource_start(dm_db->dev->pdev, 0) -
-                   MLX5_CAP64_DEV_MEM(dm_db->dev, memic_bar_start_addr)) >>
-                   PAGE_SHIFT;
+       address = dm->dev_addr & PAGE_MASK;
+       err = add_dm_mmap_entry(ctx, dm, address);
+       if (err)
+               goto err_dealloc;
 
+       page_idx = dm->mentry.rdma_entry.start_pgoff & 0xFFFF;
        err = uverbs_copy_to(attrs,
                             MLX5_IB_ATTR_ALLOC_DM_RESP_PAGE_INDEX,
-                            &page_idx, sizeof(page_idx));
+                            &page_idx,
+                            sizeof(page_idx));
        if (err)
-               goto err_dealloc;
+               goto err_copy;
 
        start_offset = dm->dev_addr & ~PAGE_MASK;
        err = uverbs_copy_to(attrs,
                             MLX5_IB_ATTR_ALLOC_DM_RESP_START_OFFSET,
                             &start_offset, sizeof(start_offset));
        if (err)
-               goto err_dealloc;
-
-       bitmap_set(to_mucontext(ctx)->dm_pages, page_idx,
-                  DIV_ROUND_UP(dm->size, PAGE_SIZE));
+               goto err_copy;
 
        return 0;
 
+err_copy:
+       rdma_user_mmap_entry_remove(&dm->mentry.rdma_entry);
 err_dealloc:
        mlx5_cmd_dealloc_memic(dm_db, dm->dev_addr, dm->size);
 
@@ -2423,23 +2470,13 @@ int mlx5_ib_dealloc_dm(struct ib_dm *ibdm, struct uverbs_attr_bundle *attrs)
        struct mlx5_ib_ucontext *ctx = rdma_udata_to_drv_context(
                &attrs->driver_udata, struct mlx5_ib_ucontext, ibucontext);
        struct mlx5_core_dev *dev = to_mdev(ibdm->device)->mdev;
-       struct mlx5_dm *dm_db = &to_mdev(ibdm->device)->dm;
        struct mlx5_ib_dm *dm = to_mdm(ibdm);
-       u32 page_idx;
        int ret;
 
        switch (dm->type) {
        case MLX5_IB_UAPI_DM_TYPE_MEMIC:
-               ret = mlx5_cmd_dealloc_memic(dm_db, dm->dev_addr, dm->size);
-               if (ret)
-                       return ret;
-
-               page_idx = (dm->dev_addr - pci_resource_start(dev->pdev, 0) -
-                           MLX5_CAP64_DEV_MEM(dev, memic_bar_start_addr)) >>
-                           PAGE_SHIFT;
-               bitmap_clear(ctx->dm_pages, page_idx,
-                            DIV_ROUND_UP(dm->size, PAGE_SIZE));
-               break;
+               rdma_user_mmap_entry_remove(&dm->mentry.rdma_entry);
+               return 0;
        case MLX5_IB_UAPI_DM_TYPE_STEERING_SW_ICM:
                ret = mlx5_dm_sw_icm_dealloc(dev, MLX5_SW_ICM_TYPE_STEERING,
                                             dm->size, ctx->devx_uid, dm->dev_addr,
@@ -3544,10 +3581,6 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
        }
 
        INIT_LIST_HEAD(&handler->list);
-       if (dst) {
-               memcpy(&dest_arr[0], dst, sizeof(*dst));
-               dest_num++;
-       }
 
        for (spec_index = 0; spec_index < flow_attr->num_of_specs; spec_index++) {
                err = parse_flow_attr(dev->mdev, spec,
@@ -3560,6 +3593,11 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
                ib_flow += ((union ib_flow_spec *)ib_flow)->size;
        }
 
+       if (dst && !(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP)) {
+               memcpy(&dest_arr[0], dst, sizeof(*dst));
+               dest_num++;
+       }
+
        if (!flow_is_multicast_only(flow_attr))
                set_underlay_qp(dev, spec, underlay_qpn);
 
@@ -3600,10 +3638,8 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
        }
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DROP) {
-               if (!(flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT)) {
+               if (!dest_num)
                        rule_dst = NULL;
-                       dest_num = 0;
-               }
        } else {
                if (is_egress)
                        flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_ALLOW;
@@ -6236,6 +6272,7 @@ static const struct ib_device_ops mlx5_ib_dev_ops = {
        .map_mr_sg = mlx5_ib_map_mr_sg,
        .map_mr_sg_pi = mlx5_ib_map_mr_sg_pi,
        .mmap = mlx5_ib_mmap,
+       .mmap_free = mlx5_ib_mmap_free,
        .modify_cq = mlx5_ib_modify_cq,
        .modify_device = mlx5_ib_modify_device,
        .modify_port = mlx5_ib_modify_port,
index 5986953..b06f32f 100644 (file)
@@ -118,6 +118,10 @@ enum {
        MLX5_MEMIC_BASE_SIZE    = 1 << MLX5_MEMIC_BASE_ALIGN,
 };
 
+enum mlx5_ib_mmap_type {
+       MLX5_IB_MMAP_TYPE_MEMIC = 1,
+};
+
 #define MLX5_LOG_SW_ICM_BLOCK_SIZE(dev)                                        \
        (MLX5_CAP_DEV_MEM(dev, log_sw_icm_alloc_granularity))
 #define MLX5_SW_ICM_BLOCK_SIZE(dev) (1 << MLX5_LOG_SW_ICM_BLOCK_SIZE(dev))
@@ -135,7 +139,6 @@ struct mlx5_ib_ucontext {
        u32                     tdn;
 
        u64                     lib_caps;
-       DECLARE_BITMAP(dm_pages, MLX5_MAX_MEMIC_PAGES);
        u16                     devx_uid;
        /* For RoCE LAG TX affinity */
        atomic_t                tx_port_affinity;
@@ -556,6 +559,12 @@ enum mlx5_ib_mtt_access_flags {
        MLX5_IB_MTT_WRITE = (1 << 1),
 };
 
+struct mlx5_user_mmap_entry {
+       struct rdma_user_mmap_entry rdma_entry;
+       u8 mmap_flag;
+       u64 address;
+};
+
 struct mlx5_ib_dm {
        struct ib_dm            ibdm;
        phys_addr_t             dev_addr;
@@ -567,6 +576,7 @@ struct mlx5_ib_dm {
                } icm_dm;
                /* other dm types specific params should be added here */
        };
+       struct mlx5_user_mmap_entry mentry;
 };
 
 #define MLX5_IB_MTT_PRESENT (MLX5_IB_MTT_READ | MLX5_IB_MTT_WRITE)
@@ -1101,6 +1111,13 @@ to_mflow_act(struct ib_flow_action *ibact)
        return container_of(ibact, struct mlx5_ib_flow_action, ib_action);
 }
 
+static inline struct mlx5_user_mmap_entry *
+to_mmmap(struct rdma_user_mmap_entry *rdma_entry)
+{
+       return container_of(rdma_entry,
+               struct mlx5_user_mmap_entry, rdma_entry);
+}
+
 int mlx5_ib_db_map_user(struct mlx5_ib_ucontext *context,
                        struct ib_udata *udata, unsigned long virt,
                        struct mlx5_db *db);
index f9a492e..831ad57 100644 (file)
@@ -389,7 +389,7 @@ void rxe_rcv(struct sk_buff *skb)
 
        calc_icrc = rxe_icrc_hdr(pkt, skb);
        calc_icrc = rxe_crc32(rxe, calc_icrc, (u8 *)payload_addr(pkt),
-                             payload_size(pkt));
+                             payload_size(pkt) + bth_pad(pkt));
        calc_icrc = (__force u32)cpu_to_be32(~calc_icrc);
        if (unlikely(calc_icrc != pack_icrc)) {
                if (skb->protocol == htons(ETH_P_IPV6))
index c5d9b55..e503117 100644 (file)
@@ -500,6 +500,12 @@ static int fill_packet(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
                        if (err)
                                return err;
                }
+               if (bth_pad(pkt)) {
+                       u8 *pad = payload_addr(pkt) + paylen;
+
+                       memset(pad, 0, bth_pad(pkt));
+                       crc = rxe_crc32(rxe, crc, pad, bth_pad(pkt));
+               }
        }
        p = payload_addr(pkt) + paylen + bth_pad(pkt);
 
index 1cbfbd9..c4a8195 100644 (file)
@@ -732,6 +732,13 @@ static enum resp_states read_reply(struct rxe_qp *qp,
        if (err)
                pr_err("Failed copying memory\n");
 
+       if (bth_pad(&ack_pkt)) {
+               struct rxe_dev *rxe = to_rdev(qp->ibqp.device);
+               u8 *pad = payload_addr(&ack_pkt) + payload;
+
+               memset(pad, 0, bth_pad(&ack_pkt));
+               icrc = rxe_crc32(rxe, icrc, pad, bth_pad(&ack_pkt));
+       }
        p = payload_addr(&ack_pkt) + payload + bth_pad(&ack_pkt);
        *p = ~icrc;
 
index 62390e9..8ad7da9 100644 (file)
@@ -63,7 +63,7 @@ struct vnic_stats {
        };
 };
 
-#define VNIC_STAT(m)            { FIELD_SIZEOF(struct opa_vnic_stats, m),   \
+#define VNIC_STAT(m)            { sizeof_field(struct opa_vnic_stats, m),   \
                                  offsetof(struct opa_vnic_stats, m) }
 
 static struct vnic_stats vnic_gstrings_stats[] = {
index d7dd6fc..f918fca 100644 (file)
@@ -224,13 +224,13 @@ static void __pass_event(struct evdev_client *client,
                 */
                client->tail = (client->head - 2) & (client->bufsize - 1);
 
-               client->buffer[client->tail].input_event_sec =
-                                               event->input_event_sec;
-               client->buffer[client->tail].input_event_usec =
-                                               event->input_event_usec;
-               client->buffer[client->tail].type = EV_SYN;
-               client->buffer[client->tail].code = SYN_DROPPED;
-               client->buffer[client->tail].value = 0;
+               client->buffer[client->tail] = (struct input_event) {
+                       .input_event_sec = event->input_event_sec,
+                       .input_event_usec = event->input_event_usec,
+                       .type = EV_SYN,
+                       .code = SYN_DROPPED,
+                       .value = 0,
+               };
 
                client->packet_head = client->tail;
        }
index 5508627..ee6c323 100644 (file)
@@ -878,16 +878,18 @@ static int input_default_setkeycode(struct input_dev *dev,
                }
        }
 
-       __clear_bit(*old_keycode, dev->keybit);
-       __set_bit(ke->keycode, dev->keybit);
-
-       for (i = 0; i < dev->keycodemax; i++) {
-               if (input_fetch_keycode(dev, i) == *old_keycode) {
-                       __set_bit(*old_keycode, dev->keybit);
-                       break; /* Setting the bit twice is useless, so break */
+       if (*old_keycode <= KEY_MAX) {
+               __clear_bit(*old_keycode, dev->keybit);
+               for (i = 0; i < dev->keycodemax; i++) {
+                       if (input_fetch_keycode(dev, i) == *old_keycode) {
+                               __set_bit(*old_keycode, dev->keybit);
+                               /* Setting the bit twice is useless, so break */
+                               break;
+                       }
                }
        }
 
+       __set_bit(ke->keycode, dev->keybit);
        return 0;
 }
 
@@ -943,9 +945,13 @@ int input_set_keycode(struct input_dev *dev,
         * Simulate keyup event if keycode is not present
         * in the keymap anymore
         */
-       if (test_bit(EV_KEY, dev->evbit) &&
-           !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
-           __test_and_clear_bit(old_keycode, dev->key)) {
+       if (old_keycode > KEY_MAX) {
+               dev_warn(dev->dev.parent ?: &dev->dev,
+                        "%s: got too big old keycode %#x\n",
+                        __func__, old_keycode);
+       } else if (test_bit(EV_KEY, dev->evbit) &&
+                  !is_event_supported(old_keycode, dev->keybit, KEY_MAX) &&
+                  __test_and_clear_bit(old_keycode, dev->key)) {
                struct input_value vals[] =  {
                        { EV_KEY, old_keycode, 0 },
                        input_value_sync
index 5379952..9f809ae 100644 (file)
@@ -78,7 +78,13 @@ static void imx_sc_check_for_events(struct work_struct *work)
                return;
        }
 
-       state = (bool)msg.state;
+       /*
+        * The response data from SCU firmware is 4 bytes,
+        * but ONLY the first byte is the key state, other
+        * 3 bytes could be some dirty data, so we should
+        * ONLY take the first byte as key state.
+        */
+       state = (bool)(msg.state & 0xff);
 
        if (state ^ priv->keystate) {
                priv->keystate = state;
index fd25378..f259313 100644 (file)
@@ -74,12 +74,16 @@ static int uinput_dev_event(struct input_dev *dev,
        struct uinput_device    *udev = input_get_drvdata(dev);
        struct timespec64       ts;
 
-       udev->buff[udev->head].type = type;
-       udev->buff[udev->head].code = code;
-       udev->buff[udev->head].value = value;
        ktime_get_ts64(&ts);
-       udev->buff[udev->head].input_event_sec = ts.tv_sec;
-       udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC;
+
+       udev->buff[udev->head] = (struct input_event) {
+               .input_event_sec = ts.tv_sec,
+               .input_event_usec = ts.tv_nsec / NSEC_PER_USEC,
+               .type = type,
+               .code = code,
+               .value = value,
+       };
+
        udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE;
 
        wake_up_interruptible(&udev->waitq);
@@ -689,13 +693,14 @@ static ssize_t uinput_read(struct file *file, char __user *buffer,
 static __poll_t uinput_poll(struct file *file, poll_table *wait)
 {
        struct uinput_device *udev = file->private_data;
+       __poll_t mask = EPOLLOUT | EPOLLWRNORM; /* uinput is always writable */
 
        poll_wait(file, &udev->waitq, wait);
 
        if (udev->head != udev->tail)
-               return EPOLLIN | EPOLLRDNORM;
+               mask |= EPOLLIN | EPOLLRDNORM;
 
-       return EPOLLOUT | EPOLLWRNORM;
+       return mask;
 }
 
 static int uinput_release(struct inode *inode, struct file *file)
index c49afbe..2f9304d 100644 (file)
@@ -6,13 +6,13 @@ config INTERCONNECT_QCOM
          Support for Qualcomm's Network-on-Chip interconnect hardware.
 
 config INTERCONNECT_QCOM_MSM8974
-       tristate "Qualcomm MSM8974 interconnect driver"
-       depends on INTERCONNECT_QCOM
-       depends on QCOM_SMD_RPM
-       select INTERCONNECT_QCOM_SMD_RPM
-       help
-         This is a driver for the Qualcomm Network-on-Chip on msm8974-based
-         platforms.
+       tristate "Qualcomm MSM8974 interconnect driver"
+       depends on INTERCONNECT_QCOM
+       depends on QCOM_SMD_RPM
+       select INTERCONNECT_QCOM_SMD_RPM
+       help
+        This is a driver for the Qualcomm Network-on-Chip on msm8974-based
+        platforms.
 
 config INTERCONNECT_QCOM_QCS404
        tristate "Qualcomm QCS404 interconnect driver"
index ce599a0..bf8bd1a 100644 (file)
@@ -652,7 +652,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct icc_onecell_data *data;
        struct icc_provider *provider;
-       struct icc_node *node;
+       struct icc_node *node, *tmp;
        size_t num_nodes, i;
        int ret;
 
@@ -732,7 +732,7 @@ static int msm8974_icc_probe(struct platform_device *pdev)
        return 0;
 
 err_del_icc:
-       list_for_each_entry(node, &provider->nodes, node_list) {
+       list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
                icc_node_del(node);
                icc_node_destroy(node->id);
        }
@@ -748,9 +748,9 @@ static int msm8974_icc_remove(struct platform_device *pdev)
 {
        struct msm8974_icc_provider *qp = platform_get_drvdata(pdev);
        struct icc_provider *provider = &qp->provider;
-       struct icc_node *n;
+       struct icc_node *n, *tmp;
 
-       list_for_each_entry(n, &provider->nodes, node_list) {
+       list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
                icc_node_del(n);
                icc_node_destroy(n->id);
        }
index b4966d8..8e0735a 100644 (file)
@@ -414,7 +414,7 @@ static int qnoc_probe(struct platform_device *pdev)
        struct icc_provider *provider;
        struct qcom_icc_node **qnodes;
        struct qcom_icc_provider *qp;
-       struct icc_node *node;
+       struct icc_node *node, *tmp;
        size_t num_nodes, i;
        int ret;
 
@@ -494,7 +494,7 @@ static int qnoc_probe(struct platform_device *pdev)
 
        return 0;
 err:
-       list_for_each_entry(node, &provider->nodes, node_list) {
+       list_for_each_entry_safe(node, tmp, &provider->nodes, node_list) {
                icc_node_del(node);
                icc_node_destroy(node->id);
        }
@@ -508,9 +508,9 @@ static int qnoc_remove(struct platform_device *pdev)
 {
        struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
        struct icc_provider *provider = &qp->provider;
-       struct icc_node *n;
+       struct icc_node *n, *tmp;
 
-       list_for_each_entry(n, &provider->nodes, node_list) {
+       list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
                icc_node_del(n);
                icc_node_destroy(n->id);
        }
index 502a6c2..387267e 100644 (file)
@@ -868,9 +868,9 @@ static int qnoc_remove(struct platform_device *pdev)
 {
        struct qcom_icc_provider *qp = platform_get_drvdata(pdev);
        struct icc_provider *provider = &qp->provider;
-       struct icc_node *n;
+       struct icc_node *n, *tmp;
 
-       list_for_each_entry(n, &provider->nodes, node_list) {
+       list_for_each_entry_safe(n, tmp, &provider->nodes, node_list) {
                icc_node_del(n);
                icc_node_destroy(n->id);
        }
index 0cc702a..a2e96a5 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/iova.h>
 #include <linux/irq.h>
 #include <linux/mm.h>
+#include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/scatterlist.h>
 #include <linux/vmalloc.h>
@@ -44,7 +45,6 @@ struct iommu_dma_cookie {
                dma_addr_t              msi_iova;
        };
        struct list_head                msi_page_list;
-       spinlock_t                      msi_lock;
 
        /* Domain for flush queue callback; NULL if flush queue not in use */
        struct iommu_domain             *fq_domain;
@@ -63,7 +63,6 @@ static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)
 
        cookie = kzalloc(sizeof(*cookie), GFP_KERNEL);
        if (cookie) {
-               spin_lock_init(&cookie->msi_lock);
                INIT_LIST_HEAD(&cookie->msi_page_list);
                cookie->type = type;
        }
@@ -399,7 +398,7 @@ static int dma_info_to_prot(enum dma_data_direction dir, bool coherent,
 }
 
 static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
-               size_t size, dma_addr_t dma_limit, struct device *dev)
+               size_t size, u64 dma_limit, struct device *dev)
 {
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
        struct iova_domain *iovad = &cookie->iovad;
@@ -424,7 +423,7 @@ static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
        dma_limit = min_not_zero(dma_limit, dev->bus_dma_limit);
 
        if (domain->geometry.force_aperture)
-               dma_limit = min(dma_limit, domain->geometry.aperture_end);
+               dma_limit = min(dma_limit, (u64)domain->geometry.aperture_end);
 
        /* Try to get PCI devices a SAC address */
        if (dma_limit > DMA_BIT_MASK(32) && dev_is_pci(dev))
@@ -477,7 +476,7 @@ static void __iommu_dma_unmap(struct device *dev, dma_addr_t dma_addr,
 }
 
 static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
-               size_t size, int prot, dma_addr_t dma_mask)
+               size_t size, int prot, u64 dma_mask)
 {
        struct iommu_domain *domain = iommu_get_dma_domain(dev);
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
@@ -1176,7 +1175,7 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
                if (msi_page->phys == msi_addr)
                        return msi_page;
 
-       msi_page = kzalloc(sizeof(*msi_page), GFP_ATOMIC);
+       msi_page = kzalloc(sizeof(*msi_page), GFP_KERNEL);
        if (!msi_page)
                return NULL;
 
@@ -1204,25 +1203,22 @@ int iommu_dma_prepare_msi(struct msi_desc *desc, phys_addr_t msi_addr)
 {
        struct device *dev = msi_desc_to_dev(desc);
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-       struct iommu_dma_cookie *cookie;
        struct iommu_dma_msi_page *msi_page;
-       unsigned long flags;
+       static DEFINE_MUTEX(msi_prepare_lock); /* see below */
 
        if (!domain || !domain->iova_cookie) {
                desc->iommu_cookie = NULL;
                return 0;
        }
 
-       cookie = domain->iova_cookie;
-
        /*
-        * We disable IRQs to rule out a possible inversion against
-        * irq_desc_lock if, say, someone tries to retarget the affinity
-        * of an MSI from within an IPI handler.
+        * In fact the whole prepare operation should already be serialised by
+        * irq_domain_mutex further up the callchain, but that's pretty subtle
+        * on its own, so consider this locking as failsafe documentation...
         */
-       spin_lock_irqsave(&cookie->msi_lock, flags);
+       mutex_lock(&msi_prepare_lock);
        msi_page = iommu_dma_get_msi_page(dev, msi_addr, domain);
-       spin_unlock_irqrestore(&cookie->msi_lock, flags);
+       mutex_unlock(&msi_prepare_lock);
 
        msi_desc_set_iommu_cookie(desc, msi_page);
 
index 0c8d81f..1801f0a 100644 (file)
@@ -5478,9 +5478,6 @@ static int intel_iommu_map(struct iommu_domain *domain,
        int prot = 0;
        int ret;
 
-       if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-               return -EINVAL;
-
        if (iommu_prot & IOMMU_READ)
                prot |= DMA_PTE_READ;
        if (iommu_prot & IOMMU_WRITE)
@@ -5523,8 +5520,6 @@ static size_t intel_iommu_unmap(struct iommu_domain *domain,
        /* Cope with horrid API which requires us to unmap more than the
           size argument if it happens to be a large-page mapping. */
        BUG_ON(!pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level));
-       if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-               return 0;
 
        if (size < VTD_PAGE_SIZE << level_to_offset_bits(level))
                size = VTD_PAGE_SIZE << level_to_offset_bits(level);
@@ -5556,9 +5551,6 @@ static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
        int level = 0;
        u64 phys = 0;
 
-       if (dmar_domain->flags & DOMAIN_FLAG_LOSE_CHILDREN)
-               return 0;
-
        pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
        if (pte)
                phys = dma_pte_addr(pte);
@@ -5632,8 +5624,10 @@ static int intel_iommu_add_device(struct device *dev)
 
        group = iommu_group_get_for_dev(dev);
 
-       if (IS_ERR(group))
-               return PTR_ERR(group);
+       if (IS_ERR(group)) {
+               ret = PTR_ERR(group);
+               goto unlink;
+       }
 
        iommu_group_put(group);
 
@@ -5659,7 +5653,8 @@ static int intel_iommu_add_device(struct device *dev)
                                if (!get_private_domain_for_dev(dev)) {
                                        dev_warn(dev,
                                                 "Failed to get a private domain.\n");
-                                       return -ENOMEM;
+                                       ret = -ENOMEM;
+                                       goto unlink;
                                }
 
                                dev_info(dev,
@@ -5674,6 +5669,10 @@ static int intel_iommu_add_device(struct device *dev)
        }
 
        return 0;
+
+unlink:
+       iommu_device_unlink(&iommu->iommu, dev);
+       return ret;
 }
 
 static void intel_iommu_remove_device(struct device *dev)
@@ -5736,8 +5735,8 @@ static void intel_iommu_get_resv_regions(struct device *device,
                struct pci_dev *pdev = to_pci_dev(device);
 
                if ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA) {
-                       reg = iommu_alloc_resv_region(0, 1UL << 24, 0,
-                                                     IOMMU_RESV_DIRECT);
+                       reg = iommu_alloc_resv_region(0, 1UL << 24, prot,
+                                                  IOMMU_RESV_DIRECT_RELAXABLE);
                        if (reg)
                                list_add_tail(&reg->list, head);
                }
@@ -5825,6 +5824,13 @@ static void intel_iommu_apply_resv_region(struct device *dev,
        WARN_ON_ONCE(!reserve_iova(&dmar_domain->iovad, start, end));
 }
 
+static struct iommu_group *intel_iommu_device_group(struct device *dev)
+{
+       if (dev_is_pci(dev))
+               return pci_device_group(dev);
+       return generic_device_group(dev);
+}
+
 #ifdef CONFIG_INTEL_IOMMU_SVM
 struct intel_iommu *intel_svm_device_to_iommu(struct device *dev)
 {
@@ -5997,7 +6003,7 @@ const struct iommu_ops intel_iommu_ops = {
        .get_resv_regions       = intel_iommu_get_resv_regions,
        .put_resv_regions       = intel_iommu_put_resv_regions,
        .apply_resv_region      = intel_iommu_apply_resv_region,
-       .device_group           = pci_device_group,
+       .device_group           = intel_iommu_device_group,
        .dev_has_feat           = intel_iommu_dev_has_feat,
        .dev_feat_enabled       = intel_iommu_dev_feat_enabled,
        .dev_enable_feat        = intel_iommu_dev_enable_feat,
index 9b15913..dca88f9 100644 (file)
@@ -104,11 +104,7 @@ static void intel_flush_svm_range_dev (struct intel_svm *svm, struct intel_svm_d
 {
        struct qi_desc desc;
 
-       /*
-        * Do PASID granu IOTLB invalidation if page selective capability is
-        * not available.
-        */
-       if (pages == -1 || !cap_pgsel_inv(svm->iommu->cap)) {
+       if (pages == -1) {
                desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
                        QI_EIOTLB_DID(sdev->did) |
                        QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
index db7bfd4..3ead597 100644 (file)
@@ -312,8 +312,8 @@ int iommu_insert_resv_region(struct iommu_resv_region *new,
        list_for_each_entry_safe(iter, tmp, regions, list) {
                phys_addr_t top_end, iter_end = iter->start + iter->length - 1;
 
-               /* no merge needed on elements of different types than @nr */
-               if (iter->type != nr->type) {
+               /* no merge needed on elements of different types than @new */
+               if (iter->type != new->type) {
                        list_move_tail(&iter->list, &stack);
                        continue;
                }
@@ -751,6 +751,7 @@ err_put_group:
        mutex_unlock(&group->mutex);
        dev->iommu_group = NULL;
        kobject_put(group->devices_kobj);
+       sysfs_remove_link(group->devices_kobj, device->name);
 err_free_name:
        kfree(device->name);
 err_remove_link:
@@ -2282,13 +2283,13 @@ request_default_domain_for_dev(struct device *dev, unsigned long type)
                goto out;
        }
 
-       iommu_group_create_direct_mappings(group, dev);
-
        /* Make the domain the default for this group */
        if (group->default_domain)
                iommu_domain_free(group->default_domain);
        group->default_domain = domain;
 
+       iommu_group_create_direct_mappings(group, dev);
+
        dev_info(dev, "Using iommu %s mapping\n",
                 type == IOMMU_DOMAIN_DMA ? "dma" : "direct");
 
index 41c605b..c7a914b 100644 (file)
@@ -233,7 +233,7 @@ static DEFINE_MUTEX(iova_cache_mutex);
 
 struct iova *alloc_iova_mem(void)
 {
-       return kmem_cache_alloc(iova_cache, GFP_ATOMIC);
+       return kmem_cache_zalloc(iova_cache, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(alloc_iova_mem);
 
index 01d18b3..c5589ee 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/delay.h>
 
 #include <asm/io.h>
-#include <asm/mach-jz4740/irq.h>
 
 struct ingenic_intc_data {
        void __iomem *base;
@@ -50,7 +49,7 @@ static irqreturn_t intc_cascade(int irq, void *data)
                while (pending) {
                        int bit = __fls(pending);
 
-                       irq = irq_find_mapping(domain, bit + (i * 32));
+                       irq = irq_linear_revmap(domain, bit + (i * 32));
                        generic_handle_irq(irq);
                        pending &= ~BIT(bit);
                }
@@ -97,8 +96,7 @@ static int __init ingenic_intc_of_init(struct device_node *node,
                goto out_unmap_irq;
        }
 
-       domain = irq_domain_add_legacy(node, num_chips * 32,
-                                      JZ4740_IRQ_BASE, 0,
+       domain = irq_domain_add_linear(node, num_chips * 32,
                                       &irq_generic_chip_ops, NULL);
        if (!domain) {
                err = -ENOMEM;
index 8df547d..0aca580 100644 (file)
@@ -256,7 +256,7 @@ static int __init plic_init(struct device_node *node,
                 * Skip contexts other than external interrupts for our
                 * privilege level.
                 */
-               if (parent.args[0] != IRQ_EXT)
+               if (parent.args[0] != RV_IRQ_EXT)
                        continue;
 
                hartid = plic_find_hart_id(parent.np);
index 08c552e..c05b121 100644 (file)
@@ -67,23 +67,34 @@ struct superblock_disk {
  * To save constantly doing look ups on disk we keep an in core copy of the
  * on-disk bitmap, the region_map.
  *
- * To further reduce metadata I/O overhead we use a second bitmap, the dmap
- * (dirty bitmap), which tracks the dirty words, i.e. longs, of the region_map.
+ * In order to track which regions are hydrated during a metadata transaction,
+ * we use a second set of bitmaps, the dmap (dirty bitmap), which includes two
+ * bitmaps, namely dirty_regions and dirty_words. The dirty_regions bitmap
+ * tracks the regions that got hydrated during the current metadata
+ * transaction. The dirty_words bitmap tracks the dirty words, i.e. longs, of
+ * the dirty_regions bitmap.
+ *
+ * This allows us to precisely track the regions that were hydrated during the
+ * current metadata transaction and update the metadata accordingly, when we
+ * commit the current transaction. This is important because dm-clone should
+ * only commit the metadata of regions that were properly flushed to the
+ * destination device beforehand. Otherwise, in case of a crash, we could end
+ * up with a corrupted dm-clone device.
  *
  * When a region finishes hydrating dm-clone calls
  * dm_clone_set_region_hydrated(), or for discard requests
  * dm_clone_cond_set_range(), which sets the corresponding bits in region_map
  * and dmap.
  *
- * During a metadata commit we scan the dmap for dirty region_map words (longs)
- * and update accordingly the on-disk metadata. Thus, we don't have to flush to
- * disk the whole region_map. We can just flush the dirty region_map words.
+ * During a metadata commit we scan dmap->dirty_words and dmap->dirty_regions
+ * and update the on-disk metadata accordingly. Thus, we don't have to flush to
+ * disk the whole region_map. We can just flush the dirty region_map bits.
  *
- * We use a dirty bitmap, which is smaller than the original region_map, to
- * reduce the amount of memory accesses during a metadata commit. As dm-bitset
- * accesses the on-disk bitmap in 64-bit word granularity, there is no
- * significant benefit in tracking the dirty region_map bits with a smaller
- * granularity.
+ * We use the helper dmap->dirty_words bitmap, which is smaller than the
+ * original region_map, to reduce the amount of memory accesses during a
+ * metadata commit. Moreover, as dm-bitset also accesses the on-disk bitmap in
+ * 64-bit word granularity, the dirty_words bitmap helps us avoid useless disk
+ * accesses.
  *
  * We could update directly the on-disk bitmap, when dm-clone calls either
  * dm_clone_set_region_hydrated() or dm_clone_cond_set_range(), buts this
@@ -92,12 +103,13 @@ struct superblock_disk {
  * e.g., in a hooked overwrite bio's completion routine, and further reduce the
  * I/O completion latency.
  *
- * We maintain two dirty bitmaps. During a metadata commit we atomically swap
- * the currently used dmap with the unused one. This allows the metadata update
- * functions to run concurrently with an ongoing commit.
+ * We maintain two dirty bitmap sets. During a metadata commit we atomically
+ * swap the currently used dmap with the unused one. This allows the metadata
+ * update functions to run concurrently with an ongoing commit.
  */
 struct dirty_map {
        unsigned long *dirty_words;
+       unsigned long *dirty_regions;
        unsigned int changed;
 };
 
@@ -115,6 +127,9 @@ struct dm_clone_metadata {
        struct dirty_map dmap[2];
        struct dirty_map *current_dmap;
 
+       /* Protected by lock */
+       struct dirty_map *committing_dmap;
+
        /*
         * In core copy of the on-disk bitmap to save constantly doing look ups
         * on disk.
@@ -461,34 +476,53 @@ static size_t bitmap_size(unsigned long nr_bits)
        return BITS_TO_LONGS(nr_bits) * sizeof(long);
 }
 
-static int dirty_map_init(struct dm_clone_metadata *cmd)
+static int __dirty_map_init(struct dirty_map *dmap, unsigned long nr_words,
+                           unsigned long nr_regions)
 {
-       cmd->dmap[0].changed = 0;
-       cmd->dmap[0].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL);
+       dmap->changed = 0;
 
-       if (!cmd->dmap[0].dirty_words) {
-               DMERR("Failed to allocate dirty bitmap");
+       dmap->dirty_words = kvzalloc(bitmap_size(nr_words), GFP_KERNEL);
+       if (!dmap->dirty_words)
+               return -ENOMEM;
+
+       dmap->dirty_regions = kvzalloc(bitmap_size(nr_regions), GFP_KERNEL);
+       if (!dmap->dirty_regions) {
+               kvfree(dmap->dirty_words);
                return -ENOMEM;
        }
 
-       cmd->dmap[1].changed = 0;
-       cmd->dmap[1].dirty_words = kvzalloc(bitmap_size(cmd->nr_words), GFP_KERNEL);
+       return 0;
+}
+
+static void __dirty_map_exit(struct dirty_map *dmap)
+{
+       kvfree(dmap->dirty_words);
+       kvfree(dmap->dirty_regions);
+}
+
+static int dirty_map_init(struct dm_clone_metadata *cmd)
+{
+       if (__dirty_map_init(&cmd->dmap[0], cmd->nr_words, cmd->nr_regions)) {
+               DMERR("Failed to allocate dirty bitmap");
+               return -ENOMEM;
+       }
 
-       if (!cmd->dmap[1].dirty_words) {
+       if (__dirty_map_init(&cmd->dmap[1], cmd->nr_words, cmd->nr_regions)) {
                DMERR("Failed to allocate dirty bitmap");
-               kvfree(cmd->dmap[0].dirty_words);
+               __dirty_map_exit(&cmd->dmap[0]);
                return -ENOMEM;
        }
 
        cmd->current_dmap = &cmd->dmap[0];
+       cmd->committing_dmap = NULL;
 
        return 0;
 }
 
 static void dirty_map_exit(struct dm_clone_metadata *cmd)
 {
-       kvfree(cmd->dmap[0].dirty_words);
-       kvfree(cmd->dmap[1].dirty_words);
+       __dirty_map_exit(&cmd->dmap[0]);
+       __dirty_map_exit(&cmd->dmap[1]);
 }
 
 static int __load_bitset_in_core(struct dm_clone_metadata *cmd)
@@ -633,21 +667,23 @@ unsigned long dm_clone_find_next_unhydrated_region(struct dm_clone_metadata *cmd
        return find_next_zero_bit(cmd->region_map, cmd->nr_regions, start);
 }
 
-static int __update_metadata_word(struct dm_clone_metadata *cmd, unsigned long word)
+static int __update_metadata_word(struct dm_clone_metadata *cmd,
+                                 unsigned long *dirty_regions,
+                                 unsigned long word)
 {
        int r;
        unsigned long index = word * BITS_PER_LONG;
        unsigned long max_index = min(cmd->nr_regions, (word + 1) * BITS_PER_LONG);
 
        while (index < max_index) {
-               if (test_bit(index, cmd->region_map)) {
+               if (test_bit(index, dirty_regions)) {
                        r = dm_bitset_set_bit(&cmd->bitset_info, cmd->bitset_root,
                                              index, &cmd->bitset_root);
-
                        if (r) {
                                DMERR("dm_bitset_set_bit failed");
                                return r;
                        }
+                       __clear_bit(index, dirty_regions);
                }
                index++;
        }
@@ -721,7 +757,7 @@ static int __flush_dmap(struct dm_clone_metadata *cmd, struct dirty_map *dmap)
                if (word == cmd->nr_words)
                        break;
 
-               r = __update_metadata_word(cmd, word);
+               r = __update_metadata_word(cmd, dmap->dirty_regions, word);
 
                if (r)
                        return r;
@@ -743,15 +779,17 @@ static int __flush_dmap(struct dm_clone_metadata *cmd, struct dirty_map *dmap)
        return 0;
 }
 
-int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
+int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd)
 {
-       int r = -EPERM;
+       int r = 0;
        struct dirty_map *dmap, *next_dmap;
 
        down_write(&cmd->lock);
 
-       if (cmd->fail_io || dm_bm_is_read_only(cmd->bm))
+       if (cmd->fail_io || dm_bm_is_read_only(cmd->bm)) {
+               r = -EPERM;
                goto out;
+       }
 
        /* Get current dirty bitmap */
        dmap = cmd->current_dmap;
@@ -763,7 +801,7 @@ int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
         * The last commit failed, so we don't have a clean dirty-bitmap to
         * use.
         */
-       if (WARN_ON(next_dmap->changed)) {
+       if (WARN_ON(next_dmap->changed || cmd->committing_dmap)) {
                r = -EINVAL;
                goto out;
        }
@@ -773,11 +811,33 @@ int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
        cmd->current_dmap = next_dmap;
        spin_unlock_irq(&cmd->bitmap_lock);
 
-       /*
-        * No one is accessing the old dirty bitmap anymore, so we can flush
-        * it.
-        */
-       r = __flush_dmap(cmd, dmap);
+       /* Set old dirty bitmap as currently committing */
+       cmd->committing_dmap = dmap;
+out:
+       up_write(&cmd->lock);
+
+       return r;
+}
+
+int dm_clone_metadata_commit(struct dm_clone_metadata *cmd)
+{
+       int r = -EPERM;
+
+       down_write(&cmd->lock);
+
+       if (cmd->fail_io || dm_bm_is_read_only(cmd->bm))
+               goto out;
+
+       if (WARN_ON(!cmd->committing_dmap)) {
+               r = -EINVAL;
+               goto out;
+       }
+
+       r = __flush_dmap(cmd, cmd->committing_dmap);
+       if (!r) {
+               /* Clear committing dmap */
+               cmd->committing_dmap = NULL;
+       }
 out:
        up_write(&cmd->lock);
 
@@ -802,6 +862,7 @@ int dm_clone_set_region_hydrated(struct dm_clone_metadata *cmd, unsigned long re
        dmap = cmd->current_dmap;
 
        __set_bit(word, dmap->dirty_words);
+       __set_bit(region_nr, dmap->dirty_regions);
        __set_bit(region_nr, cmd->region_map);
        dmap->changed = 1;
 
@@ -830,6 +891,7 @@ int dm_clone_cond_set_range(struct dm_clone_metadata *cmd, unsigned long start,
                if (!test_bit(region_nr, cmd->region_map)) {
                        word = region_nr / BITS_PER_LONG;
                        __set_bit(word, dmap->dirty_words);
+                       __set_bit(region_nr, dmap->dirty_regions);
                        __set_bit(region_nr, cmd->region_map);
                        dmap->changed = 1;
                }
index 3fe50a7..14af1eb 100644 (file)
@@ -75,7 +75,23 @@ void dm_clone_metadata_close(struct dm_clone_metadata *cmd);
 
 /*
  * Commit dm-clone metadata to disk.
+ *
+ * We use a two phase commit:
+ *
+ * 1. dm_clone_metadata_pre_commit(): Prepare the current transaction for
+ *    committing. After this is called, all subsequent metadata updates, done
+ *    through either dm_clone_set_region_hydrated() or
+ *    dm_clone_cond_set_range(), will be part of the **next** transaction.
+ *
+ * 2. dm_clone_metadata_commit(): Actually commit the current transaction to
+ *    disk and start a new transaction.
+ *
+ * This allows dm-clone to flush the destination device after step (1) to
+ * ensure that all freshly hydrated regions, for which we are updating the
+ * metadata, are properly written to non-volatile storage and won't be lost in
+ * case of a crash.
  */
+int dm_clone_metadata_pre_commit(struct dm_clone_metadata *cmd);
 int dm_clone_metadata_commit(struct dm_clone_metadata *cmd);
 
 /*
@@ -112,6 +128,7 @@ int dm_clone_metadata_abort(struct dm_clone_metadata *cmd);
  * Switches metadata to a read only mode. Once read-only mode has been entered
  * the following functions will return -EPERM:
  *
+ *   dm_clone_metadata_pre_commit()
  *   dm_clone_metadata_commit()
  *   dm_clone_set_region_hydrated()
  *   dm_clone_cond_set_range()
index b3d8907..d1e1b5b 100644 (file)
@@ -86,6 +86,12 @@ struct clone {
 
        struct dm_clone_metadata *cmd;
 
+       /*
+        * bio used to flush the destination device, before committing the
+        * metadata.
+        */
+       struct bio flush_bio;
+
        /* Region hydration hash table */
        struct hash_table_bucket *ht;
 
@@ -1108,10 +1114,13 @@ static bool need_commit_due_to_time(struct clone *clone)
 /*
  * A non-zero return indicates read-only or fail mode.
  */
-static int commit_metadata(struct clone *clone)
+static int commit_metadata(struct clone *clone, bool *dest_dev_flushed)
 {
        int r = 0;
 
+       if (dest_dev_flushed)
+               *dest_dev_flushed = false;
+
        mutex_lock(&clone->commit_lock);
 
        if (!dm_clone_changed_this_transaction(clone->cmd))
@@ -1122,8 +1131,26 @@ static int commit_metadata(struct clone *clone)
                goto out;
        }
 
-       r = dm_clone_metadata_commit(clone->cmd);
+       r = dm_clone_metadata_pre_commit(clone->cmd);
+       if (unlikely(r)) {
+               __metadata_operation_failed(clone, "dm_clone_metadata_pre_commit", r);
+               goto out;
+       }
 
+       bio_reset(&clone->flush_bio);
+       bio_set_dev(&clone->flush_bio, clone->dest_dev->bdev);
+       clone->flush_bio.bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+       r = submit_bio_wait(&clone->flush_bio);
+       if (unlikely(r)) {
+               __metadata_operation_failed(clone, "flush destination device", r);
+               goto out;
+       }
+
+       if (dest_dev_flushed)
+               *dest_dev_flushed = true;
+
+       r = dm_clone_metadata_commit(clone->cmd);
        if (unlikely(r)) {
                __metadata_operation_failed(clone, "dm_clone_metadata_commit", r);
                goto out;
@@ -1194,6 +1221,7 @@ static void process_deferred_bios(struct clone *clone)
 static void process_deferred_flush_bios(struct clone *clone)
 {
        struct bio *bio;
+       bool dest_dev_flushed;
        struct bio_list bios = BIO_EMPTY_LIST;
        struct bio_list bio_completions = BIO_EMPTY_LIST;
 
@@ -1213,7 +1241,7 @@ static void process_deferred_flush_bios(struct clone *clone)
            !(dm_clone_changed_this_transaction(clone->cmd) && need_commit_due_to_time(clone)))
                return;
 
-       if (commit_metadata(clone)) {
+       if (commit_metadata(clone, &dest_dev_flushed)) {
                bio_list_merge(&bios, &bio_completions);
 
                while ((bio = bio_list_pop(&bios)))
@@ -1227,8 +1255,17 @@ static void process_deferred_flush_bios(struct clone *clone)
        while ((bio = bio_list_pop(&bio_completions)))
                bio_endio(bio);
 
-       while ((bio = bio_list_pop(&bios)))
-               generic_make_request(bio);
+       while ((bio = bio_list_pop(&bios))) {
+               if ((bio->bi_opf & REQ_PREFLUSH) && dest_dev_flushed) {
+                       /* We just flushed the destination device as part of
+                        * the metadata commit, so there is no reason to send
+                        * another flush.
+                        */
+                       bio_endio(bio);
+               } else {
+                       generic_make_request(bio);
+               }
+       }
 }
 
 static void do_worker(struct work_struct *work)
@@ -1400,7 +1437,7 @@ static void clone_status(struct dm_target *ti, status_type_t type,
 
                /* Commit to ensure statistics aren't out-of-date */
                if (!(status_flags & DM_STATUS_NOFLUSH_FLAG) && !dm_suspended(ti))
-                       (void) commit_metadata(clone);
+                       (void) commit_metadata(clone, NULL);
 
                r = dm_clone_get_free_metadata_block_count(clone->cmd, &nr_free_metadata_blocks);
 
@@ -1834,6 +1871,7 @@ static int clone_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        bio_list_init(&clone->deferred_flush_completions);
        clone->hydration_offset = 0;
        atomic_set(&clone->hydrations_in_flight, 0);
+       bio_init(&clone->flush_bio, NULL, 0);
 
        clone->wq = alloc_workqueue("dm-" DM_MSG_PREFIX, WQ_MEM_RECLAIM, 0);
        if (!clone->wq) {
@@ -1907,6 +1945,7 @@ static void clone_dtr(struct dm_target *ti)
        struct clone *clone = ti->private;
 
        mutex_destroy(&clone->commit_lock);
+       bio_uninit(&clone->flush_bio);
 
        for (i = 0; i < clone->nr_ctr_args; i++)
                kfree(clone->ctr_args[i]);
@@ -1961,7 +2000,7 @@ static void clone_postsuspend(struct dm_target *ti)
        wait_event(clone->hydration_stopped, !atomic_read(&clone->hydrations_in_flight));
        flush_workqueue(clone->wq);
 
-       (void) commit_metadata(clone);
+       (void) commit_metadata(clone, NULL);
 }
 
 static void clone_resume(struct dm_target *ti)
index dbcc1e4..e0c3279 100644 (file)
@@ -599,45 +599,10 @@ static struct pgpath *__map_bio(struct multipath *m, struct bio *bio)
        return pgpath;
 }
 
-static struct pgpath *__map_bio_fast(struct multipath *m, struct bio *bio)
-{
-       struct pgpath *pgpath;
-       unsigned long flags;
-
-       /* Do we need to select a new pgpath? */
-       /*
-        * FIXME: currently only switching path if no path (due to failure, etc)
-        * - which negates the point of using a path selector
-        */
-       pgpath = READ_ONCE(m->current_pgpath);
-       if (!pgpath)
-               pgpath = choose_pgpath(m, bio->bi_iter.bi_size);
-
-       if (!pgpath) {
-               if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
-                       /* Queue for the daemon to resubmit */
-                       spin_lock_irqsave(&m->lock, flags);
-                       bio_list_add(&m->queued_bios, bio);
-                       spin_unlock_irqrestore(&m->lock, flags);
-                       queue_work(kmultipathd, &m->process_queued_bios);
-
-                       return ERR_PTR(-EAGAIN);
-               }
-               return NULL;
-       }
-
-       return pgpath;
-}
-
 static int __multipath_map_bio(struct multipath *m, struct bio *bio,
                               struct dm_mpath_io *mpio)
 {
-       struct pgpath *pgpath;
-
-       if (!m->hw_handler_name)
-               pgpath = __map_bio_fast(m, bio);
-       else
-               pgpath = __map_bio(m, bio);
+       struct pgpath *pgpath = __map_bio(m, bio);
 
        if (IS_ERR(pgpath))
                return DM_MAPIO_SUBMITTED;
index 3c50c4e..963d377 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/dm-bufio.h>
 
 #define DM_MSG_PREFIX "persistent snapshot"
-#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32       /* 16KB */
+#define DM_CHUNK_SIZE_DEFAULT_SECTORS 32U      /* 16KB */
 
 #define DM_PREFETCH_CHUNKS             12
 
index 4c68a7b..b88d6d7 100644 (file)
@@ -189,6 +189,15 @@ struct dm_pool_metadata {
        sector_t data_block_size;
 
        /*
+        * Pre-commit callback.
+        *
+        * This allows the thin provisioning target to run a callback before
+        * the metadata are committed.
+        */
+       dm_pool_pre_commit_fn pre_commit_fn;
+       void *pre_commit_context;
+
+       /*
         * We reserve a section of the metadata for commit overhead.
         * All reported space does *not* include this.
         */
@@ -826,6 +835,14 @@ static int __commit_transaction(struct dm_pool_metadata *pmd)
        if (unlikely(!pmd->in_service))
                return 0;
 
+       if (pmd->pre_commit_fn) {
+               r = pmd->pre_commit_fn(pmd->pre_commit_context);
+               if (r < 0) {
+                       DMERR("pre-commit callback failed");
+                       return r;
+               }
+       }
+
        r = __write_changed_details(pmd);
        if (r < 0)
                return r;
@@ -892,6 +909,8 @@ struct dm_pool_metadata *dm_pool_metadata_open(struct block_device *bdev,
        pmd->in_service = false;
        pmd->bdev = bdev;
        pmd->data_block_size = data_block_size;
+       pmd->pre_commit_fn = NULL;
+       pmd->pre_commit_context = NULL;
 
        r = __create_persistent_data_objects(pmd, format_device);
        if (r) {
@@ -2044,6 +2063,16 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
        return r;
 }
 
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+                                         dm_pool_pre_commit_fn fn,
+                                         void *context)
+{
+       pmd_write_lock_in_core(pmd);
+       pmd->pre_commit_fn = fn;
+       pmd->pre_commit_context = context;
+       pmd_write_unlock(pmd);
+}
+
 int dm_pool_metadata_set_needs_check(struct dm_pool_metadata *pmd)
 {
        int r = -EINVAL;
index f6be0d7..7ef56bd 100644 (file)
@@ -230,6 +230,13 @@ bool dm_pool_metadata_needs_check(struct dm_pool_metadata *pmd);
  */
 void dm_pool_issue_prefetches(struct dm_pool_metadata *pmd);
 
+/* Pre-commit callback */
+typedef int (*dm_pool_pre_commit_fn)(void *context);
+
+void dm_pool_register_pre_commit_callback(struct dm_pool_metadata *pmd,
+                                         dm_pool_pre_commit_fn fn,
+                                         void *context);
+
 /*----------------------------------------------------------------*/
 
 #endif
index 5a2c494..57626c2 100644 (file)
@@ -328,6 +328,7 @@ struct pool_c {
        dm_block_t low_water_blocks;
        struct pool_features requested_pf; /* Features requested during table load */
        struct pool_features adjusted_pf;  /* Features used after adjusting for constituent devices */
+       struct bio flush_bio;
 };
 
 /*
@@ -2383,8 +2384,16 @@ static void process_deferred_bios(struct pool *pool)
        while ((bio = bio_list_pop(&bio_completions)))
                bio_endio(bio);
 
-       while ((bio = bio_list_pop(&bios)))
-               generic_make_request(bio);
+       while ((bio = bio_list_pop(&bios))) {
+               /*
+                * The data device was flushed as part of metadata commit,
+                * so complete redundant flushes immediately.
+                */
+               if (bio->bi_opf & REQ_PREFLUSH)
+                       bio_endio(bio);
+               else
+                       generic_make_request(bio);
+       }
 }
 
 static void do_worker(struct work_struct *ws)
@@ -3115,6 +3124,7 @@ static void pool_dtr(struct dm_target *ti)
        __pool_dec(pt->pool);
        dm_put_device(ti, pt->metadata_dev);
        dm_put_device(ti, pt->data_dev);
+       bio_uninit(&pt->flush_bio);
        kfree(pt);
 
        mutex_unlock(&dm_thin_pool_table.mutex);
@@ -3180,6 +3190,29 @@ static void metadata_low_callback(void *context)
        dm_table_event(pool->ti->table);
 }
 
+/*
+ * We need to flush the data device **before** committing the metadata.
+ *
+ * This ensures that the data blocks of any newly inserted mappings are
+ * properly written to non-volatile storage and won't be lost in case of a
+ * crash.
+ *
+ * Failure to do so can result in data corruption in the case of internal or
+ * external snapshots and in the case of newly provisioned blocks, when block
+ * zeroing is enabled.
+ */
+static int metadata_pre_commit_callback(void *context)
+{
+       struct pool_c *pt = context;
+       struct bio *flush_bio = &pt->flush_bio;
+
+       bio_reset(flush_bio);
+       bio_set_dev(flush_bio, pt->data_dev->bdev);
+       flush_bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+       return submit_bio_wait(flush_bio);
+}
+
 static sector_t get_dev_size(struct block_device *bdev)
 {
        return i_size_read(bdev->bd_inode) >> SECTOR_SHIFT;
@@ -3348,6 +3381,7 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        pt->data_dev = data_dev;
        pt->low_water_blocks = low_water_blocks;
        pt->adjusted_pf = pt->requested_pf = pf;
+       bio_init(&pt->flush_bio, NULL, 0);
        ti->num_flush_bios = 1;
 
        /*
@@ -3374,6 +3408,10 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        if (r)
                goto out_flags_changed;
 
+       dm_pool_register_pre_commit_callback(pt->pool->pmd,
+                                            metadata_pre_commit_callback,
+                                            pt);
+
        pt->callbacks.congested_fn = pool_is_congested;
        dm_table_add_target_callbacks(ti->table, &pt->callbacks);
 
index 805b33e..4e7c9f3 100644 (file)
@@ -1159,6 +1159,7 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor
        /* not spare disk, or LEVEL_MULTIPATH */
        if (sb->level == LEVEL_MULTIPATH ||
                (rdev->desc_nr >= 0 &&
+                rdev->desc_nr < MD_SB_DISKS &&
                 sb->disks[rdev->desc_nr].state &
                 ((1<<MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE))))
                spare_disk = false;
index 21ea537..eff04fa 100644 (file)
@@ -203,7 +203,13 @@ static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
        struct btree_node *right = r->n;
        uint32_t nr_left = le32_to_cpu(left->header.nr_entries);
        uint32_t nr_right = le32_to_cpu(right->header.nr_entries);
-       unsigned threshold = 2 * merge_threshold(left) + 1;
+       /*
+        * Ensure the number of entries in each child will be greater
+        * than or equal to (max_entries / 3 + 1), so no matter which
+        * child is used for removal, the number will still be not
+        * less than (max_entries / 3).
+        */
+       unsigned int threshold = 2 * (merge_threshold(left) + 1);
 
        if (nr_left + nr_right < threshold) {
                /*
index b7c2097..322386f 100644 (file)
@@ -87,7 +87,7 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf)
        char b[BDEVNAME_SIZE];
        char b2[BDEVNAME_SIZE];
        struct r0conf *conf = kzalloc(sizeof(*conf), GFP_KERNEL);
-       unsigned short blksize = 512;
+       unsigned blksize = 512;
 
        *private_conf = ERR_PTR(-ENOMEM);
        if (!conf)
index a409ab6..201fd8a 100644 (file)
@@ -2782,7 +2782,7 @@ static sector_t raid1_sync_request(struct mddev *mddev, sector_t sector_nr,
                                write_targets++;
                        }
                }
-               if (bio->bi_end_io) {
+               if (rdev && bio->bi_end_io) {
                        atomic_inc(&rdev->nr_pending);
                        bio->bi_iter.bi_sector = sector_nr + rdev->data_offset;
                        bio_set_dev(bio, rdev->bdev);
index cab5b13..d50238d 100644 (file)
@@ -1360,7 +1360,7 @@ int ppl_init_log(struct r5conf *conf)
                return -EINVAL;
        }
 
-       max_disks = FIELD_SIZEOF(struct ppl_log, disk_flush_bitmap) *
+       max_disks = sizeof_field(struct ppl_log, disk_flush_bitmap) *
                BITS_PER_BYTE;
        if (conf->raid_disks > max_disks) {
                pr_warn("md/raid:%s PPL doesn't support over %d disks in the array\n",
index f0fc538..d4d3b67 100644 (file)
@@ -5726,7 +5726,7 @@ static bool raid5_make_request(struct mddev *mddev, struct bio * bi)
                                do_flush = false;
                        }
 
-                       if (!sh->batch_head)
+                       if (!sh->batch_head || sh == sh->batch_head)
                                set_bit(STRIPE_HANDLE, &sh->state);
                        clear_bit(STRIPE_DELAYED, &sh->state);
                        if ((!sh->batch_head || sh == sh->batch_head) &&
index 9340435..6c95dc4 100644 (file)
@@ -380,7 +380,8 @@ static void cec_data_cancel(struct cec_data *data, u8 tx_status)
        } else {
                list_del_init(&data->list);
                if (!(data->msg.tx_status & CEC_TX_STATUS_OK))
-                       data->adap->transmit_queue_sz--;
+                       if (!WARN_ON(!data->adap->transmit_queue_sz))
+                               data->adap->transmit_queue_sz--;
        }
 
        if (data->msg.tx_status & CEC_TX_STATUS_OK) {
@@ -432,6 +433,14 @@ static void cec_flush(struct cec_adapter *adap)
                 * need to do anything special in that case.
                 */
        }
+       /*
+        * If something went wrong and this counter isn't what it should
+        * be, then this will reset it back to 0. Warn if it is not 0,
+        * since it indicates a bug, either in this framework or in a
+        * CEC driver.
+        */
+       if (WARN_ON(adap->transmit_queue_sz))
+               adap->transmit_queue_sz = 0;
 }
 
 /*
@@ -456,7 +465,7 @@ int cec_thread_func(void *_adap)
                bool timeout = false;
                u8 attempts;
 
-               if (adap->transmitting) {
+               if (adap->transmit_in_progress) {
                        int err;
 
                        /*
@@ -491,7 +500,7 @@ int cec_thread_func(void *_adap)
                        goto unlock;
                }
 
-               if (adap->transmitting && timeout) {
+               if (adap->transmit_in_progress && timeout) {
                        /*
                         * If we timeout, then log that. Normally this does
                         * not happen and it is an indication of a faulty CEC
@@ -500,14 +509,18 @@ int cec_thread_func(void *_adap)
                         * so much traffic on the bus that the adapter was
                         * unable to transmit for CEC_XFER_TIMEOUT_MS (2.1s).
                         */
-                       pr_warn("cec-%s: message %*ph timed out\n", adap->name,
-                               adap->transmitting->msg.len,
-                               adap->transmitting->msg.msg);
+                       if (adap->transmitting) {
+                               pr_warn("cec-%s: message %*ph timed out\n", adap->name,
+                                       adap->transmitting->msg.len,
+                                       adap->transmitting->msg.msg);
+                               /* Just give up on this. */
+                               cec_data_cancel(adap->transmitting,
+                                               CEC_TX_STATUS_TIMEOUT);
+                       } else {
+                               pr_warn("cec-%s: transmit timed out\n", adap->name);
+                       }
                        adap->transmit_in_progress = false;
                        adap->tx_timeouts++;
-                       /* Just give up on this. */
-                       cec_data_cancel(adap->transmitting,
-                                       CEC_TX_STATUS_TIMEOUT);
                        goto unlock;
                }
 
@@ -522,7 +535,8 @@ int cec_thread_func(void *_adap)
                data = list_first_entry(&adap->transmit_queue,
                                        struct cec_data, list);
                list_del_init(&data->list);
-               adap->transmit_queue_sz--;
+               if (!WARN_ON(!data->adap->transmit_queue_sz))
+                       adap->transmit_queue_sz--;
 
                /* Make this the current transmitting message */
                adap->transmitting = data;
@@ -1085,11 +1099,11 @@ void cec_received_msg_ts(struct cec_adapter *adap,
                        valid_la = false;
                else if (!cec_msg_is_broadcast(msg) && !(dir_fl & DIRECTED))
                        valid_la = false;
-               else if (cec_msg_is_broadcast(msg) && !(dir_fl & BCAST1_4))
+               else if (cec_msg_is_broadcast(msg) && !(dir_fl & BCAST))
                        valid_la = false;
                else if (cec_msg_is_broadcast(msg) &&
-                        adap->log_addrs.cec_version >= CEC_OP_CEC_VERSION_2_0 &&
-                        !(dir_fl & BCAST2_0))
+                        adap->log_addrs.cec_version < CEC_OP_CEC_VERSION_2_0 &&
+                        !(dir_fl & BCAST1_4))
                        valid_la = false;
        }
        if (valid_la && min_len) {
index 97d6606..4dbdf31 100644 (file)
@@ -753,7 +753,7 @@ static const struct preview_update update_attrs[] = {
                preview_config_luma_enhancement,
                preview_enable_luma_enhancement,
                offsetof(struct prev_params, luma),
-               FIELD_SIZEOF(struct prev_params, luma),
+               sizeof_field(struct prev_params, luma),
                offsetof(struct omap3isp_prev_update_config, luma),
        }, /* OMAP3ISP_PREV_INVALAW */ {
                NULL,
@@ -762,55 +762,55 @@ static const struct preview_update update_attrs[] = {
                preview_config_hmed,
                preview_enable_hmed,
                offsetof(struct prev_params, hmed),
-               FIELD_SIZEOF(struct prev_params, hmed),
+               sizeof_field(struct prev_params, hmed),
                offsetof(struct omap3isp_prev_update_config, hmed),
        }, /* OMAP3ISP_PREV_CFA */ {
                preview_config_cfa,
                NULL,
                offsetof(struct prev_params, cfa),
-               FIELD_SIZEOF(struct prev_params, cfa),
+               sizeof_field(struct prev_params, cfa),
                offsetof(struct omap3isp_prev_update_config, cfa),
        }, /* OMAP3ISP_PREV_CHROMA_SUPP */ {
                preview_config_chroma_suppression,
                preview_enable_chroma_suppression,
                offsetof(struct prev_params, csup),
-               FIELD_SIZEOF(struct prev_params, csup),
+               sizeof_field(struct prev_params, csup),
                offsetof(struct omap3isp_prev_update_config, csup),
        }, /* OMAP3ISP_PREV_WB */ {
                preview_config_whitebalance,
                NULL,
                offsetof(struct prev_params, wbal),
-               FIELD_SIZEOF(struct prev_params, wbal),
+               sizeof_field(struct prev_params, wbal),
                offsetof(struct omap3isp_prev_update_config, wbal),
        }, /* OMAP3ISP_PREV_BLKADJ */ {
                preview_config_blkadj,
                NULL,
                offsetof(struct prev_params, blkadj),
-               FIELD_SIZEOF(struct prev_params, blkadj),
+               sizeof_field(struct prev_params, blkadj),
                offsetof(struct omap3isp_prev_update_config, blkadj),
        }, /* OMAP3ISP_PREV_RGB2RGB */ {
                preview_config_rgb_blending,
                NULL,
                offsetof(struct prev_params, rgb2rgb),
-               FIELD_SIZEOF(struct prev_params, rgb2rgb),
+               sizeof_field(struct prev_params, rgb2rgb),
                offsetof(struct omap3isp_prev_update_config, rgb2rgb),
        }, /* OMAP3ISP_PREV_COLOR_CONV */ {
                preview_config_csc,
                NULL,
                offsetof(struct prev_params, csc),
-               FIELD_SIZEOF(struct prev_params, csc),
+               sizeof_field(struct prev_params, csc),
                offsetof(struct omap3isp_prev_update_config, csc),
        }, /* OMAP3ISP_PREV_YC_LIMIT */ {
                preview_config_yc_range,
                NULL,
                offsetof(struct prev_params, yclimit),
-               FIELD_SIZEOF(struct prev_params, yclimit),
+               sizeof_field(struct prev_params, yclimit),
                offsetof(struct omap3isp_prev_update_config, yclimit),
        }, /* OMAP3ISP_PREV_DEFECT_COR */ {
                preview_config_dcor,
                preview_enable_dcor,
                offsetof(struct prev_params, dcor),
-               FIELD_SIZEOF(struct prev_params, dcor),
+               sizeof_field(struct prev_params, dcor),
                offsetof(struct omap3isp_prev_update_config, dcor),
        }, /* Previously OMAP3ISP_PREV_GAMMABYPASS, not used anymore */ {
                NULL,
@@ -828,13 +828,13 @@ static const struct preview_update update_attrs[] = {
                preview_config_noisefilter,
                preview_enable_noisefilter,
                offsetof(struct prev_params, nf),
-               FIELD_SIZEOF(struct prev_params, nf),
+               sizeof_field(struct prev_params, nf),
                offsetof(struct omap3isp_prev_update_config, nf),
        }, /* OMAP3ISP_PREV_GAMMA */ {
                preview_config_gammacorrn,
                preview_enable_gammacorrn,
                offsetof(struct prev_params, gamma),
-               FIELD_SIZEOF(struct prev_params, gamma),
+               sizeof_field(struct prev_params, gamma),
                offsetof(struct omap3isp_prev_update_config, gamma),
        }, /* OMAP3ISP_PREV_CONTRAST */ {
                preview_config_contrast,
index ac88ade..5960955 100644 (file)
@@ -116,6 +116,7 @@ struct pulse8 {
        unsigned int vers;
        struct completion cmd_done;
        struct work_struct work;
+       u8 work_result;
        struct delayed_work ping_eeprom_work;
        struct cec_msg rx_msg;
        u8 data[DATA_SIZE];
@@ -137,8 +138,10 @@ static void pulse8_irq_work_handler(struct work_struct *work)
 {
        struct pulse8 *pulse8 =
                container_of(work, struct pulse8, work);
+       u8 result = pulse8->work_result;
 
-       switch (pulse8->data[0] & 0x3f) {
+       pulse8->work_result = 0;
+       switch (result & 0x3f) {
        case MSGCODE_FRAME_DATA:
                cec_received_msg(pulse8->adap, &pulse8->rx_msg);
                break;
@@ -172,12 +175,12 @@ static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data,
                pulse8->escape = false;
        } else if (data == MSGEND) {
                struct cec_msg *msg = &pulse8->rx_msg;
+               u8 msgcode = pulse8->buf[0];
 
                if (debug)
                        dev_info(pulse8->dev, "received: %*ph\n",
                                 pulse8->idx, pulse8->buf);
-               pulse8->data[0] = pulse8->buf[0];
-               switch (pulse8->buf[0] & 0x3f) {
+               switch (msgcode & 0x3f) {
                case MSGCODE_FRAME_START:
                        msg->len = 1;
                        msg->msg[0] = pulse8->buf[1];
@@ -186,14 +189,20 @@ static irqreturn_t pulse8_interrupt(struct serio *serio, unsigned char data,
                        if (msg->len == CEC_MAX_MSG_SIZE)
                                break;
                        msg->msg[msg->len++] = pulse8->buf[1];
-                       if (pulse8->buf[0] & MSGCODE_FRAME_EOM)
+                       if (msgcode & MSGCODE_FRAME_EOM) {
+                               WARN_ON(pulse8->work_result);
+                               pulse8->work_result = msgcode;
                                schedule_work(&pulse8->work);
+                               break;
+                       }
                        break;
                case MSGCODE_TRANSMIT_SUCCEEDED:
                case MSGCODE_TRANSMIT_FAILED_LINE:
                case MSGCODE_TRANSMIT_FAILED_ACK:
                case MSGCODE_TRANSMIT_FAILED_TIMEOUT_DATA:
                case MSGCODE_TRANSMIT_FAILED_TIMEOUT_LINE:
+                       WARN_ON(pulse8->work_result);
+                       pulse8->work_result = msgcode;
                        schedule_work(&pulse8->work);
                        break;
                case MSGCODE_HIGH_ERROR:
index 4e70058..003b742 100644 (file)
@@ -2652,7 +2652,7 @@ struct v4l2_ioctl_info {
 /* Zero struct from after the field to the end */
 #define INFO_FL_CLEAR(v4l2_struct, field)                      \
        ((offsetof(struct v4l2_struct, field) +                 \
-         FIELD_SIZEOF(struct v4l2_struct, field)) << 16)
+         sizeof_field(struct v4l2_struct, field)) << 16)
 #define INFO_FL_CLEAR_MASK     (_IOC_SIZEMASK << 16)
 
 #define DEFINE_V4L_STUB_FUNC(_vidioc)                          \
index f9ac224..1074b88 100644 (file)
@@ -100,19 +100,19 @@ struct buflist {
  * Function prototypes. Called from OS entry point mptctl_ioctl.
  * arg contents specific to function.
  */
-static int mptctl_fw_download(unsigned long arg);
-static int mptctl_getiocinfo(unsigned long arg, unsigned int cmd);
-static int mptctl_gettargetinfo(unsigned long arg);
-static int mptctl_readtest(unsigned long arg);
-static int mptctl_mpt_command(unsigned long arg);
-static int mptctl_eventquery(unsigned long arg);
-static int mptctl_eventenable(unsigned long arg);
-static int mptctl_eventreport(unsigned long arg);
-static int mptctl_replace_fw(unsigned long arg);
-
-static int mptctl_do_reset(unsigned long arg);
-static int mptctl_hp_hostinfo(unsigned long arg, unsigned int cmd);
-static int mptctl_hp_targetinfo(unsigned long arg);
+static int mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_getiocinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
+static int mptctl_gettargetinfo(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_readtest(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_mpt_command(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventquery(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventenable(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_eventreport(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_replace_fw(MPT_ADAPTER *iocp, unsigned long arg);
+
+static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg);
+static int mptctl_hp_hostinfo(MPT_ADAPTER *iocp, unsigned long arg, unsigned int cmd);
+static int mptctl_hp_targetinfo(MPT_ADAPTER *iocp, unsigned long arg);
 
 static int  mptctl_probe(struct pci_dev *, const struct pci_device_id *);
 static void mptctl_remove(struct pci_dev *);
@@ -123,8 +123,8 @@ static long compat_mpctl_ioctl(struct file *f, unsigned cmd, unsigned long arg);
 /*
  * Private function calls.
  */
-static int mptctl_do_mpt_command(struct mpt_ioctl_command karg, void __user *mfPtr);
-static int mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen);
+static int mptctl_do_mpt_command(MPT_ADAPTER *iocp, struct mpt_ioctl_command karg, void __user *mfPtr);
+static int mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen);
 static MptSge_t *kbuf_alloc_2_sgl(int bytes, u32 dir, int sge_offset, int *frags,
                struct buflist **blp, dma_addr_t *sglbuf_dma, MPT_ADAPTER *ioc);
 static void kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma,
@@ -656,19 +656,19 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
         * by TM and FW reloads.
         */
        if ((cmd & ~IOCSIZE_MASK) == (MPTIOCINFO & ~IOCSIZE_MASK)) {
-               return mptctl_getiocinfo(arg, _IOC_SIZE(cmd));
+               return mptctl_getiocinfo(iocp, arg, _IOC_SIZE(cmd));
        } else if (cmd == MPTTARGETINFO) {
-               return mptctl_gettargetinfo(arg);
+               return mptctl_gettargetinfo(iocp, arg);
        } else if (cmd == MPTTEST) {
-               return mptctl_readtest(arg);
+               return mptctl_readtest(iocp, arg);
        } else if (cmd == MPTEVENTQUERY) {
-               return mptctl_eventquery(arg);
+               return mptctl_eventquery(iocp, arg);
        } else if (cmd == MPTEVENTENABLE) {
-               return mptctl_eventenable(arg);
+               return mptctl_eventenable(iocp, arg);
        } else if (cmd == MPTEVENTREPORT) {
-               return mptctl_eventreport(arg);
+               return mptctl_eventreport(iocp, arg);
        } else if (cmd == MPTFWREPLACE) {
-               return mptctl_replace_fw(arg);
+               return mptctl_replace_fw(iocp, arg);
        }
 
        /* All of these commands require an interrupt or
@@ -678,15 +678,15 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                return ret;
 
        if (cmd == MPTFWDOWNLOAD)
-               ret = mptctl_fw_download(arg);
+               ret = mptctl_fw_download(iocp, arg);
        else if (cmd == MPTCOMMAND)
-               ret = mptctl_mpt_command(arg);
+               ret = mptctl_mpt_command(iocp, arg);
        else if (cmd == MPTHARDRESET)
-               ret = mptctl_do_reset(arg);
+               ret = mptctl_do_reset(iocp, arg);
        else if ((cmd & ~IOCSIZE_MASK) == (HP_GETHOSTINFO & ~IOCSIZE_MASK))
-               ret = mptctl_hp_hostinfo(arg, _IOC_SIZE(cmd));
+               ret = mptctl_hp_hostinfo(iocp, arg, _IOC_SIZE(cmd));
        else if (cmd == HP_GETTARGETINFO)
-               ret = mptctl_hp_targetinfo(arg);
+               ret = mptctl_hp_targetinfo(iocp, arg);
        else
                ret = -EINVAL;
 
@@ -705,11 +705,10 @@ mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        return ret;
 }
 
-static int mptctl_do_reset(unsigned long arg)
+static int mptctl_do_reset(MPT_ADAPTER *iocp, unsigned long arg)
 {
        struct mpt_ioctl_diag_reset __user *urinfo = (void __user *) arg;
        struct mpt_ioctl_diag_reset krinfo;
-       MPT_ADAPTER             *iocp;
 
        if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) {
                printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - "
@@ -718,12 +717,6 @@ static int mptctl_do_reset(unsigned long arg)
                return -EFAULT;
        }
 
-       if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) {
-               printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n",
-                               __FILE__, __LINE__, krinfo.hdr.iocnum);
-               return -ENODEV; /* (-6) No such device or address */
-       }
-
        dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "mptctl_do_reset called.\n",
            iocp->name));
 
@@ -754,7 +747,7 @@ static int mptctl_do_reset(unsigned long arg)
  *             -ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_fw_download(unsigned long arg)
+mptctl_fw_download(MPT_ADAPTER *iocp, unsigned long arg)
 {
        struct mpt_fw_xfer __user *ufwdl = (void __user *) arg;
        struct mpt_fw_xfer       kfwdl;
@@ -766,7 +759,7 @@ mptctl_fw_download(unsigned long arg)
                return -EFAULT;
        }
 
-       return mptctl_do_fw_download(kfwdl.iocnum, kfwdl.bufp, kfwdl.fwlen);
+       return mptctl_do_fw_download(iocp, kfwdl.bufp, kfwdl.fwlen);
 }
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
@@ -784,11 +777,10 @@ mptctl_fw_download(unsigned long arg)
  *             -ENOMSG if FW upload returned bad status
  */
 static int
-mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
+mptctl_do_fw_download(MPT_ADAPTER *iocp, char __user *ufwbuf, size_t fwlen)
 {
        FWDownload_t            *dlmsg;
        MPT_FRAME_HDR           *mf;
-       MPT_ADAPTER             *iocp;
        FWDownloadTCSGE_t       *ptsge;
        MptSge_t                *sgl, *sgIn;
        char                    *sgOut;
@@ -808,17 +800,10 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
        pFWDownloadReply_t       ReplyMsg = NULL;
        unsigned long            timeleft;
 
-       if (mpt_verify_adapter(ioc, &iocp) < 0) {
-               printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n",
-                                ioc);
-               return -ENODEV; /* (-6) No such device or address */
-       } else {
-
-               /*  Valid device. Get a message frame and construct the FW download message.
-               */
-               if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
-                       return -EAGAIN;
-       }
+       /*  Valid device. Get a message frame and construct the FW download message.
+       */
+       if ((mf = mpt_get_msg_frame(mptctl_id, iocp)) == NULL)
+               return -EAGAIN;
 
        dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT
            "mptctl_do_fwdl called. mptctl_id = %xh.\n", iocp->name, mptctl_id));
@@ -826,8 +811,6 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen)
            iocp->name, ufwbuf));
        dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.fwlen = %d\n",
            iocp->name, (int)fwlen));
-       dctlprintk(iocp, printk(MYIOC_s_DEBUG_FMT "DbG: kfwdl.ioc   = %04xh\n",
-           iocp->name, ioc));
 
        dlmsg = (FWDownload_t*) mf;
        ptsge = (FWDownloadTCSGE_t *) &dlmsg->SGL;
@@ -1238,13 +1221,11 @@ kfree_sgl(MptSge_t *sgl, dma_addr_t sgl_dma, struct buflist *buflist, MPT_ADAPTE
  *             -ENODEV  if no such device/adapter
  */
 static int
-mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
+mptctl_getiocinfo (MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
 {
        struct mpt_ioctl_iocinfo __user *uarg = (void __user *) arg;
        struct mpt_ioctl_iocinfo *karg;
-       MPT_ADAPTER             *ioc;
        struct pci_dev          *pdev;
-       int                     iocnum;
        unsigned int            port;
        int                     cim_rev;
        struct scsi_device      *sdev;
@@ -1272,14 +1253,6 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
                return PTR_ERR(karg);
        }
 
-       if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               kfree(karg);
-               return -ENODEV;
-       }
-
        /* Verify the data transfer size is correct. */
        if (karg->hdr.maxDataSize != data_size) {
                printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - "
@@ -1385,15 +1358,13 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size)
  *             -ENODEV  if no such device/adapter
  */
 static int
-mptctl_gettargetinfo (unsigned long arg)
+mptctl_gettargetinfo (MPT_ADAPTER *ioc, unsigned long arg)
 {
        struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg;
        struct mpt_ioctl_targetinfo karg;
-       MPT_ADAPTER             *ioc;
        VirtDevice              *vdevice;
        char                    *pmem;
        int                     *pdata;
-       int                     iocnum;
        int                     numDevices = 0;
        int                     lun;
        int                     maxWordsLeft;
@@ -1408,13 +1379,6 @@ mptctl_gettargetinfo (unsigned long arg)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
-
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_gettargetinfo called.\n",
            ioc->name));
        /* Get the port number and set the maximum number of bytes
@@ -1510,12 +1474,10 @@ mptctl_gettargetinfo (unsigned long arg)
  *             -ENODEV  if no such device/adapter
  */
 static int
-mptctl_readtest (unsigned long arg)
+mptctl_readtest (MPT_ADAPTER *ioc, unsigned long arg)
 {
        struct mpt_ioctl_test __user *uarg = (void __user *) arg;
        struct mpt_ioctl_test    karg;
-       MPT_ADAPTER *ioc;
-       int iocnum;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) {
                printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - "
@@ -1524,13 +1486,6 @@ mptctl_readtest (unsigned long arg)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
-
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_readtest called.\n",
            ioc->name));
        /* Fill in the data and return the structure to the calling
@@ -1571,12 +1526,10 @@ mptctl_readtest (unsigned long arg)
  *             -ENODEV  if no such device/adapter
  */
 static int
-mptctl_eventquery (unsigned long arg)
+mptctl_eventquery (MPT_ADAPTER *ioc, unsigned long arg)
 {
        struct mpt_ioctl_eventquery __user *uarg = (void __user *) arg;
        struct mpt_ioctl_eventquery      karg;
-       MPT_ADAPTER *ioc;
-       int iocnum;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) {
                printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - "
@@ -1585,13 +1538,6 @@ mptctl_eventquery (unsigned long arg)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
-
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventquery called.\n",
            ioc->name));
        karg.eventEntries = MPTCTL_EVENT_LOG_SIZE;
@@ -1610,12 +1556,10 @@ mptctl_eventquery (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_eventenable (unsigned long arg)
+mptctl_eventenable (MPT_ADAPTER *ioc, unsigned long arg)
 {
        struct mpt_ioctl_eventenable __user *uarg = (void __user *) arg;
        struct mpt_ioctl_eventenable     karg;
-       MPT_ADAPTER *ioc;
-       int iocnum;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) {
                printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - "
@@ -1624,13 +1568,6 @@ mptctl_eventenable (unsigned long arg)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
-
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventenable called.\n",
            ioc->name));
        if (ioc->events == NULL) {
@@ -1658,12 +1595,10 @@ mptctl_eventenable (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_eventreport (unsigned long arg)
+mptctl_eventreport (MPT_ADAPTER *ioc, unsigned long arg)
 {
        struct mpt_ioctl_eventreport __user *uarg = (void __user *) arg;
        struct mpt_ioctl_eventreport     karg;
-       MPT_ADAPTER              *ioc;
-       int                      iocnum;
        int                      numBytes, maxEvents, max;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) {
@@ -1673,12 +1608,6 @@ mptctl_eventreport (unsigned long arg)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_eventreport called.\n",
            ioc->name));
 
@@ -1712,12 +1641,10 @@ mptctl_eventreport (unsigned long arg)
 
 /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
 static int
-mptctl_replace_fw (unsigned long arg)
+mptctl_replace_fw (MPT_ADAPTER *ioc, unsigned long arg)
 {
        struct mpt_ioctl_replace_fw __user *uarg = (void __user *) arg;
        struct mpt_ioctl_replace_fw      karg;
-       MPT_ADAPTER              *ioc;
-       int                      iocnum;
        int                      newFwSize;
 
        if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) {
@@ -1727,13 +1654,6 @@ mptctl_replace_fw (unsigned long arg)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
-
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_replace_fw called.\n",
            ioc->name));
        /* If caching FW, Free the old FW image
@@ -1780,12 +1700,10 @@ mptctl_replace_fw (unsigned long arg)
  *             -ENOMEM if memory allocation error
  */
 static int
-mptctl_mpt_command (unsigned long arg)
+mptctl_mpt_command (MPT_ADAPTER *ioc, unsigned long arg)
 {
        struct mpt_ioctl_command __user *uarg = (void __user *) arg;
        struct mpt_ioctl_command  karg;
-       MPT_ADAPTER     *ioc;
-       int             iocnum;
        int             rc;
 
 
@@ -1796,14 +1714,7 @@ mptctl_mpt_command (unsigned long arg)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
-
-       rc = mptctl_do_mpt_command (karg, &uarg->MF);
+       rc = mptctl_do_mpt_command (ioc, karg, &uarg->MF);
 
        return rc;
 }
@@ -1821,9 +1732,8 @@ mptctl_mpt_command (unsigned long arg)
  *             -EPERM if SCSI I/O and target is untagged
  */
 static int
-mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
+mptctl_do_mpt_command (MPT_ADAPTER *ioc, struct mpt_ioctl_command karg, void __user *mfPtr)
 {
-       MPT_ADAPTER     *ioc;
        MPT_FRAME_HDR   *mf = NULL;
        MPIHeader_t     *hdr;
        char            *psge;
@@ -1832,7 +1742,7 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        dma_addr_t      dma_addr_in;
        dma_addr_t      dma_addr_out;
        int             sgSize = 0;     /* Num SG elements */
-       int             iocnum, flagsLength;
+       int             flagsLength;
        int             sz, rc = 0;
        int             msgContext;
        u16             req_idx;
@@ -1847,13 +1757,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr)
        bufIn.kptr = bufOut.kptr = NULL;
        bufIn.len = bufOut.len = 0;
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
-
        spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
        if (ioc->ioc_reset_in_progress) {
                spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
@@ -2418,17 +2321,15 @@ done_free_mem:
  *             -ENOMEM if memory allocation error
  */
 static int
-mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
+mptctl_hp_hostinfo(MPT_ADAPTER *ioc, unsigned long arg, unsigned int data_size)
 {
        hp_host_info_t  __user *uarg = (void __user *) arg;
-       MPT_ADAPTER             *ioc;
        struct pci_dev          *pdev;
        char                    *pbuf=NULL;
        dma_addr_t              buf_dma;
        hp_host_info_t          karg;
        CONFIGPARMS             cfg;
        ConfigPageHeader_t      hdr;
-       int                     iocnum;
        int                     rc, cim_rev;
        ToolboxIstwiReadWriteRequest_t  *IstwiRWRequest;
        MPT_FRAME_HDR           *mf = NULL;
@@ -2452,12 +2353,6 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-           (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_hostinfo called.\n",
            ioc->name));
 
@@ -2659,15 +2554,13 @@ retry_wait:
  *             -ENOMEM if memory allocation error
  */
 static int
-mptctl_hp_targetinfo(unsigned long arg)
+mptctl_hp_targetinfo(MPT_ADAPTER *ioc, unsigned long arg)
 {
        hp_target_info_t __user *uarg = (void __user *) arg;
        SCSIDevicePage0_t       *pg0_alloc;
        SCSIDevicePage3_t       *pg3_alloc;
-       MPT_ADAPTER             *ioc;
        MPT_SCSI_HOST           *hd = NULL;
        hp_target_info_t        karg;
-       int                     iocnum;
        int                     data_sz;
        dma_addr_t              page_dma;
        CONFIGPARMS             cfg;
@@ -2681,12 +2574,6 @@ mptctl_hp_targetinfo(unsigned long arg)
                return -EFAULT;
        }
 
-       if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) ||
-               (ioc == NULL)) {
-               printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n",
-                               __FILE__, __LINE__, iocnum);
-               return -ENODEV;
-       }
        if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
                return -EINVAL;
        dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n",
@@ -2854,7 +2741,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd,
        kfw.fwlen = kfw32.fwlen;
        kfw.bufp = compat_ptr(kfw32.bufp);
 
-       ret = mptctl_do_fw_download(kfw.iocnum, kfw.bufp, kfw.fwlen);
+       ret = mptctl_do_fw_download(iocp, kfw.bufp, kfw.fwlen);
 
        mutex_unlock(&iocp->ioctl_cmds.mutex);
 
@@ -2908,7 +2795,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd,
 
        /* Pass new structure to do_mpt_command
         */
-       ret = mptctl_do_mpt_command (karg, &uarg->MF);
+       ret = mptctl_do_mpt_command (iocp, karg, &uarg->MF);
 
        mutex_unlock(&iocp->ioctl_cmds.mutex);
 
index 6d27ccf..3c2d405 100644 (file)
@@ -406,10 +406,9 @@ int enclosure_remove_device(struct enclosure_device *edev, struct device *dev)
                cdev = &edev->component[i];
                if (cdev->dev == dev) {
                        enclosure_remove_links(cdev);
-                       device_del(&cdev->cdev);
                        put_device(dev);
                        cdev->dev = NULL;
-                       return device_add(&cdev->cdev);
+                       return 0;
                }
        }
        return -ENODEV;
index 8850f47..0bf0867 100644 (file)
@@ -824,8 +824,9 @@ int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data)
        memset(args, 0, sizeof(*args));
 
        if (rc < 0) {
-               dev_err(hdev->dev, "Error %ld on waiting for CS handle %llu\n",
-                       rc, seq);
+               dev_err_ratelimited(hdev->dev,
+                               "Error %ld on waiting for CS handle %llu\n",
+                               rc, seq);
                if (rc == -ERESTARTSYS) {
                        args->out.status = HL_WAIT_CS_STATUS_INTERRUPTED;
                        rc = -EINTR;
index 17db7b3..2df6fb8 100644 (file)
@@ -176,7 +176,7 @@ struct dma_fence *hl_ctx_get_fence(struct hl_ctx *ctx, u64 seq)
        spin_lock(&ctx->cs_lock);
 
        if (seq >= ctx->cs_sequence) {
-               dev_notice(hdev->dev,
+               dev_notice_ratelimited(hdev->dev,
                        "Can't wait on seq %llu because current CS is at seq %llu\n",
                        seq, ctx->cs_sequence);
                spin_unlock(&ctx->cs_lock);
index c8d16aa..7344e8a 100644 (file)
@@ -2192,7 +2192,7 @@ static int goya_push_linux_to_device(struct hl_device *hdev)
 
 static int goya_pldm_init_cpu(struct hl_device *hdev)
 {
-       u32 val, unit_rst_val;
+       u32 unit_rst_val;
        int rc;
 
        /* Must initialize SRAM scrambler before pushing u-boot to SRAM */
@@ -2200,14 +2200,14 @@ static int goya_pldm_init_cpu(struct hl_device *hdev)
 
        /* Put ARM cores into reset */
        WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL, CPU_RESET_ASSERT);
-       val = RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
+       RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
 
        /* Reset the CA53 MACRO */
        unit_rst_val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
        WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, CA53_RESET);
-       val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+       RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
        WREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N, unit_rst_val);
-       val = RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
+       RREG32(mmPSOC_GLOBAL_CONF_UNIT_RST_N);
 
        rc = goya_push_uboot_to_device(hdev);
        if (rc)
@@ -2228,7 +2228,7 @@ static int goya_pldm_init_cpu(struct hl_device *hdev)
        /* Release ARM core 0 from reset */
        WREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL,
                                        CPU_RESET_CORE0_DEASSERT);
-       val = RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
+       RREG32(mmCPU_CA53_CFG_ARM_RST_CONTROL);
 
        return 0;
 }
@@ -2502,13 +2502,12 @@ err:
 static int goya_hw_init(struct hl_device *hdev)
 {
        struct asic_fixed_properties *prop = &hdev->asic_prop;
-       u32 val;
        int rc;
 
        dev_info(hdev->dev, "Starting initialization of H/W\n");
 
        /* Perform read from the device to make sure device is up */
-       val = RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
+       RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
 
        /*
         * Let's mark in the H/W that we have reached this point. We check
@@ -2560,7 +2559,7 @@ static int goya_hw_init(struct hl_device *hdev)
                goto disable_queues;
 
        /* Perform read from the device to flush all MSI-X configuration */
-       val = RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
+       RREG32(mmPCIE_DBI_DEVICE_ID_VENDOR_ID_REG);
 
        return 0;
 
index a4fdad0..de87693 100644 (file)
@@ -278,7 +278,7 @@ void lkdtm_STACK_GUARD_PAGE_TRAILING(void)
 
 void lkdtm_UNSET_SMEP(void)
 {
-#ifdef CONFIG_X86_64
+#if IS_ENABLED(CONFIG_X86_64) && !IS_ENABLED(CONFIG_UML)
 #define MOV_CR4_DEPTH  64
        void (*direct_write_cr4)(unsigned long val);
        unsigned char *insn;
@@ -338,13 +338,13 @@ void lkdtm_UNSET_SMEP(void)
                native_write_cr4(cr4);
        }
 #else
-       pr_err("FAIL: this test is x86_64-only\n");
+       pr_err("XFAIL: this test is x86_64-only\n");
 #endif
 }
 
-#ifdef CONFIG_X86_32
 void lkdtm_DOUBLE_FAULT(void)
 {
+#ifdef CONFIG_X86_32
        /*
         * Trigger #DF by setting the stack limit to zero.  This clobbers
         * a GDT TLS slot, which is okay because the current task will die
@@ -373,6 +373,8 @@ void lkdtm_DOUBLE_FAULT(void)
        asm volatile ("movw %0, %%ss; addl $0, (%%esp)" ::
                      "r" ((unsigned short)(GDT_ENTRY_TLS_MIN << 3)));
 
-       panic("tried to double fault but didn't die\n");
-}
+       pr_err("FAIL: tried to double fault but didn't die\n");
+#else
+       pr_err("XFAIL: this test is ia32-only\n");
 #endif
+}
index 994563a..de8a66b 100644 (file)
@@ -10,18 +10,17 @@ int ocxl_context_alloc(struct ocxl_context **context, struct ocxl_afu *afu,
        int pasid;
        struct ocxl_context *ctx;
 
-       *context = kzalloc(sizeof(struct ocxl_context), GFP_KERNEL);
-       if (!*context)
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx)
                return -ENOMEM;
 
-       ctx = *context;
-
        ctx->afu = afu;
        mutex_lock(&afu->contexts_lock);
        pasid = idr_alloc(&afu->contexts_idr, ctx, afu->pasid_base,
                        afu->pasid_base + afu->pasid_max, GFP_KERNEL);
        if (pasid < 0) {
                mutex_unlock(&afu->contexts_lock);
+               kfree(ctx);
                return pasid;
        }
        afu->pasid_count++;
@@ -43,6 +42,7 @@ int ocxl_context_alloc(struct ocxl_context **context, struct ocxl_afu *afu,
         * duration of the life of the context
         */
        ocxl_afu_get(afu);
+       *context = ctx;
        return 0;
 }
 EXPORT_SYMBOL_GPL(ocxl_context_alloc);
index 2870c25..4d1b44d 100644 (file)
@@ -18,18 +18,15 @@ static struct class *ocxl_class;
 static struct mutex minors_idr_lock;
 static struct idr minors_idr;
 
-static struct ocxl_file_info *find_file_info(dev_t devno)
+static struct ocxl_file_info *find_and_get_file_info(dev_t devno)
 {
        struct ocxl_file_info *info;
 
-       /*
-        * We don't declare an RCU critical section here, as our AFU
-        * is protected by a reference counter on the device. By the time the
-        * info reference is removed from the idr, the ref count of
-        * the device is already at 0, so no user API will access that AFU and
-        * this function can't return it.
-        */
+       mutex_lock(&minors_idr_lock);
        info = idr_find(&minors_idr, MINOR(devno));
+       if (info)
+               get_device(&info->dev);
+       mutex_unlock(&minors_idr_lock);
        return info;
 }
 
@@ -58,14 +55,16 @@ static int afu_open(struct inode *inode, struct file *file)
 
        pr_debug("%s for device %x\n", __func__, inode->i_rdev);
 
-       info = find_file_info(inode->i_rdev);
+       info = find_and_get_file_info(inode->i_rdev);
        if (!info)
                return -ENODEV;
 
        rc = ocxl_context_alloc(&ctx, info->afu, inode->i_mapping);
-       if (rc)
+       if (rc) {
+               put_device(&info->dev);
                return rc;
-
+       }
+       put_device(&info->dev);
        file->private_data = ctx;
        return 0;
 }
@@ -487,7 +486,6 @@ static void info_release(struct device *dev)
 {
        struct ocxl_file_info *info = container_of(dev, struct ocxl_file_info, dev);
 
-       free_minor(info);
        ocxl_afu_put(info->afu);
        kfree(info);
 }
@@ -577,6 +575,7 @@ void ocxl_file_unregister_afu(struct ocxl_afu *afu)
 
        ocxl_file_make_invisible(info);
        ocxl_sysfs_unregister_afu(info);
+       free_minor(info);
        device_unregister(&info->dev);
 }
 
index 189e426..010fe29 100644 (file)
 #define MSDC_PATCH_BIT_SPCPUSH    (0x1 << 29)  /* RW */
 #define MSDC_PATCH_BIT_DECRCTMO   (0x1 << 30)  /* RW */
 
+#define MSDC_PATCH_BIT1_CMDTA     (0x7 << 3)    /* RW */
 #define MSDC_PATCH_BIT1_STOP_DLY  (0xf << 8)    /* RW */
 
 #define MSDC_PATCH_BIT2_CFGRESP   (0x1 << 15)   /* RW */
@@ -1881,6 +1882,7 @@ static int hs400_tune_response(struct mmc_host *mmc, u32 opcode)
 
        /* select EMMC50 PAD CMD tune */
        sdr_set_bits(host->base + PAD_CMD_TUNE, BIT(0));
+       sdr_set_field(host->base + MSDC_PATCH_BIT1, MSDC_PATCH_BIT1_CMDTA, 2);
 
        if (mmc->ios.timing == MMC_TIMING_MMC_HS200 ||
            mmc->ios.timing == MMC_TIMING_UHS_SDR104)
index b75c82d..3d0bb5e 100644 (file)
@@ -99,7 +99,7 @@
 
 #define CORE_PWRSAVE_DLL       BIT(3)
 
-#define DDR_CONFIG_POR_VAL     0x80040853
+#define DDR_CONFIG_POR_VAL     0x80040873
 
 
 #define INVALID_TUNING_PHASE   -1
@@ -148,8 +148,9 @@ struct sdhci_msm_offset {
        u32 core_ddr_200_cfg;
        u32 core_vendor_spec3;
        u32 core_dll_config_2;
+       u32 core_dll_config_3;
+       u32 core_ddr_config_old; /* Applicable to sdcc minor ver < 0x49 */
        u32 core_ddr_config;
-       u32 core_ddr_config_2;
 };
 
 static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
@@ -177,8 +178,8 @@ static const struct sdhci_msm_offset sdhci_msm_v5_offset = {
        .core_ddr_200_cfg = 0x224,
        .core_vendor_spec3 = 0x250,
        .core_dll_config_2 = 0x254,
-       .core_ddr_config = 0x258,
-       .core_ddr_config_2 = 0x25c,
+       .core_dll_config_3 = 0x258,
+       .core_ddr_config = 0x25c,
 };
 
 static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
@@ -207,8 +208,8 @@ static const struct sdhci_msm_offset sdhci_msm_mci_offset = {
        .core_ddr_200_cfg = 0x184,
        .core_vendor_spec3 = 0x1b0,
        .core_dll_config_2 = 0x1b4,
-       .core_ddr_config = 0x1b8,
-       .core_ddr_config_2 = 0x1bc,
+       .core_ddr_config_old = 0x1b8,
+       .core_ddr_config = 0x1bc,
 };
 
 struct sdhci_msm_variant_ops {
@@ -253,6 +254,7 @@ struct sdhci_msm_host {
        const struct sdhci_msm_offset *offset;
        bool use_cdr;
        u32 transfer_mode;
+       bool updated_ddr_cfg;
 };
 
 static const struct sdhci_msm_offset *sdhci_priv_msm_offset(struct sdhci_host *host)
@@ -924,8 +926,10 @@ out:
 static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
 {
        struct mmc_host *mmc = host->mmc;
-       u32 dll_status, config;
+       u32 dll_status, config, ddr_cfg_offset;
        int ret;
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
        const struct sdhci_msm_offset *msm_offset =
                                        sdhci_priv_msm_offset(host);
 
@@ -938,8 +942,11 @@ static int sdhci_msm_cm_dll_sdc4_calibration(struct sdhci_host *host)
         * bootloaders. In the future, if this changes, then the desired
         * values will need to be programmed appropriately.
         */
-       writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr +
-                       msm_offset->core_ddr_config);
+       if (msm_host->updated_ddr_cfg)
+               ddr_cfg_offset = msm_offset->core_ddr_config;
+       else
+               ddr_cfg_offset = msm_offset->core_ddr_config_old;
+       writel_relaxed(DDR_CONFIG_POR_VAL, host->ioaddr + ddr_cfg_offset);
 
        if (mmc->ios.enhanced_strobe) {
                config = readl_relaxed(host->ioaddr +
@@ -1899,6 +1906,9 @@ static int sdhci_msm_probe(struct platform_device *pdev)
                                msm_offset->core_vendor_spec_capabilities0);
        }
 
+       if (core_major == 1 && core_minor >= 0x49)
+               msm_host->updated_ddr_cfg = true;
+
        /*
         * Power on reset state may trigger power irq if previous status of
         * PWRCTL was either BUS_ON or IO_HIGH_V. So before enabling pwr irq
index 5cca3fa..500f70a 100644 (file)
@@ -80,6 +80,7 @@ struct sdhci_esdhc {
        bool quirk_tuning_erratum_type1;
        bool quirk_tuning_erratum_type2;
        bool quirk_ignore_data_inhibit;
+       bool quirk_delay_before_data_reset;
        bool in_sw_tuning;
        unsigned int peripheral_clock;
        const struct esdhc_clk_fixup *clk_fixup;
@@ -759,14 +760,16 @@ static void esdhc_reset(struct sdhci_host *host, u8 mask)
        struct sdhci_esdhc *esdhc = sdhci_pltfm_priv(pltfm_host);
        u32 val;
 
+       if (esdhc->quirk_delay_before_data_reset &&
+           (mask & SDHCI_RESET_DATA) &&
+           (host->flags & SDHCI_REQ_USE_DMA))
+               mdelay(5);
+
        sdhci_reset(host, mask);
 
        sdhci_writel(host, host->ier, SDHCI_INT_ENABLE);
        sdhci_writel(host, host->ier, SDHCI_SIGNAL_ENABLE);
 
-       if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc"))
-               mdelay(5);
-
        if (mask & SDHCI_RESET_ALL) {
                val = sdhci_readl(host, ESDHC_TBCTL);
                val &= ~ESDHC_TB_EN;
@@ -1221,6 +1224,10 @@ static void esdhc_init(struct platform_device *pdev, struct sdhci_host *host)
        if (match)
                esdhc->clk_fixup = match->data;
        np = pdev->dev.of_node;
+
+       if (of_device_is_compatible(np, "fsl,p2020-esdhc"))
+               esdhc->quirk_delay_before_data_reset = true;
+
        clk = of_clk_get(np, 0);
        if (!IS_ERR(clk)) {
                /*
@@ -1303,8 +1310,8 @@ static int sdhci_esdhc_probe(struct platform_device *pdev)
                host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ;
 
        if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) {
-               host->quirks2 |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
-               host->quirks2 |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
+               host->quirks |= SDHCI_QUIRK_RESET_AFTER_REQUEST;
+               host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
        }
 
        if (of_device_is_compatible(np, "fsl,p5040-esdhc") ||
index acefb76..5091e2c 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mmc/slot-gpio.h>
 #include <linux/mmc/sdhci-pci-data.h>
 #include <linux/acpi.h>
+#include <linux/dmi.h>
 
 #ifdef CONFIG_X86
 #include <asm/iosf_mbi.h>
@@ -783,11 +784,18 @@ static int byt_emmc_probe_slot(struct sdhci_pci_slot *slot)
        return 0;
 }
 
+static bool glk_broken_cqhci(struct sdhci_pci_slot *slot)
+{
+       return slot->chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC &&
+              dmi_match(DMI_BIOS_VENDOR, "LENOVO");
+}
+
 static int glk_emmc_probe_slot(struct sdhci_pci_slot *slot)
 {
        int ret = byt_emmc_probe_slot(slot);
 
-       slot->host->mmc->caps2 |= MMC_CAP2_CQE;
+       if (!glk_broken_cqhci(slot))
+               slot->host->mmc->caps2 |= MMC_CAP2_CQE;
 
        if (slot->chip->pdev->device != PCI_DEVICE_ID_INTEL_GLK_EMMC) {
                slot->host->mmc->caps2 |= MMC_CAP2_HS400_ES,
index 3140fe2..1b1c26d 100644 (file)
@@ -1882,9 +1882,7 @@ void sdhci_set_uhs_signaling(struct sdhci_host *host, unsigned timing)
                ctrl_2 |= SDHCI_CTRL_UHS_SDR104;
        else if (timing == MMC_TIMING_UHS_SDR12)
                ctrl_2 |= SDHCI_CTRL_UHS_SDR12;
-       else if (timing == MMC_TIMING_SD_HS ||
-                timing == MMC_TIMING_MMC_HS ||
-                timing == MMC_TIMING_UHS_SDR25)
+       else if (timing == MMC_TIMING_UHS_SDR25)
                ctrl_2 |= SDHCI_CTRL_UHS_SDR25;
        else if (timing == MMC_TIMING_UHS_SDR50)
                ctrl_2 |= SDHCI_CTRL_UHS_SDR50;
@@ -2419,8 +2417,8 @@ static int __sdhci_execute_tuning(struct sdhci_host *host, u32 opcode)
                sdhci_send_tuning(host, opcode);
 
                if (!host->tuning_done) {
-                       pr_info("%s: Tuning timeout, falling back to fixed sampling clock\n",
-                               mmc_hostname(host->mmc));
+                       pr_debug("%s: Tuning timeout, falling back to fixed sampling clock\n",
+                                mmc_hostname(host->mmc));
                        sdhci_abort_tuning(host, opcode);
                        return -ETIMEDOUT;
                }
@@ -3769,6 +3767,9 @@ int sdhci_setup_host(struct sdhci_host *host)
                       mmc_hostname(mmc), host->version);
        }
 
+       if (host->quirks & SDHCI_QUIRK_BROKEN_CQE)
+               mmc->caps2 &= ~MMC_CAP2_CQE;
+
        if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
                host->flags |= SDHCI_USE_SDMA;
        else if (!(host->caps & SDHCI_CAN_DO_SDMA))
index 0ed3e0e..fe83ece 100644 (file)
@@ -409,6 +409,8 @@ struct sdhci_host {
 #define SDHCI_QUIRK_BROKEN_CARD_DETECTION              (1<<15)
 /* Controller reports inverted write-protect state */
 #define SDHCI_QUIRK_INVERTED_WRITE_PROTECT             (1<<16)
+/* Controller has unusable command queue engine */
+#define SDHCI_QUIRK_BROKEN_CQE                         (1<<17)
 /* Controller does not like fast PIO transfers */
 #define SDHCI_QUIRK_PIO_NEEDS_DELAY                    (1<<18)
 /* Controller does not have a LED */
index edf94ee..aa9368b 100644 (file)
@@ -148,13 +148,13 @@ static int omap2_onenand_wait(struct mtd_info *mtd, int state)
        unsigned long timeout;
        u32 syscfg;
 
-       if (state == FL_RESETING || state == FL_PREPARING_ERASE ||
+       if (state == FL_RESETTING || state == FL_PREPARING_ERASE ||
            state == FL_VERIFYING_ERASE) {
                int i = 21;
                unsigned int intr_flags = ONENAND_INT_MASTER;
 
                switch (state) {
-               case FL_RESETING:
+               case FL_RESETTING:
                        intr_flags |= ONENAND_INT_RESET;
                        break;
                case FL_PREPARING_ERASE:
@@ -328,7 +328,8 @@ static inline int omap2_onenand_dma_transfer(struct omap2_onenand *c,
        struct dma_async_tx_descriptor *tx;
        dma_cookie_t cookie;
 
-       tx = dmaengine_prep_dma_memcpy(c->dma_chan, dst, src, count, 0);
+       tx = dmaengine_prep_dma_memcpy(c->dma_chan, dst, src, count,
+                                      DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
        if (!tx) {
                dev_err(&c->pdev->dev, "Failed to prepare DMA memcpy\n");
                return -EIO;
@@ -375,7 +376,7 @@ static int omap2_onenand_read_bufferram(struct mtd_info *mtd, int area,
         * context fallback to PIO mode.
         */
        if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
-           count < 384 || in_interrupt() || oops_in_progress )
+           count < 384 || in_interrupt() || oops_in_progress)
                goto out_copy;
 
        xtra = count & 3;
@@ -422,7 +423,7 @@ static int omap2_onenand_write_bufferram(struct mtd_info *mtd, int area,
         * context fallback to PIO mode.
         */
        if (!virt_addr_valid(buf) || bram_offset & 3 || (size_t)buf & 3 ||
-           count < 384 || in_interrupt() || oops_in_progress )
+           count < 384 || in_interrupt() || oops_in_progress)
                goto out_copy;
 
        dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
@@ -528,7 +529,8 @@ static int omap2_onenand_probe(struct platform_device *pdev)
                 c->gpmc_cs, c->phys_base, c->onenand.base,
                 c->dma_chan ? "DMA" : "PIO");
 
-       if ((r = onenand_scan(&c->mtd, 1)) < 0)
+       r = onenand_scan(&c->mtd, 1);
+       if (r < 0)
                goto err_release_dma;
 
        freq = omap2_onenand_get_freq(c->onenand.version_id);
index 77bd32a..85640ee 100644 (file)
@@ -2853,7 +2853,7 @@ static int onenand_otp_write_oob_nolock(struct mtd_info *mtd, loff_t to,
 
                /* Exit OTP access mode */
                this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-               this->wait(mtd, FL_RESETING);
+               this->wait(mtd, FL_RESETTING);
 
                status = this->read_word(this->base + ONENAND_REG_CTRL_STATUS);
                status &= 0x60;
@@ -2924,7 +2924,7 @@ static int do_otp_read(struct mtd_info *mtd, loff_t from, size_t len,
 
        /* Exit OTP access mode */
        this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-       this->wait(mtd, FL_RESETING);
+       this->wait(mtd, FL_RESETTING);
 
        return ret;
 }
@@ -2968,7 +2968,7 @@ static int do_otp_write(struct mtd_info *mtd, loff_t to, size_t len,
 
        /* Exit OTP access mode */
        this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-       this->wait(mtd, FL_RESETING);
+       this->wait(mtd, FL_RESETTING);
 
        return ret;
 }
@@ -3008,7 +3008,7 @@ static int do_otp_lock(struct mtd_info *mtd, loff_t from, size_t len,
 
                /* Exit OTP access mode */
                this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-               this->wait(mtd, FL_RESETING);
+               this->wait(mtd, FL_RESETTING);
        } else {
                ops.mode = MTD_OPS_PLACE_OOB;
                ops.ooblen = len;
@@ -3413,7 +3413,7 @@ static int flexonenand_get_boundary(struct mtd_info *mtd)
                this->boundary[die] = bdry & FLEXONENAND_PI_MASK;
 
                this->command(mtd, ONENAND_CMD_RESET, 0, 0);
-               this->wait(mtd, FL_RESETING);
+               this->wait(mtd, FL_RESETTING);
 
                printk(KERN_INFO "Die %d boundary: %d%s\n", die,
                       this->boundary[die], locked ? "(Locked)" : "(Unlocked)");
@@ -3635,7 +3635,7 @@ static int flexonenand_set_boundary(struct mtd_info *mtd, int die,
        ret = this->wait(mtd, FL_WRITING);
 out:
        this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_REG_COMMAND);
-       this->wait(mtd, FL_RESETING);
+       this->wait(mtd, FL_RESETTING);
        if (!ret)
                /* Recalculate device size on boundary change*/
                flexonenand_get_size(mtd);
@@ -3671,7 +3671,7 @@ static int onenand_chip_probe(struct mtd_info *mtd)
        /* Reset OneNAND to read default register values */
        this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM);
        /* Wait reset */
-       this->wait(mtd, FL_RESETING);
+       this->wait(mtd, FL_RESETTING);
 
        /* Restore system configuration 1 */
        this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1);
index 55e5536..beb7987 100644 (file)
@@ -675,12 +675,12 @@ static int s5pc110_read_bufferram(struct mtd_info *mtd, int area,
 normal:
        if (count != mtd->writesize) {
                /* Copy the bufferram to memory to prevent unaligned access */
-               memcpy(this->page_buf, p, mtd->writesize);
-               p = this->page_buf + offset;
+               memcpy_fromio(this->page_buf, p, mtd->writesize);
+               memcpy(buffer, this->page_buf + offset, count);
+       } else {
+               memcpy_fromio(buffer, p, count);
        }
 
-       memcpy(buffer, p, count);
-
        return 0;
 }
 
index 3a36285..f6c7102 100644 (file)
@@ -914,8 +914,8 @@ static void cadence_nand_get_caps(struct cdns_nand_ctrl *cdns_ctrl)
 /* Prepare CDMA descriptor. */
 static void
 cadence_nand_cdma_desc_prepare(struct cdns_nand_ctrl *cdns_ctrl,
-                              char nf_mem, u32 flash_ptr, char *mem_ptr,
-                              char *ctrl_data_ptr, u16 ctype)
+                              char nf_mem, u32 flash_ptr, dma_addr_t mem_ptr,
+                                  dma_addr_t ctrl_data_ptr, u16 ctype)
 {
        struct cadence_nand_cdma_desc *cdma_desc = cdns_ctrl->cdma_desc;
 
@@ -931,13 +931,13 @@ cadence_nand_cdma_desc_prepare(struct cdns_nand_ctrl *cdns_ctrl,
        cdma_desc->command_flags |= CDMA_CF_DMA_MASTER;
        cdma_desc->command_flags  |= CDMA_CF_INT;
 
-       cdma_desc->memory_pointer = (uintptr_t)mem_ptr;
+       cdma_desc->memory_pointer = mem_ptr;
        cdma_desc->status = 0;
        cdma_desc->sync_flag_pointer = 0;
        cdma_desc->sync_arguments = 0;
 
        cdma_desc->command_type = ctype;
-       cdma_desc->ctrl_data_ptr = (uintptr_t)ctrl_data_ptr;
+       cdma_desc->ctrl_data_ptr = ctrl_data_ptr;
 }
 
 static u8 cadence_nand_check_desc_error(struct cdns_nand_ctrl *cdns_ctrl,
@@ -1280,8 +1280,7 @@ cadence_nand_cdma_transfer(struct cdns_nand_ctrl *cdns_ctrl, u8 chip_nr,
        }
 
        cadence_nand_cdma_desc_prepare(cdns_ctrl, chip_nr, page,
-                                      (void *)dma_buf, (void *)dma_ctrl_dat,
-                                      ctype);
+                                      dma_buf, dma_ctrl_dat, ctype);
 
        status = cadence_nand_cdma_send_and_wait(cdns_ctrl, thread_nr);
 
@@ -1360,7 +1359,7 @@ static int cadence_nand_erase(struct nand_chip *chip, u32 page)
 
        cadence_nand_cdma_desc_prepare(cdns_ctrl,
                                       cdns_chip->cs[chip->cur_cs],
-                                      page, NULL, NULL,
+                                      page, 0, 0,
                                       CDMA_CT_ERASE);
        status = cadence_nand_cdma_send_and_wait(cdns_ctrl, thread_nr);
        if (status) {
index 334fe31..b9d5d55 100644 (file)
@@ -148,6 +148,10 @@ static int gpmi_init(struct gpmi_nand_data *this)
        struct resources *r = &this->resources;
        int ret;
 
+       ret = pm_runtime_get_sync(this->dev);
+       if (ret < 0)
+               return ret;
+
        ret = gpmi_reset_block(r->gpmi_regs, false);
        if (ret)
                goto err_out;
@@ -179,8 +183,9 @@ static int gpmi_init(struct gpmi_nand_data *this)
         */
        writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
 
-       return 0;
 err_out:
+       pm_runtime_mark_last_busy(this->dev);
+       pm_runtime_put_autosuspend(this->dev);
        return ret;
 }
 
@@ -2722,6 +2727,10 @@ static int gpmi_pm_resume(struct device *dev)
                return ret;
        }
 
+       /* Set flag to get timing setup restored for next exec_op */
+       if (this->hw.clk_rate)
+               this->hw.must_apply_timings = true;
+
        /* re-init the BCH registers */
        ret = bch_set_geometry(this);
        if (ret) {
index 9e63800..3ba73f1 100644 (file)
@@ -37,6 +37,7 @@
 /* Max ECC buffer length */
 #define FMC2_MAX_ECC_BUF_LEN           (FMC2_BCHDSRS_LEN * FMC2_MAX_SG)
 
+#define FMC2_TIMEOUT_US                        1000
 #define FMC2_TIMEOUT_MS                        1000
 
 /* Timings */
@@ -53,6 +54,8 @@
 #define FMC2_PMEM                      0x88
 #define FMC2_PATT                      0x8c
 #define FMC2_HECCR                     0x94
+#define FMC2_ISR                       0x184
+#define FMC2_ICR                       0x188
 #define FMC2_CSQCR                     0x200
 #define FMC2_CSQCFGR1                  0x204
 #define FMC2_CSQCFGR2                  0x208
 #define FMC2_PATT_ATTHIZ(x)            (((x) & 0xff) << 24)
 #define FMC2_PATT_DEFAULT              0x0a0a0a0a
 
+/* Register: FMC2_ISR */
+#define FMC2_ISR_IHLF                  BIT(1)
+
+/* Register: FMC2_ICR */
+#define FMC2_ICR_CIHLF                 BIT(1)
+
 /* Register: FMC2_CSQCR */
 #define FMC2_CSQCR_CSQSTART            BIT(0)
 
@@ -1322,6 +1331,31 @@ static void stm32_fmc2_write_data(struct nand_chip *chip, const void *buf,
                stm32_fmc2_set_buswidth_16(fmc2, true);
 }
 
+static int stm32_fmc2_waitrdy(struct nand_chip *chip, unsigned long timeout_ms)
+{
+       struct stm32_fmc2_nfc *fmc2 = to_stm32_nfc(chip->controller);
+       const struct nand_sdr_timings *timings;
+       u32 isr, sr;
+
+       /* Check if there is no pending requests to the NAND flash */
+       if (readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_SR, sr,
+                                             sr & FMC2_SR_NWRF, 1,
+                                             FMC2_TIMEOUT_US))
+               dev_warn(fmc2->dev, "Waitrdy timeout\n");
+
+       /* Wait tWB before R/B# signal is low */
+       timings = nand_get_sdr_timings(&chip->data_interface);
+       ndelay(PSEC_TO_NSEC(timings->tWB_max));
+
+       /* R/B# signal is low, clear high level flag */
+       writel_relaxed(FMC2_ICR_CIHLF, fmc2->io_base + FMC2_ICR);
+
+       /* Wait R/B# signal is high */
+       return readl_relaxed_poll_timeout_atomic(fmc2->io_base + FMC2_ISR,
+                                                isr, isr & FMC2_ISR_IHLF,
+                                                5, 1000 * timeout_ms);
+}
+
 static int stm32_fmc2_exec_op(struct nand_chip *chip,
                              const struct nand_operation *op,
                              bool check_only)
@@ -1366,8 +1400,8 @@ static int stm32_fmc2_exec_op(struct nand_chip *chip,
                        break;
 
                case NAND_OP_WAITRDY_INSTR:
-                       ret = nand_soft_waitrdy(chip,
-                                               instr->ctx.waitrdy.timeout_ms);
+                       ret = stm32_fmc2_waitrdy(chip,
+                                                instr->ctx.waitrdy.timeout_ms);
                        break;
                }
        }
index 4744bf9..b9f2724 100644 (file)
@@ -247,7 +247,8 @@ static int sm_read_sector(struct sm_ftl *ftl,
 
        /* FTL can contain -1 entries that are by default filled with bits */
        if (block == -1) {
-               memset(buffer, 0xFF, SM_SECTOR_SIZE);
+               if (buffer)
+                       memset(buffer, 0xFF, SM_SECTOR_SIZE);
                return 0;
        }
 
index f4afe12..b0cd443 100644 (file)
@@ -2124,6 +2124,8 @@ static int spi_nor_sr2_bit1_quad_enable(struct spi_nor *nor)
        if (nor->bouncebuf[0] & SR2_QUAD_EN_BIT1)
                return 0;
 
+       nor->bouncebuf[0] |= SR2_QUAD_EN_BIT1;
+
        return spi_nor_write_16bit_cr_and_check(nor, nor->bouncebuf[0]);
 }
 
@@ -4596,6 +4598,7 @@ static void sst_set_default_init(struct spi_nor *nor)
 static void st_micron_set_default_init(struct spi_nor *nor)
 {
        nor->flags |= SNOR_F_HAS_LOCK;
+       nor->flags &= ~SNOR_F_HAS_16BIT_SR;
        nor->params.quad_enable = NULL;
        nor->params.set_4byte = st_micron_set_4byte;
 }
@@ -4768,9 +4771,7 @@ static void spi_nor_info_init_params(struct spi_nor *nor)
 
 static void spansion_post_sfdp_fixups(struct spi_nor *nor)
 {
-       struct mtd_info *mtd = &nor->mtd;
-
-       if (mtd->size <= SZ_16M)
+       if (nor->params.size <= SZ_16M)
                return;
 
        nor->flags |= SNOR_F_4B_OPCODES;
index fcb7c2f..48d5ec7 100644 (file)
@@ -2272,9 +2272,6 @@ static void bond_miimon_commit(struct bonding *bond)
                        } else if (BOND_MODE(bond) != BOND_MODE_ACTIVEBACKUP) {
                                /* make it immediately active */
                                bond_set_active_slave(slave);
-                       } else if (slave != primary) {
-                               /* prevent it from being the active one */
-                               bond_set_backup_slave(slave);
                        }
 
                        slave_info(bond->dev, slave->dev, "link status definitely up, %u Mbps %s duplex\n",
@@ -3702,32 +3699,35 @@ static int bond_neigh_init(struct neighbour *n)
        const struct net_device_ops *slave_ops;
        struct neigh_parms parms;
        struct slave *slave;
-       int ret;
+       int ret = 0;
 
-       slave = bond_first_slave(bond);
+       rcu_read_lock();
+       slave = bond_first_slave_rcu(bond);
        if (!slave)
-               return 0;
+               goto out;
        slave_ops = slave->dev->netdev_ops;
        if (!slave_ops->ndo_neigh_setup)
-               return 0;
-
-       parms.neigh_setup = NULL;
-       parms.neigh_cleanup = NULL;
-       ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
-       if (ret)
-               return ret;
+               goto out;
 
-       /* Assign slave's neigh_cleanup to neighbour in case cleanup is called
-        * after the last slave has been detached.  Assumes that all slaves
-        * utilize the same neigh_cleanup (true at this writing as only user
-        * is ipoib).
+       /* TODO: find another way [1] to implement this.
+        * Passing a zeroed structure is fragile,
+        * but at least we do not pass garbage.
+        *
+        * [1] One way would be that ndo_neigh_setup() never touch
+        *     struct neigh_parms, but propagate the new neigh_setup()
+        *     back to ___neigh_create() / neigh_parms_alloc()
         */
-       n->parms->neigh_cleanup = parms.neigh_cleanup;
+       memset(&parms, 0, sizeof(parms));
+       ret = slave_ops->ndo_neigh_setup(slave->dev, &parms);
 
-       if (!parms.neigh_setup)
-               return 0;
+       if (ret)
+               goto out;
 
-       return parms.neigh_setup(n);
+       if (parms.neigh_setup)
+               ret = parms.neigh_setup(n);
+out:
+       rcu_read_unlock();
+       return ret;
 }
 
 /* The bonding ndo_neigh_setup is called at init time beofre any
index a929cdd..94d10ec 100644 (file)
@@ -389,6 +389,34 @@ static struct flexcan_mb __iomem *flexcan_get_mb(const struct flexcan_priv *priv
                (&priv->regs->mb[bank][priv->mb_size * mb_index]);
 }
 
+static int flexcan_low_power_enter_ack(struct flexcan_priv *priv)
+{
+       struct flexcan_regs __iomem *regs = priv->regs;
+       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+       while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               udelay(10);
+
+       if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+static int flexcan_low_power_exit_ack(struct flexcan_priv *priv)
+{
+       struct flexcan_regs __iomem *regs = priv->regs;
+       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
+
+       while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
+               udelay(10);
+
+       if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
 static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
@@ -407,7 +435,6 @@ static void flexcan_enable_wakeup_irq(struct flexcan_priv *priv, bool enable)
 static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
-       unsigned int ackval;
        u32 reg_mcr;
 
        reg_mcr = priv->read(&regs->mcr);
@@ -418,36 +445,24 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
        regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
                           1 << priv->stm.req_bit, 1 << priv->stm.req_bit);
 
-       /* get stop acknowledgment */
-       if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
-                                    ackval, ackval & (1 << priv->stm.ack_bit),
-                                    0, FLEXCAN_TIMEOUT_US))
-               return -ETIMEDOUT;
-
-       return 0;
+       return flexcan_low_power_enter_ack(priv);
 }
 
 static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
-       unsigned int ackval;
        u32 reg_mcr;
 
        /* remove stop request */
        regmap_update_bits(priv->stm.gpr, priv->stm.req_gpr,
                           1 << priv->stm.req_bit, 0);
 
-       /* get stop acknowledgment */
-       if (regmap_read_poll_timeout(priv->stm.gpr, priv->stm.ack_gpr,
-                                    ackval, !(ackval & (1 << priv->stm.ack_bit)),
-                                    0, FLEXCAN_TIMEOUT_US))
-               return -ETIMEDOUT;
 
        reg_mcr = priv->read(&regs->mcr);
        reg_mcr &= ~FLEXCAN_MCR_SLF_WAK;
        priv->write(reg_mcr, &regs->mcr);
 
-       return 0;
+       return flexcan_low_power_exit_ack(priv);
 }
 
 static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv)
@@ -506,39 +521,25 @@ static inline int flexcan_transceiver_disable(const struct flexcan_priv *priv)
 static int flexcan_chip_enable(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
-       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
        u32 reg;
 
        reg = priv->read(&regs->mcr);
        reg &= ~FLEXCAN_MCR_MDIS;
        priv->write(reg, &regs->mcr);
 
-       while (timeout-- && (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               udelay(10);
-
-       if (priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK)
-               return -ETIMEDOUT;
-
-       return 0;
+       return flexcan_low_power_exit_ack(priv);
 }
 
 static int flexcan_chip_disable(struct flexcan_priv *priv)
 {
        struct flexcan_regs __iomem *regs = priv->regs;
-       unsigned int timeout = FLEXCAN_TIMEOUT_US / 10;
        u32 reg;
 
        reg = priv->read(&regs->mcr);
        reg |= FLEXCAN_MCR_MDIS;
        priv->write(reg, &regs->mcr);
 
-       while (timeout-- && !(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               udelay(10);
-
-       if (!(priv->read(&regs->mcr) & FLEXCAN_MCR_LPM_ACK))
-               return -ETIMEDOUT;
-
-       return 0;
+       return flexcan_low_power_enter_ack(priv);
 }
 
 static int flexcan_chip_freeze(struct flexcan_priv *priv)
@@ -1722,6 +1723,9 @@ static int __maybe_unused flexcan_resume(struct device *device)
                netif_start_queue(dev);
                if (device_may_wakeup(device)) {
                        disable_irq_wake(dev->irq);
+                       err = flexcan_exit_stop_mode(priv);
+                       if (err)
+                               return err;
                } else {
                        err = pm_runtime_force_resume(device);
                        if (err)
@@ -1767,14 +1771,9 @@ static int __maybe_unused flexcan_noirq_resume(struct device *device)
 {
        struct net_device *dev = dev_get_drvdata(device);
        struct flexcan_priv *priv = netdev_priv(dev);
-       int err;
 
-       if (netif_running(dev) && device_may_wakeup(device)) {
+       if (netif_running(dev) && device_may_wakeup(device))
                flexcan_enable_wakeup_irq(priv, false);
-               err = flexcan_exit_stop_mode(priv);
-               if (err)
-                       return err;
-       }
 
        return 0;
 }
index 3db6192..eacd428 100644 (file)
 #define TCAN4X5X_MODE_STANDBY BIT(6)
 #define TCAN4X5X_MODE_NORMAL BIT(7)
 
+#define TCAN4X5X_DISABLE_WAKE_MSK      (BIT(31) | BIT(30))
+#define TCAN4X5X_DISABLE_INH_MSK       BIT(9)
+
 #define TCAN4X5X_SW_RESET BIT(2)
 
 #define TCAN4X5X_MCAN_CONFIGURED BIT(5)
@@ -164,6 +167,28 @@ static void tcan4x5x_check_wake(struct tcan4x5x_priv *priv)
        }
 }
 
+static int tcan4x5x_reset(struct tcan4x5x_priv *priv)
+{
+       int ret = 0;
+
+       if (priv->reset_gpio) {
+               gpiod_set_value(priv->reset_gpio, 1);
+
+               /* tpulse_width minimum 30us */
+               usleep_range(30, 100);
+               gpiod_set_value(priv->reset_gpio, 0);
+       } else {
+               ret = regmap_write(priv->regmap, TCAN4X5X_CONFIG,
+                                  TCAN4X5X_SW_RESET);
+               if (ret)
+                       return ret;
+       }
+
+       usleep_range(700, 1000);
+
+       return ret;
+}
+
 static int regmap_spi_gather_write(void *context, const void *reg,
                                   size_t reg_len, const void *val,
                                   size_t val_len)
@@ -338,15 +363,34 @@ static int tcan4x5x_init(struct m_can_classdev *cdev)
        return ret;
 }
 
+static int tcan4x5x_disable_wake(struct m_can_classdev *cdev)
+{
+       struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
+
+       return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
+                                 TCAN4X5X_DISABLE_WAKE_MSK, 0x00);
+}
+
+static int tcan4x5x_disable_state(struct m_can_classdev *cdev)
+{
+       struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
+
+       return regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
+                                 TCAN4X5X_DISABLE_INH_MSK, 0x01);
+}
+
 static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
 {
        struct tcan4x5x_priv *tcan4x5x = cdev->device_data;
+       int ret;
 
        tcan4x5x->device_wake_gpio = devm_gpiod_get(cdev->dev, "device-wake",
                                                    GPIOD_OUT_HIGH);
        if (IS_ERR(tcan4x5x->device_wake_gpio)) {
-               dev_err(cdev->dev, "device-wake gpio not defined\n");
-               return -EINVAL;
+               if (PTR_ERR(tcan4x5x->device_wake_gpio) == -EPROBE_DEFER)
+                       return -EPROBE_DEFER;
+
+               tcan4x5x_disable_wake(cdev);
        }
 
        tcan4x5x->reset_gpio = devm_gpiod_get_optional(cdev->dev, "reset",
@@ -354,16 +398,17 @@ static int tcan4x5x_parse_config(struct m_can_classdev *cdev)
        if (IS_ERR(tcan4x5x->reset_gpio))
                tcan4x5x->reset_gpio = NULL;
 
+       ret = tcan4x5x_reset(tcan4x5x);
+       if (ret)
+               return ret;
+
        tcan4x5x->device_state_gpio = devm_gpiod_get_optional(cdev->dev,
                                                              "device-state",
                                                              GPIOD_IN);
-       if (IS_ERR(tcan4x5x->device_state_gpio))
+       if (IS_ERR(tcan4x5x->device_state_gpio)) {
                tcan4x5x->device_state_gpio = NULL;
-
-       tcan4x5x->power = devm_regulator_get_optional(cdev->dev,
-                                                     "vsup");
-       if (PTR_ERR(tcan4x5x->power) == -EPROBE_DEFER)
-               return -EPROBE_DEFER;
+               tcan4x5x_disable_state(cdev);
+       }
 
        return 0;
 }
@@ -398,6 +443,12 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
        if (!priv)
                return -ENOMEM;
 
+       priv->power = devm_regulator_get_optional(&spi->dev, "vsup");
+       if (PTR_ERR(priv->power) == -EPROBE_DEFER)
+               return -EPROBE_DEFER;
+       else
+               priv->power = NULL;
+
        mcan_class->device_data = priv;
 
        m_can_class_get_clocks(mcan_class);
@@ -428,10 +479,6 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
 
        spi_set_drvdata(spi, priv);
 
-       ret = tcan4x5x_parse_config(mcan_class);
-       if (ret)
-               goto out_clk;
-
        /* Configure the SPI bus */
        spi->bits_per_word = 32;
        ret = spi_setup(spi);
@@ -441,7 +488,17 @@ static int tcan4x5x_can_probe(struct spi_device *spi)
        priv->regmap = devm_regmap_init(&spi->dev, &tcan4x5x_bus,
                                        &spi->dev, &tcan4x5x_regmap);
 
-       tcan4x5x_power_enable(priv->power, 1);
+       ret = tcan4x5x_power_enable(priv->power, 1);
+       if (ret)
+               goto out_clk;
+
+       ret = tcan4x5x_parse_config(mcan_class);
+       if (ret)
+               goto out_power;
+
+       ret = tcan4x5x_init(mcan_class);
+       if (ret)
+               goto out_power;
 
        ret = m_can_class_register(mcan_class);
        if (ret)
index 8caf7af..99101d7 100644 (file)
@@ -381,13 +381,12 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
        struct net_device *dev = napi->dev;
        struct mscan_regs __iomem *regs = priv->reg_base;
        struct net_device_stats *stats = &dev->stats;
-       int npackets = 0;
-       int ret = 1;
+       int work_done = 0;
        struct sk_buff *skb;
        struct can_frame *frame;
        u8 canrflg;
 
-       while (npackets < quota) {
+       while (work_done < quota) {
                canrflg = in_8(&regs->canrflg);
                if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF)))
                        break;
@@ -408,18 +407,18 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota)
 
                stats->rx_packets++;
                stats->rx_bytes += frame->can_dlc;
-               npackets++;
+               work_done++;
                netif_receive_skb(skb);
        }
 
-       if (!(in_8(&regs->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) {
-               napi_complete(&priv->napi);
-               clear_bit(F_RX_PROGRESS, &priv->flags);
-               if (priv->can.state < CAN_STATE_BUS_OFF)
-                       out_8(&regs->canrier, priv->shadow_canrier);
-               ret = 0;
+       if (work_done < quota) {
+               if (likely(napi_complete_done(&priv->napi, work_done))) {
+                       clear_bit(F_RX_PROGRESS, &priv->flags);
+                       if (priv->can.state < CAN_STATE_BUS_OFF)
+                               out_8(&regs->canrier, priv->shadow_canrier);
+               }
        }
-       return ret;
+       return work_done;
 }
 
 static irqreturn_t mscan_isr(int irq, void *dev_id)
index 2f74f67..a4b4b74 100644 (file)
@@ -918,7 +918,7 @@ static int gs_usb_probe(struct usb_interface *intf,
                             GS_USB_BREQ_HOST_FORMAT,
                             USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
                             1,
-                            intf->altsetting[0].desc.bInterfaceNumber,
+                            intf->cur_altsetting->desc.bInterfaceNumber,
                             hconf,
                             sizeof(*hconf),
                             1000);
@@ -941,7 +941,7 @@ static int gs_usb_probe(struct usb_interface *intf,
                             GS_USB_BREQ_DEVICE_CONFIG,
                             USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
                             1,
-                            intf->altsetting[0].desc.bInterfaceNumber,
+                            intf->cur_altsetting->desc.bInterfaceNumber,
                             dconf,
                             sizeof(*dconf),
                             1000);
index 5fc0be5..7ab87a7 100644 (file)
@@ -1590,7 +1590,7 @@ static int kvaser_usb_hydra_setup_endpoints(struct kvaser_usb *dev)
        struct usb_endpoint_descriptor *ep;
        int i;
 
-       iface_desc = &dev->intf->altsetting[0];
+       iface_desc = dev->intf->cur_altsetting;
 
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                ep = &iface_desc->endpoint[i].desc;
index 07d2f3a..1b9957f 100644 (file)
@@ -608,7 +608,7 @@ static int kvaser_usb_leaf_simple_cmd_async(struct kvaser_usb_net_priv *priv,
        struct kvaser_cmd *cmd;
        int err;
 
-       cmd = kmalloc(sizeof(*cmd), GFP_ATOMIC);
+       cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
        if (!cmd)
                return -ENOMEM;
 
@@ -1140,7 +1140,7 @@ static int kvaser_usb_leaf_set_opt_mode(const struct kvaser_usb_net_priv *priv)
        struct kvaser_cmd *cmd;
        int rc;
 
-       cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
        if (!cmd)
                return -ENOMEM;
 
@@ -1206,7 +1206,7 @@ static int kvaser_usb_leaf_flush_queue(struct kvaser_usb_net_priv *priv)
        struct kvaser_cmd *cmd;
        int rc;
 
-       cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
+       cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
        if (!cmd)
                return -ENOMEM;
 
@@ -1310,7 +1310,7 @@ static int kvaser_usb_leaf_setup_endpoints(struct kvaser_usb *dev)
        struct usb_endpoint_descriptor *endpoint;
        int i;
 
-       iface_desc = &dev->intf->altsetting[0];
+       iface_desc = dev->intf->cur_altsetting;
 
        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
                endpoint = &iface_desc->endpoint[i].desc;
index 464af93..c1dbab8 100644 (file)
@@ -60,6 +60,8 @@ enum xcan_reg {
        XCAN_TXMSG_BASE_OFFSET  = 0x0100, /* TX Message Space */
        XCAN_RXMSG_BASE_OFFSET  = 0x1100, /* RX Message Space */
        XCAN_RXMSG_2_BASE_OFFSET        = 0x2100, /* RX Message Space */
+       XCAN_AFR_2_MASK_OFFSET  = 0x0A00, /* Acceptance Filter MASK */
+       XCAN_AFR_2_ID_OFFSET    = 0x0A04, /* Acceptance Filter ID */
 };
 
 #define XCAN_FRAME_ID_OFFSET(frame_base)       ((frame_base) + 0x00)
@@ -1809,6 +1811,11 @@ static int xcan_probe(struct platform_device *pdev)
 
        pm_runtime_put(&pdev->dev);
 
+       if (priv->devtype.flags & XCAN_FLAG_CANFD_2) {
+               priv->write_reg(priv, XCAN_AFR_2_ID_OFFSET, 0x00000000);
+               priv->write_reg(priv, XCAN_AFR_2_MASK_OFFSET, 0x00000000);
+       }
+
        netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx buffers: actual %d, using %d\n",
                   priv->reg_base, ndev->irq, priv->can.clock.freq,
                   hw_tx_max, priv->tx_max);
index 36828f2..edacacf 100644 (file)
@@ -347,7 +347,7 @@ static void b53_set_forwarding(struct b53_device *dev, int enable)
         * frames should be flooded or not.
         */
        b53_read8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, &mgmt);
-       mgmt |= B53_UC_FWD_EN | B53_MC_FWD_EN;
+       mgmt |= B53_UC_FWD_EN | B53_MC_FWD_EN | B53_IPMC_FWD_EN;
        b53_write8(dev, B53_CTRL_PAGE, B53_IP_MULTICAST_CTRL, mgmt);
 }
 
@@ -526,6 +526,8 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy)
 
        cpu_port = dsa_to_port(ds, port)->cpu_dp->index;
 
+       b53_br_egress_floods(ds, port, true, true);
+
        if (dev->ops->irq_enable)
                ret = dev->ops->irq_enable(dev, port);
        if (ret)
@@ -641,6 +643,8 @@ static void b53_enable_cpu_port(struct b53_device *dev, int port)
        b53_write8(dev, B53_CTRL_PAGE, B53_PORT_CTRL(port), port_ctrl);
 
        b53_brcm_hdr_setup(dev->ds, port);
+
+       b53_br_egress_floods(dev->ds, port, true, true);
 }
 
 static void b53_enable_mib(struct b53_device *dev)
@@ -1821,19 +1825,26 @@ int b53_br_egress_floods(struct dsa_switch *ds, int port,
        struct b53_device *dev = ds->priv;
        u16 uc, mc;
 
-       b53_read16(dev, B53_CTRL_PAGE, B53_UC_FWD_EN, &uc);
+       b53_read16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, &uc);
        if (unicast)
                uc |= BIT(port);
        else
                uc &= ~BIT(port);
-       b53_write16(dev, B53_CTRL_PAGE, B53_UC_FWD_EN, uc);
+       b53_write16(dev, B53_CTRL_PAGE, B53_UC_FLOOD_MASK, uc);
+
+       b53_read16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, &mc);
+       if (multicast)
+               mc |= BIT(port);
+       else
+               mc &= ~BIT(port);
+       b53_write16(dev, B53_CTRL_PAGE, B53_MC_FLOOD_MASK, mc);
 
-       b53_read16(dev, B53_CTRL_PAGE, B53_MC_FWD_EN, &mc);
+       b53_read16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, &mc);
        if (multicast)
                mc |= BIT(port);
        else
                mc &= ~BIT(port);
-       b53_write16(dev, B53_CTRL_PAGE, B53_MC_FWD_EN, mc);
+       b53_write16(dev, B53_CTRL_PAGE, B53_IPMC_FLOOD_MASK, mc);
 
        return 0;
 
index e43040c..3e86353 100644 (file)
@@ -68,7 +68,7 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
 
                /* Force link status for IMP port */
                reg = core_readl(priv, offset);
-               reg |= (MII_SW_OR | LINK_STS);
+               reg |= (MII_SW_OR | LINK_STS | GMII_SPEED_UP_2G);
                core_writel(priv, reg, offset);
 
                /* Enable Broadcast, Multicast, Unicast forwarding to IMP port */
index f3f0c3f..1962c83 100644 (file)
@@ -358,7 +358,7 @@ static int bcm_sf2_cfp_ipv4_rule_set(struct bcm_sf2_priv *priv, int port,
                return -EINVAL;
        }
 
-       ip_frag = be32_to_cpu(fs->m_ext.data[0]);
+       ip_frag = !!(be32_to_cpu(fs->h_ext.data[0]) & 1);
 
        /* Locate the first rule available */
        if (fs->location == RX_CLS_LOC_ANY)
@@ -569,7 +569,7 @@ static int bcm_sf2_cfp_rule_cmp(struct bcm_sf2_priv *priv, int port,
 
                if (rule->fs.flow_type != fs->flow_type ||
                    rule->fs.ring_cookie != fs->ring_cookie ||
-                   rule->fs.m_ext.data[0] != fs->m_ext.data[0])
+                   rule->fs.h_ext.data[0] != fs->h_ext.data[0])
                        continue;
 
                switch (fs->flow_type & ~FLOW_EXT) {
@@ -621,7 +621,7 @@ static int bcm_sf2_cfp_ipv6_rule_set(struct bcm_sf2_priv *priv, int port,
                return -EINVAL;
        }
 
-       ip_frag = be32_to_cpu(fs->m_ext.data[0]);
+       ip_frag = !!(be32_to_cpu(fs->h_ext.data[0]) & 1);
 
        layout = &udf_tcpip6_layout;
        slice_num = bcm_sf2_get_slice_number(layout, 0);
index 120a65d..b016cc2 100644 (file)
@@ -360,6 +360,11 @@ int mv88e6390_g1_set_cpu_port(struct mv88e6xxx_chip *chip, int port)
 {
        u16 ptr = MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST;
 
+       /* Use the default high priority for management frames sent to
+        * the CPU.
+        */
+       port |= MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI;
+
        return mv88e6390_g1_monitor_write(chip, ptr, port);
 }
 
index bc5a6b2..5324c6f 100644 (file)
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_INGRESS_DEST         0x2000
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_EGRESS_DEST          0x2100
 #define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST             0x3000
+#define MV88E6390_G1_MONITOR_MGMT_CTL_PTR_CPU_DEST_MGMTPRI     0x00e0
 #define MV88E6390_G1_MONITOR_MGMT_CTL_DATA_MASK                        0x00ff
 
 /* Offset 0x1C: Global Control 2 */
index 7fe256c..0b43c65 100644 (file)
@@ -393,7 +393,7 @@ phy_interface_t mv88e6390x_port_max_speed_mode(int port)
 }
 
 static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
-                                   phy_interface_t mode)
+                                   phy_interface_t mode, bool force)
 {
        u8 lane;
        u16 cmode;
@@ -427,8 +427,8 @@ static int mv88e6xxx_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
                cmode = 0;
        }
 
-       /* cmode doesn't change, nothing to do for us */
-       if (cmode == chip->ports[port].cmode)
+       /* cmode doesn't change, nothing to do for us unless forced */
+       if (cmode == chip->ports[port].cmode && !force)
                return 0;
 
        lane = mv88e6xxx_serdes_get_lane(chip, port);
@@ -484,7 +484,7 @@ int mv88e6390x_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
        if (port != 9 && port != 10)
                return -EOPNOTSUPP;
 
-       return mv88e6xxx_port_set_cmode(chip, port, mode);
+       return mv88e6xxx_port_set_cmode(chip, port, mode, false);
 }
 
 int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
@@ -504,7 +504,7 @@ int mv88e6390_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
                break;
        }
 
-       return mv88e6xxx_port_set_cmode(chip, port, mode);
+       return mv88e6xxx_port_set_cmode(chip, port, mode, false);
 }
 
 static int mv88e6341_port_set_cmode_writable(struct mv88e6xxx_chip *chip,
@@ -555,7 +555,7 @@ int mv88e6341_port_set_cmode(struct mv88e6xxx_chip *chip, int port,
        if (err)
                return err;
 
-       return mv88e6xxx_port_set_cmode(chip, port, mode);
+       return mv88e6xxx_port_set_cmode(chip, port, mode, true);
 }
 
 int mv88e6185_port_get_cmode(struct mv88e6xxx_chip *chip, int port, u8 *cmode)
index 0031ca8..6f98040 100644 (file)
@@ -2,6 +2,7 @@
 config NET_DSA_MSCC_FELIX
        tristate "Ocelot / Felix Ethernet switch support"
        depends on NET_DSA && PCI
+       depends on NET_VENDOR_MICROSEMI
        select MSCC_OCELOT_SWITCH
        select NET_DSA_TAG_OCELOT
        help
index a51ac08..bb91f3d 100644 (file)
@@ -582,7 +582,7 @@ static int sja1105_parse_ports_node(struct sja1105_private *priv,
        struct device *dev = &priv->spidev->dev;
        struct device_node *child;
 
-       for_each_child_of_node(ports_node, child) {
+       for_each_available_child_of_node(ports_node, child) {
                struct device_node *phy_node;
                phy_interface_t phy_mode;
                u32 index;
@@ -1569,8 +1569,8 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
 
        if (enabled) {
                /* Enable VLAN filtering. */
-               tpid  = ETH_P_8021AD;
-               tpid2 = ETH_P_8021Q;
+               tpid  = ETH_P_8021Q;
+               tpid2 = ETH_P_8021AD;
        } else {
                /* Disable VLAN filtering. */
                tpid  = ETH_P_SJA1105;
@@ -1579,9 +1579,9 @@ static int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled)
 
        table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
        general_params = table->entries;
-       /* EtherType used to identify outer tagged (S-tag) VLAN traffic */
-       general_params->tpid = tpid;
        /* EtherType used to identify inner tagged (C-tag) VLAN traffic */
+       general_params->tpid = tpid;
+       /* EtherType used to identify outer tagged (S-tag) VLAN traffic */
        general_params->tpid2 = tpid2;
        /* When VLAN filtering is on, we need to at least be able to
         * decode management traffic through the "backup plan".
@@ -1855,7 +1855,7 @@ static netdev_tx_t sja1105_port_deferred_xmit(struct dsa_switch *ds, int port,
        if (!clone)
                goto out;
 
-       sja1105_ptp_txtstamp_skb(ds, slot, clone);
+       sja1105_ptp_txtstamp_skb(ds, port, clone);
 
 out:
        mutex_unlock(&priv->mgmt_lock);
index 54258a2..43ab758 100644 (file)
@@ -234,7 +234,7 @@ int sja1105_ptp_commit(struct dsa_switch *ds, struct sja1105_ptp_cmd *cmd,
        if (rw == SPI_WRITE)
                priv->info->ptp_cmd_packing(buf, cmd, PACK);
 
-       rc = sja1105_xfer_buf(priv, SPI_WRITE, regs->ptp_control, buf,
+       rc = sja1105_xfer_buf(priv, rw, regs->ptp_control, buf,
                              SJA1105_SIZE_PTP_CMD);
 
        if (rw == SPI_READ)
@@ -659,7 +659,7 @@ void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
        ptp_data->clock = NULL;
 }
 
-void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
+void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int port,
                              struct sk_buff *skb)
 {
        struct sja1105_private *priv = ds->priv;
@@ -679,7 +679,7 @@ void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
                goto out;
        }
 
-       rc = sja1105_ptpegr_ts_poll(ds, slot, &ts);
+       rc = sja1105_ptpegr_ts_poll(ds, port, &ts);
        if (rc < 0) {
                dev_err(ds->dev, "timed out polling for tstamp\n");
                kfree_skb(skb);
index 0d03e13..63d2311 100644 (file)
@@ -142,6 +142,9 @@ static size_t sja1105et_general_params_entry_packing(void *buf, void *entry_ptr,
        return size;
 }
 
+/* TPID and TPID2 are intentionally reversed so that semantic
+ * compatibility with E/T is kept.
+ */
 static size_t
 sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
                                         enum packing_op op)
@@ -166,9 +169,9 @@ sja1105pqrs_general_params_entry_packing(void *buf, void *entry_ptr,
        sja1105_packing(buf, &entry->mirr_port,   141, 139, size, op);
        sja1105_packing(buf, &entry->vlmarker,    138, 107, size, op);
        sja1105_packing(buf, &entry->vlmask,      106,  75, size, op);
-       sja1105_packing(buf, &entry->tpid        74,  59, size, op);
+       sja1105_packing(buf, &entry->tpid2,        74,  59, size, op);
        sja1105_packing(buf, &entry->ignore2stf,   58,  58, size, op);
-       sja1105_packing(buf, &entry->tpid2,        57,  42, size, op);
+       sja1105_packing(buf, &entry->tpid        57,  42, size, op);
        sja1105_packing(buf, &entry->queue_ts,     41,  41, size, op);
        sja1105_packing(buf, &entry->egrmirrvid,   40,  29, size, op);
        sja1105_packing(buf, &entry->egrmirrpcp,   28,  26, size, op);
index 26b925b..fa6750d 100644 (file)
@@ -477,11 +477,6 @@ int sja1105_setup_tc_taprio(struct dsa_switch *ds, int port,
        if (admin->cycle_time_extension)
                return -ENOTSUPP;
 
-       if (!ns_to_sja1105_delta(admin->base_time)) {
-               dev_err(ds->dev, "A base time of zero is not hardware-allowed\n");
-               return -ERANGE;
-       }
-
        for (i = 0; i < admin->num_entries; i++) {
                s64 delta_ns = admin->entries[i].interval;
                s64 delta_cycles = ns_to_sja1105_delta(delta_ns);
index 7c941eb..0ce37d5 100644 (file)
@@ -72,7 +72,7 @@
 /*****************************************************************************/
 /* ENA adaptive interrupt moderation settings */
 
-#define ENA_INTR_INITIAL_TX_INTERVAL_USECS             196
+#define ENA_INTR_INITIAL_TX_INTERVAL_USECS             64
 #define ENA_INTR_INITIAL_RX_INTERVAL_USECS             0
 #define ENA_DEFAULT_INTR_DELAY_RESOLUTION              1
 
index a3250dc..fc96c66 100644 (file)
@@ -315,10 +315,9 @@ static int ena_get_coalesce(struct net_device *net_dev,
                ena_com_get_nonadaptive_moderation_interval_tx(ena_dev) *
                        ena_dev->intr_delay_resolution;
 
-       if (!ena_com_get_adaptive_moderation_enabled(ena_dev))
-               coalesce->rx_coalesce_usecs =
-                       ena_com_get_nonadaptive_moderation_interval_rx(ena_dev)
-                       * ena_dev->intr_delay_resolution;
+       coalesce->rx_coalesce_usecs =
+               ena_com_get_nonadaptive_moderation_interval_rx(ena_dev)
+               * ena_dev->intr_delay_resolution;
 
        coalesce->use_adaptive_rx_coalesce =
                ena_com_get_adaptive_moderation_enabled(ena_dev);
@@ -367,12 +366,6 @@ static int ena_set_coalesce(struct net_device *net_dev,
 
        ena_update_tx_rings_intr_moderation(adapter);
 
-       if (coalesce->use_adaptive_rx_coalesce) {
-               if (!ena_com_get_adaptive_moderation_enabled(ena_dev))
-                       ena_com_enable_adaptive_moderation(ena_dev);
-               return 0;
-       }
-
        rc = ena_com_update_nonadaptive_moderation_interval_rx(ena_dev,
                                                               coalesce->rx_coalesce_usecs);
        if (rc)
@@ -380,10 +373,13 @@ static int ena_set_coalesce(struct net_device *net_dev,
 
        ena_update_rx_rings_intr_moderation(adapter);
 
-       if (!coalesce->use_adaptive_rx_coalesce) {
-               if (ena_com_get_adaptive_moderation_enabled(ena_dev))
-                       ena_com_disable_adaptive_moderation(ena_dev);
-       }
+       if (coalesce->use_adaptive_rx_coalesce &&
+           !ena_com_get_adaptive_moderation_enabled(ena_dev))
+               ena_com_enable_adaptive_moderation(ena_dev);
+
+       if (!coalesce->use_adaptive_rx_coalesce &&
+           ena_com_get_adaptive_moderation_enabled(ena_dev))
+               ena_com_disable_adaptive_moderation(ena_dev);
 
        return 0;
 }
index d46a912..948583f 100644 (file)
@@ -1238,8 +1238,8 @@ static int ena_io_poll(struct napi_struct *napi, int budget)
        struct ena_napi *ena_napi = container_of(napi, struct ena_napi, napi);
        struct ena_ring *tx_ring, *rx_ring;
 
-       u32 tx_work_done;
-       u32 rx_work_done;
+       int tx_work_done;
+       int rx_work_done = 0;
        int tx_budget;
        int napi_comp_call = 0;
        int ret;
@@ -1256,7 +1256,11 @@ static int ena_io_poll(struct napi_struct *napi, int budget)
        }
 
        tx_work_done = ena_clean_tx_irq(tx_ring, tx_budget);
-       rx_work_done = ena_clean_rx_irq(rx_ring, napi, budget);
+       /* On netpoll the budget is zero and the handler should only clean the
+        * tx completions.
+        */
+       if (likely(budget))
+               rx_work_done = ena_clean_rx_irq(rx_ring, napi, budget);
 
        /* If the device is about to reset or down, avoid unmask
         * the interrupt and return 0 so NAPI won't reschedule
index a880f10..8083173 100644 (file)
@@ -129,13 +129,13 @@ struct xgbe_stats {
 
 #define XGMAC_MMC_STAT(_string, _var)                          \
        { _string,                                              \
-         FIELD_SIZEOF(struct xgbe_mmc_stats, _var),            \
+         sizeof_field(struct xgbe_mmc_stats, _var),            \
          offsetof(struct xgbe_prv_data, mmc_stats._var),       \
        }
 
 #define XGMAC_EXT_STAT(_string, _var)                          \
        { _string,                                              \
-         FIELD_SIZEOF(struct xgbe_ext_stats, _var),            \
+         sizeof_field(struct xgbe_ext_stats, _var),            \
          offsetof(struct xgbe_prv_data, ext_stats._var),       \
        }
 
index a17a4da..c85e3e2 100644 (file)
@@ -403,6 +403,8 @@ int aq_nic_start(struct aq_nic_s *self)
        if (err < 0)
                goto err_exit;
 
+       aq_nic_set_loopback(self);
+
        err = self->aq_hw_ops->hw_start(self->aq_hw);
        if (err < 0)
                goto err_exit;
@@ -413,8 +415,6 @@ int aq_nic_start(struct aq_nic_s *self)
 
        INIT_WORK(&self->service_task, aq_nic_service_task);
 
-       aq_nic_set_loopback(self);
-
        timer_setup(&self->service_timer, aq_nic_service_timer_cb, 0);
        aq_nic_service_timer_cb(&self->service_timer);
 
index 58e891a..ec041f7 100644 (file)
@@ -1525,9 +1525,6 @@ const struct aq_hw_ops hw_atl_ops_b0 = {
        .rx_extract_ts           = hw_atl_b0_rx_extract_ts,
        .extract_hwts            = hw_atl_b0_extract_hwts,
        .hw_set_offload          = hw_atl_b0_hw_offload_set,
-       .hw_get_hw_stats         = hw_atl_utils_get_hw_stats,
-       .hw_get_fw_version       = hw_atl_utils_get_fw_version,
-       .hw_set_offload          = hw_atl_b0_hw_offload_set,
        .hw_set_loopback         = hw_atl_b0_set_loopback,
        .hw_set_fc               = hw_atl_b0_set_fc,
 };
index 8910b62..f547baa 100644 (file)
@@ -667,9 +667,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self)
        u32 speed;
 
        mpi_state = hw_atl_utils_mpi_get_state(self);
-       speed = mpi_state & (FW2X_RATE_100M | FW2X_RATE_1G |
-                            FW2X_RATE_2G5 | FW2X_RATE_5G |
-                            FW2X_RATE_10G);
+       speed = mpi_state >> HW_ATL_MPI_SPEED_SHIFT;
 
        if (!speed) {
                link_status->mbps = 0U;
index 8f50210..61a334d 100644 (file)
@@ -313,7 +313,7 @@ struct ag71xx {
        struct ag71xx_desc *stop_desc;
        dma_addr_t stop_desc_dma;
 
-       int phy_if_mode;
+       phy_interface_t phy_if_mode;
 
        struct delayed_work restart_work;
        struct timer_list oom_timer;
@@ -1744,7 +1744,7 @@ static int ag71xx_probe(struct platform_device *pdev)
                eth_random_addr(ndev->dev_addr);
        }
 
-       err = of_get_phy_mode(np, ag->phy_if_mode);
+       err = of_get_phy_mode(np, &ag->phy_if_mode);
        if (err) {
                netif_err(ag, probe, ndev, "missing phy-mode property in DT\n");
                goto err_free;
index 035dbb1..ec25fd8 100644 (file)
@@ -1516,8 +1516,10 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
        int ethaddr_bytes = ETH_ALEN;
 
        memset(ppattern + offset, 0xff, magicsync);
-       for (j = 0; j < magicsync; j++)
-               set_bit(len++, (unsigned long *) pmask);
+       for (j = 0; j < magicsync; j++) {
+               pmask[len >> 3] |= BIT(len & 7);
+               len++;
+       }
 
        for (j = 0; j < B44_MAX_PATTERNS; j++) {
                if ((B44_PATTERN_SIZE - len) >= ETH_ALEN)
@@ -1529,7 +1531,8 @@ static int b44_magic_pattern(u8 *macaddr, u8 *ppattern, u8 *pmask, int offset)
                for (k = 0; k< ethaddr_bytes; k++) {
                        ppattern[offset + magicsync +
                                (j * ETH_ALEN) + k] = macaddr[k];
-                       set_bit(len++, (unsigned long *) pmask);
+                       pmask[len >> 3] |= BIT(len & 7);
+                       len++;
                }
        }
        return len - 1;
index 825af70..d6b1a15 100644 (file)
@@ -2323,7 +2323,7 @@ static int bcm_sysport_map_queues(struct notifier_block *nb,
                ring->switch_queue = qp;
                ring->switch_port = port;
                ring->inspect = true;
-               priv->ring_map[q + port * num_tx_queues] = ring;
+               priv->ring_map[qp + port * num_tx_queues] = ring;
                qp++;
        }
 
@@ -2338,7 +2338,7 @@ static int bcm_sysport_unmap_queues(struct notifier_block *nb,
        struct net_device *slave_dev;
        unsigned int num_tx_queues;
        struct net_device *dev;
-       unsigned int q, port;
+       unsigned int q, qp, port;
 
        priv = container_of(nb, struct bcm_sysport_priv, dsa_notifier);
        if (priv->netdev != info->master)
@@ -2364,7 +2364,8 @@ static int bcm_sysport_unmap_queues(struct notifier_block *nb,
                        continue;
 
                ring->inspect = false;
-               priv->ring_map[q + port * num_tx_queues] = NULL;
+               qp = ring->switch_queue;
+               priv->ring_map[qp + port * num_tx_queues] = NULL;
        }
 
        return 0;
index 8b08cb1..3f63ffd 100644 (file)
@@ -1109,7 +1109,7 @@ static inline u8 bnx2x_get_path_func_num(struct bnx2x *bp)
                for (i = 0; i < E1H_FUNC_MAX / 2; i++) {
                        u32 func_config =
                                MF_CFG_RD(bp,
-                                         func_mf_config[BP_PORT(bp) + 2 * i].
+                                         func_mf_config[BP_PATH(bp) + 2 * i].
                                          config);
                        func_num +=
                                ((func_config & FUNC_MF_CFG_FUNC_HIDE) ? 0 : 1);
index 192ff8d..cff64e4 100644 (file)
@@ -9976,10 +9976,18 @@ static void bnx2x_recovery_failed(struct bnx2x *bp)
  */
 static void bnx2x_parity_recover(struct bnx2x *bp)
 {
-       bool global = false;
        u32 error_recovered, error_unrecovered;
-       bool is_parity;
+       bool is_parity, global = false;
+#ifdef CONFIG_BNX2X_SRIOV
+       int vf_idx;
+
+       for (vf_idx = 0; vf_idx < bp->requested_nr_virtfn; vf_idx++) {
+               struct bnx2x_virtf *vf = BP_VF(bp, vf_idx);
 
+               if (vf)
+                       vf->state = VF_LOST;
+       }
+#endif
        DP(NETIF_MSG_HW, "Handling parity\n");
        while (1) {
                switch (bp->recovery_state) {
index 7a6e82d..bacc855 100644 (file)
@@ -1536,8 +1536,11 @@ void bnx2x_get_rss_ind_table(struct bnx2x_rss_config_obj *rss_obj,
        ((MAX_MAC_CREDIT_E2 - GET_NUM_VFS_PER_PATH(bp) * VF_MAC_CREDIT_CNT) / \
         func_num + GET_NUM_VFS_PER_PF(bp) * VF_MAC_CREDIT_CNT)
 
+#define BNX2X_VFS_VLAN_CREDIT(bp)      \
+       (GET_NUM_VFS_PER_PATH(bp) * VF_VLAN_CREDIT_CNT)
+
 #define PF_VLAN_CREDIT_E2(bp, func_num)                                         \
-       ((MAX_MAC_CREDIT_E2 - GET_NUM_VFS_PER_PATH(bp) * VF_VLAN_CREDIT_CNT) / \
+       ((MAX_VLAN_CREDIT_E2 - 1 - BNX2X_VFS_VLAN_CREDIT(bp)) / \
         func_num + GET_NUM_VFS_PER_PF(bp) * VF_VLAN_CREDIT_CNT)
 
 #endif /* BNX2X_SP_VERBS */
index b6ebd92..3a716c0 100644 (file)
@@ -139,6 +139,7 @@ struct bnx2x_virtf {
 #define VF_ACQUIRED    1       /* VF acquired, but not initialized */
 #define VF_ENABLED     2       /* VF Enabled */
 #define VF_RESET       3       /* VF FLR'd, pending cleanup */
+#define VF_LOST                4       /* Recovery while VFs are loaded */
 
        bool flr_clnup_stage;   /* true during flr cleanup */
        bool malicious;         /* true if FW indicated so, until FLR */
index 0752b7f..ea0e939 100644 (file)
@@ -2107,6 +2107,18 @@ static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
 {
        int i;
 
+       if (vf->state == VF_LOST) {
+               /* Just ack the FW and return if VFs are lost
+                * in case of parity error. VFs are supposed to be timedout
+                * on waiting for PF response.
+                */
+               DP(BNX2X_MSG_IOV,
+                  "VF 0x%x lost, not handling the request\n", vf->abs_vfid);
+
+               storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
+               return;
+       }
+
        /* check if tlv type is known */
        if (bnx2x_tlv_supported(mbx->first_tlv.tl.type)) {
                /* Lock the per vf op mutex and note the locker's identity.
index 85983f0..e6f18f6 100644 (file)
@@ -2001,6 +2001,9 @@ static int bnxt_async_event_process(struct bnxt *bp,
        case ASYNC_EVENT_CMPL_EVENT_ID_RESET_NOTIFY: {
                u32 data1 = le32_to_cpu(cmpl->event_data1);
 
+               if (!bp->fw_health)
+                       goto async_event_process_exit;
+
                bp->fw_reset_timestamp = jiffies;
                bp->fw_reset_min_dsecs = cmpl->timestamp_lo;
                if (!bp->fw_reset_min_dsecs)
@@ -4421,8 +4424,9 @@ int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap, int bmap_size,
                            FUNC_DRV_RGTR_REQ_ENABLES_ASYNC_EVENT_FWD);
 
        req.os_type = cpu_to_le16(FUNC_DRV_RGTR_REQ_OS_TYPE_LINUX);
-       flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE |
-               FUNC_DRV_RGTR_REQ_FLAGS_HOT_RESET_SUPPORT;
+       flags = FUNC_DRV_RGTR_REQ_FLAGS_16BIT_VER_MODE;
+       if (bp->fw_cap & BNXT_FW_CAP_HOT_RESET)
+               flags |= FUNC_DRV_RGTR_REQ_FLAGS_HOT_RESET_SUPPORT;
        if (bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY)
                flags |= FUNC_DRV_RGTR_REQ_FLAGS_ERROR_RECOVERY_SUPPORT |
                         FUNC_DRV_RGTR_REQ_FLAGS_MASTER_SUPPORT;
@@ -6186,7 +6190,7 @@ static void bnxt_hwrm_set_coal_params(struct bnxt *bp,
                tmr = bnxt_usec_to_coal_tmr(bp, hw_coal->coal_ticks_irq);
                val = clamp_t(u16, tmr, 1,
                              coal_cap->cmpl_aggr_dma_tmr_during_int_max);
-               req->cmpl_aggr_dma_tmr_during_int = cpu_to_le16(tmr);
+               req->cmpl_aggr_dma_tmr_during_int = cpu_to_le16(val);
                req->enables |=
                        cpu_to_le16(BNXT_COAL_CMPL_AGGR_TMR_DURING_INT_ENABLE);
        }
@@ -7115,14 +7119,6 @@ static int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp)
        rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
        if (rc)
                goto err_recovery_out;
-       if (!fw_health) {
-               fw_health = kzalloc(sizeof(*fw_health), GFP_KERNEL);
-               bp->fw_health = fw_health;
-               if (!fw_health) {
-                       rc = -ENOMEM;
-                       goto err_recovery_out;
-               }
-       }
        fw_health->flags = le32_to_cpu(resp->flags);
        if ((fw_health->flags & ERROR_RECOVERY_QCFG_RESP_FLAGS_CO_CPU) &&
            !(bp->fw_cap & BNXT_FW_CAP_KONG_MB_CHNL)) {
@@ -8796,6 +8792,9 @@ static int bnxt_hwrm_if_change(struct bnxt *bp, bool up)
                if (fw_reset) {
                        if (!test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
                                bnxt_ulp_stop(bp);
+                       bnxt_free_ctx_mem(bp);
+                       kfree(bp->ctx);
+                       bp->ctx = NULL;
                        rc = bnxt_fw_init_one(bp);
                        if (rc) {
                                set_bit(BNXT_STATE_ABORT_ERR, &bp->state);
@@ -9990,8 +9989,7 @@ static void bnxt_fw_health_check(struct bnxt *bp)
        struct bnxt_fw_health *fw_health = bp->fw_health;
        u32 val;
 
-       if (!fw_health || !fw_health->enabled ||
-           test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
+       if (!fw_health->enabled || test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
                return;
 
        if (fw_health->tmr_counter) {
@@ -10482,6 +10480,23 @@ static void bnxt_init_dflt_coal(struct bnxt *bp)
        bp->stats_coal_ticks = BNXT_DEF_STATS_COAL_TICKS;
 }
 
+static void bnxt_alloc_fw_health(struct bnxt *bp)
+{
+       if (bp->fw_health)
+               return;
+
+       if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) &&
+           !(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
+               return;
+
+       bp->fw_health = kzalloc(sizeof(*bp->fw_health), GFP_KERNEL);
+       if (!bp->fw_health) {
+               netdev_warn(bp->dev, "Failed to allocate fw_health\n");
+               bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET;
+               bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
+       }
+}
+
 static int bnxt_fw_init_one_p1(struct bnxt *bp)
 {
        int rc;
@@ -10528,6 +10543,7 @@ static int bnxt_fw_init_one_p2(struct bnxt *bp)
                netdev_warn(bp->dev, "hwrm query adv flow mgnt failure rc: %d\n",
                            rc);
 
+       bnxt_alloc_fw_health(bp);
        rc = bnxt_hwrm_error_recovery_qcfg(bp);
        if (rc)
                netdev_warn(bp->dev, "hwrm query error recovery failure rc: %d\n",
@@ -10609,6 +10625,12 @@ static int bnxt_fw_init_one(struct bnxt *bp)
        rc = bnxt_approve_mac(bp, bp->dev->dev_addr, false);
        if (rc)
                return rc;
+
+       /* In case fw capabilities have changed, destroy the unneeded
+        * reporters and create newly capable ones.
+        */
+       bnxt_dl_fw_reporters_destroy(bp, false);
+       bnxt_dl_fw_reporters_create(bp);
        bnxt_fw_init_one_p3(bp);
        return 0;
 }
@@ -10751,8 +10773,7 @@ static void bnxt_fw_reset_task(struct work_struct *work)
                bnxt_queue_fw_reset_work(bp, bp->fw_reset_min_dsecs * HZ / 10);
                return;
        case BNXT_FW_RESET_STATE_ENABLE_DEV:
-               if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state) &&
-                   bp->fw_health) {
+               if (test_bit(BNXT_STATE_FW_FATAL_COND, &bp->state)) {
                        u32 val;
 
                        val = bnxt_fw_health_readl(bp,
@@ -11044,11 +11065,23 @@ static bool bnxt_fltr_match(struct bnxt_ntuple_filter *f1,
        struct flow_keys *keys1 = &f1->fkeys;
        struct flow_keys *keys2 = &f2->fkeys;
 
-       if (keys1->addrs.v4addrs.src == keys2->addrs.v4addrs.src &&
-           keys1->addrs.v4addrs.dst == keys2->addrs.v4addrs.dst &&
-           keys1->ports.ports == keys2->ports.ports &&
-           keys1->basic.ip_proto == keys2->basic.ip_proto &&
-           keys1->basic.n_proto == keys2->basic.n_proto &&
+       if (keys1->basic.n_proto != keys2->basic.n_proto ||
+           keys1->basic.ip_proto != keys2->basic.ip_proto)
+               return false;
+
+       if (keys1->basic.n_proto == htons(ETH_P_IP)) {
+               if (keys1->addrs.v4addrs.src != keys2->addrs.v4addrs.src ||
+                   keys1->addrs.v4addrs.dst != keys2->addrs.v4addrs.dst)
+                       return false;
+       } else {
+               if (memcmp(&keys1->addrs.v6addrs.src, &keys2->addrs.v6addrs.src,
+                          sizeof(keys1->addrs.v6addrs.src)) ||
+                   memcmp(&keys1->addrs.v6addrs.dst, &keys2->addrs.v6addrs.dst,
+                          sizeof(keys1->addrs.v6addrs.dst)))
+                       return false;
+       }
+
+       if (keys1->ports.ports == keys2->ports.ports &&
            keys1->control.flags == keys2->control.flags &&
            ether_addr_equal(f1->src_mac_addr, f2->src_mac_addr) &&
            ether_addr_equal(f1->dst_mac_addr, f2->dst_mac_addr))
@@ -11340,7 +11373,7 @@ int bnxt_get_port_parent_id(struct net_device *dev,
                return -EOPNOTSUPP;
 
        /* The PF and it's VF-reps only support the switchdev framework */
-       if (!BNXT_PF(bp))
+       if (!BNXT_PF(bp) || !(bp->flags & BNXT_FLAG_DSN_VALID))
                return -EOPNOTSUPP;
 
        ppid->id_len = sizeof(bp->switch_id);
@@ -11396,11 +11429,11 @@ static void bnxt_remove_one(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct bnxt *bp = netdev_priv(dev);
 
-       if (BNXT_PF(bp)) {
+       if (BNXT_PF(bp))
                bnxt_sriov_disable(bp);
-               bnxt_dl_unregister(bp);
-       }
 
+       bnxt_dl_fw_reporters_destroy(bp, true);
+       bnxt_dl_unregister(bp);
        pci_disable_pcie_error_reporting(pdev);
        unregister_netdev(dev);
        bnxt_shutdown_tc(bp);
@@ -11415,6 +11448,8 @@ static void bnxt_remove_one(struct pci_dev *pdev)
        bnxt_dcb_free(bp);
        kfree(bp->edev);
        bp->edev = NULL;
+       kfree(bp->fw_health);
+       bp->fw_health = NULL;
        bnxt_cleanup_pci(bp);
        bnxt_free_ctx_mem(bp);
        kfree(bp->ctx);
@@ -11711,6 +11746,7 @@ static int bnxt_pcie_dsn_get(struct bnxt *bp, u8 dsn[])
        put_unaligned_le32(dw, &dsn[0]);
        pci_read_config_dword(pdev, pos + 4, &dw);
        put_unaligned_le32(dw, &dsn[4]);
+       bp->flags |= BNXT_FLAG_DSN_VALID;
        return 0;
 }
 
@@ -11822,9 +11858,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        if (BNXT_PF(bp)) {
                /* Read the adapter's DSN to use as the eswitch switch_id */
-               rc = bnxt_pcie_dsn_get(bp, bp->switch_id);
-               if (rc)
-                       goto init_err_pci_clean;
+               bnxt_pcie_dsn_get(bp, bp->switch_id);
        }
 
        /* MTU range: 60 - FW defined max */
@@ -11875,8 +11909,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (rc)
                goto init_err_cleanup_tc;
 
-       if (BNXT_PF(bp))
-               bnxt_dl_register(bp);
+       bnxt_dl_register(bp);
+       bnxt_dl_fw_reporters_create(bp);
 
        netdev_info(dev, "%s found at mem %lx, node addr %pM\n",
                    board_info[ent->driver_data].name,
index 505af5c..f143354 100644 (file)
@@ -1532,6 +1532,7 @@ struct bnxt {
        #define BNXT_FLAG_NO_AGG_RINGS  0x20000
        #define BNXT_FLAG_RX_PAGE_MODE  0x40000
        #define BNXT_FLAG_MULTI_HOST    0x100000
+       #define BNXT_FLAG_DSN_VALID     0x200000
        #define BNXT_FLAG_DOUBLE_DB     0x400000
        #define BNXT_FLAG_CHIP_NITRO_A0 0x1000000
        #define BNXT_FLAG_DIM           0x2000000
@@ -1936,9 +1937,6 @@ static inline bool bnxt_cfa_hwrm_message(u16 req_type)
        case HWRM_CFA_ENCAP_RECORD_FREE:
        case HWRM_CFA_DECAP_FILTER_ALLOC:
        case HWRM_CFA_DECAP_FILTER_FREE:
-       case HWRM_CFA_NTUPLE_FILTER_ALLOC:
-       case HWRM_CFA_NTUPLE_FILTER_FREE:
-       case HWRM_CFA_NTUPLE_FILTER_CFG:
        case HWRM_CFA_EM_FLOW_ALLOC:
        case HWRM_CFA_EM_FLOW_FREE:
        case HWRM_CFA_EM_FLOW_CFG:
index acb2dd6..3eedd44 100644 (file)
@@ -39,11 +39,10 @@ static int bnxt_fw_reporter_diagnose(struct devlink_health_reporter *reporter,
                                     struct netlink_ext_ack *extack)
 {
        struct bnxt *bp = devlink_health_reporter_priv(reporter);
-       struct bnxt_fw_health *health = bp->fw_health;
        u32 val, health_status;
        int rc;
 
-       if (!health || test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
+       if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state))
                return 0;
 
        val = bnxt_fw_health_readl(bp, BNXT_FW_HEALTH_REG);
@@ -126,21 +125,15 @@ struct devlink_health_reporter_ops bnxt_dl_fw_fatal_reporter_ops = {
        .recover = bnxt_fw_fatal_recover,
 };
 
-static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
+void bnxt_dl_fw_reporters_create(struct bnxt *bp)
 {
        struct bnxt_fw_health *health = bp->fw_health;
 
-       if (!health)
+       if (!bp->dl || !health)
                return;
 
-       health->fw_reporter =
-               devlink_health_reporter_create(bp->dl, &bnxt_dl_fw_reporter_ops,
-                                              0, false, bp);
-       if (IS_ERR(health->fw_reporter)) {
-               netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
-                           PTR_ERR(health->fw_reporter));
-               health->fw_reporter = NULL;
-       }
+       if (!(bp->fw_cap & BNXT_FW_CAP_HOT_RESET) || health->fw_reset_reporter)
+               goto err_recovery;
 
        health->fw_reset_reporter =
                devlink_health_reporter_create(bp->dl,
@@ -150,8 +143,30 @@ static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
                netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
                            PTR_ERR(health->fw_reset_reporter));
                health->fw_reset_reporter = NULL;
+               bp->fw_cap &= ~BNXT_FW_CAP_HOT_RESET;
+       }
+
+err_recovery:
+       if (!(bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY))
+               return;
+
+       if (!health->fw_reporter) {
+               health->fw_reporter =
+                       devlink_health_reporter_create(bp->dl,
+                                                      &bnxt_dl_fw_reporter_ops,
+                                                      0, false, bp);
+               if (IS_ERR(health->fw_reporter)) {
+                       netdev_warn(bp->dev, "Failed to create FW health reporter, rc = %ld\n",
+                                   PTR_ERR(health->fw_reporter));
+                       health->fw_reporter = NULL;
+                       bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
+                       return;
+               }
        }
 
+       if (health->fw_fatal_reporter)
+               return;
+
        health->fw_fatal_reporter =
                devlink_health_reporter_create(bp->dl,
                                               &bnxt_dl_fw_fatal_reporter_ops,
@@ -160,24 +175,35 @@ static void bnxt_dl_fw_reporters_create(struct bnxt *bp)
                netdev_warn(bp->dev, "Failed to create FW fatal health reporter, rc = %ld\n",
                            PTR_ERR(health->fw_fatal_reporter));
                health->fw_fatal_reporter = NULL;
+               bp->fw_cap &= ~BNXT_FW_CAP_ERROR_RECOVERY;
        }
 }
 
-static void bnxt_dl_fw_reporters_destroy(struct bnxt *bp)
+void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all)
 {
        struct bnxt_fw_health *health = bp->fw_health;
 
-       if (!health)
+       if (!bp->dl || !health)
                return;
 
-       if (health->fw_reporter)
-               devlink_health_reporter_destroy(health->fw_reporter);
-
-       if (health->fw_reset_reporter)
+       if ((all || !(bp->fw_cap & BNXT_FW_CAP_HOT_RESET)) &&
+           health->fw_reset_reporter) {
                devlink_health_reporter_destroy(health->fw_reset_reporter);
+               health->fw_reset_reporter = NULL;
+       }
 
-       if (health->fw_fatal_reporter)
+       if ((bp->fw_cap & BNXT_FW_CAP_ERROR_RECOVERY) && !all)
+               return;
+
+       if (health->fw_reporter) {
+               devlink_health_reporter_destroy(health->fw_reporter);
+               health->fw_reporter = NULL;
+       }
+
+       if (health->fw_fatal_reporter) {
                devlink_health_reporter_destroy(health->fw_fatal_reporter);
+               health->fw_fatal_reporter = NULL;
+       }
 }
 
 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event)
@@ -185,9 +211,6 @@ void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event)
        struct bnxt_fw_health *fw_health = bp->fw_health;
        struct bnxt_fw_reporter_ctx fw_reporter_ctx;
 
-       if (!fw_health)
-               return;
-
        fw_reporter_ctx.sp_event = event;
        switch (event) {
        case BNXT_FW_RESET_NOTIFY_SP_EVENT:
@@ -247,6 +270,8 @@ static const struct devlink_ops bnxt_dl_ops = {
        .flash_update     = bnxt_dl_flash_update,
 };
 
+static const struct devlink_ops bnxt_vf_dl_ops;
+
 enum bnxt_dl_param_id {
        BNXT_DEVLINK_PARAM_ID_BASE = DEVLINK_PARAM_GENERIC_ID_MAX,
        BNXT_DEVLINK_PARAM_ID_GRE_VER_CHECK,
@@ -460,7 +485,10 @@ int bnxt_dl_register(struct bnxt *bp)
                return -ENOTSUPP;
        }
 
-       dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
+       if (BNXT_PF(bp))
+               dl = devlink_alloc(&bnxt_dl_ops, sizeof(struct bnxt_dl));
+       else
+               dl = devlink_alloc(&bnxt_vf_dl_ops, sizeof(struct bnxt_dl));
        if (!dl) {
                netdev_warn(bp->dev, "devlink_alloc failed");
                return -ENOMEM;
@@ -479,6 +507,9 @@ int bnxt_dl_register(struct bnxt *bp)
                goto err_dl_free;
        }
 
+       if (!BNXT_PF(bp))
+               return 0;
+
        rc = devlink_params_register(dl, bnxt_dl_params,
                                     ARRAY_SIZE(bnxt_dl_params));
        if (rc) {
@@ -506,8 +537,6 @@ int bnxt_dl_register(struct bnxt *bp)
 
        devlink_params_publish(dl);
 
-       bnxt_dl_fw_reporters_create(bp);
-
        return 0;
 
 err_dl_port_unreg:
@@ -530,12 +559,14 @@ void bnxt_dl_unregister(struct bnxt *bp)
        if (!dl)
                return;
 
-       bnxt_dl_fw_reporters_destroy(bp);
-       devlink_port_params_unregister(&bp->dl_port, bnxt_dl_port_params,
-                                      ARRAY_SIZE(bnxt_dl_port_params));
-       devlink_port_unregister(&bp->dl_port);
-       devlink_params_unregister(dl, bnxt_dl_params,
-                                 ARRAY_SIZE(bnxt_dl_params));
+       if (BNXT_PF(bp)) {
+               devlink_port_params_unregister(&bp->dl_port,
+                                              bnxt_dl_port_params,
+                                              ARRAY_SIZE(bnxt_dl_port_params));
+               devlink_port_unregister(&bp->dl_port);
+               devlink_params_unregister(dl, bnxt_dl_params,
+                                         ARRAY_SIZE(bnxt_dl_params));
+       }
        devlink_unregister(dl);
        devlink_free(dl);
 }
index 665d4bd..6db6c3d 100644 (file)
@@ -58,6 +58,8 @@ struct bnxt_dl_nvm_param {
 
 void bnxt_devlink_health_report(struct bnxt *bp, unsigned long event);
 void bnxt_dl_health_status_update(struct bnxt *bp, bool healthy);
+void bnxt_dl_fw_reporters_create(struct bnxt *bp);
+void bnxt_dl_fw_reporters_destroy(struct bnxt *bp, bool all);
 int bnxt_dl_register(struct bnxt *bp);
 void bnxt_dl_unregister(struct bnxt *bp);
 
index 2ccf79c..08d56ec 100644 (file)
@@ -3071,8 +3071,15 @@ static int bnxt_hwrm_dbg_dma_data(struct bnxt *bp, void *msg, int msg_len,
                        }
                }
 
-               if (info->dest_buf)
-                       memcpy(info->dest_buf + off, dma_buf, len);
+               if (info->dest_buf) {
+                       if ((info->seg_start + off + len) <=
+                           BNXT_COREDUMP_BUF_LEN(info->buf_len)) {
+                               memcpy(info->dest_buf + off, dma_buf, len);
+                       } else {
+                               rc = -ENOBUFS;
+                               break;
+                       }
+               }
 
                if (cmn_req->req_type ==
                                cpu_to_le16(HWRM_DBG_COREDUMP_RETRIEVE))
@@ -3126,7 +3133,7 @@ static int bnxt_hwrm_dbg_coredump_initiate(struct bnxt *bp, u16 component_id,
 
 static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id,
                                           u16 segment_id, u32 *seg_len,
-                                          void *buf, u32 offset)
+                                          void *buf, u32 buf_len, u32 offset)
 {
        struct hwrm_dbg_coredump_retrieve_input req = {0};
        struct bnxt_hwrm_dbg_dma_info info = {NULL};
@@ -3141,8 +3148,11 @@ static int bnxt_hwrm_dbg_coredump_retrieve(struct bnxt *bp, u16 component_id,
                                seq_no);
        info.data_len_off = offsetof(struct hwrm_dbg_coredump_retrieve_output,
                                     data_len);
-       if (buf)
+       if (buf) {
                info.dest_buf = buf + offset;
+               info.buf_len = buf_len;
+               info.seg_start = offset;
+       }
 
        rc = bnxt_hwrm_dbg_dma_data(bp, &req, sizeof(req), &info);
        if (!rc)
@@ -3232,14 +3242,17 @@ bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record,
 static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
 {
        u32 ver_get_resp_len = sizeof(struct hwrm_ver_get_output);
+       u32 offset = 0, seg_hdr_len, seg_record_len, buf_len = 0;
        struct coredump_segment_record *seg_record = NULL;
-       u32 offset = 0, seg_hdr_len, seg_record_len;
        struct bnxt_coredump_segment_hdr seg_hdr;
        struct bnxt_coredump coredump = {NULL};
        time64_t start_time;
        u16 start_utc;
        int rc = 0, i;
 
+       if (buf)
+               buf_len = *dump_len;
+
        start_time = ktime_get_real_seconds();
        start_utc = sys_tz.tz_minuteswest * 60;
        seg_hdr_len = sizeof(seg_hdr);
@@ -3272,6 +3285,12 @@ static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
                u32 duration = 0, seg_len = 0;
                unsigned long start, end;
 
+               if (buf && ((offset + seg_hdr_len) >
+                           BNXT_COREDUMP_BUF_LEN(buf_len))) {
+                       rc = -ENOBUFS;
+                       goto err;
+               }
+
                start = jiffies;
 
                rc = bnxt_hwrm_dbg_coredump_initiate(bp, comp_id, seg_id);
@@ -3284,9 +3303,11 @@ static int bnxt_get_coredump(struct bnxt *bp, void *buf, u32 *dump_len)
 
                /* Write segment data into the buffer */
                rc = bnxt_hwrm_dbg_coredump_retrieve(bp, comp_id, seg_id,
-                                                    &seg_len, buf,
+                                                    &seg_len, buf, buf_len,
                                                     offset + seg_hdr_len);
-               if (rc)
+               if (rc && rc == -ENOBUFS)
+                       goto err;
+               else if (rc)
                        netdev_err(bp->dev,
                                   "Failed to retrieve coredump for seg = %d\n",
                                   seg_record->segment_id);
@@ -3316,7 +3337,8 @@ err:
                                          rc);
        kfree(coredump.data);
        *dump_len += sizeof(struct bnxt_coredump_record);
-
+       if (rc == -ENOBUFS)
+               netdev_err(bp->dev, "Firmware returned large coredump buffer");
        return rc;
 }
 
index 4428d0a..3576d95 100644 (file)
@@ -31,6 +31,8 @@ struct bnxt_coredump {
        u16             total_segs;
 };
 
+#define BNXT_COREDUMP_BUF_LEN(len) ((len) - sizeof(struct bnxt_coredump_record))
+
 struct bnxt_hwrm_dbg_dma_info {
        void *dest_buf;
        int dest_buf_size;
@@ -38,6 +40,8 @@ struct bnxt_hwrm_dbg_dma_info {
        u16 seq_off;
        u16 data_len_off;
        u16 segs;
+       u32 seg_start;
+       u32 buf_len;
 };
 
 struct hwrm_dbg_cmn_input {
index c601ff7..4a316c4 100644 (file)
@@ -113,8 +113,10 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
 {
        struct net_device *dev = edev->net;
        struct bnxt *bp = netdev_priv(dev);
+       struct bnxt_hw_resc *hw_resc;
        int max_idx, max_cp_rings;
        int avail_msix, idx;
+       int total_vecs;
        int rc = 0;
 
        ASSERT_RTNL();
@@ -142,7 +144,10 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
        }
        edev->ulp_tbl[ulp_id].msix_base = idx;
        edev->ulp_tbl[ulp_id].msix_requested = avail_msix;
-       if (bp->total_irqs < (idx + avail_msix)) {
+       hw_resc = &bp->hw_resc;
+       total_vecs = idx + avail_msix;
+       if (bp->total_irqs < total_vecs ||
+           (BNXT_NEW_RM(bp) && hw_resc->resv_irqs < total_vecs)) {
                if (netif_running(dev)) {
                        bnxt_close_nic(bp, true, false);
                        rc = bnxt_open_nic(bp, true, false);
@@ -156,7 +161,6 @@ static int bnxt_req_msix_vecs(struct bnxt_en_dev *edev, int ulp_id,
        }
 
        if (BNXT_NEW_RM(bp)) {
-               struct bnxt_hw_resc *hw_resc = &bp->hw_resc;
                int resv_msix;
 
                resv_msix = hw_resc->resv_irqs - bp->cp_nr_rings;
index f9bf7d7..b010b34 100644 (file)
@@ -398,6 +398,9 @@ static int bnxt_vf_reps_create(struct bnxt *bp)
        struct net_device *dev;
        int rc, i;
 
+       if (!(bp->flags & BNXT_FLAG_DSN_VALID))
+               return -ENODEV;
+
        bp->vf_reps = kcalloc(num_vfs, sizeof(vf_rep), GFP_KERNEL);
        if (!bp->vf_reps)
                return -ENOMEM;
index 9c767ee..f7d87c7 100644 (file)
@@ -611,21 +611,24 @@ static const struct phylink_mac_ops macb_phylink_ops = {
        .mac_link_up = macb_mac_link_up,
 };
 
+static bool macb_phy_handle_exists(struct device_node *dn)
+{
+       dn = of_parse_phandle(dn, "phy-handle", 0);
+       of_node_put(dn);
+       return dn != NULL;
+}
+
 static int macb_phylink_connect(struct macb *bp)
 {
+       struct device_node *dn = bp->pdev->dev.of_node;
        struct net_device *dev = bp->dev;
        struct phy_device *phydev;
        int ret;
 
-       if (bp->pdev->dev.of_node &&
-           of_parse_phandle(bp->pdev->dev.of_node, "phy-handle", 0)) {
-               ret = phylink_of_phy_connect(bp->phylink, bp->pdev->dev.of_node,
-                                            0);
-               if (ret) {
-                       netdev_err(dev, "Could not attach PHY (%d)\n", ret);
-                       return ret;
-               }
-       } else {
+       if (dn)
+               ret = phylink_of_phy_connect(bp->phylink, dn, 0);
+
+       if (!dn || (ret && !macb_phy_handle_exists(dn))) {
                phydev = phy_find_first(bp->mii_bus);
                if (!phydev) {
                        netdev_err(dev, "no PHY found\n");
@@ -634,10 +637,11 @@ static int macb_phylink_connect(struct macb *bp)
 
                /* attach the mac to the phy */
                ret = phylink_connect_phy(bp->phylink, phydev);
-               if (ret) {
-                       netdev_err(dev, "Could not attach to PHY (%d)\n", ret);
-                       return ret;
-               }
+       }
+
+       if (ret) {
+               netdev_err(dev, "Could not attach PHY (%d)\n", ret);
+               return ret;
        }
 
        phylink_start(bp->phylink);
@@ -664,9 +668,30 @@ static int macb_mii_probe(struct net_device *dev)
        return 0;
 }
 
+static int macb_mdiobus_register(struct macb *bp)
+{
+       struct device_node *child, *np = bp->pdev->dev.of_node;
+
+       /* Only create the PHY from the device tree if at least one PHY is
+        * described. Otherwise scan the entire MDIO bus. We do this to support
+        * old device tree that did not follow the best practices and did not
+        * describe their network PHYs.
+        */
+       for_each_available_child_of_node(np, child)
+               if (of_mdiobus_child_is_phy(child)) {
+                       /* The loop increments the child refcount,
+                        * decrement it before returning.
+                        */
+                       of_node_put(child);
+
+                       return of_mdiobus_register(bp->mii_bus, np);
+               }
+
+       return mdiobus_register(bp->mii_bus);
+}
+
 static int macb_mii_init(struct macb *bp)
 {
-       struct device_node *np;
        int err = -ENXIO;
 
        /* Enable management port */
@@ -688,9 +713,7 @@ static int macb_mii_init(struct macb *bp)
 
        dev_set_drvdata(&bp->dev->dev, bp->mii_bus);
 
-       np = bp->pdev->dev.of_node;
-
-       err = of_mdiobus_register(bp->mii_bus, np);
+       err = macb_mdiobus_register(bp);
        if (err)
                goto err_out_free_mdiobus;
 
@@ -4069,7 +4092,7 @@ static int fu540_c000_clk_init(struct platform_device *pdev, struct clk **pclk,
        mgmt->rate = 0;
        mgmt->hw.init = &init;
 
-       *tx_clk = clk_register(NULL, &mgmt->hw);
+       *tx_clk = devm_clk_register(&pdev->dev, &mgmt->hw);
        if (IS_ERR(*tx_clk))
                return PTR_ERR(*tx_clk);
 
@@ -4397,7 +4420,6 @@ err_out_free_netdev:
 
 err_disable_clocks:
        clk_disable_unprepare(tx_clk);
-       clk_unregister(tx_clk);
        clk_disable_unprepare(hclk);
        clk_disable_unprepare(pclk);
        clk_disable_unprepare(rx_clk);
@@ -4427,7 +4449,6 @@ static int macb_remove(struct platform_device *pdev)
                pm_runtime_dont_use_autosuspend(&pdev->dev);
                if (!pm_runtime_suspended(&pdev->dev)) {
                        clk_disable_unprepare(bp->tx_clk);
-                       clk_unregister(bp->tx_clk);
                        clk_disable_unprepare(bp->hclk);
                        clk_disable_unprepare(bp->pclk);
                        clk_disable_unprepare(bp->rx_clk);
index 0cc2338..dfc7750 100644 (file)
@@ -205,11 +205,11 @@ static int __cvmx_bootmem_check_version(struct octeon_device *oct,
        major_version = (u32)__cvmx_bootmem_desc_get(
                        oct, oct->bootmem_desc_addr,
                        offsetof(struct cvmx_bootmem_desc, major_version),
-                       FIELD_SIZEOF(struct cvmx_bootmem_desc, major_version));
+                       sizeof_field(struct cvmx_bootmem_desc, major_version));
        minor_version = (u32)__cvmx_bootmem_desc_get(
                        oct, oct->bootmem_desc_addr,
                        offsetof(struct cvmx_bootmem_desc, minor_version),
-                       FIELD_SIZEOF(struct cvmx_bootmem_desc, minor_version));
+                       sizeof_field(struct cvmx_bootmem_desc, minor_version));
 
        dev_dbg(&oct->pci_dev->dev, "%s: major_version=%d\n", __func__,
                major_version);
@@ -237,13 +237,13 @@ static const struct cvmx_bootmem_named_block_desc
                                oct, named_addr,
                                offsetof(struct cvmx_bootmem_named_block_desc,
                                         base_addr),
-                               FIELD_SIZEOF(
+                               sizeof_field(
                                        struct cvmx_bootmem_named_block_desc,
                                        base_addr));
                desc->size = __cvmx_bootmem_desc_get(oct, named_addr,
                                offsetof(struct cvmx_bootmem_named_block_desc,
                                         size),
-                               FIELD_SIZEOF(
+                               sizeof_field(
                                        struct cvmx_bootmem_named_block_desc,
                                        size));
 
@@ -268,20 +268,20 @@ static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct,
                                        oct, oct->bootmem_desc_addr,
                                        offsetof(struct cvmx_bootmem_desc,
                                                 named_block_array_addr),
-                                       FIELD_SIZEOF(struct cvmx_bootmem_desc,
+                                       sizeof_field(struct cvmx_bootmem_desc,
                                                     named_block_array_addr));
                u32 num_blocks = (u32)__cvmx_bootmem_desc_get(
                                        oct, oct->bootmem_desc_addr,
                                        offsetof(struct cvmx_bootmem_desc,
                                                 nb_num_blocks),
-                                       FIELD_SIZEOF(struct cvmx_bootmem_desc,
+                                       sizeof_field(struct cvmx_bootmem_desc,
                                                     nb_num_blocks));
 
                u32 name_length = (u32)__cvmx_bootmem_desc_get(
                                        oct, oct->bootmem_desc_addr,
                                        offsetof(struct cvmx_bootmem_desc,
                                                 named_block_name_len),
-                                       FIELD_SIZEOF(struct cvmx_bootmem_desc,
+                                       sizeof_field(struct cvmx_bootmem_desc,
                                                     named_block_name_len));
 
                u64 named_addr = named_block_array_addr;
@@ -292,7 +292,7 @@ static u64 cvmx_bootmem_phy_named_block_find(struct octeon_device *oct,
                                         offsetof(
                                        struct cvmx_bootmem_named_block_desc,
                                        size),
-                                        FIELD_SIZEOF(
+                                        sizeof_field(
                                        struct cvmx_bootmem_named_block_desc,
                                        size));
 
index a70ac20..becee29 100644 (file)
@@ -504,6 +504,7 @@ struct link_config {
 
        enum cc_pause  requested_fc;     /* flow control user has requested */
        enum cc_pause  fc;               /* actual link flow control */
+       enum cc_pause  advertised_fc;    /* actual advertised flow control */
 
        enum cc_fec    requested_fec;    /* Forward Error Correction: */
        enum cc_fec    fec;              /* requested and actual in use */
index 93868dc..aca9f7a 100644 (file)
@@ -3048,6 +3048,9 @@ static int sge_queue_entries(const struct adapter *adap)
        int tot_uld_entries = 0;
        int i;
 
+       if (!is_uld(adap))
+               goto lld_only;
+
        mutex_lock(&uld_mutex);
        for (i = 0; i < CXGB4_TX_MAX; i++)
                tot_uld_entries += sge_qinfo_uld_txq_entries(adap, i);
@@ -3058,6 +3061,7 @@ static int sge_queue_entries(const struct adapter *adap)
        }
        mutex_unlock(&uld_mutex);
 
+lld_only:
        return DIV_ROUND_UP(adap->sge.ethqsets, 4) +
               (adap->sge.eohw_txq ? DIV_ROUND_UP(adap->sge.eoqsets, 4) : 0) +
               tot_uld_entries +
index 20ab3b6..c837382 100644 (file)
@@ -807,8 +807,8 @@ static void get_pauseparam(struct net_device *dev,
        struct port_info *p = netdev_priv(dev);
 
        epause->autoneg = (p->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
-       epause->rx_pause = (p->link_cfg.fc & PAUSE_RX) != 0;
-       epause->tx_pause = (p->link_cfg.fc & PAUSE_TX) != 0;
+       epause->rx_pause = (p->link_cfg.advertised_fc & PAUSE_RX) != 0;
+       epause->tx_pause = (p->link_cfg.advertised_fc & PAUSE_TX) != 0;
 }
 
 static int set_pauseparam(struct net_device *dev,
index 12ff69b..0dedd3e 100644 (file)
@@ -3135,9 +3135,9 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
 {
        struct port_info *pi = netdev_priv(dev);
        struct adapter *adap = pi->adapter;
+       struct ch_sched_queue qe = { 0 };
+       struct ch_sched_params p = { 0 };
        struct sched_class *e;
-       struct ch_sched_params p;
-       struct ch_sched_queue qe;
        u32 req_rate;
        int err = 0;
 
@@ -3154,6 +3154,15 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
                return -EINVAL;
        }
 
+       qe.queue = index;
+       e = cxgb4_sched_queue_lookup(dev, &qe);
+       if (e && e->info.u.params.level != SCHED_CLASS_LEVEL_CL_RL) {
+               dev_err(adap->pdev_dev,
+                       "Queue %u already bound to class %u of type: %u\n",
+                       index, e->idx, e->info.u.params.level);
+               return -EBUSY;
+       }
+
        /* Convert from Mbps to Kbps */
        req_rate = rate * 1000;
 
@@ -3183,7 +3192,6 @@ static int cxgb_set_tx_maxrate(struct net_device *dev, int index, u32 rate)
                return 0;
 
        /* Fetch any available unused or matching scheduling class */
-       memset(&p, 0, sizeof(p));
        p.type = SCHED_CLASS_TYPE_PACKET;
        p.u.params.level    = SCHED_CLASS_LEVEL_CL_RL;
        p.u.params.mode     = SCHED_CLASS_MODE_CLASS;
index 102b370..6d48580 100644 (file)
@@ -15,6 +15,8 @@ static int cxgb4_matchall_egress_validate(struct net_device *dev,
        struct flow_action *actions = &cls->rule->action;
        struct port_info *pi = netdev2pinfo(dev);
        struct flow_action_entry *entry;
+       struct ch_sched_queue qe;
+       struct sched_class *e;
        u64 max_link_rate;
        u32 i, speed;
        int ret;
@@ -60,9 +62,61 @@ static int cxgb4_matchall_egress_validate(struct net_device *dev,
                }
        }
 
+       for (i = 0; i < pi->nqsets; i++) {
+               memset(&qe, 0, sizeof(qe));
+               qe.queue = i;
+
+               e = cxgb4_sched_queue_lookup(dev, &qe);
+               if (e && e->info.u.params.level != SCHED_CLASS_LEVEL_CH_RL) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "Some queues are already bound to different class");
+                       return -EBUSY;
+               }
+       }
+
        return 0;
 }
 
+static int cxgb4_matchall_tc_bind_queues(struct net_device *dev, u32 tc)
+{
+       struct port_info *pi = netdev2pinfo(dev);
+       struct ch_sched_queue qe;
+       int ret;
+       u32 i;
+
+       for (i = 0; i < pi->nqsets; i++) {
+               qe.queue = i;
+               qe.class = tc;
+               ret = cxgb4_sched_class_bind(dev, &qe, SCHED_QUEUE);
+               if (ret)
+                       goto out_free;
+       }
+
+       return 0;
+
+out_free:
+       while (i--) {
+               qe.queue = i;
+               qe.class = SCHED_CLS_NONE;
+               cxgb4_sched_class_unbind(dev, &qe, SCHED_QUEUE);
+       }
+
+       return ret;
+}
+
+static void cxgb4_matchall_tc_unbind_queues(struct net_device *dev)
+{
+       struct port_info *pi = netdev2pinfo(dev);
+       struct ch_sched_queue qe;
+       u32 i;
+
+       for (i = 0; i < pi->nqsets; i++) {
+               qe.queue = i;
+               qe.class = SCHED_CLS_NONE;
+               cxgb4_sched_class_unbind(dev, &qe, SCHED_QUEUE);
+       }
+}
+
 static int cxgb4_matchall_alloc_tc(struct net_device *dev,
                                   struct tc_cls_matchall_offload *cls)
 {
@@ -83,6 +137,7 @@ static int cxgb4_matchall_alloc_tc(struct net_device *dev,
        struct adapter *adap = netdev2adap(dev);
        struct flow_action_entry *entry;
        struct sched_class *e;
+       int ret;
        u32 i;
 
        tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
@@ -101,10 +156,21 @@ static int cxgb4_matchall_alloc_tc(struct net_device *dev,
                return -ENOMEM;
        }
 
+       ret = cxgb4_matchall_tc_bind_queues(dev, e->idx);
+       if (ret) {
+               NL_SET_ERR_MSG_MOD(extack,
+                                  "Could not bind queues to traffic class");
+               goto out_free;
+       }
+
        tc_port_matchall->egress.hwtc = e->idx;
        tc_port_matchall->egress.cookie = cls->cookie;
        tc_port_matchall->egress.state = CXGB4_MATCHALL_STATE_ENABLED;
        return 0;
+
+out_free:
+       cxgb4_sched_class_free(dev, e->idx);
+       return ret;
 }
 
 static void cxgb4_matchall_free_tc(struct net_device *dev)
@@ -114,6 +180,7 @@ static void cxgb4_matchall_free_tc(struct net_device *dev)
        struct adapter *adap = netdev2adap(dev);
 
        tc_port_matchall = &adap->tc_matchall->port_matchall[pi->port_id];
+       cxgb4_matchall_tc_unbind_queues(dev);
        cxgb4_sched_class_free(dev, tc_port_matchall->egress.hwtc);
 
        tc_port_matchall->egress.hwtc = SCHED_CLS_NONE;
index 477973d..ec3eb45 100644 (file)
@@ -12,8 +12,9 @@ static int cxgb4_mqprio_validate(struct net_device *dev,
        struct port_info *pi = netdev2pinfo(dev);
        struct adapter *adap = netdev2adap(dev);
        u32 speed, qcount = 0, qoffset = 0;
+       u32 start_a, start_b, end_a, end_b;
        int ret;
-       u8 i;
+       u8 i, j;
 
        if (!mqprio->qopt.num_tc)
                return 0;
@@ -47,6 +48,31 @@ static int cxgb4_mqprio_validate(struct net_device *dev,
                qoffset = max_t(u16, mqprio->qopt.offset[i], qoffset);
                qcount += mqprio->qopt.count[i];
 
+               start_a = mqprio->qopt.offset[i];
+               end_a = start_a + mqprio->qopt.count[i] - 1;
+               for (j = i + 1; j < mqprio->qopt.num_tc; j++) {
+                       start_b = mqprio->qopt.offset[j];
+                       end_b = start_b + mqprio->qopt.count[j] - 1;
+
+                       /* If queue count is 0, then the traffic
+                        * belonging to this class will not use
+                        * ETHOFLD queues. So, no need to validate
+                        * further.
+                        */
+                       if (!mqprio->qopt.count[i])
+                               break;
+
+                       if (!mqprio->qopt.count[j])
+                               continue;
+
+                       if (max_t(u32, start_a, start_b) <=
+                           min_t(u32, end_a, end_b)) {
+                               netdev_err(dev,
+                                          "Queues can't overlap across tc\n");
+                               return -EINVAL;
+                       }
+               }
+
                /* Convert byte per second to bits per second */
                min_rate += (mqprio->min_rate[i] * 8);
                max_rate += (mqprio->max_rate[i] * 8);
@@ -145,6 +171,10 @@ static int cxgb4_mqprio_alloc_hw_resources(struct net_device *dev)
                        kfree(adap->sge.eohw_rxq);
                        return -ENOMEM;
                }
+
+               refcount_set(&adap->tc_mqprio->refcnt, 1);
+       } else {
+               refcount_inc(&adap->tc_mqprio->refcnt);
        }
 
        if (!(adap->flags & CXGB4_USING_MSIX))
@@ -205,7 +235,6 @@ static int cxgb4_mqprio_alloc_hw_resources(struct net_device *dev)
                        cxgb4_enable_rx(adap, &eorxq->rspq);
        }
 
-       refcount_inc(&adap->tc_mqprio->refcnt);
        return 0;
 
 out_free_msix:
@@ -234,9 +263,10 @@ out_free_queues:
                t4_sge_free_ethofld_txq(adap, eotxq);
        }
 
-       kfree(adap->sge.eohw_txq);
-       kfree(adap->sge.eohw_rxq);
-
+       if (refcount_dec_and_test(&adap->tc_mqprio->refcnt)) {
+               kfree(adap->sge.eohw_txq);
+               kfree(adap->sge.eohw_rxq);
+       }
        return ret;
 }
 
index 3e61bd5..cebe141 100644 (file)
@@ -165,6 +165,22 @@ static void *t4_sched_entry_lookup(struct port_info *pi,
        return found;
 }
 
+struct sched_class *cxgb4_sched_queue_lookup(struct net_device *dev,
+                                            struct ch_sched_queue *p)
+{
+       struct port_info *pi = netdev2pinfo(dev);
+       struct sched_queue_entry *qe = NULL;
+       struct adapter *adap = pi->adapter;
+       struct sge_eth_txq *txq;
+
+       if (p->queue < 0 || p->queue >= pi->nqsets)
+               return NULL;
+
+       txq = &adap->sge.ethtxq[pi->first_qset + p->queue];
+       qe = t4_sched_entry_lookup(pi, SCHED_QUEUE, txq->q.cntxt_id);
+       return qe ? &pi->sched_tbl->tab[qe->param.class] : NULL;
+}
+
 static int t4_sched_queue_unbind(struct port_info *pi, struct ch_sched_queue *p)
 {
        struct sched_queue_entry *qe = NULL;
index e92ff68..5cc74a5 100644 (file)
@@ -103,6 +103,8 @@ static inline bool valid_class_id(struct net_device *dev, u8 class_id)
        return true;
 }
 
+struct sched_class *cxgb4_sched_queue_lookup(struct net_device *dev,
+                                            struct ch_sched_queue *p);
 int cxgb4_sched_class_bind(struct net_device *dev, void *arg,
                           enum sched_bind_type type);
 int cxgb4_sched_class_unbind(struct net_device *dev, void *arg,
index 19d18ac..844fdcf 100644 (file)
@@ -4089,7 +4089,8 @@ static inline fw_port_cap32_t cc_to_fwcap_pause(enum cc_pause cc_pause)
                if (cc_pause & PAUSE_TX)
                        fw_pause |= FW_PORT_CAP32_802_3_PAUSE;
                else
-                       fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
+                       fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR |
+                                   FW_PORT_CAP32_802_3_PAUSE;
        } else if (cc_pause & PAUSE_TX) {
                fw_pause |= FW_PORT_CAP32_802_3_ASM_DIR;
        }
@@ -8563,17 +8564,17 @@ static fw_port_cap32_t lstatus_to_fwcap(u32 lstatus)
 void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
 {
        const struct fw_port_cmd *cmd = (const void *)rpl;
-       int action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
-       struct adapter *adapter = pi->adapter;
+       fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
        struct link_config *lc = &pi->link_cfg;
-       int link_ok, linkdnrc;
-       enum fw_port_type port_type;
+       struct adapter *adapter = pi->adapter;
+       unsigned int speed, fc, fec, adv_fc;
        enum fw_port_module_type mod_type;
-       unsigned int speed, fc, fec;
-       fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
+       int action, link_ok, linkdnrc;
+       enum fw_port_type port_type;
 
        /* Extract the various fields from the Port Information message.
         */
+       action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
        switch (action) {
        case FW_PORT_ACTION_GET_PORT_INFO: {
                u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
@@ -8611,6 +8612,7 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
        }
 
        fec = fwcap_to_cc_fec(acaps);
+       adv_fc = fwcap_to_cc_pause(acaps);
        fc = fwcap_to_cc_pause(linkattr);
        speed = fwcap_to_speed(linkattr);
 
@@ -8667,7 +8669,9 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
        }
 
        if (link_ok != lc->link_ok || speed != lc->speed ||
-           fc != lc->fc || fec != lc->fec) {   /* something changed */
+           fc != lc->fc || adv_fc != lc->advertised_fc ||
+           fec != lc->fec) {
+               /* something changed */
                if (!link_ok && lc->link_ok) {
                        lc->link_down_rc = linkdnrc;
                        dev_warn_ratelimited(adapter->pdev_dev,
@@ -8677,6 +8681,7 @@ void t4_handle_get_port_info(struct port_info *pi, const __be64 *rpl)
                }
                lc->link_ok = link_ok;
                lc->speed = speed;
+               lc->advertised_fc = adv_fc;
                lc->fc = fc;
                lc->fec = fec;
 
index f6fc087..f4d41f9 100644 (file)
@@ -1690,8 +1690,8 @@ static void cxgb4vf_get_pauseparam(struct net_device *dev,
        struct port_info *pi = netdev_priv(dev);
 
        pauseparam->autoneg = (pi->link_cfg.requested_fc & PAUSE_AUTONEG) != 0;
-       pauseparam->rx_pause = (pi->link_cfg.fc & PAUSE_RX) != 0;
-       pauseparam->tx_pause = (pi->link_cfg.fc & PAUSE_TX) != 0;
+       pauseparam->rx_pause = (pi->link_cfg.advertised_fc & PAUSE_RX) != 0;
+       pauseparam->tx_pause = (pi->link_cfg.advertised_fc & PAUSE_TX) != 0;
 }
 
 /*
index ccca67c..57cfd10 100644 (file)
@@ -135,6 +135,7 @@ struct link_config {
 
        enum cc_pause   requested_fc;   /* flow control user has requested */
        enum cc_pause   fc;             /* actual link flow control */
+       enum cc_pause   advertised_fc;  /* actual advertised flow control */
 
        enum cc_fec     auto_fec;       /* Forward Error Correction: */
        enum cc_fec     requested_fec;  /*   "automatic" (IEEE 802.3), */
index 8a389d6..9d49ff2 100644 (file)
@@ -1913,16 +1913,16 @@ static const char *t4vf_link_down_rc_str(unsigned char link_down_rc)
 static void t4vf_handle_get_port_info(struct port_info *pi,
                                      const struct fw_port_cmd *cmd)
 {
-       int action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
-       struct adapter *adapter = pi->adapter;
+       fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
        struct link_config *lc = &pi->link_cfg;
-       int link_ok, linkdnrc;
-       enum fw_port_type port_type;
+       struct adapter *adapter = pi->adapter;
+       unsigned int speed, fc, fec, adv_fc;
        enum fw_port_module_type mod_type;
-       unsigned int speed, fc, fec;
-       fw_port_cap32_t pcaps, acaps, lpacaps, linkattr;
+       int action, link_ok, linkdnrc;
+       enum fw_port_type port_type;
 
        /* Extract the various fields from the Port Information message. */
+       action = FW_PORT_CMD_ACTION_G(be32_to_cpu(cmd->action_to_len16));
        switch (action) {
        case FW_PORT_ACTION_GET_PORT_INFO: {
                u32 lstatus = be32_to_cpu(cmd->u.info.lstatus_to_modtype);
@@ -1982,6 +1982,7 @@ static void t4vf_handle_get_port_info(struct port_info *pi,
        }
 
        fec = fwcap_to_cc_fec(acaps);
+       adv_fc = fwcap_to_cc_pause(acaps);
        fc = fwcap_to_cc_pause(linkattr);
        speed = fwcap_to_speed(linkattr);
 
@@ -2012,7 +2013,9 @@ static void t4vf_handle_get_port_info(struct port_info *pi,
        }
 
        if (link_ok != lc->link_ok || speed != lc->speed ||
-           fc != lc->fc || fec != lc->fec) {   /* something changed */
+           fc != lc->fc || adv_fc != lc->advertised_fc ||
+           fec != lc->fec) {
+               /* something changed */
                if (!link_ok && lc->link_ok) {
                        lc->link_down_rc = linkdnrc;
                        dev_warn_ratelimited(adapter->pdev_dev,
@@ -2022,6 +2025,7 @@ static void t4vf_handle_get_port_info(struct port_info *pi,
                }
                lc->link_ok = link_ok;
                lc->speed = speed;
+               lc->advertised_fc = adv_fc;
                lc->fc = fc;
                lc->fec = fec;
 
index a8f4c69..2814b96 100644 (file)
@@ -576,6 +576,8 @@ static int gmac_setup_txqs(struct net_device *netdev)
 
        if (port->txq_dma_base & ~DMA_Q_BASE_MASK) {
                dev_warn(geth->dev, "TX queue base is not aligned\n");
+               dma_free_coherent(geth->dev, len * sizeof(*desc_ring),
+                                 desc_ring, port->txq_dma_base);
                kfree(skb_tab);
                return -ENOMEM;
        }
index 5bb5abf..022a54a 100644 (file)
@@ -23,7 +23,7 @@ struct be_ethtool_stat {
 };
 
 enum {DRVSTAT_TX, DRVSTAT_RX, DRVSTAT};
-#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
+#define FIELDINFO(_struct, field) sizeof_field(_struct, field), \
                                        offsetof(_struct, field)
 #define DRVSTAT_TX_INFO(field) #field, DRVSTAT_TX,\
                                        FIELDINFO(struct be_tx_stats, field)
index 6a9d12d..a301f00 100644 (file)
@@ -1719,7 +1719,7 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
        int page_offset;
        unsigned int sz;
        int *count_ptr;
-       int i;
+       int i, j;
 
        vaddr = phys_to_virt(addr);
        WARN_ON(!IS_ALIGNED((unsigned long)vaddr, SMP_CACHE_BYTES));
@@ -1736,14 +1736,14 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
                WARN_ON(!IS_ALIGNED((unsigned long)sg_vaddr,
                                    SMP_CACHE_BYTES));
 
+               dma_unmap_page(priv->rx_dma_dev, sg_addr,
+                              DPAA_BP_RAW_SIZE, DMA_FROM_DEVICE);
+
                /* We may use multiple Rx pools */
                dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
                if (!dpaa_bp)
                        goto free_buffers;
 
-               count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
-               dma_unmap_page(priv->rx_dma_dev, sg_addr,
-                              DPAA_BP_RAW_SIZE, DMA_FROM_DEVICE);
                if (!skb) {
                        sz = dpaa_bp->size +
                                SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
@@ -1786,7 +1786,9 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
                        skb_add_rx_frag(skb, i - 1, head_page, frag_off,
                                        frag_len, dpaa_bp->size);
                }
+
                /* Update the pool count for the current {cpu x bpool} */
+               count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
                (*count_ptr)--;
 
                if (qm_sg_entry_is_final(&sgt[i]))
@@ -1800,26 +1802,25 @@ static struct sk_buff *sg_fd_to_skb(const struct dpaa_priv *priv,
        return skb;
 
 free_buffers:
-       /* compensate sw bpool counter changes */
-       for (i--; i >= 0; i--) {
-               dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
-               if (dpaa_bp) {
-                       count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
-                       (*count_ptr)++;
-               }
-       }
        /* free all the SG entries */
-       for (i = 0; i < DPAA_SGT_MAX_ENTRIES ; i++) {
-               sg_addr = qm_sg_addr(&sgt[i]);
+       for (j = 0; j < DPAA_SGT_MAX_ENTRIES ; j++) {
+               sg_addr = qm_sg_addr(&sgt[j]);
                sg_vaddr = phys_to_virt(sg_addr);
+               /* all pages 0..i were unmaped */
+               if (j > i)
+                       dma_unmap_page(priv->rx_dma_dev, qm_sg_addr(&sgt[j]),
+                                      DPAA_BP_RAW_SIZE, DMA_FROM_DEVICE);
                free_pages((unsigned long)sg_vaddr, 0);
-               dpaa_bp = dpaa_bpid2pool(sgt[i].bpid);
-               if (dpaa_bp) {
-                       count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
-                       (*count_ptr)--;
+               /* counters 0..i-1 were decremented */
+               if (j >= i) {
+                       dpaa_bp = dpaa_bpid2pool(sgt[j].bpid);
+                       if (dpaa_bp) {
+                               count_ptr = this_cpu_ptr(dpaa_bp->percpu_count);
+                               (*count_ptr)--;
+                       }
                }
 
-               if (qm_sg_entry_is_final(&sgt[i]))
+               if (qm_sg_entry_is_final(&sgt[j]))
                        break;
        }
        /* free the SGT fragment */
index a9503ae..6437fe6 100644 (file)
@@ -160,10 +160,10 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
        irq = mc_dev->irqs[0];
        ptp_qoriq->irq = irq->msi_desc->irq;
 
-       err = devm_request_threaded_irq(dev, ptp_qoriq->irq, NULL,
-                                       dpaa2_ptp_irq_handler_thread,
-                                       IRQF_NO_SUSPEND | IRQF_ONESHOT,
-                                       dev_name(dev), ptp_qoriq);
+       err = request_threaded_irq(ptp_qoriq->irq, NULL,
+                                  dpaa2_ptp_irq_handler_thread,
+                                  IRQF_NO_SUSPEND | IRQF_ONESHOT,
+                                  dev_name(dev), ptp_qoriq);
        if (err < 0) {
                dev_err(dev, "devm_request_threaded_irq(): %d\n", err);
                goto err_free_mc_irq;
@@ -173,18 +173,20 @@ static int dpaa2_ptp_probe(struct fsl_mc_device *mc_dev)
                                   DPRTC_IRQ_INDEX, 1);
        if (err < 0) {
                dev_err(dev, "dprtc_set_irq_enable(): %d\n", err);
-               goto err_free_mc_irq;
+               goto err_free_threaded_irq;
        }
 
        err = ptp_qoriq_init(ptp_qoriq, base, &dpaa2_ptp_caps);
        if (err)
-               goto err_free_mc_irq;
+               goto err_free_threaded_irq;
 
        dpaa2_phc_index = ptp_qoriq->phc_index;
        dev_set_drvdata(dev, ptp_qoriq);
 
        return 0;
 
+err_free_threaded_irq:
+       free_irq(ptp_qoriq->irq, ptp_qoriq);
 err_free_mc_irq:
        fsl_mc_free_irqs(mc_dev);
 err_unmap:
index 05c1899..9294027 100644 (file)
@@ -2199,8 +2199,14 @@ static void fec_enet_get_regs(struct net_device *ndev,
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
        u32 __iomem *theregs = (u32 __iomem *)fep->hwp;
+       struct device *dev = &fep->pdev->dev;
        u32 *buf = (u32 *)regbuf;
        u32 i, off;
+       int ret;
+
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
+               return;
 
        regs->version = fec_enet_register_version;
 
@@ -2216,6 +2222,9 @@ static void fec_enet_get_regs(struct net_device *ndev,
                off >>= 2;
                buf[off] = readl(&theregs[off]);
        }
+
+       pm_runtime_mark_last_busy(dev);
+       pm_runtime_put_autosuspend(dev);
 }
 
 static int fec_enet_get_ts_info(struct net_device *ndev,
index edec61d..9f52e72 100644 (file)
@@ -418,8 +418,6 @@ bool gve_clean_rx_done(struct gve_rx_ring *rx, int budget,
        rx->cnt = cnt;
        rx->fill_cnt += work_done;
 
-       /* restock desc ring slots */
-       dma_wmb();      /* Ensure descs are visible before ringing doorbell */
        gve_rx_write_doorbell(priv, rx);
        return gve_rx_work_pending(rx);
 }
index f488943..d0244fe 100644 (file)
@@ -487,10 +487,6 @@ netdev_tx_t gve_tx(struct sk_buff *skb, struct net_device *dev)
                 * may have added descriptors without ringing the doorbell.
                 */
 
-               /* Ensure tx descs from a prior gve_tx are visible before
-                * ringing doorbell.
-                */
-               dma_wmb();
                gve_tx_put_doorbell(priv, tx->q_resources, tx->req);
                return NETDEV_TX_BUSY;
        }
@@ -505,8 +501,6 @@ netdev_tx_t gve_tx(struct sk_buff *skb, struct net_device *dev)
        if (!netif_xmit_stopped(tx->netdev_txq) && netdev_xmit_more())
                return NETDEV_TX_OK;
 
-       /* Ensure tx descs are visible before ringing doorbell */
-       dma_wmb();
        gve_tx_put_doorbell(priv, tx->q_resources, tx->req);
        return NETDEV_TX_OK;
 }
index 3e9b6d5..150a8cc 100644 (file)
@@ -543,9 +543,9 @@ hip04_mac_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        skb_tx_timestamp(skb);
 
        hip04_set_xmit_desc(priv, phys);
-       priv->tx_head = TX_NEXT(tx_head);
        count++;
        netdev_sent_queue(ndev, skb->len);
+       priv->tx_head = TX_NEXT(tx_head);
 
        stats->tx_bytes += skb->len;
        stats->tx_packets++;
index 14ab204..eb69e5c 100644 (file)
@@ -565,7 +565,6 @@ static int hns_nic_poll_rx_skb(struct hns_nic_ring_data *ring_data,
        skb = *out_skb = napi_alloc_skb(&ring_data->napi,
                                        HNS_RX_HEAD_SIZE);
        if (unlikely(!skb)) {
-               netdev_err(ndev, "alloc rx skb fail\n");
                ring->stats.sw_err_cnt++;
                return -ENOMEM;
        }
@@ -1056,7 +1055,6 @@ static int hns_nic_common_poll(struct napi_struct *napi, int budget)
                container_of(napi, struct hns_nic_ring_data, napi);
        struct hnae_ring *ring = ring_data->ring;
 
-try_again:
        clean_complete += ring_data->poll_one(
                                ring_data, budget - clean_complete,
                                ring_data->ex_process);
@@ -1066,7 +1064,7 @@ try_again:
                        napi_complete(napi);
                        ring->q->handle->dev->ops->toggle_ring_irq(ring, 0);
                } else {
-                       goto try_again;
+                       return budget;
                }
        }
 
index 69545dd..b3deb5e 100644 (file)
@@ -54,6 +54,8 @@ MODULE_PARM_DESC(debug, " Network interface message level setting");
 #define HNS3_INNER_VLAN_TAG    1
 #define HNS3_OUTER_VLAN_TAG    2
 
+#define HNS3_MIN_TX_LEN                33U
+
 /* hns3_pci_tbl - PCI Device ID Table
  *
  * Last entry must be all 0s
@@ -1405,6 +1407,10 @@ netdev_tx_t hns3_nic_net_xmit(struct sk_buff *skb, struct net_device *netdev)
        int bd_num = 0;
        int ret;
 
+       /* Hardware can only handle short frames above 32 bytes */
+       if (skb_put_padto(skb, HNS3_MIN_TX_LEN))
+               return NETDEV_TX_OK;
+
        /* Prefetch the data used later */
        prefetch(skb->data);
 
index d862e9b..13dbd24 100644 (file)
@@ -10240,7 +10240,7 @@ static int hclge_get_dfx_reg_len(struct hclge_dev *hdev, int *len)
                return ret;
        }
 
-       data_len_per_desc = FIELD_SIZEOF(struct hclge_desc, data);
+       data_len_per_desc = sizeof_field(struct hclge_desc, data);
        *len = 0;
        for (i = 0; i < dfx_reg_type_num; i++) {
                bd_num = bd_num_list[i];
index fbc39a2..180224e 100644 (file)
@@ -614,7 +614,7 @@ static void hclge_tm_vport_tc_info_update(struct hclge_vport *vport)
        }
 
        memcpy(kinfo->prio_tc, hdev->tm_info.prio_tc,
-              FIELD_SIZEOF(struct hnae3_knic_private_info, prio_tc));
+              sizeof_field(struct hnae3_knic_private_info, prio_tc));
 }
 
 static void hclge_tm_vport_info_update(struct hclge_dev *hdev)
index 60ec48f..966aea9 100644 (file)
@@ -450,7 +450,7 @@ static u32 hinic_get_rxfh_indir_size(struct net_device *netdev)
 
 #define HINIC_FUNC_STAT(_stat_item) {  \
        .name = #_stat_item, \
-       .size = FIELD_SIZEOF(struct hinic_vport_stats, _stat_item), \
+       .size = sizeof_field(struct hinic_vport_stats, _stat_item), \
        .offset = offsetof(struct hinic_vport_stats, _stat_item) \
 }
 
@@ -477,7 +477,7 @@ static struct hinic_stats hinic_function_stats[] = {
 
 #define HINIC_PORT_STAT(_stat_item) { \
        .name = #_stat_item, \
-       .size = FIELD_SIZEOF(struct hinic_phy_port_stats, _stat_item), \
+       .size = sizeof_field(struct hinic_phy_port_stats, _stat_item), \
        .offset = offsetof(struct hinic_phy_port_stats, _stat_item) \
 }
 
@@ -571,7 +571,7 @@ static struct hinic_stats hinic_port_stats[] = {
 
 #define HINIC_TXQ_STAT(_stat_item) { \
        .name = "txq%d_"#_stat_item, \
-       .size = FIELD_SIZEOF(struct hinic_txq_stats, _stat_item), \
+       .size = sizeof_field(struct hinic_txq_stats, _stat_item), \
        .offset = offsetof(struct hinic_txq_stats, _stat_item) \
 }
 
@@ -586,7 +586,7 @@ static struct hinic_stats hinic_tx_queue_stats[] = {
 
 #define HINIC_RXQ_STAT(_stat_item) { \
        .name = "rxq%d_"#_stat_item, \
-       .size = FIELD_SIZEOF(struct hinic_rxq_stats, _stat_item), \
+       .size = sizeof_field(struct hinic_rxq_stats, _stat_item), \
        .offset = offsetof(struct hinic_rxq_stats, _stat_item) \
 }
 
index c900807..830791a 100644 (file)
@@ -184,7 +184,7 @@ static int ibmvnic_wait_for_completion(struct ibmvnic_adapter *adapter,
                        netdev_err(netdev, "Device down!\n");
                        return -ENODEV;
                }
-               if (retry--)
+               if (!retry--)
                        break;
                if (wait_for_completion_timeout(comp_done, div_timeout))
                        return 0;
index 6c51b1b..37a2314 100644 (file)
@@ -185,13 +185,12 @@ struct e1000_phy_regs {
 
 /* board specific private data structure */
 struct e1000_adapter {
+       struct timer_list watchdog_timer;
        struct timer_list phy_info_timer;
        struct timer_list blink_timer;
 
        struct work_struct reset_task;
-       struct delayed_work watchdog_task;
-
-       struct workqueue_struct *e1000_workqueue;
+       struct work_struct watchdog_task;
 
        const struct e1000_info *ei;
 
index fe7997c..7c5b18d 100644 (file)
@@ -1780,8 +1780,7 @@ static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data)
                }
                /* guard against interrupt when we're going down */
                if (!test_bit(__E1000_DOWN, &adapter->state))
-                       mod_delayed_work(adapter->e1000_workqueue,
-                                        &adapter->watchdog_task, HZ);
+                       mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
        /* Reset on uncorrectable ECC error */
@@ -1861,8 +1860,7 @@ static irqreturn_t e1000_intr(int __always_unused irq, void *data)
                }
                /* guard against interrupt when we're going down */
                if (!test_bit(__E1000_DOWN, &adapter->state))
-                       mod_delayed_work(adapter->e1000_workqueue,
-                                        &adapter->watchdog_task, HZ);
+                       mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
        /* Reset on uncorrectable ECC error */
@@ -1907,8 +1905,7 @@ static irqreturn_t e1000_msix_other(int __always_unused irq, void *data)
                hw->mac.get_link_status = true;
                /* guard against interrupt when we're going down */
                if (!test_bit(__E1000_DOWN, &adapter->state))
-                       mod_delayed_work(adapter->e1000_workqueue,
-                                        &adapter->watchdog_task, HZ);
+                       mod_timer(&adapter->watchdog_timer, jiffies + 1);
        }
 
        if (!test_bit(__E1000_DOWN, &adapter->state))
@@ -4284,6 +4281,7 @@ void e1000e_down(struct e1000_adapter *adapter, bool reset)
 
        napi_synchronize(&adapter->napi);
 
+       del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
 
        spin_lock(&adapter->stats64_lock);
@@ -5155,11 +5153,25 @@ static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter)
        }
 }
 
+/**
+ * e1000_watchdog - Timer Call-back
+ * @data: pointer to adapter cast into an unsigned long
+ **/
+static void e1000_watchdog(struct timer_list *t)
+{
+       struct e1000_adapter *adapter = from_timer(adapter, t, watchdog_timer);
+
+       /* Do the rest outside of interrupt context */
+       schedule_work(&adapter->watchdog_task);
+
+       /* TODO: make this use queue_delayed_work() */
+}
+
 static void e1000_watchdog_task(struct work_struct *work)
 {
        struct e1000_adapter *adapter = container_of(work,
                                                     struct e1000_adapter,
-                                                    watchdog_task.work);
+                                                    watchdog_task);
        struct net_device *netdev = adapter->netdev;
        struct e1000_mac_info *mac = &adapter->hw.mac;
        struct e1000_phy_info *phy = &adapter->hw.phy;
@@ -5407,9 +5419,8 @@ link_up:
 
        /* Reset the timer */
        if (!test_bit(__E1000_DOWN, &adapter->state))
-               queue_delayed_work(adapter->e1000_workqueue,
-                                  &adapter->watchdog_task,
-                                  round_jiffies(2 * HZ));
+               mod_timer(&adapter->watchdog_timer,
+                         round_jiffies(jiffies + 2 * HZ));
 }
 
 #define E1000_TX_FLAGS_CSUM            0x00000001
@@ -7449,21 +7460,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                goto err_eeprom;
        }
 
-       adapter->e1000_workqueue = alloc_workqueue("%s", WQ_MEM_RECLAIM, 0,
-                                                  e1000e_driver_name);
-
-       if (!adapter->e1000_workqueue) {
-               err = -ENOMEM;
-               goto err_workqueue;
-       }
-
-       INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog_task);
-       queue_delayed_work(adapter->e1000_workqueue, &adapter->watchdog_task,
-                          0);
-
+       timer_setup(&adapter->watchdog_timer, e1000_watchdog, 0);
        timer_setup(&adapter->phy_info_timer, e1000_update_phy_info, 0);
 
        INIT_WORK(&adapter->reset_task, e1000_reset_task);
+       INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task);
        INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround);
        INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task);
        INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang);
@@ -7557,9 +7558,6 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 
 err_register:
-       flush_workqueue(adapter->e1000_workqueue);
-       destroy_workqueue(adapter->e1000_workqueue);
-err_workqueue:
        if (!(adapter->flags & FLAG_HAS_AMT))
                e1000e_release_hw_control(adapter);
 err_eeprom:
@@ -7604,17 +7602,15 @@ static void e1000_remove(struct pci_dev *pdev)
         * from being rescheduled.
         */
        set_bit(__E1000_DOWN, &adapter->state);
+       del_timer_sync(&adapter->watchdog_timer);
        del_timer_sync(&adapter->phy_info_timer);
 
        cancel_work_sync(&adapter->reset_task);
+       cancel_work_sync(&adapter->watchdog_task);
        cancel_work_sync(&adapter->downshift_task);
        cancel_work_sync(&adapter->update_phy_task);
        cancel_work_sync(&adapter->print_hang_task);
 
-       cancel_delayed_work(&adapter->watchdog_task);
-       flush_workqueue(adapter->e1000_workqueue);
-       destroy_workqueue(adapter->e1000_workqueue);
-
        if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) {
                cancel_work_sync(&adapter->tx_hwtstamp_work);
                if (adapter->tx_hwtstamp_skb) {
index c681d2d..68edf55 100644 (file)
@@ -18,7 +18,7 @@ struct fm10k_stats {
 
 #define FM10K_STAT_FIELDS(_type, _name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
+       .sizeof_stat = sizeof_field(_type, _stat), \
        .stat_offset = offsetof(_type, _stat) \
 }
 
index cb63673..4833187 100644 (file)
@@ -1152,7 +1152,7 @@ void i40e_set_fec_in_flags(u8 fec_cfg, u32 *flags);
 
 static inline bool i40e_enabled_xdp_vsi(struct i40e_vsi *vsi)
 {
-       return !!vsi->xdp_prog;
+       return !!READ_ONCE(vsi->xdp_prog);
 }
 
 int i40e_create_queue_channel(struct i40e_vsi *vsi, struct i40e_channel *ch);
index 9f0a4e9..37514a7 100644 (file)
@@ -536,6 +536,11 @@ static void i40e_set_hw_flags(struct i40e_hw *hw)
                    (aq->api_maj_ver == 1 &&
                     aq->api_min_ver >= I40E_MINOR_VER_FW_LLDP_STOPPABLE_X722))
                        hw->flags |= I40E_HW_FLAG_FW_LLDP_STOPPABLE;
+
+               if (aq->api_maj_ver > 1 ||
+                   (aq->api_maj_ver == 1 &&
+                    aq->api_min_ver >= I40E_MINOR_VER_GET_LINK_INFO_X722))
+                       hw->flags |= I40E_HW_FLAG_AQ_PHY_ACCESS_CAPABLE;
                /* fall through */
        default:
                break;
index d24d873..317f3f1 100644 (file)
@@ -43,7 +43,7 @@ struct i40e_stats {
  */
 #define I40E_STAT(_type, _name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
+       .sizeof_stat = sizeof_field(_type, _stat), \
        .stat_offset = offsetof(_type, _stat) \
 }
 
index be24d42..a3da422 100644 (file)
@@ -659,7 +659,7 @@ i40e_status i40e_shutdown_lan_hmc(struct i40e_hw *hw)
 
 #define I40E_HMC_STORE(_struct, _ele)          \
        offsetof(struct _struct, _ele),         \
-       FIELD_SIZEOF(struct _struct, _ele)
+       sizeof_field(struct _struct, _ele)
 
 struct i40e_context_ele {
        u16 offset;
index 1ccabea..2c5af6d 100644 (file)
@@ -6823,8 +6823,8 @@ void i40e_down(struct i40e_vsi *vsi)
        for (i = 0; i < vsi->num_queue_pairs; i++) {
                i40e_clean_tx_ring(vsi->tx_rings[i]);
                if (i40e_enabled_xdp_vsi(vsi)) {
-                       /* Make sure that in-progress ndo_xdp_xmit
-                        * calls are completed.
+                       /* Make sure that in-progress ndo_xdp_xmit and
+                        * ndo_xsk_wakeup calls are completed.
                         */
                        synchronize_rcu();
                        i40e_clean_tx_ring(vsi->xdp_rings[i]);
@@ -12546,8 +12546,12 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi,
 
        old_prog = xchg(&vsi->xdp_prog, prog);
 
-       if (need_reset)
+       if (need_reset) {
+               if (!prog)
+                       /* Wait until ndo_xsk_wakeup completes. */
+                       synchronize_rcu();
                i40e_reset_and_rebuild(pf, true, true);
+       }
 
        for (i = 0; i < vsi->num_queue_pairs; i++)
                WRITE_ONCE(vsi->rx_rings[i]->xdp_prog, vsi->xdp_prog);
index 6a3f0fc..69523ac 100644 (file)
@@ -2322,6 +2322,22 @@ static int i40e_ctrl_vf_rx_rings(struct i40e_vsi *vsi, unsigned long q_map,
 }
 
 /**
+ * i40e_vc_validate_vqs_bitmaps - validate Rx/Tx queue bitmaps from VIRTHCHNL
+ * @vqs: virtchnl_queue_select structure containing bitmaps to validate
+ *
+ * Returns true if validation was successful, else false.
+ */
+static bool i40e_vc_validate_vqs_bitmaps(struct virtchnl_queue_select *vqs)
+{
+       if ((!vqs->rx_queues && !vqs->tx_queues) ||
+           vqs->rx_queues >= BIT(I40E_MAX_VF_QUEUES) ||
+           vqs->tx_queues >= BIT(I40E_MAX_VF_QUEUES))
+               return false;
+
+       return true;
+}
+
+/**
  * i40e_vc_enable_queues_msg
  * @vf: pointer to the VF info
  * @msg: pointer to the msg buffer
@@ -2346,7 +2362,7 @@ static int i40e_vc_enable_queues_msg(struct i40e_vf *vf, u8 *msg)
                goto error_param;
        }
 
-       if ((0 == vqs->rx_queues) && (0 == vqs->tx_queues)) {
+       if (i40e_vc_validate_vqs_bitmaps(vqs)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
@@ -2408,9 +2424,7 @@ static int i40e_vc_disable_queues_msg(struct i40e_vf *vf, u8 *msg)
                goto error_param;
        }
 
-       if ((vqs->rx_queues == 0 && vqs->tx_queues == 0) ||
-           vqs->rx_queues > I40E_MAX_VF_QUEUES ||
-           vqs->tx_queues > I40E_MAX_VF_QUEUES) {
+       if (i40e_vc_validate_vqs_bitmaps(vqs)) {
                aq_ret = I40E_ERR_PARAM;
                goto error_param;
        }
index d07e1a8..f73cd91 100644 (file)
@@ -787,8 +787,12 @@ int i40e_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
 {
        struct i40e_netdev_priv *np = netdev_priv(dev);
        struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
        struct i40e_ring *ring;
 
+       if (test_bit(__I40E_CONFIG_BUSY, pf->state))
+               return -ENETDOWN;
+
        if (test_bit(__I40E_VSI_DOWN, vsi->state))
                return -ENETDOWN;
 
index 29de3ae..bd1b1ed 100644 (file)
@@ -415,4 +415,6 @@ void iavf_enable_channels(struct iavf_adapter *adapter);
 void iavf_disable_channels(struct iavf_adapter *adapter);
 void iavf_add_cloud_filter(struct iavf_adapter *adapter);
 void iavf_del_cloud_filter(struct iavf_adapter *adapter);
+struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
+                                       const u8 *macaddr);
 #endif /* _IAVF_H_ */
index dad3eec..84c3d8d 100644 (file)
@@ -42,7 +42,7 @@ struct iavf_stats {
  */
 #define IAVF_STAT(_type, _name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
+       .sizeof_stat = sizeof_field(_type, _stat), \
        .stat_offset = offsetof(_type, _stat) \
 }
 
index 821987d..8e16be9 100644 (file)
@@ -743,9 +743,8 @@ iavf_mac_filter *iavf_find_filter(struct iavf_adapter *adapter,
  *
  * Returns ptr to the filter object or NULL when no memory available.
  **/
-static struct
-iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
-                                const u8 *macaddr)
+struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
+                                       const u8 *macaddr)
 {
        struct iavf_mac_filter *f;
 
@@ -2065,9 +2064,9 @@ static void iavf_reset_task(struct work_struct *work)
        struct virtchnl_vf_resource *vfres = adapter->vf_res;
        struct net_device *netdev = adapter->netdev;
        struct iavf_hw *hw = &adapter->hw;
+       struct iavf_mac_filter *f, *ftmp;
        struct iavf_vlan_filter *vlf;
        struct iavf_cloud_filter *cf;
-       struct iavf_mac_filter *f;
        u32 reg_val;
        int i = 0, err;
        bool running;
@@ -2181,6 +2180,16 @@ continue_reset:
 
        spin_lock_bh(&adapter->mac_vlan_list_lock);
 
+       /* Delete filter for the current MAC address, it could have
+        * been changed by the PF via administratively set MAC.
+        * Will be re-added via VIRTCHNL_OP_GET_VF_RESOURCES.
+        */
+       list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+               if (ether_addr_equal(f->macaddr, adapter->hw.mac.addr)) {
+                       list_del(&f->list);
+                       kfree(f);
+               }
+       }
        /* re-add all MAC filters */
        list_for_each_entry(f, &adapter->mac_filter_list, list) {
                f->add = true;
index c46770e..1ab9cb3 100644 (file)
@@ -1359,6 +1359,9 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                        ether_addr_copy(netdev->perm_addr,
                                        adapter->hw.mac.addr);
                }
+               spin_lock_bh(&adapter->mac_vlan_list_lock);
+               iavf_add_filter(adapter, adapter->hw.mac.addr);
+               spin_unlock_bh(&adapter->mac_vlan_list_lock);
                iavf_process_config(adapter);
                }
                break;
index aec3c6c..9ebd93e 100644 (file)
@@ -15,7 +15,7 @@ struct ice_stats {
 
 #define ICE_STAT(_type, _name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(_type, _stat), \
+       .sizeof_stat = sizeof_field(_type, _stat), \
        .stat_offset = offsetof(_type, _stat) \
 }
 
@@ -36,10 +36,10 @@ static int ice_q_stats_len(struct net_device *netdev)
 #define ICE_VSI_STATS_LEN      ARRAY_SIZE(ice_gstrings_vsi_stats)
 
 #define ICE_PFC_STATS_LEN ( \
-               (FIELD_SIZEOF(struct ice_pf, stats.priority_xoff_rx) + \
-                FIELD_SIZEOF(struct ice_pf, stats.priority_xon_rx) + \
-                FIELD_SIZEOF(struct ice_pf, stats.priority_xoff_tx) + \
-                FIELD_SIZEOF(struct ice_pf, stats.priority_xon_tx)) \
+               (sizeof_field(struct ice_pf, stats.priority_xoff_rx) + \
+                sizeof_field(struct ice_pf, stats.priority_xon_rx) + \
+                sizeof_field(struct ice_pf, stats.priority_xoff_tx) + \
+                sizeof_field(struct ice_pf, stats.priority_xon_tx)) \
                 / sizeof(u64))
 #define ICE_ALL_STATS_LEN(n)   (ICE_PF_STATS_LEN + ICE_PFC_STATS_LEN + \
                                 ICE_VSI_STATS_LEN + ice_q_stats_len(n))
index ad34f22..0997d35 100644 (file)
@@ -302,7 +302,7 @@ struct ice_ctx_ele {
 
 #define ICE_CTX_STORE(_struct, _ele, _width, _lsb) {   \
        .offset = offsetof(struct _struct, _ele),       \
-       .size_of = FIELD_SIZEOF(struct _struct, _ele),  \
+       .size_of = sizeof_field(struct _struct, _ele),  \
        .width = _width,                                \
        .lsb = _lsb,                                    \
 }
index 8a6ef35..438b42c 100644 (file)
@@ -530,7 +530,7 @@ static s32 igb_set_sfp_media_type_82575(struct e1000_hw *hw)
                dev_spec->module_plugged = true;
                if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) {
                        hw->phy.media_type = e1000_media_type_internal_serdes;
-               } else if (eth_flags->e100_base_fx) {
+               } else if (eth_flags->e100_base_fx || eth_flags->e100_base_lx) {
                        dev_spec->sgmii_active = true;
                        hw->phy.media_type = e1000_media_type_internal_serdes;
                } else if (eth_flags->e1000_base_t) {
@@ -657,14 +657,10 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw)
                        break;
                }
 
-               /* do not change link mode for 100BaseFX */
-               if (dev_spec->eth_flags.e100_base_fx)
-                       break;
-
                /* change current link mode setting */
                ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
 
-               if (hw->phy.media_type == e1000_media_type_copper)
+               if (dev_spec->sgmii_active)
                        ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII;
                else
                        ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
index 3182b05..445fbdc 100644 (file)
@@ -26,7 +26,7 @@ struct igb_stats {
 
 #define IGB_STAT(_name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(struct igb_adapter, _stat), \
+       .sizeof_stat = sizeof_field(struct igb_adapter, _stat), \
        .stat_offset = offsetof(struct igb_adapter, _stat) \
 }
 static const struct igb_stats igb_gstrings_stats[] = {
@@ -76,7 +76,7 @@ static const struct igb_stats igb_gstrings_stats[] = {
 
 #define IGB_NETDEV_STAT(_net_stat) { \
        .stat_string = __stringify(_net_stat), \
-       .sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \
+       .sizeof_stat = sizeof_field(struct rtnl_link_stats64, _net_stat), \
        .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \
 }
 static const struct igb_stats igb_gstrings_net_stats[] = {
@@ -181,7 +181,7 @@ static int igb_get_link_ksettings(struct net_device *netdev,
                                advertising &= ~ADVERTISED_1000baseKX_Full;
                        }
                }
-               if (eth_flags->e100_base_fx) {
+               if (eth_flags->e100_base_fx || eth_flags->e100_base_lx) {
                        supported |= SUPPORTED_100baseT_Full;
                        advertising |= ADVERTISED_100baseT_Full;
                }
index ac98f1d..455c1cd 100644 (file)
@@ -16,7 +16,7 @@ struct igc_stats {
 
 #define IGC_STAT(_name, _stat) { \
        .stat_string = _name, \
-       .sizeof_stat = FIELD_SIZEOF(struct igc_adapter, _stat), \
+       .sizeof_stat = sizeof_field(struct igc_adapter, _stat), \
        .stat_offset = offsetof(struct igc_adapter, _stat) \
 }
 
@@ -67,7 +67,7 @@ static const struct igc_stats igc_gstrings_stats[] = {
 
 #define IGC_NETDEV_STAT(_net_stat) { \
        .stat_string = __stringify(_net_stat), \
-       .sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \
+       .sizeof_stat = sizeof_field(struct rtnl_link_stats64, _net_stat), \
        .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \
 }
 
index c8c93ac..c65eb1a 100644 (file)
@@ -19,10 +19,10 @@ struct ixgb_stats {
 };
 
 #define IXGB_STAT(m)           IXGB_STATS, \
-                               FIELD_SIZEOF(struct ixgb_adapter, m), \
+                               sizeof_field(struct ixgb_adapter, m), \
                                offsetof(struct ixgb_adapter, m)
 #define IXGB_NETDEV_STAT(m)    NETDEV_STATS, \
-                               FIELD_SIZEOF(struct net_device, m), \
+                               sizeof_field(struct net_device, m), \
                                offsetof(struct net_device, m)
 
 static struct ixgb_stats ixgb_gstrings_stats[] = {
index 25c097c..a2b2ad1 100644 (file)
@@ -5239,7 +5239,7 @@ static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
        struct ixgbe_hw *hw = &adapter->hw;
        struct hlist_node *node2;
        struct ixgbe_fdir_filter *filter;
-       u64 action;
+       u8 queue;
 
        spin_lock(&adapter->fdir_perfect_lock);
 
@@ -5248,17 +5248,34 @@ static void ixgbe_fdir_filter_restore(struct ixgbe_adapter *adapter)
 
        hlist_for_each_entry_safe(filter, node2,
                                  &adapter->fdir_filter_list, fdir_node) {
-               action = filter->action;
-               if (action != IXGBE_FDIR_DROP_QUEUE && action != 0)
-                       action =
-                       (action >> ETHTOOL_RX_FLOW_SPEC_RING_VF_OFF) - 1;
+               if (filter->action == IXGBE_FDIR_DROP_QUEUE) {
+                       queue = IXGBE_FDIR_DROP_QUEUE;
+               } else {
+                       u32 ring = ethtool_get_flow_spec_ring(filter->action);
+                       u8 vf = ethtool_get_flow_spec_ring_vf(filter->action);
+
+                       if (!vf && (ring >= adapter->num_rx_queues)) {
+                               e_err(drv, "FDIR restore failed without VF, ring: %u\n",
+                                     ring);
+                               continue;
+                       } else if (vf &&
+                                  ((vf > adapter->num_vfs) ||
+                                    ring >= adapter->num_rx_queues_per_pool)) {
+                               e_err(drv, "FDIR restore failed with VF, vf: %hhu, ring: %u\n",
+                                     vf, ring);
+                               continue;
+                       }
+
+                       /* Map the ring onto the absolute queue index */
+                       if (!vf)
+                               queue = adapter->rx_ring[ring]->reg_idx;
+                       else
+                               queue = ((vf - 1) *
+                                       adapter->num_rx_queues_per_pool) + ring;
+               }
 
                ixgbe_fdir_write_perfect_filter_82599(hw,
-                               &filter->filter,
-                               filter->sw_idx,
-                               (action == IXGBE_FDIR_DROP_QUEUE) ?
-                               IXGBE_FDIR_DROP_QUEUE :
-                               adapter->rx_ring[action]->reg_idx);
+                               &filter->filter, filter->sw_idx, queue);
        }
 
        spin_unlock(&adapter->fdir_perfect_lock);
@@ -10261,7 +10278,12 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
 
        /* If transitioning XDP modes reconfigure rings */
        if (need_reset) {
-               int err = ixgbe_setup_tc(dev, adapter->hw_tcs);
+               int err;
+
+               if (!prog)
+                       /* Wait until ndo_xsk_wakeup completes. */
+                       synchronize_rcu();
+               err = ixgbe_setup_tc(dev, adapter->hw_tcs);
 
                if (err) {
                        rcu_assign_pointer(adapter->xdp_prog, old_prog);
index d6feaac..b43be9f 100644 (file)
@@ -709,10 +709,14 @@ int ixgbe_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
        if (qid >= adapter->num_xdp_queues)
                return -ENXIO;
 
-       if (!adapter->xdp_ring[qid]->xsk_umem)
+       ring = adapter->xdp_ring[qid];
+
+       if (test_bit(__IXGBE_TX_DISABLED, &ring->state))
+               return -ENETDOWN;
+
+       if (!ring->xsk_umem)
                return -ENXIO;
 
-       ring = adapter->xdp_ring[qid];
        if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
                u64 eics = BIT_ULL(ring->q_vector->v_idx);
 
index 54459b6..f7f309c 100644 (file)
@@ -31,14 +31,14 @@ struct ixgbe_stats {
 #define IXGBEVF_STAT(_name, _stat) { \
        .stat_string = _name, \
        .type = IXGBEVF_STATS, \
-       .sizeof_stat = FIELD_SIZEOF(struct ixgbevf_adapter, _stat), \
+       .sizeof_stat = sizeof_field(struct ixgbevf_adapter, _stat), \
        .stat_offset = offsetof(struct ixgbevf_adapter, _stat) \
 }
 
 #define IXGBEVF_NETDEV_STAT(_net_stat) { \
        .stat_string = #_net_stat, \
        .type = NETDEV_STATS, \
-       .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \
+       .sizeof_stat = sizeof_field(struct net_device_stats, _net_stat), \
        .stat_offset = offsetof(struct net_device_stats, _net_stat) \
 }
 
index 076f2da..64ec0e7 100644 (file)
@@ -2081,11 +2081,6 @@ static int ixgbevf_write_uc_addr_list(struct net_device *netdev)
        struct ixgbe_hw *hw = &adapter->hw;
        int count = 0;
 
-       if ((netdev_uc_count(netdev)) > 10) {
-               pr_err("Too many unicast filters - No Space\n");
-               return -ENOSPC;
-       }
-
        if (!netdev_uc_empty(netdev)) {
                struct netdev_hw_addr *ha;
 
index d5b6441..65a0932 100644 (file)
@@ -1432,11 +1432,11 @@ struct mv643xx_eth_stats {
 };
 
 #define SSTAT(m)                                               \
-       { #m, FIELD_SIZEOF(struct net_device_stats, m),         \
+       { #m, sizeof_field(struct net_device_stats, m),         \
          offsetof(struct net_device, stats.m), -1 }
 
 #define MIBSTAT(m)                                             \
-       { #m, FIELD_SIZEOF(struct mib_counters, m),             \
+       { #m, sizeof_field(struct mib_counters, m),             \
          -1, offsetof(struct mv643xx_eth_private, mib_counters.m) }
 
 static const struct mv643xx_eth_stats mv643xx_eth_stats[] = {
index 71a872d..67ad8b8 100644 (file)
@@ -2081,7 +2081,11 @@ static int
 mvneta_run_xdp(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
               struct bpf_prog *prog, struct xdp_buff *xdp)
 {
-       u32 ret, act = bpf_prog_run_xdp(prog, xdp);
+       unsigned int len;
+       u32 ret, act;
+
+       len = xdp->data_end - xdp->data_hard_start - pp->rx_offset_correction;
+       act = bpf_prog_run_xdp(prog, xdp);
 
        switch (act) {
        case XDP_PASS:
@@ -2094,9 +2098,8 @@ mvneta_run_xdp(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
                if (err) {
                        ret = MVNETA_XDP_DROPPED;
                        __page_pool_put_page(rxq->page_pool,
-                                       virt_to_head_page(xdp->data),
-                                       xdp->data_end - xdp->data_hard_start,
-                                       true);
+                                            virt_to_head_page(xdp->data),
+                                            len, true);
                } else {
                        ret = MVNETA_XDP_REDIR;
                }
@@ -2106,9 +2109,8 @@ mvneta_run_xdp(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
                ret = mvneta_xdp_xmit_back(pp, xdp);
                if (ret != MVNETA_XDP_TX)
                        __page_pool_put_page(rxq->page_pool,
-                                       virt_to_head_page(xdp->data),
-                                       xdp->data_end - xdp->data_hard_start,
-                                       true);
+                                            virt_to_head_page(xdp->data),
+                                            len, true);
                break;
        default:
                bpf_warn_invalid_xdp_action(act);
@@ -2119,8 +2121,7 @@ mvneta_run_xdp(struct mvneta_port *pp, struct mvneta_rx_queue *rxq,
        case XDP_DROP:
                __page_pool_put_page(rxq->page_pool,
                                     virt_to_head_page(xdp->data),
-                                    xdp->data_end - xdp->data_hard_start,
-                                    true);
+                                    len, true);
                ret = MVNETA_XDP_DROPPED;
                break;
        }
index 62dc2f3..14e372c 100644 (file)
@@ -3680,7 +3680,7 @@ static int mvpp2_open(struct net_device *dev)
                valid = true;
        }
 
-       if (priv->hw_version == MVPP22 && port->link_irq && !port->phylink) {
+       if (priv->hw_version == MVPP22 && port->link_irq) {
                err = request_irq(port->link_irq, mvpp2_link_status_isr, 0,
                                  dev->name, port);
                if (err) {
index eaf08f7..64ed725 100644 (file)
@@ -182,7 +182,7 @@ int mlx4_crdump_collect(struct mlx4_dev *dev)
        crdump_enable_crspace_access(dev, cr_space);
 
        /* Get the available snapshot ID for the dumps */
-       id = devlink_region_shapshot_id_get(devlink);
+       id = devlink_region_snapshot_id_get(devlink);
 
        /* Try to capture dumps */
        mlx4_crdump_collect_crspace(dev, cr_space, id);
index a1202e5..8bf1f08 100644 (file)
@@ -611,7 +611,7 @@ static u32 ptys_get_active_port(struct mlx4_ptys_reg *ptys_reg)
 }
 
 #define MLX4_LINK_MODES_SZ \
-       (FIELD_SIZEOF(struct mlx4_ptys_reg, eth_proto_cap) * 8)
+       (sizeof_field(struct mlx4_ptys_reg, eth_proto_cap) * 8)
 
 enum ethtool_report {
        SUPPORTED = 0,
index 2c16add..9c84276 100644 (file)
@@ -760,7 +760,7 @@ enum {
        MLX5E_STATE_OPENED,
        MLX5E_STATE_DESTROYING,
        MLX5E_STATE_XDP_TX_ENABLED,
-       MLX5E_STATE_XDP_OPEN,
+       MLX5E_STATE_XDP_ACTIVE,
 };
 
 struct mlx5e_rqt {
index 68d5930..d48292c 100644 (file)
@@ -122,6 +122,22 @@ enum {
 #endif
 };
 
+#define MLX5E_TTC_NUM_GROUPS   3
+#define MLX5E_TTC_GROUP1_SIZE  (BIT(3) + MLX5E_NUM_TUNNEL_TT)
+#define MLX5E_TTC_GROUP2_SIZE   BIT(1)
+#define MLX5E_TTC_GROUP3_SIZE   BIT(0)
+#define MLX5E_TTC_TABLE_SIZE   (MLX5E_TTC_GROUP1_SIZE +\
+                                MLX5E_TTC_GROUP2_SIZE +\
+                                MLX5E_TTC_GROUP3_SIZE)
+
+#define MLX5E_INNER_TTC_NUM_GROUPS     3
+#define MLX5E_INNER_TTC_GROUP1_SIZE    BIT(3)
+#define MLX5E_INNER_TTC_GROUP2_SIZE    BIT(1)
+#define MLX5E_INNER_TTC_GROUP3_SIZE    BIT(0)
+#define MLX5E_INNER_TTC_TABLE_SIZE     (MLX5E_INNER_TTC_GROUP1_SIZE +\
+                                        MLX5E_INNER_TTC_GROUP2_SIZE +\
+                                        MLX5E_INNER_TTC_GROUP3_SIZE)
+
 #ifdef CONFIG_MLX5_EN_RXNFC
 
 struct mlx5e_ethtool_table {
index 1d6b588..3a97564 100644 (file)
@@ -197,9 +197,10 @@ int mlx5e_health_report(struct mlx5e_priv *priv,
                        struct devlink_health_reporter *reporter, char *err_str,
                        struct mlx5e_err_ctx *err_ctx)
 {
-       if (!reporter) {
-               netdev_err(priv->netdev, err_str);
+       netdev_err(priv->netdev, err_str);
+
+       if (!reporter)
                return err_ctx->recover(&err_ctx->ctx);
-       }
+
        return devlink_health_report(reporter, err_str, err_ctx);
 }
index 36ac1e3..d7587f4 100644 (file)
@@ -75,12 +75,18 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
 static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
 {
        set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+
+       if (priv->channels.params.xdp_prog)
+               set_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
 }
 
 static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
 {
+       if (priv->channels.params.xdp_prog)
+               clear_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
+
        clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
-       /* let other device's napi(s) see our new state */
+       /* Let other device's napi(s) and XSK wakeups see our new state. */
        synchronize_rcu();
 }
 
@@ -89,19 +95,9 @@ static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
        return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
 }
 
-static inline void mlx5e_xdp_set_open(struct mlx5e_priv *priv)
-{
-       set_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
-}
-
-static inline void mlx5e_xdp_set_closed(struct mlx5e_priv *priv)
-{
-       clear_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
-}
-
-static inline bool mlx5e_xdp_is_open(struct mlx5e_priv *priv)
+static inline bool mlx5e_xdp_is_active(struct mlx5e_priv *priv)
 {
-       return test_bit(MLX5E_STATE_XDP_OPEN, &priv->state);
+       return test_bit(MLX5E_STATE_XDP_ACTIVE, &priv->state);
 }
 
 static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
index 631af8d..c28cbae 100644 (file)
@@ -144,6 +144,7 @@ void mlx5e_close_xsk(struct mlx5e_channel *c)
 {
        clear_bit(MLX5E_CHANNEL_STATE_XSK, c->state);
        napi_synchronize(&c->napi);
+       synchronize_rcu(); /* Sync with the XSK wakeup. */
 
        mlx5e_close_rq(&c->xskrq);
        mlx5e_close_cq(&c->xskrq.cq);
index 8782747..fe2d596 100644 (file)
@@ -14,7 +14,7 @@ int mlx5e_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
        struct mlx5e_channel *c;
        u16 ix;
 
-       if (unlikely(!mlx5e_xdp_is_open(priv)))
+       if (unlikely(!mlx5e_xdp_is_active(priv)))
                return -ENETDOWN;
 
        if (unlikely(!mlx5e_qid_get_ch_if_in_group(params, qid, MLX5E_RQ_GROUP_XSK, &ix)))
index 15b7f0f..73d3dc0 100644 (file)
@@ -904,22 +904,6 @@ del_rules:
        return err;
 }
 
-#define MLX5E_TTC_NUM_GROUPS   3
-#define MLX5E_TTC_GROUP1_SIZE  (BIT(3) + MLX5E_NUM_TUNNEL_TT)
-#define MLX5E_TTC_GROUP2_SIZE   BIT(1)
-#define MLX5E_TTC_GROUP3_SIZE   BIT(0)
-#define MLX5E_TTC_TABLE_SIZE   (MLX5E_TTC_GROUP1_SIZE +\
-                                MLX5E_TTC_GROUP2_SIZE +\
-                                MLX5E_TTC_GROUP3_SIZE)
-
-#define MLX5E_INNER_TTC_NUM_GROUPS     3
-#define MLX5E_INNER_TTC_GROUP1_SIZE    BIT(3)
-#define MLX5E_INNER_TTC_GROUP2_SIZE    BIT(1)
-#define MLX5E_INNER_TTC_GROUP3_SIZE    BIT(0)
-#define MLX5E_INNER_TTC_TABLE_SIZE     (MLX5E_INNER_TTC_GROUP1_SIZE +\
-                                        MLX5E_INNER_TTC_GROUP2_SIZE +\
-                                        MLX5E_INNER_TTC_GROUP3_SIZE)
-
 static int mlx5e_create_ttc_table_groups(struct mlx5e_ttc_table *ttc,
                                         bool use_ipv)
 {
index 4980e80..4997b8a 100644 (file)
@@ -3000,12 +3000,9 @@ void mlx5e_timestamp_init(struct mlx5e_priv *priv)
 int mlx5e_open_locked(struct net_device *netdev)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
-       bool is_xdp = priv->channels.params.xdp_prog;
        int err;
 
        set_bit(MLX5E_STATE_OPENED, &priv->state);
-       if (is_xdp)
-               mlx5e_xdp_set_open(priv);
 
        err = mlx5e_open_channels(priv, &priv->channels);
        if (err)
@@ -3020,8 +3017,6 @@ int mlx5e_open_locked(struct net_device *netdev)
        return 0;
 
 err_clear_state_opened_flag:
-       if (is_xdp)
-               mlx5e_xdp_set_closed(priv);
        clear_bit(MLX5E_STATE_OPENED, &priv->state);
        return err;
 }
@@ -3053,8 +3048,6 @@ int mlx5e_close_locked(struct net_device *netdev)
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state))
                return 0;
 
-       if (priv->channels.params.xdp_prog)
-               mlx5e_xdp_set_closed(priv);
        clear_bit(MLX5E_STATE_OPENED, &priv->state);
 
        netif_carrier_off(priv->netdev);
@@ -4371,16 +4364,6 @@ static int mlx5e_xdp_allowed(struct mlx5e_priv *priv, struct bpf_prog *prog)
        return 0;
 }
 
-static int mlx5e_xdp_update_state(struct mlx5e_priv *priv)
-{
-       if (priv->channels.params.xdp_prog)
-               mlx5e_xdp_set_open(priv);
-       else
-               mlx5e_xdp_set_closed(priv);
-
-       return 0;
-}
-
 static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
@@ -4415,7 +4398,7 @@ static int mlx5e_xdp_set(struct net_device *netdev, struct bpf_prog *prog)
                mlx5e_set_rq_type(priv->mdev, &new_channels.params);
                old_prog = priv->channels.params.xdp_prog;
 
-               err = mlx5e_safe_switch_channels(priv, &new_channels, mlx5e_xdp_update_state);
+               err = mlx5e_safe_switch_channels(priv, &new_channels, NULL);
                if (err)
                        goto unlock;
        } else {
index 9b32a9c..024e1cd 100644 (file)
@@ -592,7 +592,7 @@ static void mlx5e_hairpin_set_ttc_params(struct mlx5e_hairpin *hp,
        for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
                ttc_params->indir_tirn[tt] = hp->indir_tirn[tt];
 
-       ft_attr->max_fte = MLX5E_NUM_TT;
+       ft_attr->max_fte = MLX5E_TTC_TABLE_SIZE;
        ft_attr->level = MLX5E_TC_TTC_FT_LEVEL;
        ft_attr->prio = MLX5E_TC_PRIO;
 }
@@ -2999,6 +2999,25 @@ static struct ip_tunnel_info *dup_tun_info(const struct ip_tunnel_info *tun_info
        return kmemdup(tun_info, tun_size, GFP_KERNEL);
 }
 
+static bool is_duplicated_encap_entry(struct mlx5e_priv *priv,
+                                     struct mlx5e_tc_flow *flow,
+                                     int out_index,
+                                     struct mlx5e_encap_entry *e,
+                                     struct netlink_ext_ack *extack)
+{
+       int i;
+
+       for (i = 0; i < out_index; i++) {
+               if (flow->encaps[i].e != e)
+                       continue;
+               NL_SET_ERR_MSG_MOD(extack, "can't duplicate encap action");
+               netdev_err(priv->netdev, "can't duplicate encap action\n");
+               return true;
+       }
+
+       return false;
+}
+
 static int mlx5e_attach_encap(struct mlx5e_priv *priv,
                              struct mlx5e_tc_flow *flow,
                              struct net_device *mirred_dev,
@@ -3034,6 +3053,12 @@ static int mlx5e_attach_encap(struct mlx5e_priv *priv,
 
        /* must verify if encap is valid or not */
        if (e) {
+               /* Check that entry was not already attached to this flow */
+               if (is_duplicated_encap_entry(priv, flow, out_index, e, extack)) {
+                       err = -EOPNOTSUPP;
+                       goto out_err;
+               }
+
                mutex_unlock(&esw->offloads.encap_tbl_lock);
                wait_for_completion(&e->res_ready);
 
@@ -3220,6 +3245,26 @@ bool mlx5e_is_valid_eswitch_fwd_dev(struct mlx5e_priv *priv,
               same_hw_devs(priv, netdev_priv(out_dev));
 }
 
+static bool is_duplicated_output_device(struct net_device *dev,
+                                       struct net_device *out_dev,
+                                       int *ifindexes, int if_count,
+                                       struct netlink_ext_ack *extack)
+{
+       int i;
+
+       for (i = 0; i < if_count; i++) {
+               if (ifindexes[i] == out_dev->ifindex) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "can't duplicate output to same device");
+                       netdev_err(dev, "can't duplicate output to same device: %s\n",
+                                  out_dev->name);
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
                                struct flow_action *flow_action,
                                struct mlx5e_tc_flow *flow,
@@ -3231,11 +3276,12 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
        struct mlx5e_tc_flow_parse_attr *parse_attr = attr->parse_attr;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
        const struct ip_tunnel_info *info = NULL;
+       int ifindexes[MLX5_MAX_FLOW_FWD_VPORTS];
        bool ft_flow = mlx5e_is_ft_flow(flow);
        const struct flow_action_entry *act;
+       int err, i, if_count = 0;
        bool encap = false;
        u32 action = 0;
-       int err, i;
 
        if (!flow_action_has_entries(flow_action))
                return -EINVAL;
@@ -3312,6 +3358,16 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv,
                                struct net_device *uplink_dev = mlx5_eswitch_uplink_get_proto_dev(esw, REP_ETH);
                                struct net_device *uplink_upper;
 
+                               if (is_duplicated_output_device(priv->netdev,
+                                                               out_dev,
+                                                               ifindexes,
+                                                               if_count,
+                                                               extack))
+                                       return -EOPNOTSUPP;
+
+                               ifindexes[if_count] = out_dev->ifindex;
+                               if_count++;
+
                                rcu_read_lock();
                                uplink_upper =
                                        netdev_master_upper_dev_get_rcu(uplink_dev);
index c76da30..e4ec0e0 100644 (file)
@@ -87,10 +87,10 @@ static const struct rhashtable_params rhash_sa = {
         * value is not constant during the lifetime
         * of the key object.
         */
-       .key_len = FIELD_SIZEOF(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) -
-                  FIELD_SIZEOF(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
+       .key_len = sizeof_field(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) -
+                  sizeof_field(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
        .key_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) +
-                     FIELD_SIZEOF(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
+                     sizeof_field(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),
        .head_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hash),
        .automatic_shrinking = true,
        .min_size = 1,
index d605774..8c5df6c 100644 (file)
@@ -209,7 +209,7 @@ enum fs_i_lock_class {
 };
 
 static const struct rhashtable_params rhash_fte = {
-       .key_len = FIELD_SIZEOF(struct fs_fte, val),
+       .key_len = sizeof_field(struct fs_fte, val),
        .key_offset = offsetof(struct fs_fte, val),
        .head_offset = offsetof(struct fs_fte, hash),
        .automatic_shrinking = true,
@@ -217,7 +217,7 @@ static const struct rhashtable_params rhash_fte = {
 };
 
 static const struct rhashtable_params rhash_fg = {
-       .key_len = FIELD_SIZEOF(struct mlx5_flow_group, mask),
+       .key_len = sizeof_field(struct mlx5_flow_group, mask),
        .key_offset = offsetof(struct mlx5_flow_group, mask),
        .head_offset = offsetof(struct mlx5_flow_group, hash),
        .automatic_shrinking = true,
@@ -531,16 +531,9 @@ static void del_hw_fte(struct fs_node *node)
        }
 }
 
-static void del_sw_fte_rcu(struct rcu_head *head)
-{
-       struct fs_fte *fte = container_of(head, struct fs_fte, rcu);
-       struct mlx5_flow_steering *steering = get_steering(&fte->node);
-
-       kmem_cache_free(steering->ftes_cache, fte);
-}
-
 static void del_sw_fte(struct fs_node *node)
 {
+       struct mlx5_flow_steering *steering = get_steering(node);
        struct mlx5_flow_group *fg;
        struct fs_fte *fte;
        int err;
@@ -553,8 +546,7 @@ static void del_sw_fte(struct fs_node *node)
                                     rhash_fte);
        WARN_ON(err);
        ida_simple_remove(&fg->fte_allocator, fte->index - fg->start_index);
-
-       call_rcu(&fte->rcu, del_sw_fte_rcu);
+       kmem_cache_free(steering->ftes_cache, fte);
 }
 
 static void del_hw_flow_group(struct fs_node *node)
@@ -1633,47 +1625,22 @@ static u64 matched_fgs_get_version(struct list_head *match_head)
 }
 
 static struct fs_fte *
-lookup_fte_for_write_locked(struct mlx5_flow_group *g, const u32 *match_value)
+lookup_fte_locked(struct mlx5_flow_group *g,
+                 const u32 *match_value,
+                 bool take_write)
 {
        struct fs_fte *fte_tmp;
 
-       nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);
-
-       fte_tmp = rhashtable_lookup_fast(&g->ftes_hash, match_value, rhash_fte);
-       if (!fte_tmp || !tree_get_node(&fte_tmp->node)) {
-               fte_tmp = NULL;
-               goto out;
-       }
-
-       if (!fte_tmp->node.active) {
-               tree_put_node(&fte_tmp->node, false);
-               fte_tmp = NULL;
-               goto out;
-       }
-       nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
-
-out:
-       up_write_ref_node(&g->node, false);
-       return fte_tmp;
-}
-
-static struct fs_fte *
-lookup_fte_for_read_locked(struct mlx5_flow_group *g, const u32 *match_value)
-{
-       struct fs_fte *fte_tmp;
-
-       if (!tree_get_node(&g->node))
-               return NULL;
-
-       rcu_read_lock();
-       fte_tmp = rhashtable_lookup(&g->ftes_hash, match_value, rhash_fte);
+       if (take_write)
+               nested_down_write_ref_node(&g->node, FS_LOCK_PARENT);
+       else
+               nested_down_read_ref_node(&g->node, FS_LOCK_PARENT);
+       fte_tmp = rhashtable_lookup_fast(&g->ftes_hash, match_value,
+                                        rhash_fte);
        if (!fte_tmp || !tree_get_node(&fte_tmp->node)) {
-               rcu_read_unlock();
                fte_tmp = NULL;
                goto out;
        }
-       rcu_read_unlock();
-
        if (!fte_tmp->node.active) {
                tree_put_node(&fte_tmp->node, false);
                fte_tmp = NULL;
@@ -1681,19 +1648,12 @@ lookup_fte_for_read_locked(struct mlx5_flow_group *g, const u32 *match_value)
        }
 
        nested_down_write_ref_node(&fte_tmp->node, FS_LOCK_CHILD);
-
 out:
-       tree_put_node(&g->node, false);
-       return fte_tmp;
-}
-
-static struct fs_fte *
-lookup_fte_locked(struct mlx5_flow_group *g, const u32 *match_value, bool write)
-{
-       if (write)
-               return lookup_fte_for_write_locked(g, match_value);
+       if (take_write)
+               up_write_ref_node(&g->node, false);
        else
-               return lookup_fte_for_read_locked(g, match_value);
+               up_read_ref_node(&g->node);
+       return fte_tmp;
 }
 
 static struct mlx5_flow_handle *
index e8cd997..c2621b9 100644 (file)
@@ -203,7 +203,6 @@ struct fs_fte {
        enum fs_fte_status              status;
        struct mlx5_fc                  *counter;
        struct rhash_head               hash;
-       struct rcu_head rcu;
        int                             modify_mask;
 };
 
index 173e2c1..cf7b8da 100644 (file)
@@ -1193,6 +1193,12 @@ int mlx5_load_one(struct mlx5_core_dev *dev, bool boot)
        if (err)
                goto err_load;
 
+       if (boot) {
+               err = mlx5_devlink_register(priv_to_devlink(dev), dev->device);
+               if (err)
+                       goto err_devlink_reg;
+       }
+
        if (mlx5_device_registered(dev)) {
                mlx5_attach_device(dev);
        } else {
@@ -1210,6 +1216,9 @@ out:
        return err;
 
 err_reg_dev:
+       if (boot)
+               mlx5_devlink_unregister(priv_to_devlink(dev));
+err_devlink_reg:
        mlx5_unload(dev);
 err_load:
        if (boot)
@@ -1347,10 +1356,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 
        request_module_nowait(MLX5_IB_MOD);
 
-       err = mlx5_devlink_register(devlink, &pdev->dev);
-       if (err)
-               goto clean_load;
-
        err = mlx5_crdump_enable(dev);
        if (err)
                dev_err(&pdev->dev, "mlx5_crdump_enable failed with error code %d\n", err);
@@ -1358,9 +1363,6 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        pci_save_state(pdev);
        return 0;
 
-clean_load:
-       mlx5_unload_one(dev, true);
-
 err_load_one:
        mlx5_pci_close(dev);
 pci_init_err:
index 32e94d2..e4cff7a 100644 (file)
@@ -209,7 +209,7 @@ static void dr_rule_rehash_copy_ste_ctrl(struct mlx5dr_matcher *matcher,
        /* We need to copy the refcount since this ste
         * may have been traversed several times
         */
-       refcount_set(&new_ste->refcount, refcount_read(&cur_ste->refcount));
+       new_ste->refcount = cur_ste->refcount;
 
        /* Link old STEs rule_mem list to the new ste */
        mlx5dr_rule_update_rule_member(cur_ste, new_ste);
@@ -638,6 +638,9 @@ static int dr_rule_add_member(struct mlx5dr_rule_rx_tx *nic_rule,
        if (!rule_mem)
                return -ENOMEM;
 
+       INIT_LIST_HEAD(&rule_mem->list);
+       INIT_LIST_HEAD(&rule_mem->use_ste_list);
+
        rule_mem->ste = ste;
        list_add_tail(&rule_mem->list, &nic_rule->rule_members_list);
 
index a5a2669..c6c7d1d 100644 (file)
@@ -348,7 +348,7 @@ static void dr_ste_replace(struct mlx5dr_ste *dst, struct mlx5dr_ste *src)
        if (dst->next_htbl)
                dst->next_htbl->pointing_ste = dst;
 
-       refcount_set(&dst->refcount, refcount_read(&src->refcount));
+       dst->refcount = src->refcount;
 
        INIT_LIST_HEAD(&dst->rule_list);
        list_splice_tail_init(&src->rule_list, &dst->rule_list);
@@ -565,7 +565,7 @@ bool mlx5dr_ste_is_not_valid_entry(u8 *p_hw_ste)
 
 bool mlx5dr_ste_not_used_ste(struct mlx5dr_ste *ste)
 {
-       return !refcount_read(&ste->refcount);
+       return !ste->refcount;
 }
 
 /* Init one ste as a pattern for ste data array */
@@ -689,14 +689,14 @@ struct mlx5dr_ste_htbl *mlx5dr_ste_htbl_alloc(struct mlx5dr_icm_pool *pool,
        htbl->ste_arr = chunk->ste_arr;
        htbl->hw_ste_arr = chunk->hw_ste_arr;
        htbl->miss_list = chunk->miss_list;
-       refcount_set(&htbl->refcount, 0);
+       htbl->refcount = 0;
 
        for (i = 0; i < chunk->num_of_entries; i++) {
                struct mlx5dr_ste *ste = &htbl->ste_arr[i];
 
                ste->hw_ste = htbl->hw_ste_arr + i * DR_STE_SIZE_REDUCED;
                ste->htbl = htbl;
-               refcount_set(&ste->refcount, 0);
+               ste->refcount = 0;
                INIT_LIST_HEAD(&ste->miss_list_node);
                INIT_LIST_HEAD(&htbl->miss_list[i]);
                INIT_LIST_HEAD(&ste->rule_list);
@@ -713,7 +713,7 @@ out_free_htbl:
 
 int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl)
 {
-       if (refcount_read(&htbl->refcount))
+       if (htbl->refcount)
                return -EBUSY;
 
        mlx5dr_icm_free_chunk(htbl->chunk);
index 290fe61..3fdf4a5 100644 (file)
@@ -123,7 +123,7 @@ struct mlx5dr_matcher_rx_tx;
 struct mlx5dr_ste {
        u8 *hw_ste;
        /* refcount: indicates the num of rules that using this ste */
-       refcount_t refcount;
+       u32 refcount;
 
        /* attached to the miss_list head at each htbl entry */
        struct list_head miss_list_node;
@@ -155,7 +155,7 @@ struct mlx5dr_ste_htbl_ctrl {
 struct mlx5dr_ste_htbl {
        u8 lu_type;
        u16 byte_mask;
-       refcount_t refcount;
+       u32 refcount;
        struct mlx5dr_icm_chunk *chunk;
        struct mlx5dr_ste *ste_arr;
        u8 *hw_ste_arr;
@@ -206,13 +206,14 @@ int mlx5dr_ste_htbl_free(struct mlx5dr_ste_htbl *htbl);
 
 static inline void mlx5dr_htbl_put(struct mlx5dr_ste_htbl *htbl)
 {
-       if (refcount_dec_and_test(&htbl->refcount))
+       htbl->refcount--;
+       if (!htbl->refcount)
                mlx5dr_ste_htbl_free(htbl);
 }
 
 static inline void mlx5dr_htbl_get(struct mlx5dr_ste_htbl *htbl)
 {
-       refcount_inc(&htbl->refcount);
+       htbl->refcount++;
 }
 
 /* STE utils */
@@ -254,14 +255,15 @@ static inline void mlx5dr_ste_put(struct mlx5dr_ste *ste,
                                  struct mlx5dr_matcher *matcher,
                                  struct mlx5dr_matcher_rx_tx *nic_matcher)
 {
-       if (refcount_dec_and_test(&ste->refcount))
+       ste->refcount--;
+       if (!ste->refcount)
                mlx5dr_ste_free(ste, matcher, nic_matcher);
 }
 
 /* initial as 0, increased only when ste appears in a new rule */
 static inline void mlx5dr_ste_get(struct mlx5dr_ste *ste)
 {
-       refcount_inc(&ste->refcount);
+       ste->refcount++;
 }
 
 void mlx5dr_ste_set_hit_addr_by_next_htbl(u8 *hw_ste,
index 544344a..79057af 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/netlink.h>
+#include <linux/vmalloc.h>
 #include <linux/xz.h>
 #include "mlxfw_mfa2.h"
 #include "mlxfw_mfa2_file.h"
@@ -548,7 +549,7 @@ mlxfw_mfa2_file_component_get(const struct mlxfw_mfa2_file *mfa2_file,
        comp_size = be32_to_cpu(comp->size);
        comp_buf_size = comp_size + mlxfw_mfa2_comp_magic_len;
 
-       comp_data = kmalloc(sizeof(*comp_data) + comp_buf_size, GFP_KERNEL);
+       comp_data = vzalloc(sizeof(*comp_data) + comp_buf_size);
        if (!comp_data)
                return ERR_PTR(-ENOMEM);
        comp_data->comp.data_size = comp_size;
@@ -570,7 +571,7 @@ mlxfw_mfa2_file_component_get(const struct mlxfw_mfa2_file *mfa2_file,
        comp_data->comp.data = comp_data->buff + mlxfw_mfa2_comp_magic_len;
        return &comp_data->comp;
 err_out:
-       kfree(comp_data);
+       vfree(comp_data);
        return ERR_PTR(err);
 }
 
@@ -579,7 +580,7 @@ void mlxfw_mfa2_file_component_put(struct mlxfw_mfa2_component *comp)
        const struct mlxfw_mfa2_comp_data *comp_data;
 
        comp_data = container_of(comp, struct mlxfw_mfa2_comp_data, comp);
-       kfree(comp_data);
+       vfree(comp_data);
 }
 
 void mlxfw_mfa2_file_fini(struct mlxfw_mfa2_file *mfa2_file)
index 5294a16..af30e8a 100644 (file)
@@ -5472,6 +5472,7 @@ enum mlxsw_reg_htgt_trap_group {
        MLXSW_REG_HTGT_TRAP_GROUP_SP_LBERROR,
        MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0,
        MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP1,
+       MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP,
 
        __MLXSW_REG_HTGT_TRAP_GROUP_MAX,
        MLXSW_REG_HTGT_TRAP_GROUP_MAX = __MLXSW_REG_HTGT_TRAP_GROUP_MAX - 1
index 556dca3..8ed1519 100644 (file)
@@ -860,23 +860,17 @@ static netdev_tx_t mlxsw_sp_port_xmit(struct sk_buff *skb,
        u64 len;
        int err;
 
+       if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
+               this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
+       }
+
        memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
 
        if (mlxsw_core_skb_transmit_busy(mlxsw_sp->core, &tx_info))
                return NETDEV_TX_BUSY;
 
-       if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
-               struct sk_buff *skb_orig = skb;
-
-               skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
-               if (!skb) {
-                       this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
-                       dev_kfree_skb_any(skb_orig);
-                       return NETDEV_TX_OK;
-               }
-               dev_consume_skb_any(skb_orig);
-       }
-
        if (eth_skb_pad(skb)) {
                this_cpu_inc(mlxsw_sp_port->pcpu_stats->tx_dropped);
                return NETDEV_TX_OK;
@@ -1215,6 +1209,9 @@ static void update_stats_cache(struct work_struct *work)
                             periodic_hw_stats.update_dw.work);
 
        if (!netif_carrier_ok(mlxsw_sp_port->dev))
+               /* Note: mlxsw_sp_port_down_wipe_counters() clears the cache as
+                * necessary when port goes down.
+                */
                goto out;
 
        mlxsw_sp_port_get_hw_stats(mlxsw_sp_port->dev,
@@ -4324,6 +4321,15 @@ static int mlxsw_sp_port_unsplit(struct mlxsw_core *mlxsw_core, u8 local_port,
        return 0;
 }
 
+static void
+mlxsw_sp_port_down_wipe_counters(struct mlxsw_sp_port *mlxsw_sp_port)
+{
+       int i;
+
+       for (i = 0; i < TC_MAX_QUEUE; i++)
+               mlxsw_sp_port->periodic_hw_stats.xstats.backlog[i] = 0;
+}
+
 static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
                                     char *pude_pl, void *priv)
 {
@@ -4345,6 +4351,7 @@ static void mlxsw_sp_pude_event_func(const struct mlxsw_reg_info *reg,
        } else {
                netdev_info(mlxsw_sp_port->dev, "link down\n");
                netif_carrier_off(mlxsw_sp_port->dev);
+               mlxsw_sp_port_down_wipe_counters(mlxsw_sp_port);
        }
 }
 
@@ -4542,8 +4549,8 @@ static const struct mlxsw_listener mlxsw_sp_listener[] = {
        MLXSW_SP_RXL_MARK(ROUTER_ALERT_IPV6, TRAP_TO_CPU, ROUTER_EXP, false),
        MLXSW_SP_RXL_MARK(IPIP_DECAP_ERROR, TRAP_TO_CPU, ROUTER_EXP, false),
        MLXSW_SP_RXL_MARK(DECAP_ECN0, TRAP_TO_CPU, ROUTER_EXP, false),
-       MLXSW_SP_RXL_MARK(IPV4_VRRP, TRAP_TO_CPU, ROUTER_EXP, false),
-       MLXSW_SP_RXL_MARK(IPV6_VRRP, TRAP_TO_CPU, ROUTER_EXP, false),
+       MLXSW_SP_RXL_MARK(IPV4_VRRP, TRAP_TO_CPU, VRRP, false),
+       MLXSW_SP_RXL_MARK(IPV6_VRRP, TRAP_TO_CPU, VRRP, false),
        /* PKT Sample trap */
        MLXSW_RXL(mlxsw_sp_rx_listener_sample_func, PKT_SAMPLE, MIRROR_TO_CPU,
                  false, SP_IP2ME, DISCARD),
@@ -4626,6 +4633,10 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)
                        rate = 19 * 1024;
                        burst_size = 12;
                        break;
+               case MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP:
+                       rate = 360;
+                       burst_size = 7;
+                       break;
                default:
                        continue;
                }
@@ -4665,6 +4676,7 @@ static int mlxsw_sp_trap_groups_set(struct mlxsw_core *mlxsw_core)
                case MLXSW_REG_HTGT_TRAP_GROUP_SP_OSPF:
                case MLXSW_REG_HTGT_TRAP_GROUP_SP_PIM:
                case MLXSW_REG_HTGT_TRAP_GROUP_SP_PTP0:
+               case MLXSW_REG_HTGT_TRAP_GROUP_SP_VRRP:
                        priority = 5;
                        tc = 5;
                        break;
@@ -5127,6 +5139,27 @@ static int mlxsw_sp2_init(struct mlxsw_core *mlxsw_core,
        return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
 }
 
+static int mlxsw_sp3_init(struct mlxsw_core *mlxsw_core,
+                         const struct mlxsw_bus_info *mlxsw_bus_info,
+                         struct netlink_ext_ack *extack)
+{
+       struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
+
+       mlxsw_sp->kvdl_ops = &mlxsw_sp2_kvdl_ops;
+       mlxsw_sp->afa_ops = &mlxsw_sp2_act_afa_ops;
+       mlxsw_sp->afk_ops = &mlxsw_sp2_afk_ops;
+       mlxsw_sp->mr_tcam_ops = &mlxsw_sp2_mr_tcam_ops;
+       mlxsw_sp->acl_tcam_ops = &mlxsw_sp2_acl_tcam_ops;
+       mlxsw_sp->nve_ops_arr = mlxsw_sp2_nve_ops_arr;
+       mlxsw_sp->mac_mask = mlxsw_sp2_mac_mask;
+       mlxsw_sp->rif_ops_arr = mlxsw_sp2_rif_ops_arr;
+       mlxsw_sp->sb_vals = &mlxsw_sp2_sb_vals;
+       mlxsw_sp->port_type_speed_ops = &mlxsw_sp2_port_type_speed_ops;
+       mlxsw_sp->ptp_ops = &mlxsw_sp2_ptp_ops;
+
+       return mlxsw_sp_init(mlxsw_core, mlxsw_bus_info, extack);
+}
+
 static void mlxsw_sp_fini(struct mlxsw_core *mlxsw_core)
 {
        struct mlxsw_sp *mlxsw_sp = mlxsw_core_driver_priv(mlxsw_core);
@@ -5629,7 +5662,7 @@ static struct mlxsw_driver mlxsw_sp2_driver = {
 static struct mlxsw_driver mlxsw_sp3_driver = {
        .kind                           = mlxsw_sp3_driver_name,
        .priv_size                      = sizeof(struct mlxsw_sp),
-       .init                           = mlxsw_sp2_init,
+       .init                           = mlxsw_sp3_init,
        .fini                           = mlxsw_sp_fini,
        .basic_trap_groups_set          = mlxsw_sp_basic_trap_groups_set,
        .port_split                     = mlxsw_sp_port_split,
index 68cc673..0124bfe 100644 (file)
@@ -195,6 +195,20 @@ mlxsw_sp_qdisc_get_xstats(struct mlxsw_sp_port *mlxsw_sp_port,
        return -EOPNOTSUPP;
 }
 
+static u64
+mlxsw_sp_xstats_backlog(struct mlxsw_sp_port_xstats *xstats, int tclass_num)
+{
+       return xstats->backlog[tclass_num] +
+              xstats->backlog[tclass_num + 8];
+}
+
+static u64
+mlxsw_sp_xstats_tail_drop(struct mlxsw_sp_port_xstats *xstats, int tclass_num)
+{
+       return xstats->tail_drop[tclass_num] +
+              xstats->tail_drop[tclass_num + 8];
+}
+
 static void
 mlxsw_sp_qdisc_bstats_per_priority_get(struct mlxsw_sp_port_xstats *xstats,
                                       u8 prio_bitmap, u64 *tx_packets,
@@ -269,7 +283,7 @@ mlxsw_sp_setup_tc_qdisc_red_clean_stats(struct mlxsw_sp_port *mlxsw_sp_port,
                                               &stats_base->tx_bytes);
        red_base->prob_mark = xstats->ecn;
        red_base->prob_drop = xstats->wred_drop[tclass_num];
-       red_base->pdrop = xstats->tail_drop[tclass_num];
+       red_base->pdrop = mlxsw_sp_xstats_tail_drop(xstats, tclass_num);
 
        stats_base->overlimits = red_base->prob_drop + red_base->prob_mark;
        stats_base->drops = red_base->prob_drop + red_base->pdrop;
@@ -370,7 +384,8 @@ mlxsw_sp_qdisc_get_red_xstats(struct mlxsw_sp_port *mlxsw_sp_port,
 
        early_drops = xstats->wred_drop[tclass_num] - xstats_base->prob_drop;
        marks = xstats->ecn - xstats_base->prob_mark;
-       pdrops = xstats->tail_drop[tclass_num] - xstats_base->pdrop;
+       pdrops = mlxsw_sp_xstats_tail_drop(xstats, tclass_num) -
+                xstats_base->pdrop;
 
        res->pdrop += pdrops;
        res->prob_drop += early_drops;
@@ -403,9 +418,10 @@ mlxsw_sp_qdisc_get_red_stats(struct mlxsw_sp_port *mlxsw_sp_port,
 
        overlimits = xstats->wred_drop[tclass_num] + xstats->ecn -
                     stats_base->overlimits;
-       drops = xstats->wred_drop[tclass_num] + xstats->tail_drop[tclass_num] -
+       drops = xstats->wred_drop[tclass_num] +
+               mlxsw_sp_xstats_tail_drop(xstats, tclass_num) -
                stats_base->drops;
-       backlog = xstats->backlog[tclass_num];
+       backlog = mlxsw_sp_xstats_backlog(xstats, tclass_num);
 
        _bstats_update(stats_ptr->bstats, tx_bytes, tx_packets);
        stats_ptr->qstats->overlimits += overlimits;
@@ -576,9 +592,9 @@ mlxsw_sp_qdisc_get_prio_stats(struct mlxsw_sp_port *mlxsw_sp_port,
        tx_packets = stats->tx_packets - stats_base->tx_packets;
 
        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
-               drops += xstats->tail_drop[i];
+               drops += mlxsw_sp_xstats_tail_drop(xstats, i);
                drops += xstats->wred_drop[i];
-               backlog += xstats->backlog[i];
+               backlog += mlxsw_sp_xstats_backlog(xstats, i);
        }
        drops = drops - stats_base->drops;
 
@@ -614,7 +630,7 @@ mlxsw_sp_setup_tc_qdisc_prio_clean_stats(struct mlxsw_sp_port *mlxsw_sp_port,
 
        stats_base->drops = 0;
        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
-               stats_base->drops += xstats->tail_drop[i];
+               stats_base->drops += mlxsw_sp_xstats_tail_drop(xstats, i);
                stats_base->drops += xstats->wred_drop[i];
        }
 
@@ -651,6 +667,13 @@ mlxsw_sp_qdisc_prio_graft(struct mlxsw_sp_port *mlxsw_sp_port,
            mlxsw_sp_port->tclass_qdiscs[tclass_num].handle == p->child_handle)
                return 0;
 
+       if (!p->child_handle) {
+               /* This is an invisible FIFO replacing the original Qdisc.
+                * Ignore it--the original Qdisc's destroy will follow.
+                */
+               return 0;
+       }
+
        /* See if the grafted qdisc is already offloaded on any tclass. If so,
         * unoffload it.
         */
index 30bfe38..8290e82 100644 (file)
@@ -5742,8 +5742,13 @@ static void mlxsw_sp_router_fib6_del(struct mlxsw_sp *mlxsw_sp,
        if (mlxsw_sp_fib6_rt_should_ignore(rt))
                return;
 
+       /* Multipath routes are first added to the FIB trie and only then
+        * notified. If we vetoed the addition, we will get a delete
+        * notification for a route we do not have. Therefore, do not warn if
+        * route was not found.
+        */
        fib6_entry = mlxsw_sp_fib6_entry_lookup(mlxsw_sp, rt);
-       if (WARN_ON(!fib6_entry))
+       if (!fib6_entry)
                return;
 
        /* If not all the nexthops are deleted, then only reduce the nexthop
@@ -7074,6 +7079,9 @@ static int mlxsw_sp_router_port_check_rif_addr(struct mlxsw_sp *mlxsw_sp,
 
        for (i = 0; i < MLXSW_CORE_RES_GET(mlxsw_sp->core, MAX_RIFS); i++) {
                rif = mlxsw_sp->router->rifs[i];
+               if (rif && rif->ops &&
+                   rif->ops->type == MLXSW_SP_RIF_TYPE_IPIP_LB)
+                       continue;
                if (rif && rif->dev && rif->dev != dev &&
                    !ether_addr_equal_masked(rif->dev->dev_addr, dev_addr,
                                             mlxsw_sp->mac_mask)) {
index de6cb22..f0e98ec 100644 (file)
@@ -299,22 +299,17 @@ static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb,
        u64 len;
        int err;
 
+       if (skb_cow_head(skb, MLXSW_TXHDR_LEN)) {
+               this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
+       }
+
        memset(skb->cb, 0, sizeof(struct mlxsw_skb_cb));
 
        if (mlxsw_core_skb_transmit_busy(mlxsw_sx->core, &tx_info))
                return NETDEV_TX_BUSY;
 
-       if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) {
-               struct sk_buff *skb_orig = skb;
-
-               skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN);
-               if (!skb) {
-                       this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped);
-                       dev_kfree_skb_any(skb_orig);
-                       return NETDEV_TX_OK;
-               }
-               dev_consume_skb_any(skb_orig);
-       }
        mlxsw_sx_txhdr_construct(skb, &tx_info);
        /* TX header is consumed by HW on the way so we shouldn't count its
         * bytes as being sent.
index c80bb83..0a721f6 100644 (file)
@@ -2652,17 +2652,17 @@ static int mem_ldx_skb(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
 
        switch (meta->insn.off) {
        case offsetof(struct __sk_buff, len):
-               if (size != FIELD_SIZEOF(struct __sk_buff, len))
+               if (size != sizeof_field(struct __sk_buff, len))
                        return -EOPNOTSUPP;
                wrp_mov(nfp_prog, dst, plen_reg(nfp_prog));
                break;
        case offsetof(struct __sk_buff, data):
-               if (size != FIELD_SIZEOF(struct __sk_buff, data))
+               if (size != sizeof_field(struct __sk_buff, data))
                        return -EOPNOTSUPP;
                wrp_mov(nfp_prog, dst, pptr_reg(nfp_prog));
                break;
        case offsetof(struct __sk_buff, data_end):
-               if (size != FIELD_SIZEOF(struct __sk_buff, data_end))
+               if (size != sizeof_field(struct __sk_buff, data_end))
                        return -EOPNOTSUPP;
                emit_alu(nfp_prog, dst,
                         plen_reg(nfp_prog), ALU_OP_ADD, pptr_reg(nfp_prog));
@@ -2683,12 +2683,12 @@ static int mem_ldx_xdp(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
 
        switch (meta->insn.off) {
        case offsetof(struct xdp_md, data):
-               if (size != FIELD_SIZEOF(struct xdp_md, data))
+               if (size != sizeof_field(struct xdp_md, data))
                        return -EOPNOTSUPP;
                wrp_mov(nfp_prog, dst, pptr_reg(nfp_prog));
                break;
        case offsetof(struct xdp_md, data_end):
-               if (size != FIELD_SIZEOF(struct xdp_md, data_end))
+               if (size != sizeof_field(struct xdp_md, data_end))
                        return -EOPNOTSUPP;
                emit_alu(nfp_prog, dst,
                         plen_reg(nfp_prog), ALU_OP_ADD, pptr_reg(nfp_prog));
index 8f73277..11c83a9 100644 (file)
@@ -15,7 +15,7 @@
 
 const struct rhashtable_params nfp_bpf_maps_neutral_params = {
        .nelem_hint             = 4,
-       .key_len                = FIELD_SIZEOF(struct bpf_map, id),
+       .key_len                = sizeof_field(struct bpf_map, id),
        .key_offset             = offsetof(struct nfp_bpf_neutral_map, map_id),
        .head_offset            = offsetof(struct nfp_bpf_neutral_map, l),
        .automatic_shrinking    = true,
index 95a0d39..ac02369 100644 (file)
@@ -374,7 +374,7 @@ nfp_bpf_map_alloc(struct nfp_app_bpf *bpf, struct bpf_offloaded_map *offmap)
        }
 
        use_map_size = DIV_ROUND_UP(offmap->map.value_size, 4) *
-                      FIELD_SIZEOF(struct nfp_bpf_map, use_map[0]);
+                      sizeof_field(struct nfp_bpf_map, use_map[0]);
 
        nfp_map = kzalloc(sizeof(*nfp_map) + use_map_size, GFP_USER);
        if (!nfp_map)
index 31d9459..e0c985f 100644 (file)
@@ -24,7 +24,7 @@ struct nfp_app;
 #define NFP_FL_STAT_ID_MU_NUM          GENMASK(31, 22)
 #define NFP_FL_STAT_ID_STAT            GENMASK(21, 0)
 
-#define NFP_FL_STATS_ELEM_RS           FIELD_SIZEOF(struct nfp_fl_stats_id, \
+#define NFP_FL_STATS_ELEM_RS           sizeof_field(struct nfp_fl_stats_id, \
                                                     init_unalloc)
 #define NFP_FLOWER_MASK_ENTRY_RS       256
 #define NFP_FLOWER_MASK_ELEMENT_RS     1
index 7c4a15e..5defd31 100644 (file)
@@ -65,17 +65,17 @@ static int nfp_get_stats_entry(struct nfp_app *app, u32 *stats_context_id)
        freed_stats_id = priv->stats_ring_size;
        /* Check for unallocated entries first. */
        if (priv->stats_ids.init_unalloc > 0) {
-               if (priv->active_mem_unit == priv->total_mem_units) {
-                       priv->stats_ids.init_unalloc--;
-                       priv->active_mem_unit = 0;
-               }
-
                *stats_context_id =
                        FIELD_PREP(NFP_FL_STAT_ID_STAT,
                                   priv->stats_ids.init_unalloc - 1) |
                        FIELD_PREP(NFP_FL_STAT_ID_MU_NUM,
                                   priv->active_mem_unit);
-               priv->active_mem_unit++;
+
+               if (++priv->active_mem_unit == priv->total_mem_units) {
+                       priv->stats_ids.init_unalloc--;
+                       priv->active_mem_unit = 0;
+               }
+
                return 0;
        }
 
index 1a3008e..b36aa5b 100644 (file)
@@ -20,7 +20,7 @@ struct pch_gbe_stats {
 #define PCH_GBE_STAT(m)                                                \
 {                                                              \
        .string = #m,                                           \
-       .size = FIELD_SIZEOF(struct pch_gbe_hw_stats, m),       \
+       .size = sizeof_field(struct pch_gbe_hw_stats, m),       \
        .offset = offsetof(struct pch_gbe_hw_stats, m),         \
 }
 
index c303a92..e8a1b27 100644 (file)
@@ -464,7 +464,7 @@ struct qede_fastpath {
        struct qede_tx_queue    *txq;
        struct qede_tx_queue    *xdp_tx;
 
-#define VEC_NAME_SIZE  (FIELD_SIZEOF(struct net_device, name) + 8)
+#define VEC_NAME_SIZE  (sizeof_field(struct net_device, name) + 8)
        char    name[VEC_NAME_SIZE];
 };
 
index d6cfe4f..d1ce453 100644 (file)
@@ -1230,7 +1230,7 @@ qede_configure_mcast_filtering(struct net_device *ndev,
        netif_addr_lock_bh(ndev);
 
        mc_count = netdev_mc_count(ndev);
-       if (mc_count < 64) {
+       if (mc_count <= 64) {
                netdev_for_each_mc_addr(ha, ndev) {
                        ether_addr_copy(temp, ha->addr);
                        temp += ETH_ALEN;
index 481b096..34fa391 100644 (file)
@@ -1406,6 +1406,7 @@ static int qede_alloc_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq)
                rxq->rx_buf_seg_size = roundup_pow_of_two(size);
        } else {
                rxq->rx_buf_seg_size = PAGE_SIZE;
+               edev->ndev->features &= ~NETIF_F_GRO_HW;
        }
 
        /* Allocate the parallel driver ring for Rx buffers */
@@ -1450,6 +1451,7 @@ static int qede_alloc_mem_rxq(struct qede_dev *edev, struct qede_rx_queue *rxq)
                }
        }
 
+       edev->gro_disable = !(edev->ndev->features & NETIF_F_GRO_HW);
        if (!edev->gro_disable)
                qede_set_tpa_param(rxq);
 err:
@@ -1702,8 +1704,6 @@ static void qede_init_fp(struct qede_dev *edev)
                snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
                         edev->ndev->name, queue_id);
        }
-
-       edev->gro_disable = !(edev->ndev->features & NETIF_F_GRO_HW);
 }
 
 static int qede_set_real_num_queues(struct qede_dev *edev)
index b4b8ba0..986f265 100644 (file)
@@ -2756,6 +2756,9 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
        int err;
 
        for (i = 0; i < qdev->num_large_buffers; i++) {
+               lrg_buf_cb = &qdev->lrg_buf[i];
+               memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
+
                skb = netdev_alloc_skb(qdev->ndev,
                                       qdev->lrg_buffer_len);
                if (unlikely(!skb)) {
@@ -2766,11 +2769,7 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
                        ql_free_large_buffers(qdev);
                        return -ENOMEM;
                } else {
-
-                       lrg_buf_cb = &qdev->lrg_buf[i];
-                       memset(lrg_buf_cb, 0, sizeof(struct ql_rcv_buf_cb));
                        lrg_buf_cb->index = i;
-                       lrg_buf_cb->skb = skb;
                        /*
                         * We save some space to copy the ethhdr from first
                         * buffer
@@ -2792,6 +2791,7 @@ static int ql_alloc_large_buffers(struct ql3_adapter *qdev)
                                return -ENOMEM;
                        }
 
+                       lrg_buf_cb->skb = skb;
                        dma_unmap_addr_set(lrg_buf_cb, mapaddr, map);
                        dma_unmap_len_set(lrg_buf_cb, maplen,
                                          qdev->lrg_buffer_len -
index a4cd6f2..75d83c3 100644 (file)
@@ -20,7 +20,7 @@ struct qlcnic_stats {
        int stat_offset;
 };
 
-#define QLC_SIZEOF(m) FIELD_SIZEOF(struct qlcnic_adapter, m)
+#define QLC_SIZEOF(m) sizeof_field(struct qlcnic_adapter, m)
 #define QLC_OFF(m) offsetof(struct qlcnic_adapter, m)
 static const u32 qlcnic_fw_dump_level[] = {
        0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff
index 355cc81..cbc6b84 100644 (file)
@@ -37,7 +37,7 @@ struct fw_info {
        u8      chksum;
 } __packed;
 
-#define FW_OPCODE_SIZE FIELD_SIZEOF(struct rtl_fw_phy_action, code[0])
+#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0])
 
 static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw)
 {
index e19b49c..3591285 100644 (file)
@@ -2204,24 +2204,28 @@ static size_t __sh_eth_get_regs(struct net_device *ndev, u32 *buf)
        if (cd->tsu) {
                add_tsu_reg(ARSTR);
                add_tsu_reg(TSU_CTRST);
-               add_tsu_reg(TSU_FWEN0);
-               add_tsu_reg(TSU_FWEN1);
-               add_tsu_reg(TSU_FCM);
-               add_tsu_reg(TSU_BSYSL0);
-               add_tsu_reg(TSU_BSYSL1);
-               add_tsu_reg(TSU_PRISL0);
-               add_tsu_reg(TSU_PRISL1);
-               add_tsu_reg(TSU_FWSL0);
-               add_tsu_reg(TSU_FWSL1);
+               if (cd->dual_port) {
+                       add_tsu_reg(TSU_FWEN0);
+                       add_tsu_reg(TSU_FWEN1);
+                       add_tsu_reg(TSU_FCM);
+                       add_tsu_reg(TSU_BSYSL0);
+                       add_tsu_reg(TSU_BSYSL1);
+                       add_tsu_reg(TSU_PRISL0);
+                       add_tsu_reg(TSU_PRISL1);
+                       add_tsu_reg(TSU_FWSL0);
+                       add_tsu_reg(TSU_FWSL1);
+               }
                add_tsu_reg(TSU_FWSLC);
-               add_tsu_reg(TSU_QTAGM0);
-               add_tsu_reg(TSU_QTAGM1);
-               add_tsu_reg(TSU_FWSR);
-               add_tsu_reg(TSU_FWINMK);
-               add_tsu_reg(TSU_ADQT0);
-               add_tsu_reg(TSU_ADQT1);
-               add_tsu_reg(TSU_VTAG0);
-               add_tsu_reg(TSU_VTAG1);
+               if (cd->dual_port) {
+                       add_tsu_reg(TSU_QTAGM0);
+                       add_tsu_reg(TSU_QTAGM1);
+                       add_tsu_reg(TSU_FWSR);
+                       add_tsu_reg(TSU_FWINMK);
+                       add_tsu_reg(TSU_ADQT0);
+                       add_tsu_reg(TSU_ADQT1);
+                       add_tsu_reg(TSU_VTAG0);
+                       add_tsu_reg(TSU_VTAG1);
+               }
                add_tsu_reg(TSU_ADSBSY);
                add_tsu_reg(TSU_TEN);
                add_tsu_reg(TSU_POST1);
index 0775b94..466483c 100644 (file)
@@ -30,7 +30,7 @@ struct sxgbe_stats {
 #define SXGBE_STAT(m)                                          \
 {                                                              \
        #m,                                                     \
-       FIELD_SIZEOF(struct sxgbe_extra_stats, m),              \
+       sizeof_field(struct sxgbe_extra_stats, m),              \
        offsetof(struct sxgbe_priv_data, xstats.m)              \
 }
 
index c56fcbb..52ed111 100644 (file)
@@ -2296,7 +2296,7 @@ __setup("sxgbeeth=", sxgbe_cmdline_opt);
 
 
 
-MODULE_DESCRIPTION("SAMSUNG 10G/2.5G/1G Ethernet PLATFORM driver");
+MODULE_DESCRIPTION("Samsung 10G/2.5G/1G Ethernet PLATFORM driver");
 
 MODULE_PARM_DESC(debug, "Message Level (-1: default, 0: no output, 16: all)");
 MODULE_PARM_DESC(eee_timer, "EEE-LPI Default LS timer value");
index 992c773..7a38d7f 100644 (file)
@@ -1472,6 +1472,12 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
        n_xdp_tx = num_possible_cpus();
        n_xdp_ev = DIV_ROUND_UP(n_xdp_tx, EFX_TXQ_TYPES);
 
+       vec_count = pci_msix_vec_count(efx->pci_dev);
+       if (vec_count < 0)
+               return vec_count;
+
+       max_channels = min_t(unsigned int, vec_count, max_channels);
+
        /* Check resources.
         * We need a channel per event queue, plus a VI per tx queue.
         * This may be more pessimistic than it needs to be.
@@ -1493,11 +1499,6 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
                          n_xdp_tx, n_xdp_ev);
        }
 
-       n_channels = min(n_channels, max_channels);
-
-       vec_count = pci_msix_vec_count(efx->pci_dev);
-       if (vec_count < 0)
-               return vec_count;
        if (vec_count < n_channels) {
                netif_err(efx, drv, efx->net_dev,
                          "WARNING: Insufficient MSI-X vectors available (%d < %u).\n",
@@ -1507,11 +1508,9 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
                n_channels = vec_count;
        }
 
-       efx->n_channels = n_channels;
+       n_channels = min(n_channels, max_channels);
 
-       /* Do not create the PTP TX queue(s) if PTP uses the MC directly. */
-       if (extra_channels && !efx_ptp_use_mac_tx_timestamps(efx))
-               n_channels--;
+       efx->n_channels = n_channels;
 
        /* Ignore XDP tx channels when creating rx channels. */
        n_channels -= efx->n_xdp_channels;
@@ -1531,11 +1530,10 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
                efx->n_rx_channels = n_channels;
        }
 
-       if (efx->n_xdp_channels)
-               efx->xdp_channel_offset = efx->tx_channel_offset +
-                                         efx->n_tx_channels;
-       else
-               efx->xdp_channel_offset = efx->n_channels;
+       efx->n_rx_channels = min(efx->n_rx_channels, parallelism);
+       efx->n_tx_channels = min(efx->n_tx_channels, parallelism);
+
+       efx->xdp_channel_offset = n_channels;
 
        netif_dbg(efx, drv, efx->net_dev,
                  "Allocating %u RX channels\n",
@@ -1550,6 +1548,7 @@ static int efx_allocate_msix_channels(struct efx_nic *efx,
 static int efx_probe_interrupts(struct efx_nic *efx)
 {
        unsigned int extra_channels = 0;
+       unsigned int rss_spread;
        unsigned int i, j;
        int rc;
 
@@ -1631,8 +1630,7 @@ static int efx_probe_interrupts(struct efx_nic *efx)
        for (i = 0; i < EFX_MAX_EXTRA_CHANNELS; i++) {
                if (!efx->extra_channel_type[i])
                        continue;
-               if (efx->interrupt_mode != EFX_INT_MODE_MSIX ||
-                   efx->n_channels <= extra_channels) {
+               if (j <= efx->tx_channel_offset + efx->n_tx_channels) {
                        efx->extra_channel_type[i]->handle_no_channel(efx);
                } else {
                        --j;
@@ -1643,16 +1641,17 @@ static int efx_probe_interrupts(struct efx_nic *efx)
                }
        }
 
+       rss_spread = efx->n_rx_channels;
        /* RSS might be usable on VFs even if it is disabled on the PF */
 #ifdef CONFIG_SFC_SRIOV
        if (efx->type->sriov_wanted) {
-               efx->rss_spread = ((efx->n_rx_channels > 1 ||
+               efx->rss_spread = ((rss_spread > 1 ||
                                    !efx->type->sriov_wanted(efx)) ?
-                                  efx->n_rx_channels : efx_vf_size(efx));
+                                  rss_spread : efx_vf_size(efx));
                return 0;
        }
 #endif
-       efx->rss_spread = efx->n_rx_channels;
+       efx->rss_spread = rss_spread;
 
        return 0;
 }
index 1f88212..dfd5182 100644 (file)
@@ -1533,9 +1533,7 @@ static inline bool efx_channel_is_xdp_tx(struct efx_channel *channel)
 
 static inline bool efx_channel_has_tx_queues(struct efx_channel *channel)
 {
-       return efx_channel_is_xdp_tx(channel) ||
-              (channel->type && channel->type->want_txqs &&
-               channel->type->want_txqs(channel));
+       return true;
 }
 
 static inline struct efx_tx_queue *
index ef52b24..c29bf86 100644 (file)
@@ -96,11 +96,12 @@ static inline void efx_sync_rx_buffer(struct efx_nic *efx,
 
 void efx_rx_config_page_split(struct efx_nic *efx)
 {
-       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + efx->rx_ip_align,
+       efx->rx_page_buf_step = ALIGN(efx->rx_dma_len + efx->rx_ip_align +
+                                     XDP_PACKET_HEADROOM,
                                      EFX_RX_BUF_ALIGNMENT);
        efx->rx_bufs_per_page = efx->rx_buffer_order ? 1 :
                ((PAGE_SIZE - sizeof(struct efx_rx_page_state)) /
-               (efx->rx_page_buf_step + XDP_PACKET_HEADROOM));
+               efx->rx_page_buf_step);
        efx->rx_buffer_truesize = (PAGE_SIZE << efx->rx_buffer_order) /
                efx->rx_bufs_per_page;
        efx->rx_pages_per_batch = DIV_ROUND_UP(EFX_RX_PREFERRED_BATCH,
@@ -190,14 +191,13 @@ static int efx_init_rx_buffers(struct efx_rx_queue *rx_queue, bool atomic)
                page_offset = sizeof(struct efx_rx_page_state);
 
                do {
-                       page_offset += XDP_PACKET_HEADROOM;
-                       dma_addr += XDP_PACKET_HEADROOM;
-
                        index = rx_queue->added_count & rx_queue->ptr_mask;
                        rx_buf = efx_rx_buffer(rx_queue, index);
-                       rx_buf->dma_addr = dma_addr + efx->rx_ip_align;
+                       rx_buf->dma_addr = dma_addr + efx->rx_ip_align +
+                                          XDP_PACKET_HEADROOM;
                        rx_buf->page = page;
-                       rx_buf->page_offset = page_offset + efx->rx_ip_align;
+                       rx_buf->page_offset = page_offset + efx->rx_ip_align +
+                                             XDP_PACKET_HEADROOM;
                        rx_buf->len = efx->rx_dma_len;
                        rx_buf->flags = 0;
                        ++rx_queue->added_count;
index f7e927a..b703242 100644 (file)
@@ -424,16 +424,22 @@ static void ave_ethtool_get_wol(struct net_device *ndev,
                phy_ethtool_get_wol(ndev->phydev, wol);
 }
 
-static int ave_ethtool_set_wol(struct net_device *ndev,
-                              struct ethtool_wolinfo *wol)
+static int __ave_ethtool_set_wol(struct net_device *ndev,
+                                struct ethtool_wolinfo *wol)
 {
-       int ret;
-
        if (!ndev->phydev ||
            (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE)))
                return -EOPNOTSUPP;
 
-       ret = phy_ethtool_set_wol(ndev->phydev, wol);
+       return phy_ethtool_set_wol(ndev->phydev, wol);
+}
+
+static int ave_ethtool_set_wol(struct net_device *ndev,
+                              struct ethtool_wolinfo *wol)
+{
+       int ret;
+
+       ret = __ave_ethtool_set_wol(ndev, wol);
        if (!ret)
                device_set_wakeup_enable(&ndev->dev, !!wol->wolopts);
 
@@ -1216,7 +1222,7 @@ static int ave_init(struct net_device *ndev)
 
        /* set wol initial state disabled */
        wol.wolopts = 0;
-       ave_ethtool_set_wol(ndev, &wol);
+       __ave_ethtool_set_wol(ndev, &wol);
 
        if (!phy_interface_is_rgmii(phydev))
                phy_set_max_speed(phydev, SPEED_100);
@@ -1768,7 +1774,7 @@ static int ave_resume(struct device *dev)
 
        ave_ethtool_get_wol(ndev, &wol);
        wol.wolopts = priv->wolopts;
-       ave_ethtool_set_wol(ndev, &wol);
+       __ave_ethtool_set_wol(ndev, &wol);
 
        if (ndev->phydev) {
                ret = phy_resume(ndev->phydev);
index b210e98..94f9468 100644 (file)
@@ -365,9 +365,8 @@ struct dma_features {
        unsigned int arpoffsel;
 };
 
-/* GMAC TX FIFO is 8K, Rx FIFO is 16K */
-#define BUF_SIZE_16KiB 16384
-/* RX Buffer size must be < 8191 and multiple of 4/8/16 bytes */
+/* RX Buffer size must be multiple of 4/8/16 bytes */
+#define BUF_SIZE_16KiB 16368
 #define BUF_SIZE_8KiB 8188
 #define BUF_SIZE_4KiB 4096
 #define BUF_SIZE_2KiB 2048
index bd6c010..0e2fa14 100644 (file)
@@ -112,6 +112,14 @@ static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac)
        struct device *dev = dwmac->dev;
        const char *parent_name, *mux_parent_names[MUX_CLK_NUM_PARENTS];
        struct meson8b_dwmac_clk_configs *clk_configs;
+       static const struct clk_div_table div_table[] = {
+               { .div = 2, .val = 2, },
+               { .div = 3, .val = 3, },
+               { .div = 4, .val = 4, },
+               { .div = 5, .val = 5, },
+               { .div = 6, .val = 6, },
+               { .div = 7, .val = 7, },
+       };
 
        clk_configs = devm_kzalloc(dev, sizeof(*clk_configs), GFP_KERNEL);
        if (!clk_configs)
@@ -146,9 +154,9 @@ static int meson8b_init_rgmii_tx_clk(struct meson8b_dwmac *dwmac)
        clk_configs->m250_div.reg = dwmac->regs + PRG_ETH0;
        clk_configs->m250_div.shift = PRG_ETH0_CLK_M250_DIV_SHIFT;
        clk_configs->m250_div.width = PRG_ETH0_CLK_M250_DIV_WIDTH;
-       clk_configs->m250_div.flags = CLK_DIVIDER_ONE_BASED |
-                               CLK_DIVIDER_ALLOW_ZERO |
-                               CLK_DIVIDER_ROUND_CLOSEST;
+       clk_configs->m250_div.table = div_table;
+       clk_configs->m250_div.flags = CLK_DIVIDER_ALLOW_ZERO |
+                                     CLK_DIVIDER_ROUND_CLOSEST;
        clk = meson8b_dwmac_register_clk(dwmac, "m250_div", &parent_name, 1,
                                         &clk_divider_ops,
                                         &clk_configs->m250_div.hw);
index 1c8d84e..01b484c 100644 (file)
@@ -957,6 +957,9 @@ static int sun8i_dwmac_set_syscon(struct stmmac_priv *priv)
                /* default */
                break;
        case PHY_INTERFACE_MODE_RGMII:
+       case PHY_INTERFACE_MODE_RGMII_ID:
+       case PHY_INTERFACE_MODE_RGMII_RXID:
+       case PHY_INTERFACE_MODE_RGMII_TXID:
                reg |= SYSCON_EPIT | SYSCON_ETCS_INT_GMII;
                break;
        case PHY_INTERFACE_MODE_RMII:
index 26353ef..7d40760 100644 (file)
@@ -44,7 +44,7 @@ static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
         * rate, which then uses the auto-reparenting feature of the
         * clock driver, and enabling/disabling the clock.
         */
-       if (gmac->interface == PHY_INTERFACE_MODE_RGMII) {
+       if (phy_interface_mode_is_rgmii(gmac->interface)) {
                clk_set_rate(gmac->tx_clk, SUN7I_GMAC_GMII_RGMII_RATE);
                clk_prepare_enable(gmac->tx_clk);
                gmac->clk_enabled = 1;
index 3b6e559..ef8a07c 100644 (file)
 #define XGMAC_DMA_CH_RX_CONTROL(x)     (0x00003108 + (0x80 * (x)))
 #define XGMAC_RxPBL                    GENMASK(21, 16)
 #define XGMAC_RxPBL_SHIFT              16
+#define XGMAC_RBSZ                     GENMASK(14, 1)
+#define XGMAC_RBSZ_SHIFT               1
 #define XGMAC_RXST                     BIT(0)
 #define XGMAC_DMA_CH_TxDESC_HADDR(x)   (0x00003110 + (0x80 * (x)))
 #define XGMAC_DMA_CH_TxDESC_LADDR(x)   (0x00003114 + (0x80 * (x)))
index 22a7f0c..f3f08cc 100644 (file)
@@ -482,7 +482,8 @@ static void dwxgmac2_set_bfsize(void __iomem *ioaddr, int bfsize, u32 chan)
        u32 value;
 
        value = readl(ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
-       value |= bfsize << 1;
+       value &= ~XGMAC_RBSZ;
+       value |= bfsize << XGMAC_RBSZ_SHIFT;
        writel(value, ioaddr + XGMAC_DMA_CH_RX_CONTROL(chan));
 }
 
index 1a76883..b29603e 100644 (file)
@@ -34,7 +34,7 @@ struct stmmac_stats {
 };
 
 #define STMMAC_STAT(m) \
-       { #m, FIELD_SIZEOF(struct stmmac_extra_stats, m),       \
+       { #m, sizeof_field(struct stmmac_extra_stats, m),       \
        offsetof(struct stmmac_priv, xstats.m)}
 
 static const struct stmmac_stats stmmac_gstrings_stats[] = {
@@ -163,7 +163,7 @@ static const struct stmmac_stats stmmac_gstrings_stats[] = {
 
 /* HW MAC Management counters (if supported) */
 #define STMMAC_MMC_STAT(m)     \
-       { #m, FIELD_SIZEOF(struct stmmac_counters, m),  \
+       { #m, sizeof_field(struct stmmac_counters, m),  \
        offsetof(struct stmmac_priv, mmc.m)}
 
 static const struct stmmac_stats stmmac_mmc[] = {
index bbc65bd..80d59b7 100644 (file)
@@ -46,7 +46,7 @@
 #include "dwxgmac2.h"
 #include "hwif.h"
 
-#define        STMMAC_ALIGN(x)         __ALIGN_KERNEL(x, SMP_CACHE_BYTES)
+#define        STMMAC_ALIGN(x)         ALIGN(ALIGN(x, SMP_CACHE_BYTES), 16)
 #define        TSO_MAX_BUFF_SIZE       (SZ_16K - 1)
 
 /* Module parameters */
@@ -106,6 +106,7 @@ MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
 static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
 
 #ifdef CONFIG_DEBUG_FS
+static const struct net_device_ops stmmac_netdev_ops;
 static void stmmac_init_fs(struct net_device *dev);
 static void stmmac_exit_fs(struct net_device *dev);
 #endif
@@ -1109,7 +1110,9 @@ static int stmmac_set_bfsize(int mtu, int bufsize)
 {
        int ret = bufsize;
 
-       if (mtu >= BUF_SIZE_4KiB)
+       if (mtu >= BUF_SIZE_8KiB)
+               ret = BUF_SIZE_16KiB;
+       else if (mtu >= BUF_SIZE_4KiB)
                ret = BUF_SIZE_8KiB;
        else if (mtu >= BUF_SIZE_2KiB)
                ret = BUF_SIZE_4KiB;
@@ -1293,19 +1296,9 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
        struct stmmac_priv *priv = netdev_priv(dev);
        u32 rx_count = priv->plat->rx_queues_to_use;
        int ret = -ENOMEM;
-       int bfsize = 0;
        int queue;
        int i;
 
-       bfsize = stmmac_set_16kib_bfsize(priv, dev->mtu);
-       if (bfsize < 0)
-               bfsize = 0;
-
-       if (bfsize < BUF_SIZE_16KiB)
-               bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
-
-       priv->dma_buf_sz = bfsize;
-
        /* RX INITIALIZATION */
        netif_dbg(priv, probe, priv->dev,
                  "SKB addresses:\nskb\t\tskb data\tdma data\n");
@@ -1347,8 +1340,6 @@ static int init_dma_rx_desc_rings(struct net_device *dev, gfp_t flags)
                }
        }
 
-       buf_sz = bfsize;
-
        return 0;
 
 err_init_rx_buffers:
@@ -2658,6 +2649,7 @@ static void stmmac_hw_teardown(struct net_device *dev)
 static int stmmac_open(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
+       int bfsize = 0;
        u32 chan;
        int ret;
 
@@ -2677,7 +2669,16 @@ static int stmmac_open(struct net_device *dev)
        memset(&priv->xstats, 0, sizeof(struct stmmac_extra_stats));
        priv->xstats.threshold = tc;
 
-       priv->dma_buf_sz = STMMAC_ALIGN(buf_sz);
+       bfsize = stmmac_set_16kib_bfsize(priv, dev->mtu);
+       if (bfsize < 0)
+               bfsize = 0;
+
+       if (bfsize < BUF_SIZE_16KiB)
+               bfsize = stmmac_set_bfsize(dev->mtu, priv->dma_buf_sz);
+
+       priv->dma_buf_sz = bfsize;
+       buf_sz = bfsize;
+
        priv->rx_copybreak = STMMAC_RX_COPYBREAK;
 
        ret = alloc_dma_desc_resources(priv);
@@ -3053,8 +3054,6 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
                tx_q->tx_count_frames = 0;
                stmmac_set_tx_ic(priv, desc);
                priv->xstats.tx_set_ic_bit++;
-       } else {
-               stmmac_tx_timer_arm(priv, queue);
        }
 
        /* We've used all descriptors we need for this skb, however,
@@ -3125,6 +3124,7 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
        stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
+       stmmac_tx_timer_arm(priv, queue);
 
        return NETDEV_TX_OK;
 
@@ -3276,8 +3276,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                tx_q->tx_count_frames = 0;
                stmmac_set_tx_ic(priv, desc);
                priv->xstats.tx_set_ic_bit++;
-       } else {
-               stmmac_tx_timer_arm(priv, queue);
        }
 
        /* We've used all descriptors we need for this skb, however,
@@ -3366,6 +3364,7 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_q->tx_tail_addr = tx_q->dma_tx_phy + (tx_q->cur_tx * sizeof(*desc));
        stmmac_set_tx_tail_ptr(priv, priv->ioaddr, tx_q->tx_tail_addr, queue);
+       stmmac_tx_timer_arm(priv, queue);
 
        return NETDEV_TX_OK;
 
@@ -3646,8 +3645,9 @@ read_again:
                 * feature is always disabled and packets need to be
                 * stripped manually.
                 */
-               if (unlikely(priv->synopsys_id >= DWMAC_CORE_4_00) ||
-                   unlikely(status != llc_snap)) {
+               if (likely(!(status & rx_not_ls)) &&
+                   (likely(priv->synopsys_id >= DWMAC_CORE_4_00) ||
+                    unlikely(status != llc_snap))) {
                        if (buf2_len)
                                buf2_len -= ETH_FCS_LEN;
                        else
@@ -3829,12 +3829,24 @@ static void stmmac_set_rx_mode(struct net_device *dev)
 static int stmmac_change_mtu(struct net_device *dev, int new_mtu)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
+       int txfifosz = priv->plat->tx_fifo_size;
+
+       if (txfifosz == 0)
+               txfifosz = priv->dma_cap.tx_fifo_size;
+
+       txfifosz /= priv->plat->tx_queues_to_use;
 
        if (netif_running(dev)) {
                netdev_err(priv->dev, "must be stopped to change its MTU\n");
                return -EBUSY;
        }
 
+       new_mtu = STMMAC_ALIGN(new_mtu);
+
+       /* If condition true, FIFO is too small or MTU too large */
+       if ((txfifosz < new_mtu) || (new_mtu > BUF_SIZE_16KiB))
+               return -EINVAL;
+
        dev->mtu = new_mtu;
 
        netdev_update_features(dev);
@@ -4245,6 +4257,34 @@ static int stmmac_dma_cap_show(struct seq_file *seq, void *v)
 }
 DEFINE_SHOW_ATTRIBUTE(stmmac_dma_cap);
 
+/* Use network device events to rename debugfs file entries.
+ */
+static int stmmac_device_event(struct notifier_block *unused,
+                              unsigned long event, void *ptr)
+{
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct stmmac_priv *priv = netdev_priv(dev);
+
+       if (dev->netdev_ops != &stmmac_netdev_ops)
+               goto done;
+
+       switch (event) {
+       case NETDEV_CHANGENAME:
+               if (priv->dbgfs_dir)
+                       priv->dbgfs_dir = debugfs_rename(stmmac_fs_dir,
+                                                        priv->dbgfs_dir,
+                                                        stmmac_fs_dir,
+                                                        dev->name);
+               break;
+       }
+done:
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block stmmac_notifier = {
+       .notifier_call = stmmac_device_event,
+};
+
 static void stmmac_init_fs(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
@@ -4259,12 +4299,15 @@ static void stmmac_init_fs(struct net_device *dev)
        /* Entry to report the DMA HW features */
        debugfs_create_file("dma_cap", 0444, priv->dbgfs_dir, dev,
                            &stmmac_dma_cap_fops);
+
+       register_netdevice_notifier(&stmmac_notifier);
 }
 
 static void stmmac_exit_fs(struct net_device *dev)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
 
+       unregister_netdevice_notifier(&stmmac_notifier);
        debugfs_remove_recursive(priv->dbgfs_dir);
 }
 #endif /* CONFIG_DEBUG_FS */
index bedaff0..4775f49 100644 (file)
@@ -320,7 +320,7 @@ out:
 static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
                         struct device_node *np, struct device *dev)
 {
-       bool mdio = true;
+       bool mdio = !of_phy_is_fixed_link(np);
        static const struct of_device_id need_mdio_ids[] = {
                { .compatible = "snps,dwc-qos-ethernet-4.10" },
                {},
index f3d8b93..450d7da 100644 (file)
@@ -80,7 +80,7 @@ static struct sk_buff *stmmac_test_get_udp_skb(struct stmmac_priv *priv,
        if (attr->max_size && (attr->max_size > size))
                size = attr->max_size;
 
-       skb = netdev_alloc_skb_ip_align(priv->dev, size);
+       skb = netdev_alloc_skb(priv->dev, size);
        if (!skb)
                return NULL;
 
@@ -244,6 +244,8 @@ static int stmmac_test_loopback_validate(struct sk_buff *skb,
                                         struct net_device *orig_ndev)
 {
        struct stmmac_test_priv *tpriv = pt->af_packet_priv;
+       unsigned char *src = tpriv->packet->src;
+       unsigned char *dst = tpriv->packet->dst;
        struct stmmachdr *shdr;
        struct ethhdr *ehdr;
        struct udphdr *uhdr;
@@ -260,15 +262,15 @@ static int stmmac_test_loopback_validate(struct sk_buff *skb,
                goto out;
 
        ehdr = (struct ethhdr *)skb_mac_header(skb);
-       if (tpriv->packet->dst) {
-               if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst))
+       if (dst) {
+               if (!ether_addr_equal_unaligned(ehdr->h_dest, dst))
                        goto out;
        }
        if (tpriv->packet->sarc) {
-               if (!ether_addr_equal(ehdr->h_source, ehdr->h_dest))
+               if (!ether_addr_equal_unaligned(ehdr->h_source, ehdr->h_dest))
                        goto out;
-       } else if (tpriv->packet->src) {
-               if (!ether_addr_equal(ehdr->h_source, tpriv->packet->src))
+       } else if (src) {
+               if (!ether_addr_equal_unaligned(ehdr->h_source, src))
                        goto out;
        }
 
@@ -624,6 +626,8 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv)
                return -EOPNOTSUPP;
        if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
                return -EOPNOTSUPP;
+       if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
+               return -EOPNOTSUPP;
 
        while (--tries) {
                /* We only need to check the mc_addr for collisions */
@@ -666,6 +670,8 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv)
 
        if (stmmac_filter_check(priv))
                return -EOPNOTSUPP;
+       if (netdev_uc_count(priv->dev) >= priv->hw->unicast_filter_entries)
+               return -EOPNOTSUPP;
        if (netdev_mc_count(priv->dev) >= priv->hw->multicast_filter_bins)
                return -EOPNOTSUPP;
 
@@ -710,7 +716,7 @@ static int stmmac_test_flowctrl_validate(struct sk_buff *skb,
        struct ethhdr *ehdr;
 
        ehdr = (struct ethhdr *)skb_mac_header(skb);
-       if (!ether_addr_equal(ehdr->h_source, orig_ndev->dev_addr))
+       if (!ether_addr_equal_unaligned(ehdr->h_source, orig_ndev->dev_addr))
                goto out;
        if (ehdr->h_proto != htons(ETH_P_PAUSE))
                goto out;
@@ -847,12 +853,16 @@ static int stmmac_test_vlan_validate(struct sk_buff *skb,
        if (tpriv->vlan_id) {
                if (skb->vlan_proto != htons(proto))
                        goto out;
-               if (skb->vlan_tci != tpriv->vlan_id)
+               if (skb->vlan_tci != tpriv->vlan_id) {
+                       /* Means filter did not work. */
+                       tpriv->ok = false;
+                       complete(&tpriv->comp);
                        goto out;
+               }
        }
 
        ehdr = (struct ethhdr *)skb_mac_header(skb);
-       if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->dst))
+       if (!ether_addr_equal_unaligned(ehdr->h_dest, tpriv->packet->dst))
                goto out;
 
        ihdr = ip_hdr(skb);
@@ -961,6 +971,9 @@ static int stmmac_test_vlanfilt_perfect(struct stmmac_priv *priv)
 {
        int ret, prev_cap = priv->dma_cap.vlhash;
 
+       if (!(priv->dev->features & NETIF_F_HW_VLAN_CTAG_FILTER))
+               return -EOPNOTSUPP;
+
        priv->dma_cap.vlhash = 0;
        ret = __stmmac_test_vlanfilt(priv);
        priv->dma_cap.vlhash = prev_cap;
@@ -1053,6 +1066,9 @@ static int stmmac_test_dvlanfilt_perfect(struct stmmac_priv *priv)
 {
        int ret, prev_cap = priv->dma_cap.vlhash;
 
+       if (!(priv->dev->features & NETIF_F_HW_VLAN_STAG_FILTER))
+               return -EOPNOTSUPP;
+
        priv->dma_cap.vlhash = 0;
        ret = __stmmac_test_dvlanfilt(priv);
        priv->dma_cap.vlhash = prev_cap;
@@ -1319,16 +1335,19 @@ static int __stmmac_test_l3filt(struct stmmac_priv *priv, u32 dst, u32 src,
        struct stmmac_packet_attrs attr = { };
        struct flow_dissector *dissector;
        struct flow_cls_offload *cls;
+       int ret, old_enable = 0;
        struct flow_rule *rule;
-       int ret;
 
        if (!tc_can_offload(priv->dev))
                return -EOPNOTSUPP;
        if (!priv->dma_cap.l3l4fnum)
                return -EOPNOTSUPP;
-       if (priv->rss.enable)
+       if (priv->rss.enable) {
+               old_enable = priv->rss.enable;
+               priv->rss.enable = false;
                stmmac_rss_configure(priv, priv->hw, NULL,
                                     priv->plat->rx_queues_to_use);
+       }
 
        dissector = kzalloc(sizeof(*dissector), GFP_KERNEL);
        if (!dissector) {
@@ -1395,7 +1414,8 @@ cleanup_cls:
 cleanup_dissector:
        kfree(dissector);
 cleanup_rss:
-       if (priv->rss.enable) {
+       if (old_enable) {
+               priv->rss.enable = old_enable;
                stmmac_rss_configure(priv, priv->hw, &priv->rss,
                                     priv->plat->rx_queues_to_use);
        }
@@ -1440,16 +1460,19 @@ static int __stmmac_test_l4filt(struct stmmac_priv *priv, u32 dst, u32 src,
        struct stmmac_packet_attrs attr = { };
        struct flow_dissector *dissector;
        struct flow_cls_offload *cls;
+       int ret, old_enable = 0;
        struct flow_rule *rule;
-       int ret;
 
        if (!tc_can_offload(priv->dev))
                return -EOPNOTSUPP;
        if (!priv->dma_cap.l3l4fnum)
                return -EOPNOTSUPP;
-       if (priv->rss.enable)
+       if (priv->rss.enable) {
+               old_enable = priv->rss.enable;
+               priv->rss.enable = false;
                stmmac_rss_configure(priv, priv->hw, NULL,
                                     priv->plat->rx_queues_to_use);
+       }
 
        dissector = kzalloc(sizeof(*dissector), GFP_KERNEL);
        if (!dissector) {
@@ -1521,7 +1544,8 @@ cleanup_cls:
 cleanup_dissector:
        kfree(dissector);
 cleanup_rss:
-       if (priv->rss.enable) {
+       if (old_enable) {
+               priv->rss.enable = old_enable;
                stmmac_rss_configure(priv, priv->hw, &priv->rss,
                                     priv->plat->rx_queues_to_use);
        }
@@ -1574,7 +1598,7 @@ static int stmmac_test_arp_validate(struct sk_buff *skb,
        struct arphdr *ahdr;
 
        ehdr = (struct ethhdr *)skb_mac_header(skb);
-       if (!ether_addr_equal(ehdr->h_dest, tpriv->packet->src))
+       if (!ether_addr_equal_unaligned(ehdr->h_dest, tpriv->packet->src))
                goto out;
 
        ahdr = arp_hdr(skb);
index 7d972e0..9ffae12 100644 (file)
@@ -577,6 +577,10 @@ static int tc_setup_cls(struct stmmac_priv *priv,
 {
        int ret = 0;
 
+       /* When RSS is enabled, the filtering will be bypassed */
+       if (priv->rss.enable)
+               return -EBUSY;
+
        switch (cls->command) {
        case FLOW_CLS_REPLACE:
                ret = tc_add_flow(priv, cls);
index a46f418..bf98e0f 100644 (file)
@@ -63,6 +63,7 @@ config TI_CPSW_SWITCHDEV
        tristate "TI CPSW Switch Support with switchdev"
        depends on ARCH_DAVINCI || ARCH_OMAP2PLUS || COMPILE_TEST
        depends on NET_SWITCHDEV
+       select PAGE_POOL
        select TI_DAVINCI_MDIO
        select MFD_SYSCON
        select REGMAP
index d34df8e..ecf776a 100644 (file)
@@ -5,6 +5,7 @@
 
 obj-$(CONFIG_TI_CPSW) += cpsw-common.o
 obj-$(CONFIG_TI_DAVINCI_EMAC) += cpsw-common.o
+obj-$(CONFIG_TI_CPSW_SWITCHDEV) += cpsw-common.o
 
 obj-$(CONFIG_TLAN) += tlan.o
 obj-$(CONFIG_CPMAC) += cpmac.o
index 31248a6..fa54efe 100644 (file)
@@ -73,13 +73,13 @@ enum {
 };
 
 #define CPSW_STAT(m)           CPSW_STATS,                             \
-                               FIELD_SIZEOF(struct cpsw_hw_stats, m), \
+                               sizeof_field(struct cpsw_hw_stats, m), \
                                offsetof(struct cpsw_hw_stats, m)
 #define CPDMA_RX_STAT(m)       CPDMA_RX_STATS,                            \
-                               FIELD_SIZEOF(struct cpdma_chan_stats, m), \
+                               sizeof_field(struct cpdma_chan_stats, m), \
                                offsetof(struct cpdma_chan_stats, m)
 #define CPDMA_TX_STAT(m)       CPDMA_TX_STATS,                            \
-                               FIELD_SIZEOF(struct cpdma_chan_stats, m), \
+                               sizeof_field(struct cpdma_chan_stats, m), \
                                offsetof(struct cpdma_chan_stats, m)
 
 static const struct cpsw_stats cpsw_gstrings_stats[] = {
index 37ba708..6614fa3 100644 (file)
@@ -1018,7 +1018,6 @@ static int cpdma_chan_submit_si(struct submit_info *si)
        struct cpdma_chan               *chan = si->chan;
        struct cpdma_ctlr               *ctlr = chan->ctlr;
        int                             len = si->len;
-       int                             swlen = len;
        struct cpdma_desc __iomem       *desc;
        dma_addr_t                      buffer;
        u32                             mode;
@@ -1046,7 +1045,6 @@ static int cpdma_chan_submit_si(struct submit_info *si)
        if (si->data_dma) {
                buffer = si->data_dma;
                dma_sync_single_for_device(ctlr->dev, buffer, len, chan->dir);
-               swlen |= CPDMA_DMA_EXT_MAP;
        } else {
                buffer = dma_map_single(ctlr->dev, si->data_virt, len, chan->dir);
                ret = dma_mapping_error(ctlr->dev, buffer);
@@ -1065,7 +1063,8 @@ static int cpdma_chan_submit_si(struct submit_info *si)
        writel_relaxed(mode | len, &desc->hw_mode);
        writel_relaxed((uintptr_t)si->token, &desc->sw_token);
        writel_relaxed(buffer, &desc->sw_buffer);
-       writel_relaxed(swlen, &desc->sw_len);
+       writel_relaxed(si->data_dma ? len | CPDMA_DMA_EXT_MAP : len,
+                      &desc->sw_len);
        desc_read(desc, sw_len);
 
        __cpdma_chan_submit(chan, desc);
index 86a3f42..d6a192c 100644 (file)
@@ -783,28 +783,28 @@ struct netcp_ethtool_stat {
 #define GBE_STATSA_INFO(field)                                         \
 {                                                                      \
        "GBE_A:"#field, GBE_STATSA_MODULE,                              \
-       FIELD_SIZEOF(struct gbe_hw_stats, field),                       \
+       sizeof_field(struct gbe_hw_stats, field),                       \
        offsetof(struct gbe_hw_stats, field)                            \
 }
 
 #define GBE_STATSB_INFO(field)                                         \
 {                                                                      \
        "GBE_B:"#field, GBE_STATSB_MODULE,                              \
-       FIELD_SIZEOF(struct gbe_hw_stats, field),                       \
+       sizeof_field(struct gbe_hw_stats, field),                       \
        offsetof(struct gbe_hw_stats, field)                            \
 }
 
 #define GBE_STATSC_INFO(field)                                         \
 {                                                                      \
        "GBE_C:"#field, GBE_STATSC_MODULE,                              \
-       FIELD_SIZEOF(struct gbe_hw_stats, field),                       \
+       sizeof_field(struct gbe_hw_stats, field),                       \
        offsetof(struct gbe_hw_stats, field)                            \
 }
 
 #define GBE_STATSD_INFO(field)                                         \
 {                                                                      \
        "GBE_D:"#field, GBE_STATSD_MODULE,                              \
-       FIELD_SIZEOF(struct gbe_hw_stats, field),                       \
+       sizeof_field(struct gbe_hw_stats, field),                       \
        offsetof(struct gbe_hw_stats, field)                            \
 }
 
@@ -957,7 +957,7 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = {
 #define GBENU_STATS_HOST(field)                                        \
 {                                                              \
        "GBE_HOST:"#field, GBENU_STATS0_MODULE,                 \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
@@ -967,56 +967,56 @@ static const struct netcp_ethtool_stat gbe13_et_stats[] = {
 #define GBENU_STATS_P1(field)                                  \
 {                                                              \
        "GBE_P1:"#field, GBENU_STATS1_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P2(field)                                  \
 {                                                              \
        "GBE_P2:"#field, GBENU_STATS2_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P3(field)                                  \
 {                                                              \
        "GBE_P3:"#field, GBENU_STATS3_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P4(field)                                  \
 {                                                              \
        "GBE_P4:"#field, GBENU_STATS4_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P5(field)                                  \
 {                                                              \
        "GBE_P5:"#field, GBENU_STATS5_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P6(field)                                  \
 {                                                              \
        "GBE_P6:"#field, GBENU_STATS6_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P7(field)                                  \
 {                                                              \
        "GBE_P7:"#field, GBENU_STATS7_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
 #define GBENU_STATS_P8(field)                                  \
 {                                                              \
        "GBE_P8:"#field, GBENU_STATS8_MODULE,                   \
-       FIELD_SIZEOF(struct gbenu_hw_stats, field),             \
+       sizeof_field(struct gbenu_hw_stats, field),             \
        offsetof(struct gbenu_hw_stats, field)                  \
 }
 
@@ -1607,21 +1607,21 @@ static const struct netcp_ethtool_stat gbenu_et_stats[] = {
 #define XGBE_STATS0_INFO(field)                                \
 {                                                      \
        "GBE_0:"#field, XGBE_STATS0_MODULE,             \
-       FIELD_SIZEOF(struct xgbe_hw_stats, field),      \
+       sizeof_field(struct xgbe_hw_stats, field),      \
        offsetof(struct xgbe_hw_stats, field)           \
 }
 
 #define XGBE_STATS1_INFO(field)                                \
 {                                                      \
        "GBE_1:"#field, XGBE_STATS1_MODULE,             \
-       FIELD_SIZEOF(struct xgbe_hw_stats, field),      \
+       sizeof_field(struct xgbe_hw_stats, field),      \
        offsetof(struct xgbe_hw_stats, field)           \
 }
 
 #define XGBE_STATS2_INFO(field)                                \
 {                                                      \
        "GBE_2:"#field, XGBE_STATS2_MODULE,             \
-       FIELD_SIZEOF(struct xgbe_hw_stats, field),      \
+       sizeof_field(struct xgbe_hw_stats, field),      \
        offsetof(struct xgbe_hw_stats, field)           \
 }
 
index 09f3604..746736c 100644 (file)
@@ -21,7 +21,7 @@ struct fjes_stats {
 
 #define FJES_STAT(name, stat) { \
        .stat_string = name, \
-       .sizeof_stat = FIELD_SIZEOF(struct fjes_adapter, stat), \
+       .sizeof_stat = sizeof_field(struct fjes_adapter, stat), \
        .stat_offset = offsetof(struct fjes_adapter, stat) \
 }
 
index b517c1a..91a1059 100644 (file)
@@ -166,6 +166,9 @@ static int fjes_acpi_add(struct acpi_device *device)
        /* create platform_device */
        plat_dev = platform_device_register_simple(DRV_NAME, 0, fjes_resource,
                                                   ARRAY_SIZE(fjes_resource));
+       if (IS_ERR(plat_dev))
+               return PTR_ERR(plat_dev);
+
        device->driver_data = plat_dev;
 
        return 0;
index 5c6b7fc..75757e9 100644 (file)
@@ -1156,7 +1156,7 @@ static void geneve_setup(struct net_device *dev)
 
 static const struct nla_policy geneve_policy[IFLA_GENEVE_MAX + 1] = {
        [IFLA_GENEVE_ID]                = { .type = NLA_U32 },
-       [IFLA_GENEVE_REMOTE]            = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+       [IFLA_GENEVE_REMOTE]            = { .len = sizeof_field(struct iphdr, daddr) },
        [IFLA_GENEVE_REMOTE6]           = { .len = sizeof(struct in6_addr) },
        [IFLA_GENEVE_TTL]               = { .type = NLA_U8 },
        [IFLA_GENEVE_TOS]               = { .type = NLA_U8 },
index ecfe262..f6222ad 100644 (file)
@@ -38,7 +38,6 @@ struct pdp_ctx {
        struct hlist_node       hlist_addr;
 
        union {
-               u64             tid;
                struct {
                        u64     tid;
                        u16     flow;
@@ -541,7 +540,7 @@ static int gtp_build_skb_ip4(struct sk_buff *skb, struct net_device *dev,
                mtu = dst_mtu(&rt->dst);
        }
 
-       rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu);
+       rt->dst.ops->update_pmtu(&rt->dst, NULL, skb, mtu, false);
 
        if (!skb_is_gso(skb) && (iph->frag_off & htons(IP_DF)) &&
            mtu < ntohs(iph->tot_len)) {
@@ -641,9 +640,16 @@ static void gtp_link_setup(struct net_device *dev)
 }
 
 static int gtp_hashtable_new(struct gtp_dev *gtp, int hsize);
-static void gtp_hashtable_free(struct gtp_dev *gtp);
 static int gtp_encap_enable(struct gtp_dev *gtp, struct nlattr *data[]);
 
+static void gtp_destructor(struct net_device *dev)
+{
+       struct gtp_dev *gtp = netdev_priv(dev);
+
+       kfree(gtp->addr_hash);
+       kfree(gtp->tid_hash);
+}
+
 static int gtp_newlink(struct net *src_net, struct net_device *dev,
                       struct nlattr *tb[], struct nlattr *data[],
                       struct netlink_ext_ack *extack)
@@ -661,10 +667,13 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
        if (err < 0)
                return err;
 
-       if (!data[IFLA_GTP_PDP_HASHSIZE])
+       if (!data[IFLA_GTP_PDP_HASHSIZE]) {
                hashsize = 1024;
-       else
+       } else {
                hashsize = nla_get_u32(data[IFLA_GTP_PDP_HASHSIZE]);
+               if (!hashsize)
+                       hashsize = 1024;
+       }
 
        err = gtp_hashtable_new(gtp, hashsize);
        if (err < 0)
@@ -678,13 +687,15 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev,
 
        gn = net_generic(dev_net(dev), gtp_net_id);
        list_add_rcu(&gtp->list, &gn->gtp_dev_list);
+       dev->priv_destructor = gtp_destructor;
 
        netdev_dbg(dev, "registered new GTP interface\n");
 
        return 0;
 
 out_hashtable:
-       gtp_hashtable_free(gtp);
+       kfree(gtp->addr_hash);
+       kfree(gtp->tid_hash);
 out_encap:
        gtp_encap_disable(gtp);
        return err;
@@ -693,8 +704,13 @@ out_encap:
 static void gtp_dellink(struct net_device *dev, struct list_head *head)
 {
        struct gtp_dev *gtp = netdev_priv(dev);
+       struct pdp_ctx *pctx;
+       int i;
+
+       for (i = 0; i < gtp->hash_size; i++)
+               hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid)
+                       pdp_context_delete(pctx);
 
-       gtp_hashtable_free(gtp);
        list_del_rcu(&gtp->list);
        unregister_netdevice_queue(dev, head);
 }
@@ -772,20 +788,6 @@ err1:
        return -ENOMEM;
 }
 
-static void gtp_hashtable_free(struct gtp_dev *gtp)
-{
-       struct pdp_ctx *pctx;
-       int i;
-
-       for (i = 0; i < gtp->hash_size; i++)
-               hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid)
-                       pdp_context_delete(pctx);
-
-       synchronize_rcu();
-       kfree(gtp->addr_hash);
-       kfree(gtp->tid_hash);
-}
-
 static struct sock *gtp_encap_enable_socket(int fd, int type,
                                            struct gtp_dev *gtp)
 {
@@ -811,7 +813,7 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
        lock_sock(sock->sk);
        if (sock->sk->sk_user_data) {
                sk = ERR_PTR(-EBUSY);
-               goto out_sock;
+               goto out_rel_sock;
        }
 
        sk = sock->sk;
@@ -824,8 +826,9 @@ static struct sock *gtp_encap_enable_socket(int fd, int type,
 
        setup_udp_tunnel_sock(sock_net(sock->sk), sock, &tuncfg);
 
-out_sock:
+out_rel_sock:
        release_sock(sock->sk);
+out_sock:
        sockfd_put(sock);
        return sk;
 }
@@ -926,24 +929,31 @@ static void ipv4_pdp_fill(struct pdp_ctx *pctx, struct genl_info *info)
        }
 }
 
-static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk,
-                       struct genl_info *info)
+static int gtp_pdp_add(struct gtp_dev *gtp, struct sock *sk,
+                      struct genl_info *info)
 {
+       struct pdp_ctx *pctx, *pctx_tid = NULL;
        struct net_device *dev = gtp->dev;
        u32 hash_ms, hash_tid = 0;
-       struct pdp_ctx *pctx;
+       unsigned int version;
        bool found = false;
        __be32 ms_addr;
 
        ms_addr = nla_get_be32(info->attrs[GTPA_MS_ADDRESS]);
        hash_ms = ipv4_hashfn(ms_addr) % gtp->hash_size;
+       version = nla_get_u32(info->attrs[GTPA_VERSION]);
 
-       hlist_for_each_entry_rcu(pctx, &gtp->addr_hash[hash_ms], hlist_addr) {
-               if (pctx->ms_addr_ip4.s_addr == ms_addr) {
-                       found = true;
-                       break;
-               }
-       }
+       pctx = ipv4_pdp_find(gtp, ms_addr);
+       if (pctx)
+               found = true;
+       if (version == GTP_V0)
+               pctx_tid = gtp0_pdp_find(gtp,
+                                        nla_get_u64(info->attrs[GTPA_TID]));
+       else if (version == GTP_V1)
+               pctx_tid = gtp1_pdp_find(gtp,
+                                        nla_get_u32(info->attrs[GTPA_I_TEI]));
+       if (pctx_tid)
+               found = true;
 
        if (found) {
                if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
@@ -951,6 +961,11 @@ static int ipv4_pdp_add(struct gtp_dev *gtp, struct sock *sk,
                if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
                        return -EOPNOTSUPP;
 
+               if (pctx && pctx_tid)
+                       return -EEXIST;
+               if (!pctx)
+                       pctx = pctx_tid;
+
                ipv4_pdp_fill(pctx, info);
 
                if (pctx->gtp_version == GTP_V0)
@@ -1074,7 +1089,7 @@ static int gtp_genl_new_pdp(struct sk_buff *skb, struct genl_info *info)
                goto out_unlock;
        }
 
-       err = ipv4_pdp_add(gtp, sk, info);
+       err = gtp_pdp_add(gtp, sk, info);
 
 out_unlock:
        rcu_read_unlock();
@@ -1232,43 +1247,46 @@ static int gtp_genl_dump_pdp(struct sk_buff *skb,
                                struct netlink_callback *cb)
 {
        struct gtp_dev *last_gtp = (struct gtp_dev *)cb->args[2], *gtp;
+       int i, j, bucket = cb->args[0], skip = cb->args[1];
        struct net *net = sock_net(skb->sk);
-       struct gtp_net *gn = net_generic(net, gtp_net_id);
-       unsigned long tid = cb->args[1];
-       int i, k = cb->args[0], ret;
        struct pdp_ctx *pctx;
+       struct gtp_net *gn;
+
+       gn = net_generic(net, gtp_net_id);
 
        if (cb->args[4])
                return 0;
 
+       rcu_read_lock();
        list_for_each_entry_rcu(gtp, &gn->gtp_dev_list, list) {
                if (last_gtp && last_gtp != gtp)
                        continue;
                else
                        last_gtp = NULL;
 
-               for (i = k; i < gtp->hash_size; i++) {
-                       hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i], hlist_tid) {
-                               if (tid && tid != pctx->u.tid)
-                                       continue;
-                               else
-                                       tid = 0;
-
-                               ret = gtp_genl_fill_info(skb,
-                                                        NETLINK_CB(cb->skb).portid,
-                                                        cb->nlh->nlmsg_seq,
-                                                        cb->nlh->nlmsg_type, pctx);
-                               if (ret < 0) {
+               for (i = bucket; i < gtp->hash_size; i++) {
+                       j = 0;
+                       hlist_for_each_entry_rcu(pctx, &gtp->tid_hash[i],
+                                                hlist_tid) {
+                               if (j >= skip &&
+                                   gtp_genl_fill_info(skb,
+                                           NETLINK_CB(cb->skb).portid,
+                                           cb->nlh->nlmsg_seq,
+                                           cb->nlh->nlmsg_type, pctx)) {
                                        cb->args[0] = i;
-                                       cb->args[1] = pctx->u.tid;
+                                       cb->args[1] = j;
                                        cb->args[2] = (unsigned long)gtp;
                                        goto out;
                                }
+                               j++;
                        }
+                       skip = 0;
                }
+               bucket = 0;
        }
        cb->args[4] = 1;
 out:
+       rcu_read_unlock();
        return skb->len;
 }
 
index 23281ae..71d6629 100644 (file)
@@ -654,10 +654,10 @@ static void sixpack_close(struct tty_struct *tty)
 {
        struct sixpack *sp;
 
-       write_lock_bh(&disc_data_lock);
+       write_lock_irq(&disc_data_lock);
        sp = tty->disc_data;
        tty->disc_data = NULL;
-       write_unlock_bh(&disc_data_lock);
+       write_unlock_irq(&disc_data_lock);
        if (!sp)
                return;
 
index c5bfa19..deef142 100644 (file)
@@ -773,10 +773,10 @@ static void mkiss_close(struct tty_struct *tty)
 {
        struct mkiss *ax;
 
-       write_lock_bh(&disc_data_lock);
+       write_lock_irq(&disc_data_lock);
        ax = tty->disc_data;
        tty->disc_data = NULL;
-       write_unlock_bh(&disc_data_lock);
+       write_unlock_irq(&disc_data_lock);
 
        if (!ax)
                return;
index 9caa876..dc44819 100644 (file)
@@ -169,7 +169,6 @@ struct rndis_device {
 
        u8 hw_mac_adr[ETH_ALEN];
        u8 rss_key[NETVSC_HASH_KEYLEN];
-       u16 rx_table[ITAB_NUM];
 };
 
 
@@ -940,6 +939,8 @@ struct net_device_context {
 
        u32 tx_table[VRSS_SEND_TAB_SIZE];
 
+       u16 rx_table[ITAB_NUM];
+
        /* Ethtool settings */
        u8 duplex;
        u32 speed;
index eff8fef..f3f9eb8 100644 (file)
@@ -571,7 +571,7 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net)
 
        /* Use the skb control buffer for building up the packet */
        BUILD_BUG_ON(sizeof(struct hv_netvsc_packet) >
-                       FIELD_SIZEOF(struct sk_buff, cb));
+                       sizeof_field(struct sk_buff, cb));
        packet = (struct hv_netvsc_packet *)skb->cb;
 
        packet->q_idx = skb_get_queue_mapping(skb);
@@ -1662,7 +1662,7 @@ static int netvsc_get_rxfh(struct net_device *dev, u32 *indir, u8 *key,
        rndis_dev = ndev->extension;
        if (indir) {
                for (i = 0; i < ITAB_NUM; i++)
-                       indir[i] = rndis_dev->rx_table[i];
+                       indir[i] = ndc->rx_table[i];
        }
 
        if (key)
@@ -1692,7 +1692,7 @@ static int netvsc_set_rxfh(struct net_device *dev, const u32 *indir,
                                return -EINVAL;
 
                for (i = 0; i < ITAB_NUM; i++)
-                       rndis_dev->rx_table[i] = indir[i];
+                       ndc->rx_table[i] = indir[i];
        }
 
        if (!key) {
index 206b4e7..e66d77d 100644 (file)
@@ -773,6 +773,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
                                   const u8 *rss_key, u16 flag)
 {
        struct net_device *ndev = rdev->ndev;
+       struct net_device_context *ndc = netdev_priv(ndev);
        struct rndis_request *request;
        struct rndis_set_request *set;
        struct rndis_set_complete *set_complete;
@@ -812,7 +813,7 @@ static int rndis_set_rss_param_msg(struct rndis_device *rdev,
        /* Set indirection table entries */
        itab = (u32 *)(rssp + 1);
        for (i = 0; i < ITAB_NUM; i++)
-               itab[i] = rdev->rx_table[i];
+               itab[i] = ndc->rx_table[i];
 
        /* Set hask key values */
        keyp = (u8 *)((unsigned long)rssp + rssp->hashkey_offset);
@@ -1171,6 +1172,9 @@ int rndis_set_subchannel(struct net_device *ndev,
        wait_event(nvdev->subchan_open,
                   atomic_read(&nvdev->open_chn) == nvdev->num_chn);
 
+       for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
+               ndev_ctx->tx_table[i] = i % nvdev->num_chn;
+
        /* ignore failures from setting rss parameters, still have channels */
        if (dev_info)
                rndis_filter_set_rss_param(rdev, dev_info->rss_key);
@@ -1180,9 +1184,6 @@ int rndis_set_subchannel(struct net_device *ndev,
        netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
        netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
 
-       for (i = 0; i < VRSS_SEND_TAB_SIZE; i++)
-               ndev_ctx->tx_table[i] = i % nvdev->num_chn;
-
        return 0;
 }
 
@@ -1312,6 +1313,7 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
                                      struct netvsc_device_info *device_info)
 {
        struct net_device *net = hv_get_drvdata(dev);
+       struct net_device_context *ndc = netdev_priv(net);
        struct netvsc_device *net_device;
        struct rndis_device *rndis_device;
        struct ndis_recv_scale_cap rsscap;
@@ -1398,9 +1400,11 @@ struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
        /* We will use the given number of channels if available. */
        net_device->num_chn = min(net_device->max_chn, device_info->num_chn);
 
-       for (i = 0; i < ITAB_NUM; i++)
-               rndis_device->rx_table[i] = ethtool_rxfh_indir_default(
+       if (!netif_is_rxfh_configured(net)) {
+               for (i = 0; i < ITAB_NUM; i++)
+                       ndc->rx_table[i] = ethtool_rxfh_indir_default(
                                                i, net_device->num_chn);
+       }
 
        atomic_set(&net_device->open_chn, 1);
        vmbus_set_sc_create_callback(dev->channel, netvsc_sc_open);
@@ -1439,8 +1443,6 @@ void rndis_filter_device_remove(struct hv_device *dev,
        /* Halt and release the rndis device */
        rndis_filter_halt_device(net_dev, rndis_dev);
 
-       net_dev->extension = NULL;
-
        netvsc_device_remove(dev);
 }
 
index 05631d9..c5bf615 100644 (file)
@@ -513,10 +513,11 @@ static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
        const struct macvlan_dev *dest;
 
        if (vlan->mode == MACVLAN_MODE_BRIDGE) {
-               const struct ethhdr *eth = (void *)skb->data;
+               const struct ethhdr *eth = skb_eth_hdr(skb);
 
                /* send to other bridge ports directly */
                if (is_multicast_ether_addr(eth->h_dest)) {
+                       skb_reset_mac_header(skb);
                        macvlan_broadcast(skb, port, dev, MACVLAN_MODE_BRIDGE);
                        goto xmit_world;
                }
index 059711e..4b39aba 100644 (file)
@@ -53,7 +53,7 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file,
 
        get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE);
 
-       id = devlink_region_shapshot_id_get(priv_to_devlink(nsim_dev));
+       id = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev));
        err = devlink_region_snapshot_create(nsim_dev->dummy_region,
                                             dummy_data, id, kfree);
        if (err) {
index 5848219..8dc461f 100644 (file)
@@ -340,14 +340,14 @@ config DAVICOM_PHY
          Currently supports dm9161e and dm9131
 
 config DP83822_PHY
-       tristate "Texas Instruments DP83822 PHY"
+       tristate "Texas Instruments DP83822/825 PHYs"
        ---help---
-         Supports the DP83822 PHY.
+         Supports the DP83822 and DP83825I PHYs.
 
 config DP83TC811_PHY
-       tristate "Texas Instruments DP83TC822 PHY"
+       tristate "Texas Instruments DP83TC811 PHY"
        ---help---
-         Supports the DP83TC822 PHY.
+         Supports the DP83TC811 PHY.
 
 config DP83848_PHY
        tristate "Texas Instruments DP83848 PHY"
index 3b29d38..975789d 100644 (file)
@@ -627,6 +627,8 @@ static struct phy_driver aqr_driver[] = {
        .config_intr    = aqr_config_intr,
        .ack_interrupt  = aqr_ack_interrupt,
        .read_status    = aqr_read_status,
+       .suspend        = aqr107_suspend,
+       .resume         = aqr107_resume,
 },
 {
        PHY_ID_MATCH_MODEL(PHY_ID_AQR106),
index 9cd9dce..01cf713 100644 (file)
@@ -97,6 +97,7 @@
 #define DP83867_PHYCR_FIFO_DEPTH_MAX           0x03
 #define DP83867_PHYCR_FIFO_DEPTH_MASK          GENMASK(15, 14)
 #define DP83867_PHYCR_RESERVED_MASK            BIT(11)
+#define DP83867_PHYCR_FORCE_LINK_GOOD          BIT(10)
 
 /* RGMIIDCTL bits */
 #define DP83867_RGMII_TX_CLK_DELAY_MAX         0xf
@@ -599,7 +600,12 @@ static int dp83867_phy_reset(struct phy_device *phydev)
 
        usleep_range(10, 20);
 
-       return 0;
+       /* After reset FORCE_LINK_GOOD bit is set. Although the
+        * default value should be unset. Disable FORCE_LINK_GOOD
+        * for the phy to work properly.
+        */
+       return phy_modify(phydev, MII_DP83867_PHYCTRL,
+                        DP83867_PHYCR_FORCE_LINK_GOOD, 0);
 }
 
 static struct phy_driver dp83867_driver[] = {
index 0887ed2..b13c528 100644 (file)
@@ -553,7 +553,7 @@ static const struct device_type mdio_bus_phy_type = {
        .pm = MDIO_BUS_PHY_PM_OPS,
 };
 
-static int phy_request_driver_module(struct phy_device *dev, int phy_id)
+static int phy_request_driver_module(struct phy_device *dev, u32 phy_id)
 {
        int ret;
 
@@ -565,15 +565,15 @@ static int phy_request_driver_module(struct phy_device *dev, int phy_id)
         * then modprobe isn't available.
         */
        if (IS_ENABLED(CONFIG_MODULES) && ret < 0 && ret != -ENOENT) {
-               phydev_err(dev, "error %d loading PHY driver module for ID 0x%08x\n",
-                          ret, phy_id);
+               phydev_err(dev, "error %d loading PHY driver module for ID 0x%08lx\n",
+                          ret, (unsigned long)phy_id);
                return ret;
        }
 
        return 0;
 }
 
-struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
+struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
                                     bool is_c45,
                                     struct phy_c45_device_ids *c45_ids)
 {
index 9a616d6..ee7a718 100644 (file)
@@ -442,8 +442,7 @@ static void phylink_mac_link_up(struct phylink *pl,
 
        pl->cur_interface = link_state.interface;
        pl->ops->mac_link_up(pl->config, pl->link_an_mode,
-                            pl->phy_state.interface,
-                            pl->phydev);
+                            pl->cur_interface, pl->phydev);
 
        if (ndev)
                netif_carrier_on(ndev);
@@ -567,6 +566,9 @@ static int phylink_register_sfp(struct phylink *pl,
        struct sfp_bus *bus;
        int ret;
 
+       if (!fwnode)
+               return 0;
+
        bus = sfp_bus_find_fwnode(fwnode);
        if (IS_ERR(bus)) {
                ret = PTR_ERR(bus);
index cf1f3f0..75bdfae 100644 (file)
@@ -511,7 +511,7 @@ static int lan78xx_read_stats(struct lan78xx_net *dev,
                }
        } else {
                netdev_warn(dev->net,
-                           "Failed to read stat ret = 0x%x", ret);
+                           "Failed to read stat ret = %d", ret);
        }
 
        kfree(stats);
@@ -1808,6 +1808,7 @@ static int lan78xx_mdio_init(struct lan78xx_net *dev)
        dev->mdiobus->read = lan78xx_mdiobus_read;
        dev->mdiobus->write = lan78xx_mdiobus_write;
        dev->mdiobus->name = "lan78xx-mdiobus";
+       dev->mdiobus->parent = &dev->udev->dev;
 
        snprintf(dev->mdiobus->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
                 dev->udev->bus->busnum, dev->udev->devnum);
@@ -2723,11 +2724,6 @@ static int lan78xx_stop(struct net_device *net)
        return 0;
 }
 
-static int lan78xx_linearize(struct sk_buff *skb)
-{
-       return skb_linearize(skb);
-}
-
 static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev,
                                       struct sk_buff *skb, gfp_t flags)
 {
@@ -2739,8 +2735,10 @@ static struct sk_buff *lan78xx_tx_prep(struct lan78xx_net *dev,
                return NULL;
        }
 
-       if (lan78xx_linearize(skb) < 0)
+       if (skb_linearize(skb)) {
+               dev_kfree_skb_any(skb);
                return NULL;
+       }
 
        tx_cmd_a = (u32)(skb->len & TX_CMD_A_LEN_MASK_) | TX_CMD_A_FCS_;
 
@@ -3752,6 +3750,7 @@ static int lan78xx_probe(struct usb_interface *intf,
 
        /* MTU range: 68 - 9000 */
        netdev->max_mtu = MAX_SINGLE_PACKET_SIZE;
+       netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER);
 
        dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0;
        dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1;
index 4196c0e..9485c8d 100644 (file)
@@ -1062,6 +1062,7 @@ static const struct usb_device_id products[] = {
        {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0125)},     /* Quectel EC25, EC20 R2.0  Mini PCIe */
        {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0306)},     /* Quectel EP06/EG06/EM06 */
        {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0512)},     /* Quectel EG12/EM12 */
+       {QMI_QUIRK_QUECTEL_DYNCFG(0x2c7c, 0x0800)},     /* Quectel RM500Q-GL */
 
        /* 3. Combined interface devices matching on interface number */
        {QMI_FIXED_INTF(0x0408, 0xea42, 4)},    /* Yota / Megafon M100-1 */
index c5ebf35..031cb8f 100644 (file)
@@ -6597,6 +6597,9 @@ static int rtl8152_probe(struct usb_interface *intf,
                return -ENODEV;
        }
 
+       if (intf->cur_altsetting->desc.bNumEndpoints < 3)
+               return -ENODEV;
+
        usb_reset_device(udev);
        netdev = alloc_etherdev(sizeof(struct r8152));
        if (!netdev) {
index 34c1eab..389d19d 100644 (file)
@@ -865,7 +865,7 @@ static struct sk_buff *sierra_net_tx_fixup(struct usbnet *dev,
        u16 len;
        bool need_tail;
 
-       BUILD_BUG_ON(FIELD_SIZEOF(struct usbnet, data)
+       BUILD_BUG_ON(sizeof_field(struct usbnet, data)
                                < sizeof(struct cdc_state));
 
        dev_dbg(&dev->udev->dev, "%s", __func__);
index 30e511c..9ce6d30 100644 (file)
@@ -2184,7 +2184,7 @@ static int __init usbnet_init(void)
 {
        /* Compiler should optimize this out. */
        BUILD_BUG_ON(
-               FIELD_SIZEOF(struct sk_buff, cb) < sizeof(struct skb_data));
+               sizeof_field(struct sk_buff, cb) < sizeof(struct skb_data));
 
        eth_random_addr(node_id);
        return 0;
index 4c34375..1c5159d 100644 (file)
@@ -2541,7 +2541,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                ndst = &rt->dst;
                skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM);
 
-               tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
+               tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb);
                ttl = ttl ? : ip4_dst_hoplimit(&rt->dst);
                err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr),
                                      vni, md, flags, udp_sum);
@@ -2581,7 +2581,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
 
                skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM);
 
-               tos = ip_tunnel_ecn_encap(tos, old_iph, skb);
+               tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb);
                ttl = ttl ? : ip6_dst_hoplimit(ndst);
                skb_scrub_packet(skb, xnet);
                err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
@@ -3069,10 +3069,10 @@ static void vxlan_raw_setup(struct net_device *dev)
 
 static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
        [IFLA_VXLAN_ID]         = { .type = NLA_U32 },
-       [IFLA_VXLAN_GROUP]      = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+       [IFLA_VXLAN_GROUP]      = { .len = sizeof_field(struct iphdr, daddr) },
        [IFLA_VXLAN_GROUP6]     = { .len = sizeof(struct in6_addr) },
        [IFLA_VXLAN_LINK]       = { .type = NLA_U32 },
-       [IFLA_VXLAN_LOCAL]      = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
+       [IFLA_VXLAN_LOCAL]      = { .len = sizeof_field(struct iphdr, saddr) },
        [IFLA_VXLAN_LOCAL6]     = { .len = sizeof(struct in6_addr) },
        [IFLA_VXLAN_TOS]        = { .type = NLA_U8 },
        [IFLA_VXLAN_TTL]        = { .type = NLA_U8 },
index ca0f3be..aef7de2 100644 (file)
@@ -73,7 +73,7 @@ static struct ucc_tdm_info utdm_primary_info = {
        },
 };
 
-static struct ucc_tdm_info utdm_info[MAX_HDLC_NUM];
+static struct ucc_tdm_info utdm_info[UCC_MAX_NUM];
 
 static int uhdlc_init(struct ucc_hdlc_private *priv)
 {
index 0f1217b..e30d91a 100644 (file)
@@ -64,7 +64,7 @@ static struct lapbethdev *lapbeth_get_x25_dev(struct net_device *dev)
 {
        struct lapbethdev *lapbeth;
 
-       list_for_each_entry_rcu(lapbeth, &lapbeth_devices, node) {
+       list_for_each_entry_rcu(lapbeth, &lapbeth_devices, node, lockdep_rtnl_is_held()) {
                if (lapbeth->ethdev == dev) 
                        return lapbeth;
        }
index e2e679a..77ccf36 100644 (file)
@@ -708,7 +708,7 @@ static netdev_tx_t sdla_transmit(struct sk_buff *skb,
 
                                        spin_lock_irqsave(&sdla_lock, flags);
                                        SDLA_WINDOW(dev, addr);
-                                       pbuf = (void *)(((int) dev->mem_start) + (addr & SDLA_ADDR_MASK));
+                                       pbuf = (void *)(dev->mem_start + (addr & SDLA_ADDR_MASK));
                                        __sdla_write(dev, pbuf->buf_addr, skb->data, skb->len);
                                        SDLA_WINDOW(dev, addr);
                                        pbuf->opp_flag = 1;
index 83cc877..978f003 100644 (file)
@@ -8958,6 +8958,7 @@ int ath10k_mac_register(struct ath10k *ar)
        wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
        wiphy_ext_feature_set(ar->hw->wiphy,
                              NL80211_EXT_FEATURE_SET_SCAN_DWELL);
+       wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_AQL);
 
        if (test_bit(WMI_SERVICE_TX_DATA_ACK_RSSI, ar->wmi.svc_map) ||
            test_bit(WMI_SERVICE_HTT_MGMT_TX_COMP_VALID_FLAGS, ar->wmi.svc_map))
index 956fa78..56d1a77 100644 (file)
@@ -83,7 +83,7 @@ static int ath9k_pci_fixup(struct pci_dev *pdev, const u16 *cal_data,
                        val = swahb32(val);
                }
 
-               __raw_writel(val, mem + reg);
+               iowrite32(val, mem + reg);
                usleep_range(100, 120);
        }
 
index 040cec1..b0b7eca 100644 (file)
@@ -1111,18 +1111,18 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* same thing for QuZ... */
        if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) {
-               if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr)
-                       iwl_trans->cfg = &iwl_ax101_cfg_quz_hr;
-               else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr)
-                       iwl_trans->cfg = &iwl_ax201_cfg_quz_hr;
-               else if (iwl_trans->cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
-                       iwl_trans->cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
-               else if (iwl_trans->cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
-                       iwl_trans->cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
-               else if (iwl_trans->cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
-                       iwl_trans->cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
-               else if (iwl_trans->cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
-                       iwl_trans->cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
+               if (cfg == &iwl_ax101_cfg_qu_hr)
+                       cfg = &iwl_ax101_cfg_quz_hr;
+               else if (cfg == &iwl_ax201_cfg_qu_hr)
+                       cfg = &iwl_ax201_cfg_quz_hr;
+               else if (cfg == &iwl9461_2ac_cfg_qu_b0_jf_b0)
+                       cfg = &iwl9461_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (cfg == &iwl9462_2ac_cfg_qu_b0_jf_b0)
+                       cfg = &iwl9462_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (cfg == &iwl9560_2ac_cfg_qu_b0_jf_b0)
+                       cfg = &iwl9560_2ac_cfg_quz_a0_jf_b0_soc;
+               else if (cfg == &iwl9560_2ac_160_cfg_qu_b0_jf_b0)
+                       cfg = &iwl9560_2ac_160_cfg_quz_a0_jf_b0_soc;
        }
 
 #endif
index 0252716..0d8b2a8 100644 (file)
 #include "internal.h"
 #include "fw/dbg.h"
 
-static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
-{
-       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
-                         HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
-       udelay(20);
-       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
-                         HPM_HIPM_GEN_CFG_CR_PG_EN |
-                         HPM_HIPM_GEN_CFG_CR_SLP_EN);
-       udelay(20);
-       iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
-                           HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
-
-       iwl_trans_sw_reset(trans);
-       iwl_clear_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
-
-       return 0;
-}
-
 /*
  * Start up NIC's basic functionality after it has been reset
  * (e.g. after platform boot, or shutdown via iwl_pcie_apm_stop())
@@ -110,13 +92,6 @@ int iwl_pcie_gen2_apm_init(struct iwl_trans *trans)
 
        iwl_pcie_apm_config(trans);
 
-       if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
-           trans->cfg->integrated) {
-               ret = iwl_pcie_gen2_force_power_gating(trans);
-               if (ret)
-                       return ret;
-       }
-
        ret = iwl_finish_nic_init(trans, trans->trans_cfg);
        if (ret)
                return ret;
index af9bc6b..a067713 100644 (file)
@@ -1783,6 +1783,29 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
        return 0;
 }
 
+static int iwl_pcie_gen2_force_power_gating(struct iwl_trans *trans)
+{
+       int ret;
+
+       ret = iwl_finish_nic_init(trans, trans->trans_cfg);
+       if (ret < 0)
+               return ret;
+
+       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                         HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+       udelay(20);
+       iwl_set_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                         HPM_HIPM_GEN_CFG_CR_PG_EN |
+                         HPM_HIPM_GEN_CFG_CR_SLP_EN);
+       udelay(20);
+       iwl_clear_bits_prph(trans, HPM_HIPM_GEN_CFG,
+                           HPM_HIPM_GEN_CFG_CR_FORCE_ACTIVE);
+
+       iwl_trans_pcie_sw_reset(trans);
+
+       return 0;
+}
+
 static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -1802,6 +1825,13 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 
        iwl_trans_pcie_sw_reset(trans);
 
+       if (trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000 &&
+           trans->cfg->integrated) {
+               err = iwl_pcie_gen2_force_power_gating(trans);
+               if (err)
+                       return err;
+       }
+
        err = iwl_pcie_apm_init(trans);
        if (err)
                return err;
index fe14814..c604613 100644 (file)
@@ -774,7 +774,7 @@ void lbs_debugfs_remove_one(struct lbs_private *priv)
 
 #ifdef PROC_DEBUG
 
-#define item_size(n)   (FIELD_SIZEOF(struct lbs_private, n))
+#define item_size(n)   (sizeof_field(struct lbs_private, n))
 #define item_addr(n)   (offsetof(struct lbs_private, n))
 
 
index 74e5056..6dd835f 100644 (file)
@@ -229,6 +229,14 @@ static int mwifiex_process_country_ie(struct mwifiex_private *priv,
                            "11D: skip setting domain info in FW\n");
                return 0;
        }
+
+       if (country_ie_len >
+           (IEEE80211_COUNTRY_STRING_LEN + MWIFIEX_MAX_TRIPLET_802_11D)) {
+               mwifiex_dbg(priv->adapter, ERROR,
+                           "11D: country_ie_len overflow!, deauth AP\n");
+               return -EINVAL;
+       }
+
        memcpy(priv->adapter->country_code, &country_ie[2], 2);
 
        domain_info->country_code[0] = country_ie[2];
@@ -272,8 +280,9 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
        priv->scan_block = false;
 
        if (bss) {
-               if (adapter->region_code == 0x00)
-                       mwifiex_process_country_ie(priv, bss);
+               if (adapter->region_code == 0x00 &&
+                   mwifiex_process_country_ie(priv, bss))
+                       return -EINVAL;
 
                /* Allocate and fill new bss descriptor */
                bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
index 0931304..7caf1d2 100644 (file)
@@ -953,59 +953,117 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
 
                switch (*pos) {
                case WLAN_EID_SUPP_RATES:
+                       if (pos[1] > 32)
+                               return;
                        sta_ptr->tdls_cap.rates_len = pos[1];
                        for (i = 0; i < pos[1]; i++)
                                sta_ptr->tdls_cap.rates[i] = pos[i + 2];
                        break;
 
                case WLAN_EID_EXT_SUPP_RATES:
+                       if (pos[1] > 32)
+                               return;
                        basic = sta_ptr->tdls_cap.rates_len;
+                       if (pos[1] > 32 - basic)
+                               return;
                        for (i = 0; i < pos[1]; i++)
                                sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2];
                        sta_ptr->tdls_cap.rates_len += pos[1];
                        break;
                case WLAN_EID_HT_CAPABILITY:
-                       memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos,
+                       if (pos > end - sizeof(struct ieee80211_ht_cap) - 2)
+                               return;
+                       if (pos[1] != sizeof(struct ieee80211_ht_cap))
+                               return;
+                       /* copy the ie's value into ht_capb*/
+                       memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos + 2,
                               sizeof(struct ieee80211_ht_cap));
                        sta_ptr->is_11n_enabled = 1;
                        break;
                case WLAN_EID_HT_OPERATION:
-                       memcpy(&sta_ptr->tdls_cap.ht_oper, pos,
+                       if (pos > end -
+                           sizeof(struct ieee80211_ht_operation) - 2)
+                               return;
+                       if (pos[1] != sizeof(struct ieee80211_ht_operation))
+                               return;
+                       /* copy the ie's value into ht_oper*/
+                       memcpy(&sta_ptr->tdls_cap.ht_oper, pos + 2,
                               sizeof(struct ieee80211_ht_operation));
                        break;
                case WLAN_EID_BSS_COEX_2040:
+                       if (pos > end - 3)
+                               return;
+                       if (pos[1] != 1)
+                               return;
                        sta_ptr->tdls_cap.coex_2040 = pos[2];
                        break;
                case WLAN_EID_EXT_CAPABILITY:
+                       if (pos > end - sizeof(struct ieee_types_header))
+                               return;
+                       if (pos[1] < sizeof(struct ieee_types_header))
+                               return;
+                       if (pos[1] > 8)
+                               return;
                        memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos,
                               sizeof(struct ieee_types_header) +
                               min_t(u8, pos[1], 8));
                        break;
                case WLAN_EID_RSN:
+                       if (pos > end - sizeof(struct ieee_types_header))
+                               return;
+                       if (pos[1] < sizeof(struct ieee_types_header))
+                               return;
+                       if (pos[1] > IEEE_MAX_IE_SIZE -
+                           sizeof(struct ieee_types_header))
+                               return;
                        memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos,
                               sizeof(struct ieee_types_header) +
                               min_t(u8, pos[1], IEEE_MAX_IE_SIZE -
                                     sizeof(struct ieee_types_header)));
                        break;
                case WLAN_EID_QOS_CAPA:
+                       if (pos > end - 3)
+                               return;
+                       if (pos[1] != 1)
+                               return;
                        sta_ptr->tdls_cap.qos_info = pos[2];
                        break;
                case WLAN_EID_VHT_OPERATION:
-                       if (priv->adapter->is_hw_11ac_capable)
-                               memcpy(&sta_ptr->tdls_cap.vhtoper, pos,
+                       if (priv->adapter->is_hw_11ac_capable) {
+                               if (pos > end -
+                                   sizeof(struct ieee80211_vht_operation) - 2)
+                                       return;
+                               if (pos[1] !=
+                                   sizeof(struct ieee80211_vht_operation))
+                                       return;
+                               /* copy the ie's value into vhtoper*/
+                               memcpy(&sta_ptr->tdls_cap.vhtoper, pos + 2,
                                       sizeof(struct ieee80211_vht_operation));
+                       }
                        break;
                case WLAN_EID_VHT_CAPABILITY:
                        if (priv->adapter->is_hw_11ac_capable) {
-                               memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos,
+                               if (pos > end -
+                                   sizeof(struct ieee80211_vht_cap) - 2)
+                                       return;
+                               if (pos[1] != sizeof(struct ieee80211_vht_cap))
+                                       return;
+                               /* copy the ie's value into vhtcap*/
+                               memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos + 2,
                                       sizeof(struct ieee80211_vht_cap));
                                sta_ptr->is_11ac_enabled = 1;
                        }
                        break;
                case WLAN_EID_AID:
-                       if (priv->adapter->is_hw_11ac_capable)
+                       if (priv->adapter->is_hw_11ac_capable) {
+                               if (pos > end - 4)
+                                       return;
+                               if (pos[1] != 2)
+                                       return;
                                sta_ptr->tdls_cap.aid =
                                        get_unaligned_le16((pos + 2));
+                       }
+                       break;
                default:
                        break;
                }
index c386992..7cafcec 100644 (file)
@@ -36,11 +36,11 @@ struct mwifiex_cb {
 };
 
 /* size/addr for mwifiex_debug_info */
-#define item_size(n)           (FIELD_SIZEOF(struct mwifiex_debug_info, n))
+#define item_size(n)           (sizeof_field(struct mwifiex_debug_info, n))
 #define item_addr(n)           (offsetof(struct mwifiex_debug_info, n))
 
 /* size/addr for struct mwifiex_adapter */
-#define adapter_item_size(n)   (FIELD_SIZEOF(struct mwifiex_adapter, n))
+#define adapter_item_size(n)   (sizeof_field(struct mwifiex_adapter, n))
 #define adapter_item_addr(n)   (offsetof(struct mwifiex_adapter, n))
 
 struct mwifiex_debug_data {
index a03e2d0..d140552 100644 (file)
@@ -342,8 +342,11 @@ int mt76x0_eeprom_init(struct mt76x02_dev *dev)
        dev_info(dev->mt76.dev, "EEPROM ver:%02hhx fae:%02hhx\n",
                 version, fae);
 
-       mt76x02_mac_setaddr(dev, dev->mt76.eeprom.data + MT_EE_MAC_ADDR);
+       memcpy(dev->mt76.macaddr, (u8 *)dev->mt76.eeprom.data + MT_EE_MAC_ADDR,
+              ETH_ALEN);
        mt76_eeprom_override(&dev->mt76);
+       mt76x02_mac_setaddr(dev, dev->mt76.macaddr);
+
        mt76x0_set_chip_cap(dev);
        mt76x0_set_freq_offset(dev);
        mt76x0_set_temp_offset(dev);
index 68dd7bb..f15ba3d 100644 (file)
@@ -628,18 +628,6 @@ err:
 
 static void xenvif_disconnect_queue(struct xenvif_queue *queue)
 {
-       if (queue->tx_irq) {
-               unbind_from_irqhandler(queue->tx_irq, queue);
-               if (queue->tx_irq == queue->rx_irq)
-                       queue->rx_irq = 0;
-               queue->tx_irq = 0;
-       }
-
-       if (queue->rx_irq) {
-               unbind_from_irqhandler(queue->rx_irq, queue);
-               queue->rx_irq = 0;
-       }
-
        if (queue->task) {
                kthread_stop(queue->task);
                queue->task = NULL;
@@ -655,6 +643,18 @@ static void xenvif_disconnect_queue(struct xenvif_queue *queue)
                queue->napi.poll = NULL;
        }
 
+       if (queue->tx_irq) {
+               unbind_from_irqhandler(queue->tx_irq, queue);
+               if (queue->tx_irq == queue->rx_irq)
+                       queue->rx_irq = 0;
+               queue->tx_irq = 0;
+       }
+
+       if (queue->rx_irq) {
+               unbind_from_irqhandler(queue->rx_irq, queue);
+               queue->rx_irq = 0;
+       }
+
        xenvif_unmap_frontend_data_rings(queue);
 }
 
index 4d1909a..9f60e4d 100644 (file)
@@ -278,7 +278,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,
 
        r = devm_acpi_dev_add_driver_gpios(dev, acpi_nxp_nci_gpios);
        if (r)
-               return r;
+               dev_dbg(dev, "Unable to add GPIO mapping table\n");
 
        phy->gpiod_en = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW);
        if (IS_ERR(phy->gpiod_en)) {
index 4590fbf..f5bb7ac 100644 (file)
@@ -391,7 +391,7 @@ static int pn533_acr122_poweron_rdr(struct pn533_usb_phy *phy)
                       cmd, sizeof(cmd), false);
 
        rc = usb_bulk_msg(phy->udev, phy->out_urb->pipe, buffer, sizeof(cmd),
-                         &transferred, 0);
+                         &transferred, 5000);
        kfree(buffer);
        if (rc || (transferred != sizeof(cmd))) {
                nfc_err(&phy->udev->dev,
index be110d9..de613c6 100644 (file)
@@ -507,7 +507,10 @@ int s3fwrn5_fw_recv_frame(struct nci_dev *ndev, struct sk_buff *skb)
        struct s3fwrn5_info *info = nci_get_drvdata(ndev);
        struct s3fwrn5_fw_info *fw_info = &info->fw_info;
 
-       BUG_ON(fw_info->rsp);
+       if (WARN_ON(fw_info->rsp)) {
+               kfree_skb(skb);
+               return -EINVAL;
+       }
 
        fw_info->rsp = skb;
 
index dfe37a5..5dc32b7 100644 (file)
@@ -222,6 +222,8 @@ static blk_status_t nvme_error_status(u16 status)
        case NVME_SC_CAP_EXCEEDED:
                return BLK_STS_NOSPC;
        case NVME_SC_LBA_RANGE:
+       case NVME_SC_CMD_INTERRUPTED:
+       case NVME_SC_NS_NOT_READY:
                return BLK_STS_TARGET;
        case NVME_SC_BAD_ATTRIBUTES:
        case NVME_SC_ONCS_NOT_SUPPORTED:
@@ -1735,6 +1737,8 @@ static int nvme_report_ns_ids(struct nvme_ctrl *ctrl, unsigned int nsid,
                if (ret)
                        dev_warn(ctrl->device,
                                 "Identify Descriptors failed (%d)\n", ret);
+               if (ret > 0)
+                       ret = 0;
        }
        return ret;
 }
@@ -2852,6 +2856,10 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
                 * admin connect
                 */
                if (ctrl->cntlid != le16_to_cpu(id->cntlid)) {
+                       dev_err(ctrl->device,
+                               "Mismatching cntlid: Connect %u vs Identify "
+                               "%u, rejecting\n",
+                               ctrl->cntlid, le16_to_cpu(id->cntlid));
                        ret = -EINVAL;
                        goto out_free;
                }
index 679a721..5a70ac3 100644 (file)
@@ -95,7 +95,7 @@ struct nvme_fc_fcp_op {
 
 struct nvme_fcp_op_w_sgl {
        struct nvme_fc_fcp_op   op;
-       struct scatterlist      sgl[SG_CHUNK_SIZE];
+       struct scatterlist      sgl[NVME_INLINE_SG_CNT];
        uint8_t                 priv[0];
 };
 
@@ -342,7 +342,8 @@ nvme_fc_register_localport(struct nvme_fc_port_info *pinfo,
            !template->ls_req || !template->fcp_io ||
            !template->ls_abort || !template->fcp_abort ||
            !template->max_hw_queues || !template->max_sgl_segments ||
-           !template->max_dif_sgl_segments || !template->dma_boundary) {
+           !template->max_dif_sgl_segments || !template->dma_boundary ||
+           !template->module) {
                ret = -EINVAL;
                goto out_reghost_failed;
        }
@@ -2015,6 +2016,7 @@ nvme_fc_ctrl_free(struct kref *ref)
 {
        struct nvme_fc_ctrl *ctrl =
                container_of(ref, struct nvme_fc_ctrl, ref);
+       struct nvme_fc_lport *lport = ctrl->lport;
        unsigned long flags;
 
        if (ctrl->ctrl.tagset) {
@@ -2041,6 +2043,7 @@ nvme_fc_ctrl_free(struct kref *ref)
        if (ctrl->ctrl.opts)
                nvmf_free_options(ctrl->ctrl.opts);
        kfree(ctrl);
+       module_put(lport->ops->module);
 }
 
 static void
@@ -2141,7 +2144,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
        freq->sg_table.sgl = freq->first_sgl;
        ret = sg_alloc_table_chained(&freq->sg_table,
                        blk_rq_nr_phys_segments(rq), freq->sg_table.sgl,
-                       SG_CHUNK_SIZE);
+                       NVME_INLINE_SG_CNT);
        if (ret)
                return -ENOMEM;
 
@@ -2150,7 +2153,7 @@ nvme_fc_map_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
        freq->sg_cnt = fc_dma_map_sg(ctrl->lport->dev, freq->sg_table.sgl,
                                op->nents, rq_dma_dir(rq));
        if (unlikely(freq->sg_cnt <= 0)) {
-               sg_free_table_chained(&freq->sg_table, SG_CHUNK_SIZE);
+               sg_free_table_chained(&freq->sg_table, NVME_INLINE_SG_CNT);
                freq->sg_cnt = 0;
                return -EFAULT;
        }
@@ -2173,7 +2176,7 @@ nvme_fc_unmap_data(struct nvme_fc_ctrl *ctrl, struct request *rq,
        fc_dma_unmap_sg(ctrl->lport->dev, freq->sg_table.sgl, op->nents,
                        rq_dma_dir(rq));
 
-       sg_free_table_chained(&freq->sg_table, SG_CHUNK_SIZE);
+       sg_free_table_chained(&freq->sg_table, NVME_INLINE_SG_CNT);
 
        freq->sg_cnt = 0;
 }
@@ -2910,10 +2913,22 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
 static void
 __nvme_fc_terminate_io(struct nvme_fc_ctrl *ctrl)
 {
-       nvme_stop_keep_alive(&ctrl->ctrl);
+       /*
+        * if state is connecting - the error occurred as part of a
+        * reconnect attempt. The create_association error paths will
+        * clean up any outstanding io.
+        *
+        * if it's a different state - ensure all pending io is
+        * terminated. Given this can delay while waiting for the
+        * aborted io to return, we recheck adapter state below
+        * before changing state.
+        */
+       if (ctrl->ctrl.state != NVME_CTRL_CONNECTING) {
+               nvme_stop_keep_alive(&ctrl->ctrl);
 
-       /* will block will waiting for io to terminate */
-       nvme_fc_delete_association(ctrl);
+               /* will block will waiting for io to terminate */
+               nvme_fc_delete_association(ctrl);
+       }
 
        if (ctrl->ctrl.state != NVME_CTRL_CONNECTING &&
            !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
@@ -3059,10 +3074,15 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
                goto out_fail;
        }
 
+       if (!try_module_get(lport->ops->module)) {
+               ret = -EUNATCH;
+               goto out_free_ctrl;
+       }
+
        idx = ida_simple_get(&nvme_fc_ctrl_cnt, 0, 0, GFP_KERNEL);
        if (idx < 0) {
                ret = -ENOSPC;
-               goto out_free_ctrl;
+               goto out_mod_put;
        }
 
        ctrl->ctrl.opts = opts;
@@ -3215,6 +3235,8 @@ out_free_queues:
 out_free_ida:
        put_device(ctrl->dev);
        ida_simple_remove(&nvme_fc_ctrl_cnt, ctrl->cnum);
+out_mod_put:
+       module_put(lport->ops->module);
 out_free_ctrl:
        kfree(ctrl);
 out_fail:
index 3b9cbe0..1024fec 100644 (file)
@@ -28,6 +28,12 @@ extern unsigned int admin_timeout;
 #define NVME_DEFAULT_KATO      5
 #define NVME_KATO_GRACE                10
 
+#ifdef CONFIG_ARCH_NO_SG_CHAIN
+#define  NVME_INLINE_SG_CNT  0
+#else
+#define  NVME_INLINE_SG_CNT  2
+#endif
+
 extern struct workqueue_struct *nvme_wq;
 extern struct workqueue_struct *nvme_reset_wq;
 extern struct workqueue_struct *nvme_delete_wq;
index dcaad58..365a2dd 100644 (file)
@@ -68,14 +68,14 @@ static int io_queue_depth = 1024;
 module_param_cb(io_queue_depth, &io_queue_depth_ops, &io_queue_depth, 0644);
 MODULE_PARM_DESC(io_queue_depth, "set io queue depth, should >= 2");
 
-static int write_queues;
-module_param(write_queues, int, 0644);
+static unsigned int write_queues;
+module_param(write_queues, uint, 0644);
 MODULE_PARM_DESC(write_queues,
        "Number of queues to use for writes. If not set, reads and writes "
        "will share a queue set.");
 
-static int poll_queues;
-module_param(poll_queues, int, 0644);
+static unsigned int poll_queues;
+module_param(poll_queues, uint, 0644);
 MODULE_PARM_DESC(poll_queues, "Number of queues to use for polled IO.");
 
 struct nvme_dev;
@@ -176,7 +176,6 @@ struct nvme_queue {
        u16 sq_tail;
        u16 last_sq_tail;
        u16 cq_head;
-       u16 last_cq_head;
        u16 qid;
        u8 cq_phase;
        u8 sqes;
@@ -1026,10 +1025,7 @@ static irqreturn_t nvme_irq(int irq, void *data)
         * the irq handler, even if that was on another CPU.
         */
        rmb();
-       if (nvmeq->cq_head != nvmeq->last_cq_head)
-               ret = IRQ_HANDLED;
        nvme_process_cq(nvmeq, &start, &end, -1);
-       nvmeq->last_cq_head = nvmeq->cq_head;
        wmb();
 
        if (start != end) {
@@ -1549,7 +1545,7 @@ static int nvme_create_queue(struct nvme_queue *nvmeq, int qid, bool polled)
        result = adapter_alloc_sq(dev, qid, nvmeq);
        if (result < 0)
                return result;
-       else if (result)
+       if (result)
                goto release_cq;
 
        nvmeq->cq_vector = vector;
@@ -2058,7 +2054,6 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                .priv           = dev,
        };
        unsigned int irq_queues, this_p_queues;
-       unsigned int nr_cpus = num_possible_cpus();
 
        /*
         * Poll queues don't need interrupts, but we need at least one IO
@@ -2069,10 +2064,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                this_p_queues = nr_io_queues - 1;
                irq_queues = 1;
        } else {
-               if (nr_cpus < nr_io_queues - this_p_queues)
-                       irq_queues = nr_cpus + 1;
-               else
-                       irq_queues = nr_io_queues - this_p_queues + 1;
+               irq_queues = nr_io_queues - this_p_queues + 1;
        }
        dev->io_queues[HCTX_TYPE_POLL] = this_p_queues;
 
@@ -3142,6 +3134,9 @@ static int __init nvme_init(void)
        BUILD_BUG_ON(sizeof(struct nvme_create_sq) != 64);
        BUILD_BUG_ON(sizeof(struct nvme_delete_queue) != 64);
        BUILD_BUG_ON(IRQ_AFFINITY_MAX_SETS < 2);
+
+       write_queues = min(write_queues, num_possible_cpus());
+       poll_queues = min(poll_queues, num_possible_cpus());
        return pci_register_driver(&nvme_driver);
 }
 
index dce5945..2a47c6c 100644 (file)
@@ -731,7 +731,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
                set->reserved_tags = 2; /* connect + keep-alive */
                set->numa_node = nctrl->numa_node;
                set->cmd_size = sizeof(struct nvme_rdma_request) +
-                       SG_CHUNK_SIZE * sizeof(struct scatterlist);
+                       NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
                set->driver_data = ctrl;
                set->nr_hw_queues = 1;
                set->timeout = ADMIN_TIMEOUT;
@@ -745,7 +745,7 @@ static struct blk_mq_tag_set *nvme_rdma_alloc_tagset(struct nvme_ctrl *nctrl,
                set->numa_node = nctrl->numa_node;
                set->flags = BLK_MQ_F_SHOULD_MERGE;
                set->cmd_size = sizeof(struct nvme_rdma_request) +
-                       SG_CHUNK_SIZE * sizeof(struct scatterlist);
+                       NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
                set->driver_data = ctrl;
                set->nr_hw_queues = nctrl->queue_count - 1;
                set->timeout = NVME_IO_TIMEOUT;
@@ -1160,7 +1160,7 @@ static void nvme_rdma_unmap_data(struct nvme_rdma_queue *queue,
        }
 
        ib_dma_unmap_sg(ibdev, req->sg_table.sgl, req->nents, rq_dma_dir(rq));
-       sg_free_table_chained(&req->sg_table, SG_CHUNK_SIZE);
+       sg_free_table_chained(&req->sg_table, NVME_INLINE_SG_CNT);
 }
 
 static int nvme_rdma_set_sg_null(struct nvme_command *c)
@@ -1276,7 +1276,7 @@ static int nvme_rdma_map_data(struct nvme_rdma_queue *queue,
        req->sg_table.sgl = req->first_sgl;
        ret = sg_alloc_table_chained(&req->sg_table,
                        blk_rq_nr_phys_segments(rq), req->sg_table.sgl,
-                       SG_CHUNK_SIZE);
+                       NVME_INLINE_SG_CNT);
        if (ret)
                return -ENOMEM;
 
@@ -1314,7 +1314,7 @@ out:
 out_unmap_sg:
        ib_dma_unmap_sg(ibdev, req->sg_table.sgl, req->nents, rq_dma_dir(rq));
 out_free_table:
-       sg_free_table_chained(&req->sg_table, SG_CHUNK_SIZE);
+       sg_free_table_chained(&req->sg_table, NVME_INLINE_SG_CNT);
        return ret;
 }
 
index 56c21b5..72a7e41 100644 (file)
@@ -24,6 +24,16 @@ u32 nvmet_get_log_page_len(struct nvme_command *cmd)
        return len;
 }
 
+static u32 nvmet_feat_data_len(struct nvmet_req *req, u32 cdw10)
+{
+       switch (cdw10 & 0xff) {
+       case NVME_FEAT_HOST_ID:
+               return sizeof(req->sq->ctrl->hostid);
+       default:
+               return 0;
+       }
+}
+
 u64 nvmet_get_log_page_offset(struct nvme_command *cmd)
 {
        return le64_to_cpu(cmd->get_log_page.lpo);
@@ -778,7 +788,7 @@ static void nvmet_execute_get_features(struct nvmet_req *req)
        u32 cdw10 = le32_to_cpu(req->cmd->common.cdw10);
        u16 status = 0;
 
-       if (!nvmet_check_data_len(req, 0))
+       if (!nvmet_check_data_len(req, nvmet_feat_data_len(req, cdw10)))
                return;
 
        switch (cdw10 & 0xff) {
index b50b53d..1c50af6 100644 (file)
@@ -850,6 +850,7 @@ fcloop_targetport_delete(struct nvmet_fc_target_port *targetport)
 #define FCLOOP_DMABOUND_4G             0xFFFFFFFF
 
 static struct nvme_fc_port_template fctemplate = {
+       .module                 = THIS_MODULE,
        .localport_delete       = fcloop_localport_delete,
        .remoteport_delete      = fcloop_remoteport_delete,
        .create_queue           = fcloop_create_queue,
index a758bb3..4df4ebd 100644 (file)
@@ -76,7 +76,7 @@ static void nvme_loop_complete_rq(struct request *req)
 {
        struct nvme_loop_iod *iod = blk_mq_rq_to_pdu(req);
 
-       sg_free_table_chained(&iod->sg_table, SG_CHUNK_SIZE);
+       sg_free_table_chained(&iod->sg_table, NVME_INLINE_SG_CNT);
        nvme_complete_rq(req);
 }
 
@@ -156,7 +156,7 @@ static blk_status_t nvme_loop_queue_rq(struct blk_mq_hw_ctx *hctx,
                iod->sg_table.sgl = iod->first_sgl;
                if (sg_alloc_table_chained(&iod->sg_table,
                                blk_rq_nr_phys_segments(req),
-                               iod->sg_table.sgl, SG_CHUNK_SIZE)) {
+                               iod->sg_table.sgl, NVME_INLINE_SG_CNT)) {
                        nvme_cleanup_cmd(req);
                        return BLK_STS_RESOURCE;
                }
@@ -342,7 +342,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
        ctrl->admin_tag_set.reserved_tags = 2; /* connect + keep-alive */
        ctrl->admin_tag_set.numa_node = NUMA_NO_NODE;
        ctrl->admin_tag_set.cmd_size = sizeof(struct nvme_loop_iod) +
-               SG_CHUNK_SIZE * sizeof(struct scatterlist);
+               NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
        ctrl->admin_tag_set.driver_data = ctrl;
        ctrl->admin_tag_set.nr_hw_queues = 1;
        ctrl->admin_tag_set.timeout = ADMIN_TIMEOUT;
@@ -516,7 +516,7 @@ static int nvme_loop_create_io_queues(struct nvme_loop_ctrl *ctrl)
        ctrl->tag_set.numa_node = NUMA_NO_NODE;
        ctrl->tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
        ctrl->tag_set.cmd_size = sizeof(struct nvme_loop_iod) +
-               SG_CHUNK_SIZE * sizeof(struct scatterlist);
+               NVME_INLINE_SG_CNT * sizeof(struct scatterlist);
        ctrl->tag_set.driver_data = ctrl;
        ctrl->tag_set.nr_hw_queues = ctrl->ctrl.queue_count - 1;
        ctrl->tag_set.timeout = NVME_IO_TIMEOUT;
index c6b87ce..fc757ef 100644 (file)
@@ -162,7 +162,7 @@ static const struct of_device_id whitelist_phys[] = {
  * A device which is not a phy is expected to have a compatible string
  * indicating what sort of device it is.
  */
-static bool of_mdiobus_child_is_phy(struct device_node *child)
+bool of_mdiobus_child_is_phy(struct device_node *child)
 {
        u32 phy_id;
 
@@ -187,6 +187,7 @@ static bool of_mdiobus_child_is_phy(struct device_node *child)
 
        return false;
 }
+EXPORT_SYMBOL(of_mdiobus_child_is_phy);
 
 /**
  * of_mdiobus_register - Register mii_bus and create PHYs from the device tree
index d93891a..3371e4a 100644 (file)
@@ -518,10 +518,11 @@ static int __init of_platform_default_populate_init(void)
 {
        struct device_node *node;
 
+       device_links_supplier_sync_state_pause();
+
        if (!of_have_populated_dt())
                return -ENODEV;
 
-       device_links_supplier_sync_state_pause();
        /*
         * Handle certain compatibles explicitly, since we don't want to create
         * platform_devices for every node in /reserved-memory with a
@@ -545,8 +546,7 @@ arch_initcall_sync(of_platform_default_populate_init);
 
 static int __init of_platform_sync_state_init(void)
 {
-       if (of_have_populated_dt())
-               device_links_supplier_sync_state_resume();
+       device_links_supplier_sync_state_resume();
        return 0;
 }
 late_initcall_sync(of_platform_sync_state_init);
index d9b63bf..94af6f5 100644 (file)
@@ -834,10 +834,12 @@ static int rockchip_pcie_cfg_atu(struct rockchip_pcie *rockchip)
        if (!entry)
                return -ENODEV;
 
+       /* store the register number offset to program RC io outbound ATU */
+       offset = size >> 20;
+
        size = resource_size(entry->res);
        pci_addr = entry->res->start - entry->offset;
 
-       offset = size >> 20;
        for (reg_no = 0; reg_no < (size >> 20); reg_no++) {
                err = rockchip_pcie_prog_ob_atu(rockchip,
                                                reg_no + 1 + offset,
index 773128f..d704ecc 100644 (file)
@@ -814,7 +814,7 @@ static int smmu_pmu_probe(struct platform_device *pdev)
        if (err) {
                dev_err(dev, "Error %d registering hotplug, PMU @%pa\n",
                        err, &res_0->start);
-               goto out_cpuhp_err;
+               return err;
        }
 
        err = perf_pmu_register(&smmu_pmu->pmu, name, -1);
@@ -833,8 +833,6 @@ static int smmu_pmu_probe(struct platform_device *pdev)
 
 out_unregister:
        cpuhp_state_remove_instance_nocalls(cpuhp_state_num, &smmu_pmu->node);
-out_cpuhp_err:
-       put_cpu();
        return err;
 }
 
index ead06c6..12e71a3 100644 (file)
@@ -115,7 +115,7 @@ struct cpcap_usb_ints_state {
 enum cpcap_gpio_mode {
        CPCAP_DM_DP,
        CPCAP_MDM_RX_TX,
-       CPCAP_UNKNOWN,
+       CPCAP_UNKNOWN_DISABLED, /* Seems to disable USB lines */
        CPCAP_OTG_DM_DP,
 };
 
@@ -134,6 +134,8 @@ struct cpcap_phy_ddata {
        struct iio_channel *id;
        struct regulator *vusb;
        atomic_t active;
+       unsigned int vbus_provider:1;
+       unsigned int docked:1;
 };
 
 static bool cpcap_usb_vbus_valid(struct cpcap_phy_ddata *ddata)
@@ -207,6 +209,19 @@ static int cpcap_phy_get_ints_state(struct cpcap_phy_ddata *ddata,
 static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata);
 static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata);
 
+static void cpcap_usb_try_musb_mailbox(struct cpcap_phy_ddata *ddata,
+                                      enum musb_vbus_id_status status)
+{
+       int error;
+
+       error = musb_mailbox(status);
+       if (!error)
+               return;
+
+       dev_dbg(ddata->dev, "%s: musb_mailbox failed: %i\n",
+               __func__, error);
+}
+
 static void cpcap_usb_detect(struct work_struct *work)
 {
        struct cpcap_phy_ddata *ddata;
@@ -220,16 +235,66 @@ static void cpcap_usb_detect(struct work_struct *work)
        if (error)
                return;
 
-       if (s.id_ground) {
-               dev_dbg(ddata->dev, "id ground, USB host mode\n");
+       vbus = cpcap_usb_vbus_valid(ddata);
+
+       /* We need to kick the VBUS as USB A-host */
+       if (s.id_ground && ddata->vbus_provider) {
+               dev_dbg(ddata->dev, "still in USB A-host mode, kicking VBUS\n");
+
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
+
+               error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
+                                          CPCAP_BIT_VBUSSTBY_EN |
+                                          CPCAP_BIT_VBUSEN_SPI,
+                                          CPCAP_BIT_VBUSEN_SPI);
+               if (error)
+                       goto out_err;
+
+               return;
+       }
+
+       if (vbus && s.id_ground && ddata->docked) {
+               dev_dbg(ddata->dev, "still docked as A-host, signal ID down\n");
+
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
+
+               return;
+       }
+
+       /* No VBUS needed with docks */
+       if (vbus && s.id_ground && !ddata->vbus_provider) {
+               dev_dbg(ddata->dev, "connected to a dock\n");
+
+               ddata->docked = true;
+
                error = cpcap_usb_set_usb_mode(ddata);
                if (error)
                        goto out_err;
 
-               error = musb_mailbox(MUSB_ID_GROUND);
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
+
+               /*
+                * Force check state again after musb has reoriented,
+                * otherwise devices won't enumerate after loading PHY
+                * driver.
+                */
+               schedule_delayed_work(&ddata->detect_work,
+                                     msecs_to_jiffies(1000));
+
+               return;
+       }
+
+       if (s.id_ground && !ddata->docked) {
+               dev_dbg(ddata->dev, "id ground, USB host mode\n");
+
+               ddata->vbus_provider = true;
+
+               error = cpcap_usb_set_usb_mode(ddata);
                if (error)
                        goto out_err;
 
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_ID_GROUND);
+
                error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
                                           CPCAP_BIT_VBUSSTBY_EN |
                                           CPCAP_BIT_VBUSEN_SPI,
@@ -248,43 +313,26 @@ static void cpcap_usb_detect(struct work_struct *work)
 
        vbus = cpcap_usb_vbus_valid(ddata);
 
+       /* Otherwise assume we're connected to a USB host */
        if (vbus) {
-               /* Are we connected to a docking station with vbus? */
-               if (s.id_ground) {
-                       dev_dbg(ddata->dev, "connected to a dock\n");
-
-                       /* No VBUS needed with docks */
-                       error = cpcap_usb_set_usb_mode(ddata);
-                       if (error)
-                               goto out_err;
-                       error = musb_mailbox(MUSB_ID_GROUND);
-                       if (error)
-                               goto out_err;
-
-                       return;
-               }
-
-               /* Otherwise assume we're connected to a USB host */
                dev_dbg(ddata->dev, "connected to USB host\n");
                error = cpcap_usb_set_usb_mode(ddata);
                if (error)
                        goto out_err;
-               error = musb_mailbox(MUSB_VBUS_VALID);
-               if (error)
-                       goto out_err;
+               cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_VALID);
 
                return;
        }
 
+       ddata->vbus_provider = false;
+       ddata->docked = false;
+       cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
+
        /* Default to debug UART mode */
        error = cpcap_usb_set_uart_mode(ddata);
        if (error)
                goto out_err;
 
-       error = musb_mailbox(MUSB_VBUS_OFF);
-       if (error)
-               goto out_err;
-
        dev_dbg(ddata->dev, "set UART mode\n");
 
        return;
@@ -376,7 +424,8 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
 {
        int error;
 
-       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
+       /* Disable lines to prevent glitches from waking up mdm6600 */
+       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
        if (error)
                goto out_err;
 
@@ -403,6 +452,11 @@ static int cpcap_usb_set_uart_mode(struct cpcap_phy_ddata *ddata)
        if (error)
                goto out_err;
 
+       /* Enable UART mode */
+       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_DM_DP);
+       if (error)
+               goto out_err;
+
        return 0;
 
 out_err:
@@ -415,7 +469,8 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
 {
        int error;
 
-       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
+       /* Disable lines to prevent glitches from waking up mdm6600 */
+       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_UNKNOWN_DISABLED);
        if (error)
                return error;
 
@@ -434,12 +489,6 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
        if (error)
                goto out_err;
 
-       error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC2,
-                                  CPCAP_BIT_USBXCVREN,
-                                  CPCAP_BIT_USBXCVREN);
-       if (error)
-               goto out_err;
-
        error = regmap_update_bits(ddata->reg, CPCAP_REG_USBC3,
                                   CPCAP_BIT_PU_SPI |
                                   CPCAP_BIT_DMPD_SPI |
@@ -455,6 +504,11 @@ static int cpcap_usb_set_usb_mode(struct cpcap_phy_ddata *ddata)
        if (error)
                goto out_err;
 
+       /* Enable USB mode */
+       error = cpcap_usb_gpio_set_mode(ddata, CPCAP_OTG_DM_DP);
+       if (error)
+               goto out_err;
+
        return 0;
 
 out_err:
@@ -649,9 +703,7 @@ static int cpcap_usb_phy_remove(struct platform_device *pdev)
        if (error)
                dev_err(ddata->dev, "could not set UART mode\n");
 
-       error = musb_mailbox(MUSB_VBUS_OFF);
-       if (error)
-               dev_err(ddata->dev, "could not set mailbox\n");
+       cpcap_usb_try_musb_mailbox(ddata, MUSB_VBUS_OFF);
 
        usb_remove_phy(&ddata->phy);
        cancel_delayed_work_sync(&ddata->detect_work);
index ee184d5..f20524f 100644 (file)
@@ -200,7 +200,7 @@ static void phy_mdm6600_status(struct work_struct *work)
        struct phy_mdm6600 *ddata;
        struct device *dev;
        DECLARE_BITMAP(values, PHY_MDM6600_NR_STATUS_LINES);
-       int error, i, val = 0;
+       int error;
 
        ddata = container_of(work, struct phy_mdm6600, status_work.work);
        dev = ddata->dev;
@@ -212,16 +212,11 @@ static void phy_mdm6600_status(struct work_struct *work)
        if (error)
                return;
 
-       for (i = 0; i < PHY_MDM6600_NR_STATUS_LINES; i++) {
-               val |= test_bit(i, values) << i;
-               dev_dbg(ddata->dev, "XXX %s: i: %i values[i]: %i val: %i\n",
-                       __func__, i, test_bit(i, values), val);
-       }
-       ddata->status = values[0];
+       ddata->status = values[0] & ((1 << PHY_MDM6600_NR_STATUS_LINES) - 1);
 
        dev_info(dev, "modem status: %i %s\n",
                 ddata->status,
-                phy_mdm6600_status_name[ddata->status & 7]);
+                phy_mdm6600_status_name[ddata->status]);
        complete(&ddata->ack);
 }
 
index 091e203..66f9172 100644 (file)
@@ -66,7 +66,7 @@
 /* QPHY_V3_PCS_MISC_CLAMP_ENABLE register bits */
 #define CLAMP_EN                               BIT(0) /* enables i/o clamp_n */
 
-#define PHY_INIT_COMPLETE_TIMEOUT              1000
+#define PHY_INIT_COMPLETE_TIMEOUT              10000
 #define POWER_DOWN_DELAY_US_MIN                        10
 #define POWER_DOWN_DELAY_US_MAX                        11
 
index 2b97fb1..9ca20c9 100644 (file)
@@ -603,6 +603,8 @@ static long inno_hdmi_phy_rk3228_clk_round_rate(struct clk_hw *hw,
 {
        const struct pre_pll_config *cfg = pre_pll_cfg_table;
 
+       rate = (rate / 1000) * 1000;
+
        for (; cfg->pixclock != 0; cfg++)
                if (cfg->pixclock == rate && !cfg->fracdiv)
                        break;
@@ -755,6 +757,8 @@ static long inno_hdmi_phy_rk3328_clk_round_rate(struct clk_hw *hw,
 {
        const struct pre_pll_config *cfg = pre_pll_cfg_table;
 
+       rate = (rate / 1000) * 1000;
+
        for (; cfg->pixclock != 0; cfg++)
                if (cfg->pixclock == rate)
                        break;
index 3bfbf2f..df0ef69 100644 (file)
@@ -422,6 +422,7 @@ config PINCTRL_TB10X
 
 config PINCTRL_EQUILIBRIUM
        tristate "Generic pinctrl and GPIO driver for Intel Lightning Mountain SoC"
+       depends on OF && HAS_IOMEM
        select PINMUX
        select PINCONF
        select GPIOLIB
index c6800d2..bb07024 100644 (file)
@@ -1088,60 +1088,52 @@ SSSF_PIN_DECL(AF15, GPIOV7, LPCSMI, SIG_DESC_SET(SCU434, 15));
 
 #define AB7 176
 SIG_EXPR_LIST_DECL_SESG(AB7, LAD0, LPC, SIG_DESC_SET(SCU434, 16),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AB7, ESPID0, ESPI, SIG_DESC_SET(SCU434, 16),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AB7, ESPID0, ESPI, SIG_DESC_SET(SCU434, 16));
 PIN_DECL_2(AB7, GPIOW0, LAD0, ESPID0);
 
 #define AB8 177
 SIG_EXPR_LIST_DECL_SESG(AB8, LAD1, LPC, SIG_DESC_SET(SCU434, 17),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AB8, ESPID1, ESPI, SIG_DESC_SET(SCU434, 17),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AB8, ESPID1, ESPI, SIG_DESC_SET(SCU434, 17));
 PIN_DECL_2(AB8, GPIOW1, LAD1, ESPID1);
 
 #define AC8 178
 SIG_EXPR_LIST_DECL_SESG(AC8, LAD2, LPC, SIG_DESC_SET(SCU434, 18),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AC8, ESPID2, ESPI, SIG_DESC_SET(SCU434, 18),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AC8, ESPID2, ESPI, SIG_DESC_SET(SCU434, 18));
 PIN_DECL_2(AC8, GPIOW2, LAD2, ESPID2);
 
 #define AC7 179
 SIG_EXPR_LIST_DECL_SESG(AC7, LAD3, LPC, SIG_DESC_SET(SCU434, 19),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AC7, ESPID3, ESPI, SIG_DESC_SET(SCU434, 19),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AC7, ESPID3, ESPI, SIG_DESC_SET(SCU434, 19));
 PIN_DECL_2(AC7, GPIOW3, LAD3, ESPID3);
 
 #define AE7 180
 SIG_EXPR_LIST_DECL_SESG(AE7, LCLK, LPC, SIG_DESC_SET(SCU434, 20),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AE7, ESPICK, ESPI, SIG_DESC_SET(SCU434, 20),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AE7, ESPICK, ESPI, SIG_DESC_SET(SCU434, 20));
 PIN_DECL_2(AE7, GPIOW4, LCLK, ESPICK);
 
 #define AF7 181
 SIG_EXPR_LIST_DECL_SESG(AF7, LFRAME, LPC, SIG_DESC_SET(SCU434, 21),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AF7, ESPICS, ESPI, SIG_DESC_SET(SCU434, 21),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AF7, ESPICS, ESPI, SIG_DESC_SET(SCU434, 21));
 PIN_DECL_2(AF7, GPIOW5, LFRAME, ESPICS);
 
 #define AD7 182
 SIG_EXPR_LIST_DECL_SESG(AD7, LSIRQ, LSIRQ, SIG_DESC_SET(SCU434, 22),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AD7, ESPIALT, ESPIALT, SIG_DESC_SET(SCU434, 22),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AD7, ESPIALT, ESPIALT, SIG_DESC_SET(SCU434, 22));
 PIN_DECL_2(AD7, GPIOW6, LSIRQ, ESPIALT);
 FUNC_GROUP_DECL(LSIRQ, AD7);
 FUNC_GROUP_DECL(ESPIALT, AD7);
 
 #define AD8 183
 SIG_EXPR_LIST_DECL_SESG(AD8, LPCRST, LPC, SIG_DESC_SET(SCU434, 23),
-                         SIG_DESC_CLEAR(SCU510, 6));
-SIG_EXPR_LIST_DECL_SESG(AD8, ESPIRST, ESPI, SIG_DESC_SET(SCU434, 23),
                          SIG_DESC_SET(SCU510, 6));
+SIG_EXPR_LIST_DECL_SESG(AD8, ESPIRST, ESPI, SIG_DESC_SET(SCU434, 23));
 PIN_DECL_2(AD8, GPIOW7, LPCRST, ESPIRST);
 
 FUNC_GROUP_DECL(LPC, AB7, AB8, AC8, AC7, AE7, AF7, AD8);
index f1806fd..530426a 100644 (file)
@@ -2,6 +2,7 @@
 config PINCTRL_LOCHNAGAR
        tristate "Cirrus Logic Lochnagar pinctrl driver"
        depends on MFD_LOCHNAGAR
+       select GPIOLIB
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
index 9ffb222..55141d5 100644 (file)
@@ -110,7 +110,6 @@ struct byt_gpio {
        struct platform_device *pdev;
        struct pinctrl_dev *pctl_dev;
        struct pinctrl_desc pctl_desc;
-       raw_spinlock_t lock;
        const struct intel_pinctrl_soc_data *soc_data;
        struct intel_community *communities_copy;
        struct byt_gpio_pin_context *saved_context;
@@ -494,34 +493,34 @@ static const struct intel_pinctrl_soc_data byt_sus_soc_data = {
 };
 
 static const struct pinctrl_pin_desc byt_ncore_pins[] = {
-       PINCTRL_PIN(0, "GPIO_NCORE0"),
-       PINCTRL_PIN(1, "GPIO_NCORE1"),
-       PINCTRL_PIN(2, "GPIO_NCORE2"),
-       PINCTRL_PIN(3, "GPIO_NCORE3"),
-       PINCTRL_PIN(4, "GPIO_NCORE4"),
-       PINCTRL_PIN(5, "GPIO_NCORE5"),
-       PINCTRL_PIN(6, "GPIO_NCORE6"),
-       PINCTRL_PIN(7, "GPIO_NCORE7"),
-       PINCTRL_PIN(8, "GPIO_NCORE8"),
-       PINCTRL_PIN(9, "GPIO_NCORE9"),
-       PINCTRL_PIN(10, "GPIO_NCORE10"),
-       PINCTRL_PIN(11, "GPIO_NCORE11"),
-       PINCTRL_PIN(12, "GPIO_NCORE12"),
-       PINCTRL_PIN(13, "GPIO_NCORE13"),
-       PINCTRL_PIN(14, "GPIO_NCORE14"),
-       PINCTRL_PIN(15, "GPIO_NCORE15"),
-       PINCTRL_PIN(16, "GPIO_NCORE16"),
-       PINCTRL_PIN(17, "GPIO_NCORE17"),
-       PINCTRL_PIN(18, "GPIO_NCORE18"),
-       PINCTRL_PIN(19, "GPIO_NCORE19"),
-       PINCTRL_PIN(20, "GPIO_NCORE20"),
-       PINCTRL_PIN(21, "GPIO_NCORE21"),
-       PINCTRL_PIN(22, "GPIO_NCORE22"),
-       PINCTRL_PIN(23, "GPIO_NCORE23"),
-       PINCTRL_PIN(24, "GPIO_NCORE24"),
-       PINCTRL_PIN(25, "GPIO_NCORE25"),
-       PINCTRL_PIN(26, "GPIO_NCORE26"),
-       PINCTRL_PIN(27, "GPIO_NCORE27"),
+       PINCTRL_PIN(0, "HV_DDI0_HPD"),
+       PINCTRL_PIN(1, "HV_DDI0_DDC_SDA"),
+       PINCTRL_PIN(2, "HV_DDI0_DDC_SCL"),
+       PINCTRL_PIN(3, "PANEL0_VDDEN"),
+       PINCTRL_PIN(4, "PANEL0_BKLTEN"),
+       PINCTRL_PIN(5, "PANEL0_BKLTCTL"),
+       PINCTRL_PIN(6, "HV_DDI1_HPD"),
+       PINCTRL_PIN(7, "HV_DDI1_DDC_SDA"),
+       PINCTRL_PIN(8, "HV_DDI1_DDC_SCL"),
+       PINCTRL_PIN(9, "PANEL1_VDDEN"),
+       PINCTRL_PIN(10, "PANEL1_BKLTEN"),
+       PINCTRL_PIN(11, "PANEL1_BKLTCTL"),
+       PINCTRL_PIN(12, "GP_INTD_DSI_TE1"),
+       PINCTRL_PIN(13, "HV_DDI2_DDC_SDA"),
+       PINCTRL_PIN(14, "HV_DDI2_DDC_SCL"),
+       PINCTRL_PIN(15, "GP_CAMERASB00"),
+       PINCTRL_PIN(16, "GP_CAMERASB01"),
+       PINCTRL_PIN(17, "GP_CAMERASB02"),
+       PINCTRL_PIN(18, "GP_CAMERASB03"),
+       PINCTRL_PIN(19, "GP_CAMERASB04"),
+       PINCTRL_PIN(20, "GP_CAMERASB05"),
+       PINCTRL_PIN(21, "GP_CAMERASB06"),
+       PINCTRL_PIN(22, "GP_CAMERASB07"),
+       PINCTRL_PIN(23, "GP_CAMERASB08"),
+       PINCTRL_PIN(24, "GP_CAMERASB09"),
+       PINCTRL_PIN(25, "GP_CAMERASB10"),
+       PINCTRL_PIN(26, "GP_CAMERASB11"),
+       PINCTRL_PIN(27, "GP_INTD_DSI_TE2"),
 };
 
 static const unsigned int byt_ncore_pins_map[BYT_NGPIO_NCORE] = {
@@ -549,6 +548,8 @@ static const struct intel_pinctrl_soc_data *byt_soc_data[] = {
        NULL
 };
 
+static DEFINE_RAW_SPINLOCK(byt_lock);
+
 static struct intel_community *byt_get_community(struct byt_gpio *vg,
                                                 unsigned int pin)
 {
@@ -658,7 +659,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
        unsigned long flags;
        int i;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        for (i = 0; i < group.npins; i++) {
                void __iomem *padcfg0;
@@ -678,7 +679,7 @@ static void byt_set_group_simple_mux(struct byt_gpio *vg,
                writel(value, padcfg0);
        }
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static void byt_set_group_mixed_mux(struct byt_gpio *vg,
@@ -688,7 +689,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
        unsigned long flags;
        int i;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        for (i = 0; i < group.npins; i++) {
                void __iomem *padcfg0;
@@ -708,7 +709,7 @@ static void byt_set_group_mixed_mux(struct byt_gpio *vg,
                writel(value, padcfg0);
        }
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
@@ -749,11 +750,11 @@ static void byt_gpio_clear_triggering(struct byt_gpio *vg, unsigned int offset)
        unsigned long flags;
        u32 value;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        value = readl(reg);
        value &= ~(BYT_TRIG_POS | BYT_TRIG_NEG | BYT_TRIG_LVL);
        writel(value, reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
@@ -765,7 +766,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
        u32 value, gpio_mux;
        unsigned long flags;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        /*
         * In most cases, func pin mux 000 means GPIO function.
@@ -787,7 +788,7 @@ static int byt_gpio_request_enable(struct pinctrl_dev *pctl_dev,
                         "pin %u forcibly re-configured as GPIO\n", offset);
        }
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        pm_runtime_get(&vg->pdev->dev);
 
@@ -815,7 +816,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
        unsigned long flags;
        u32 value;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        value = readl(val_reg);
        value &= ~BYT_DIR_MASK;
@@ -832,7 +833,7 @@ static int byt_gpio_set_direction(struct pinctrl_dev *pctl_dev,
                     "Potential Error: Setting GPIO with direct_irq_en to output");
        writel(value, val_reg);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        return 0;
 }
@@ -901,11 +902,11 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
        u32 conf, pull, val, debounce;
        u16 arg = 0;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        conf = readl(conf_reg);
        pull = conf & BYT_PULL_ASSIGN_MASK;
        val = readl(val_reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        switch (param) {
        case PIN_CONFIG_BIAS_DISABLE:
@@ -932,9 +933,9 @@ static int byt_pin_config_get(struct pinctrl_dev *pctl_dev, unsigned int offset,
                if (!(conf & BYT_DEBOUNCE_EN))
                        return -EINVAL;
 
-               raw_spin_lock_irqsave(&vg->lock, flags);
+               raw_spin_lock_irqsave(&byt_lock, flags);
                debounce = readl(db_reg);
-               raw_spin_unlock_irqrestore(&vg->lock, flags);
+               raw_spin_unlock_irqrestore(&byt_lock, flags);
 
                switch (debounce & BYT_DEBOUNCE_PULSE_MASK) {
                case BYT_DEBOUNCE_PULSE_375US:
@@ -986,7 +987,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
        u32 conf, val, debounce;
        int i, ret = 0;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
 
        conf = readl(conf_reg);
        val = readl(val_reg);
@@ -1094,7 +1095,7 @@ static int byt_pin_config_set(struct pinctrl_dev *pctl_dev,
        if (!ret)
                writel(conf, conf_reg);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        return ret;
 }
@@ -1119,9 +1120,9 @@ static int byt_gpio_get(struct gpio_chip *chip, unsigned int offset)
        unsigned long flags;
        u32 val;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        val = readl(reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        return !!(val & BYT_LEVEL);
 }
@@ -1136,13 +1137,13 @@ static void byt_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
        if (!reg)
                return;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        old_val = readl(reg);
        if (value)
                writel(old_val | BYT_LEVEL, reg);
        else
                writel(old_val & ~BYT_LEVEL, reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
@@ -1155,9 +1156,9 @@ static int byt_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
        if (!reg)
                return -EINVAL;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        value = readl(reg);
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        if (!(value & BYT_OUTPUT_EN))
                return 0;
@@ -1200,14 +1201,14 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
                const char *label;
                unsigned int pin;
 
-               raw_spin_lock_irqsave(&vg->lock, flags);
+               raw_spin_lock_irqsave(&byt_lock, flags);
                pin = vg->soc_data->pins[i].number;
                reg = byt_gpio_reg(vg, pin, BYT_CONF0_REG);
                if (!reg) {
                        seq_printf(s,
                                   "Could not retrieve pin %i conf0 reg\n",
                                   pin);
-                       raw_spin_unlock_irqrestore(&vg->lock, flags);
+                       raw_spin_unlock_irqrestore(&byt_lock, flags);
                        continue;
                }
                conf0 = readl(reg);
@@ -1216,11 +1217,11 @@ static void byt_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
                if (!reg) {
                        seq_printf(s,
                                   "Could not retrieve pin %i val reg\n", pin);
-                       raw_spin_unlock_irqrestore(&vg->lock, flags);
+                       raw_spin_unlock_irqrestore(&byt_lock, flags);
                        continue;
                }
                val = readl(reg);
-               raw_spin_unlock_irqrestore(&vg->lock, flags);
+               raw_spin_unlock_irqrestore(&byt_lock, flags);
 
                comm = byt_get_community(vg, pin);
                if (!comm) {
@@ -1304,9 +1305,9 @@ static void byt_irq_ack(struct irq_data *d)
        if (!reg)
                return;
 
-       raw_spin_lock(&vg->lock);
+       raw_spin_lock(&byt_lock);
        writel(BIT(offset % 32), reg);
-       raw_spin_unlock(&vg->lock);
+       raw_spin_unlock(&byt_lock);
 }
 
 static void byt_irq_mask(struct irq_data *d)
@@ -1330,7 +1331,7 @@ static void byt_irq_unmask(struct irq_data *d)
        if (!reg)
                return;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        value = readl(reg);
 
        switch (irqd_get_trigger_type(d)) {
@@ -1353,7 +1354,7 @@ static void byt_irq_unmask(struct irq_data *d)
 
        writel(value, reg);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 }
 
 static int byt_irq_type(struct irq_data *d, unsigned int type)
@@ -1367,7 +1368,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
        if (!reg || offset >= vg->chip.ngpio)
                return -EINVAL;
 
-       raw_spin_lock_irqsave(&vg->lock, flags);
+       raw_spin_lock_irqsave(&byt_lock, flags);
        value = readl(reg);
 
        WARN(value & BYT_DIRECT_IRQ_EN,
@@ -1389,7 +1390,7 @@ static int byt_irq_type(struct irq_data *d, unsigned int type)
        else if (type & IRQ_TYPE_LEVEL_MASK)
                irq_set_handler_locked(d, handle_level_irq);
 
-       raw_spin_unlock_irqrestore(&vg->lock, flags);
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
 
        return 0;
 }
@@ -1425,9 +1426,9 @@ static void byt_gpio_irq_handler(struct irq_desc *desc)
                        continue;
                }
 
-               raw_spin_lock(&vg->lock);
+               raw_spin_lock(&byt_lock);
                pending = readl(reg);
-               raw_spin_unlock(&vg->lock);
+               raw_spin_unlock(&byt_lock);
                for_each_set_bit(pin, &pending, 32) {
                        virq = irq_find_mapping(vg->chip.irq.domain, base + pin);
                        generic_handle_irq(virq);
@@ -1450,9 +1451,9 @@ static void byt_init_irq_valid_mask(struct gpio_chip *chip,
         */
 }
 
-static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
+static int byt_gpio_irq_init_hw(struct gpio_chip *chip)
 {
-       struct gpio_chip *gc = &vg->chip;
+       struct byt_gpio *vg = gpiochip_get_data(chip);
        struct device *dev = &vg->pdev->dev;
        void __iomem *reg;
        u32 base, value;
@@ -1476,7 +1477,7 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
 
                value = readl(reg);
                if (value & BYT_DIRECT_IRQ_EN) {
-                       clear_bit(i, gc->irq.valid_mask);
+                       clear_bit(i, chip->irq.valid_mask);
                        dev_dbg(dev, "excluding GPIO %d from IRQ domain\n", i);
                } else if ((value & BYT_PIN_MUX) == byt_get_gpio_mux(vg, i)) {
                        byt_gpio_clear_triggering(vg, i);
@@ -1504,6 +1505,21 @@ static void byt_gpio_irq_init_hw(struct byt_gpio *vg)
                                "GPIO interrupt error, pins misconfigured. INT_STAT%u: 0x%08x\n",
                                base / 32, value);
        }
+
+       return 0;
+}
+
+static int byt_gpio_add_pin_ranges(struct gpio_chip *chip)
+{
+       struct byt_gpio *vg = gpiochip_get_data(chip);
+       struct device *dev = &vg->pdev->dev;
+       int ret;
+
+       ret = gpiochip_add_pin_range(chip, dev_name(dev), 0, 0, vg->soc_data->npins);
+       if (ret)
+               dev_err(dev, "failed to add GPIO pin range\n");
+
+       return ret;
 }
 
 static int byt_gpio_probe(struct byt_gpio *vg)
@@ -1518,6 +1534,7 @@ static int byt_gpio_probe(struct byt_gpio *vg)
        gc->label       = dev_name(&vg->pdev->dev);
        gc->base        = -1;
        gc->can_sleep   = false;
+       gc->add_pin_ranges = byt_gpio_add_pin_ranges;
        gc->parent      = &vg->pdev->dev;
        gc->ngpio       = vg->soc_data->npins;
        gc->irq.init_valid_mask = byt_init_irq_valid_mask;
@@ -1528,33 +1545,30 @@ static int byt_gpio_probe(struct byt_gpio *vg)
        if (!vg->saved_context)
                return -ENOMEM;
 #endif
-       ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
-       if (ret) {
-               dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
-               return ret;
-       }
-
-       ret = gpiochip_add_pin_range(&vg->chip, dev_name(&vg->pdev->dev),
-                                    0, 0, vg->soc_data->npins);
-       if (ret) {
-               dev_err(&vg->pdev->dev, "failed to add GPIO pin range\n");
-               return ret;
-       }
 
        /* set up interrupts  */
        irq_rc = platform_get_resource(vg->pdev, IORESOURCE_IRQ, 0);
        if (irq_rc && irq_rc->start) {
-               byt_gpio_irq_init_hw(vg);
-               ret = gpiochip_irqchip_add(gc, &byt_irqchip, 0,
-                                          handle_bad_irq, IRQ_TYPE_NONE);
-               if (ret) {
-                       dev_err(&vg->pdev->dev, "failed to add irqchip\n");
-                       return ret;
-               }
+               struct gpio_irq_chip *girq;
+
+               girq = &gc->irq;
+               girq->chip = &byt_irqchip;
+               girq->init_hw = byt_gpio_irq_init_hw;
+               girq->parent_handler = byt_gpio_irq_handler;
+               girq->num_parents = 1;
+               girq->parents = devm_kcalloc(&vg->pdev->dev, girq->num_parents,
+                                            sizeof(*girq->parents), GFP_KERNEL);
+               if (!girq->parents)
+                       return -ENOMEM;
+               girq->parents[0] = (unsigned int)irq_rc->start;
+               girq->default_type = IRQ_TYPE_NONE;
+               girq->handler = handle_bad_irq;
+       }
 
-               gpiochip_set_chained_irqchip(gc, &byt_irqchip,
-                                            (unsigned)irq_rc->start,
-                                            byt_gpio_irq_handler);
+       ret = devm_gpiochip_add_data(&vg->pdev->dev, gc, vg);
+       if (ret) {
+               dev_err(&vg->pdev->dev, "failed adding byt-gpio chip\n");
+               return ret;
        }
 
        return ret;
@@ -1638,8 +1652,6 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
                return PTR_ERR(vg->pctl_dev);
        }
 
-       raw_spin_lock_init(&vg->lock);
-
        ret = byt_gpio_probe(vg);
        if (ret)
                return ret;
@@ -1654,8 +1666,11 @@ static int byt_pinctrl_probe(struct platform_device *pdev)
 static int byt_gpio_suspend(struct device *dev)
 {
        struct byt_gpio *vg = dev_get_drvdata(dev);
+       unsigned long flags;
        int i;
 
+       raw_spin_lock_irqsave(&byt_lock, flags);
+
        for (i = 0; i < vg->soc_data->npins; i++) {
                void __iomem *reg;
                u32 value;
@@ -1676,14 +1691,18 @@ static int byt_gpio_suspend(struct device *dev)
                vg->saved_context[i].val = value;
        }
 
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
        return 0;
 }
 
 static int byt_gpio_resume(struct device *dev)
 {
        struct byt_gpio *vg = dev_get_drvdata(dev);
+       unsigned long flags;
        int i;
 
+       raw_spin_lock_irqsave(&byt_lock, flags);
+
        for (i = 0; i < vg->soc_data->npins; i++) {
                void __iomem *reg;
                u32 value;
@@ -1721,6 +1740,7 @@ static int byt_gpio_resume(struct device *dev)
                }
        }
 
+       raw_spin_unlock_irqrestore(&byt_lock, flags);
        return 0;
 }
 #endif
index 582fa8a..60527b9 100644 (file)
@@ -149,6 +149,7 @@ struct chv_pin_context {
  * @chip: GPIO chip in this pin controller
  * @irqchip: IRQ chip in this pin controller
  * @regs: MMIO registers
+ * @irq: Our parent irq
  * @intr_lines: Stores mapping between 16 HW interrupt wires and GPIO
  *             offset (in GPIO number space)
  * @community: Community this pinctrl instance represents
@@ -165,6 +166,7 @@ struct chv_pinctrl {
        struct gpio_chip chip;
        struct irq_chip irqchip;
        void __iomem *regs;
+       unsigned int irq;
        unsigned int intr_lines[16];
        const struct chv_community *community;
        u32 saved_intmask;
@@ -1555,39 +1557,9 @@ static void chv_init_irq_valid_mask(struct gpio_chip *chip,
        }
 }
 
-static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
+static int chv_gpio_irq_init_hw(struct gpio_chip *chip)
 {
-       const struct chv_gpio_pinrange *range;
-       struct gpio_chip *chip = &pctrl->chip;
-       bool need_valid_mask = !dmi_check_system(chv_no_valid_mask);
-       const struct chv_community *community = pctrl->community;
-       int ret, i, irq_base;
-
-       *chip = chv_gpio_chip;
-
-       chip->ngpio = community->pins[community->npins - 1].number + 1;
-       chip->label = dev_name(pctrl->dev);
-       chip->parent = pctrl->dev;
-       chip->base = -1;
-       if (need_valid_mask)
-               chip->irq.init_valid_mask = chv_init_irq_valid_mask;
-
-       ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
-       if (ret) {
-               dev_err(pctrl->dev, "Failed to register gpiochip\n");
-               return ret;
-       }
-
-       for (i = 0; i < community->ngpio_ranges; i++) {
-               range = &community->gpio_ranges[i];
-               ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev),
-                                            range->base, range->base,
-                                            range->npins);
-               if (ret) {
-                       dev_err(pctrl->dev, "failed to add GPIO pin range\n");
-                       return ret;
-               }
-       }
+       struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
 
        /*
         * The same set of machines in chv_no_valid_mask[] have incorrectly
@@ -1596,7 +1568,7 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
         *
         * See also https://bugzilla.kernel.org/show_bug.cgi?id=197953.
         */
-       if (!need_valid_mask) {
+       if (!pctrl->chip.irq.init_valid_mask) {
                /*
                 * Mask all interrupts the community is able to generate
                 * but leave the ones that can only generate GPEs unmasked.
@@ -1608,15 +1580,47 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
        /* Clear all interrupts */
        chv_writel(0xffff, pctrl->regs + CHV_INTSTAT);
 
-       if (!need_valid_mask) {
-               irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0,
-                                               community->npins, NUMA_NO_NODE);
-               if (irq_base < 0) {
-                       dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n");
-                       return irq_base;
+       return 0;
+}
+
+static int chv_gpio_add_pin_ranges(struct gpio_chip *chip)
+{
+       struct chv_pinctrl *pctrl = gpiochip_get_data(chip);
+       const struct chv_community *community = pctrl->community;
+       const struct chv_gpio_pinrange *range;
+       int ret, i;
+
+       for (i = 0; i < community->ngpio_ranges; i++) {
+               range = &community->gpio_ranges[i];
+               ret = gpiochip_add_pin_range(chip, dev_name(pctrl->dev),
+                                            range->base, range->base,
+                                            range->npins);
+               if (ret) {
+                       dev_err(pctrl->dev, "failed to add GPIO pin range\n");
+                       return ret;
                }
        }
 
+       return 0;
+}
+
+static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
+{
+       const struct chv_gpio_pinrange *range;
+       struct gpio_chip *chip = &pctrl->chip;
+       bool need_valid_mask = !dmi_check_system(chv_no_valid_mask);
+       const struct chv_community *community = pctrl->community;
+       int ret, i, irq_base;
+
+       *chip = chv_gpio_chip;
+
+       chip->ngpio = community->pins[community->npins - 1].number + 1;
+       chip->label = dev_name(pctrl->dev);
+       chip->add_pin_ranges = chv_gpio_add_pin_ranges;
+       chip->parent = pctrl->dev;
+       chip->base = -1;
+
+       pctrl->irq = irq;
        pctrl->irqchip.name = "chv-gpio";
        pctrl->irqchip.irq_startup = chv_gpio_irq_startup;
        pctrl->irqchip.irq_ack = chv_gpio_irq_ack;
@@ -1625,10 +1629,27 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
        pctrl->irqchip.irq_set_type = chv_gpio_irq_type;
        pctrl->irqchip.flags = IRQCHIP_SKIP_SET_WAKE;
 
-       ret = gpiochip_irqchip_add(chip, &pctrl->irqchip, 0,
-                                  handle_bad_irq, IRQ_TYPE_NONE);
+       chip->irq.chip = &pctrl->irqchip;
+       chip->irq.init_hw = chv_gpio_irq_init_hw;
+       chip->irq.parent_handler = chv_gpio_irq_handler;
+       chip->irq.num_parents = 1;
+       chip->irq.parents = &pctrl->irq;
+       chip->irq.default_type = IRQ_TYPE_NONE;
+       chip->irq.handler = handle_bad_irq;
+       if (need_valid_mask) {
+               chip->irq.init_valid_mask = chv_init_irq_valid_mask;
+       } else {
+               irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0,
+                                               community->npins, NUMA_NO_NODE);
+               if (irq_base < 0) {
+                       dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n");
+                       return irq_base;
+               }
+       }
+
+       ret = devm_gpiochip_add_data(pctrl->dev, chip, pctrl);
        if (ret) {
-               dev_err(pctrl->dev, "failed to add IRQ chip\n");
+               dev_err(pctrl->dev, "Failed to register gpiochip\n");
                return ret;
        }
 
@@ -1642,8 +1663,6 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq)
                }
        }
 
-       gpiochip_set_chained_irqchip(chip, &pctrl->irqchip, irq,
-                                    chv_gpio_irq_handler);
        return 0;
 }
 
index 3c80828..bbc919b 100644 (file)
@@ -441,6 +441,7 @@ static int meson_pinconf_get_drive_strength(struct meson_pinctrl *pc,
                return ret;
 
        meson_calc_reg_and_bit(bank, pin, REG_DS, &reg, &bit);
+       bit = bit << 1;
 
        ret = regmap_read(pc->reg_ds, reg, &val);
        if (ret)
index 24e0e2e..369e043 100644 (file)
@@ -1809,7 +1809,7 @@ static void ingenic_set_bias(struct ingenic_pinctrl *jzpc,
 static void ingenic_set_output_level(struct ingenic_pinctrl *jzpc,
                                     unsigned int pin, bool high)
 {
-       if (jzpc->version >= ID_JZ4770)
+       if (jzpc->version >= ID_JZ4760)
                ingenic_config_pin(jzpc, pin, JZ4760_GPIO_PAT0, high);
        else
                ingenic_config_pin(jzpc, pin, JZ4740_GPIO_DATA, high);
index e914f6e..9503ddf 100644 (file)
@@ -85,7 +85,7 @@ bool pinmux_can_be_used_for_gpio(struct pinctrl_dev *pctldev, unsigned pin)
        const struct pinmux_ops *ops = pctldev->desc->pmxops;
 
        /* Can't inspect pin, assume it can be used */
-       if (!desc)
+       if (!desc || !ops)
                return true;
 
        if (ops->strict && desc->mux_usecount)
index bb0edf5..5731d1b 100644 (file)
@@ -73,13 +73,6 @@ static int send_kbbl_msg(struct wilco_ec_device *ec,
                return ret;
        }
 
-       if (response->status) {
-               dev_err(ec->dev,
-                       "EC reported failure sending keyboard LEDs command: %d",
-                       response->status);
-               return -EIO;
-       }
-
        return 0;
 }
 
@@ -87,6 +80,7 @@ static int set_kbbl(struct wilco_ec_device *ec, enum led_brightness brightness)
 {
        struct wilco_keyboard_leds_msg request;
        struct wilco_keyboard_leds_msg response;
+       int ret;
 
        memset(&request, 0, sizeof(request));
        request.command = WILCO_EC_COMMAND_KBBL;
@@ -94,7 +88,18 @@ static int set_kbbl(struct wilco_ec_device *ec, enum led_brightness brightness)
        request.mode    = WILCO_KBBL_MODE_FLAG_PWM;
        request.percent = brightness;
 
-       return send_kbbl_msg(ec, &request, &response);
+       ret = send_kbbl_msg(ec, &request, &response);
+       if (ret < 0)
+               return ret;
+
+       if (response.status) {
+               dev_err(ec->dev,
+                       "EC reported failure sending keyboard LEDs command: %d",
+                       response.status);
+               return -EIO;
+       }
+
+       return 0;
 }
 
 static int kbbl_exist(struct wilco_ec_device *ec, bool *exists)
@@ -140,6 +145,13 @@ static int kbbl_init(struct wilco_ec_device *ec)
        if (ret < 0)
                return ret;
 
+       if (response.status) {
+               dev_err(ec->dev,
+                       "EC reported failure sending keyboard LEDs command: %d",
+                       response.status);
+               return -EIO;
+       }
+
        if (response.mode & WILCO_KBBL_MODE_FLAG_PWM)
                return response.percent;
 
index 61753b6..5d21c6a 100644 (file)
@@ -309,7 +309,7 @@ static struct platform_driver mlxbf_bootctl_driver = {
        .probe = mlxbf_bootctl_probe,
        .driver = {
                .name = "mlxbf-bootctl",
-               .groups = mlxbf_bootctl_groups,
+               .dev_groups = mlxbf_bootctl_groups,
                .acpi_match_table = mlxbf_bootctl_acpi_ids,
        }
 };
index 9a5c9fd..5739a96 100644 (file)
@@ -149,7 +149,7 @@ struct mlxbf_tmfifo_irq_info {
  * @work: work struct for deferred process
  * @timer: background timer
  * @vring: Tx/Rx ring
- * @spin_lock: spin lock
+ * @spin_lock: Tx/Rx spin lock
  * @is_ready: ready flag
  */
 struct mlxbf_tmfifo {
@@ -164,7 +164,7 @@ struct mlxbf_tmfifo {
        struct work_struct work;
        struct timer_list timer;
        struct mlxbf_tmfifo_vring *vring[2];
-       spinlock_t spin_lock;           /* spin lock */
+       spinlock_t spin_lock[2];        /* spin lock */
        bool is_ready;
 };
 
@@ -525,7 +525,7 @@ static void mlxbf_tmfifo_console_tx(struct mlxbf_tmfifo *fifo, int avail)
        writeq(*(u64 *)&hdr, fifo->tx_base + MLXBF_TMFIFO_TX_DATA);
 
        /* Use spin-lock to protect the 'cons->tx_buf'. */
-       spin_lock_irqsave(&fifo->spin_lock, flags);
+       spin_lock_irqsave(&fifo->spin_lock[0], flags);
 
        while (size > 0) {
                addr = cons->tx_buf.buf + cons->tx_buf.tail;
@@ -552,7 +552,7 @@ static void mlxbf_tmfifo_console_tx(struct mlxbf_tmfifo *fifo, int avail)
                }
        }
 
-       spin_unlock_irqrestore(&fifo->spin_lock, flags);
+       spin_unlock_irqrestore(&fifo->spin_lock[0], flags);
 }
 
 /* Rx/Tx one word in the descriptor buffer. */
@@ -731,9 +731,9 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
                fifo->vring[is_rx] = NULL;
 
                /* Notify upper layer that packet is done. */
-               spin_lock_irqsave(&fifo->spin_lock, flags);
+               spin_lock_irqsave(&fifo->spin_lock[is_rx], flags);
                vring_interrupt(0, vring->vq);
-               spin_unlock_irqrestore(&fifo->spin_lock, flags);
+               spin_unlock_irqrestore(&fifo->spin_lock[is_rx], flags);
        }
 
 mlxbf_tmfifo_desc_done:
@@ -852,10 +852,10 @@ static bool mlxbf_tmfifo_virtio_notify(struct virtqueue *vq)
                 * worker handler.
                 */
                if (vring->vdev_id == VIRTIO_ID_CONSOLE) {
-                       spin_lock_irqsave(&fifo->spin_lock, flags);
+                       spin_lock_irqsave(&fifo->spin_lock[0], flags);
                        tm_vdev = fifo->vdev[VIRTIO_ID_CONSOLE];
                        mlxbf_tmfifo_console_output(tm_vdev, vring);
-                       spin_unlock_irqrestore(&fifo->spin_lock, flags);
+                       spin_unlock_irqrestore(&fifo->spin_lock[0], flags);
                } else if (test_and_set_bit(MLXBF_TM_TX_LWM_IRQ,
                                            &fifo->pend_events)) {
                        return true;
@@ -1189,7 +1189,8 @@ static int mlxbf_tmfifo_probe(struct platform_device *pdev)
        if (!fifo)
                return -ENOMEM;
 
-       spin_lock_init(&fifo->spin_lock);
+       spin_lock_init(&fifo->spin_lock[0]);
+       spin_lock_init(&fifo->spin_lock[1]);
        INIT_WORK(&fifo->work, mlxbf_tmfifo_work_handler);
        mutex_init(&fifo->lock);
 
index f4d0a86..5e77b0d 100644 (file)
@@ -18,7 +18,7 @@ if MIPS_PLATFORM_DEVICES
 
 config CPU_HWMON
        tristate "Loongson-3 CPU HWMon Driver"
-       depends on CONFIG_MACH_LOONGSON64
+       depends on MACH_LOONGSON64
        select HWMON
        default y
        help
index 821b08e..982f0cc 100644 (file)
@@ -512,13 +512,7 @@ static void kbd_led_update(struct asus_wmi *asus)
 {
        int ctrl_param = 0;
 
-       /*
-        * bits 0-2: level
-        * bit 7: light on/off
-        */
-       if (asus->kbd_led_wk > 0)
-               ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
-
+       ctrl_param = 0x80 | (asus->kbd_led_wk & 0x7F);
        asus_wmi_set_devstate(ASUS_WMI_DEVID_KBD_BACKLIGHT, ctrl_param, NULL);
 }
 
index be85ed9..b471b86 100644 (file)
 
 #define MAX_SPEED 3
 
-static int temp_limits[3] = { 55000, 60000, 65000 };
+#define TEMP_LIMIT0_DEFAULT    55000
+#define TEMP_LIMIT1_DEFAULT    60000
+#define TEMP_LIMIT2_DEFAULT    65000
+
+#define HYSTERESIS_DEFAULT     3000
+
+#define SPEED_ON_AC_DEFAULT    2
+
+static int temp_limits[3] = {
+       TEMP_LIMIT0_DEFAULT, TEMP_LIMIT1_DEFAULT, TEMP_LIMIT2_DEFAULT,
+};
 module_param_array(temp_limits, int, NULL, 0444);
 MODULE_PARM_DESC(temp_limits,
                 "Millicelsius values above which the fan speed increases");
 
-static int hysteresis = 3000;
+static int hysteresis = HYSTERESIS_DEFAULT;
 module_param(hysteresis, int, 0444);
 MODULE_PARM_DESC(hysteresis,
                 "Hysteresis in millicelsius before lowering the fan speed");
 
-static int speed_on_ac = 2;
+static int speed_on_ac = SPEED_ON_AC_DEFAULT;
 module_param(speed_on_ac, int, 0444);
 MODULE_PARM_DESC(speed_on_ac,
                 "minimum fan speed to allow when system is powered by AC");
@@ -117,21 +127,24 @@ static int gpd_pocket_fan_probe(struct platform_device *pdev)
        int i;
 
        for (i = 0; i < ARRAY_SIZE(temp_limits); i++) {
-               if (temp_limits[i] < 40000 || temp_limits[i] > 70000) {
+               if (temp_limits[i] < 20000 || temp_limits[i] > 90000) {
                        dev_err(&pdev->dev, "Invalid temp-limit %d (must be between 40000 and 70000)\n",
                                temp_limits[i]);
-                       return -EINVAL;
+                       temp_limits[0] = TEMP_LIMIT0_DEFAULT;
+                       temp_limits[1] = TEMP_LIMIT1_DEFAULT;
+                       temp_limits[2] = TEMP_LIMIT2_DEFAULT;
+                       break;
                }
        }
        if (hysteresis < 1000 || hysteresis > 10000) {
                dev_err(&pdev->dev, "Invalid hysteresis %d (must be between 1000 and 10000)\n",
                        hysteresis);
-               return -EINVAL;
+               hysteresis = HYSTERESIS_DEFAULT;
        }
        if (speed_on_ac < 0 || speed_on_ac > MAX_SPEED) {
                dev_err(&pdev->dev, "Invalid speed_on_ac %d (must be between 0 and 3)\n",
                        speed_on_ac);
-               return -EINVAL;
+               speed_on_ac = SPEED_ON_AC_DEFAULT;
        }
 
        fan = devm_kzalloc(&pdev->dev, sizeof(*fan), GFP_KERNEL);
index 9579a70..a881b70 100644 (file)
@@ -300,7 +300,7 @@ static int __init hp_wmi_bios_2008_later(void)
 
 static int __init hp_wmi_bios_2009_later(void)
 {
-       int state = 0;
+       u8 state[128];
        int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state,
                                       sizeof(state), sizeof(state));
        if (!ret)
index 512ad23..35ed971 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (c) 2010 Intel Corporation
  */
index fdee577..8203ae3 100644 (file)
@@ -1,4 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Intel Core SoC Power Management Controller Header File
  *
index 6fe829f..e1266f5 100644 (file)
@@ -44,6 +44,8 @@ static const struct x86_cpu_id intel_pmc_core_platform_ids[] = {
        INTEL_CPU_FAM6(KABYLAKE, pmc_core_device),
        INTEL_CPU_FAM6(CANNONLAKE_L, pmc_core_device),
        INTEL_CPU_FAM6(ICELAKE_L, pmc_core_device),
+       INTEL_CPU_FAM6(COMETLAKE, pmc_core_device),
+       INTEL_CPU_FAM6(COMETLAKE_L, pmc_core_device),
        {}
 };
 MODULE_DEVICE_TABLE(x86cpu, intel_pmc_core_platform_ids);
index 48b112b..9b11ef1 100644 (file)
@@ -2,7 +2,7 @@
 
 /*
  * PC-Engines APUv2/APUv3 board platform driver
- * for gpio buttons and LEDs
+ * for GPIO buttons and LEDs
  *
  * Copyright (C) 2018 metux IT consult
  * Author: Enrico Weigelt <info@metux.net>
 
 /*
  * NOTE: this driver only supports APUv2/3 - not APUv1, as this one
- * has completely different register layouts
+ * has completely different register layouts.
  */
 
-/* register mappings */
+/* Register mappings */
 #define APU2_GPIO_REG_LED1             AMD_FCH_GPIO_REG_GPIO57
 #define APU2_GPIO_REG_LED2             AMD_FCH_GPIO_REG_GPIO58
 #define APU2_GPIO_REG_LED3             AMD_FCH_GPIO_REG_GPIO59_DEVSLP1
@@ -35,7 +35,7 @@
 #define APU2_GPIO_REG_MPCIE2           AMD_FCH_GPIO_REG_GPIO59_DEVSLP0
 #define APU2_GPIO_REG_MPCIE3           AMD_FCH_GPIO_REG_GPIO51
 
-/* order in which the gpio lines are defined in the register list */
+/* Order in which the GPIO lines are defined in the register list */
 #define APU2_GPIO_LINE_LED1            0
 #define APU2_GPIO_LINE_LED2            1
 #define APU2_GPIO_LINE_LED3            2
@@ -44,7 +44,7 @@
 #define APU2_GPIO_LINE_MPCIE2          5
 #define APU2_GPIO_LINE_MPCIE3          6
 
-/* gpio device */
+/* GPIO device */
 
 static int apu2_gpio_regs[] = {
        [APU2_GPIO_LINE_LED1]           = APU2_GPIO_REG_LED1,
@@ -72,7 +72,7 @@ static const struct amd_fch_gpio_pdata board_apu2 = {
        .gpio_names     = apu2_gpio_names,
 };
 
-/* gpio leds device */
+/* GPIO LEDs device */
 
 static const struct gpio_led apu2_leds[] = {
        { .name = "apu:green:1" },
@@ -95,12 +95,12 @@ static struct gpiod_lookup_table gpios_led_table = {
                                NULL, 1, GPIO_ACTIVE_LOW),
                GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_LED3,
                                NULL, 2, GPIO_ACTIVE_LOW),
-               GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_REG_SIMSWAP,
+               GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_SIMSWAP,
                                NULL, 3, GPIO_ACTIVE_LOW),
        }
 };
 
-/* gpio keyboard device */
+/* GPIO keyboard device */
 
 static struct gpio_keys_button apu2_keys_buttons[] = {
        {
@@ -129,12 +129,12 @@ static struct gpiod_lookup_table gpios_key_table = {
        }
 };
 
-/* board setup */
+/* Board setup */
 
-/* note: matching works on string prefix, so "apu2" must come before "apu" */
+/* Note: matching works on string prefix, so "apu2" must come before "apu" */
 static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
 
-       /* APU2 w/ legacy bios < 4.0.8 */
+       /* APU2 w/ legacy BIOS < 4.0.8 */
        {
                .ident          = "apu2",
                .matches        = {
@@ -143,7 +143,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data    = (void *)&board_apu2,
        },
-       /* APU2 w/ legacy bios >= 4.0.8 */
+       /* APU2 w/ legacy BIOS >= 4.0.8 */
        {
                .ident          = "apu2",
                .matches        = {
@@ -152,7 +152,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data    = (void *)&board_apu2,
        },
-       /* APU2 w/ maainline bios */
+       /* APU2 w/ mainline BIOS */
        {
                .ident          = "apu2",
                .matches        = {
@@ -162,7 +162,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                .driver_data    = (void *)&board_apu2,
        },
 
-       /* APU3 w/ legacy bios < 4.0.8 */
+       /* APU3 w/ legacy BIOS < 4.0.8 */
        {
                .ident          = "apu3",
                .matches        = {
@@ -171,7 +171,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data = (void *)&board_apu2,
        },
-       /* APU3 w/ legacy bios >= 4.0.8 */
+       /* APU3 w/ legacy BIOS >= 4.0.8 */
        {
                .ident       = "apu3",
                .matches     = {
@@ -180,7 +180,7 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data = (void *)&board_apu2,
        },
-       /* APU3 w/ mainline bios */
+       /* APU3 w/ mainline BIOS */
        {
                .ident       = "apu3",
                .matches     = {
@@ -189,6 +189,33 @@ static const struct dmi_system_id apu_gpio_dmi_table[] __initconst = {
                },
                .driver_data = (void *)&board_apu2,
        },
+       /* APU4 w/ legacy BIOS < 4.0.8 */
+       {
+               .ident        = "apu4",
+               .matches    = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
+                       DMI_MATCH(DMI_BOARD_NAME, "APU4")
+               },
+               .driver_data = (void *)&board_apu2,
+       },
+       /* APU4 w/ legacy BIOS >= 4.0.8 */
+       {
+               .ident       = "apu4",
+               .matches     = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
+                       DMI_MATCH(DMI_BOARD_NAME, "apu4")
+               },
+               .driver_data = (void *)&board_apu2,
+       },
+       /* APU4 w/ mainline BIOS */
+       {
+               .ident       = "apu4",
+               .matches     = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "PC Engines"),
+                       DMI_MATCH(DMI_BOARD_NAME, "PC Engines apu4")
+               },
+               .driver_data = (void *)&board_apu2,
+       },
        {}
 };
 
@@ -223,7 +250,7 @@ static int __init apu_board_init(void)
 
        id = dmi_first_match(apu_gpio_dmi_table);
        if (!id) {
-               pr_err("failed to detect apu board via dmi\n");
+               pr_err("failed to detect APU board via DMI\n");
                return -ENODEV;
        }
 
@@ -262,7 +289,7 @@ module_init(apu_board_init);
 module_exit(apu_board_exit);
 
 MODULE_AUTHOR("Enrico Weigelt, metux IT consult <info@metux.net>");
-MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LED/keys driver");
+MODULE_DESCRIPTION("PC Engines APUv2/APUv3 board GPIO/LEDs/keys driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(dmi, apu_gpio_dmi_table);
 MODULE_ALIAS("platform:pcengines-apuv2");
index 07d1b91..52ef141 100644 (file)
@@ -429,6 +429,14 @@ static const struct dmi_system_id critclk_systems[] = {
                        DMI_MATCH(DMI_PRODUCT_VERSION, "6AV7882-0"),
                },
        },
+       {
+               .ident = "CONNECT X300",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "SIEMENS AG"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "A5E45074588"),
+               },
+       },
+
        { /*sentinel*/ }
 };
 
index a67701e..2e5b6a6 100644 (file)
@@ -1295,6 +1295,9 @@ struct rapl_package *rapl_add_package(int cpu, struct rapl_if_priv *priv)
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        int ret;
 
+       if (!rapl_defaults)
+               return ERR_PTR(-ENODEV);
+
        rp = kzalloc(sizeof(struct rapl_package), GFP_KERNEL);
        if (!rp)
                return ERR_PTR(-ENOMEM);
index b45d2b8..b0d1b8d 100644 (file)
@@ -121,7 +121,7 @@ config PTP_1588_CLOCK_KVM
 
 config PTP_1588_CLOCK_IDTCM
        tristate "IDT CLOCKMATRIX as PTP clock"
-       depends on PTP_1588_CLOCK
+       depends on PTP_1588_CLOCK && I2C
        default n
        help
          This driver adds support for using IDT CLOCKMATRIX(TM) as a PTP
index e60eab7..b84f16b 100644 (file)
@@ -166,10 +166,11 @@ static struct posix_clock_operations ptp_clock_ops = {
        .read           = ptp_read,
 };
 
-static void delete_ptp_clock(struct posix_clock *pc)
+static void ptp_clock_release(struct device *dev)
 {
-       struct ptp_clock *ptp = container_of(pc, struct ptp_clock, clock);
+       struct ptp_clock *ptp = container_of(dev, struct ptp_clock, dev);
 
+       ptp_cleanup_pin_groups(ptp);
        mutex_destroy(&ptp->tsevq_mux);
        mutex_destroy(&ptp->pincfg_mux);
        ida_simple_remove(&ptp_clocks_map, ptp->index);
@@ -213,7 +214,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
        }
 
        ptp->clock.ops = ptp_clock_ops;
-       ptp->clock.release = delete_ptp_clock;
        ptp->info = info;
        ptp->devid = MKDEV(major, index);
        ptp->index = index;
@@ -236,15 +236,6 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
        if (err)
                goto no_pin_groups;
 
-       /* Create a new device in our class. */
-       ptp->dev = device_create_with_groups(ptp_class, parent, ptp->devid,
-                                            ptp, ptp->pin_attr_groups,
-                                            "ptp%d", ptp->index);
-       if (IS_ERR(ptp->dev)) {
-               err = PTR_ERR(ptp->dev);
-               goto no_device;
-       }
-
        /* Register a new PPS source. */
        if (info->pps) {
                struct pps_source_info pps;
@@ -260,8 +251,18 @@ struct ptp_clock *ptp_clock_register(struct ptp_clock_info *info,
                }
        }
 
-       /* Create a posix clock. */
-       err = posix_clock_register(&ptp->clock, ptp->devid);
+       /* Initialize a new device of our class in our clock structure. */
+       device_initialize(&ptp->dev);
+       ptp->dev.devt = ptp->devid;
+       ptp->dev.class = ptp_class;
+       ptp->dev.parent = parent;
+       ptp->dev.groups = ptp->pin_attr_groups;
+       ptp->dev.release = ptp_clock_release;
+       dev_set_drvdata(&ptp->dev, ptp);
+       dev_set_name(&ptp->dev, "ptp%d", ptp->index);
+
+       /* Create a posix clock and link it to the device. */
+       err = posix_clock_register(&ptp->clock, &ptp->dev);
        if (err) {
                pr_err("failed to create posix clock\n");
                goto no_clock;
@@ -273,8 +274,6 @@ no_clock:
        if (ptp->pps_source)
                pps_unregister_source(ptp->pps_source);
 no_pps:
-       device_destroy(ptp_class, ptp->devid);
-no_device:
        ptp_cleanup_pin_groups(ptp);
 no_pin_groups:
        if (ptp->kworker)
@@ -304,10 +303,8 @@ int ptp_clock_unregister(struct ptp_clock *ptp)
        if (ptp->pps_source)
                pps_unregister_source(ptp->pps_source);
 
-       device_destroy(ptp_class, ptp->devid);
-       ptp_cleanup_pin_groups(ptp);
-
        posix_clock_unregister(&ptp->clock);
+
        return 0;
 }
 EXPORT_SYMBOL(ptp_clock_unregister);
index 9171d42..6b97155 100644 (file)
@@ -28,7 +28,7 @@ struct timestamp_event_queue {
 
 struct ptp_clock {
        struct posix_clock clock;
-       struct device *dev;
+       struct device dev;
        struct ptp_clock_info *info;
        dev_t devid;
        int index; /* index into clocks.map */
index 989506b..16f0c85 100644 (file)
@@ -413,10 +413,13 @@ static int axp20x_set_ramp_delay(struct regulator_dev *rdev, int ramp)
                int i;
 
                for (i = 0; i < rate_count; i++) {
-                       if (ramp <= slew_rates[i])
-                               cfg = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(i);
-                       else
+                       if (ramp > slew_rates[i])
                                break;
+
+                       if (id == AXP20X_DCDC2)
+                               cfg = AXP20X_DCDC2_LDO3_V_RAMP_DCDC2_RATE(i);
+                       else
+                               cfg = AXP20X_DCDC2_LDO3_V_RAMP_LDO3_RATE(i);
                }
 
                if (cfg == 0xff) {
@@ -605,7 +608,7 @@ static const struct regulator_desc axp22x_regulators[] = {
                 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
        AXP_DESC(AXP22X, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
                 AXP22X_ELDO2_V_OUT, AXP22X_ELDO2_V_OUT_MASK,
-                AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO1_MASK),
+                AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO2_MASK),
        AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
                 AXP22X_ELDO3_V_OUT, AXP22X_ELDO3_V_OUT_MASK,
                 AXP22X_PWR_OUT_CTRL2, AXP22X_PWR_OUT_ELDO3_MASK),
index ec76402..5bf8a2d 100644 (file)
@@ -101,7 +101,6 @@ static const struct regulator_ops bd70528_ldo_ops = {
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_time_sel = regulator_set_voltage_time_sel,
-       .set_ramp_delay = bd70528_set_ramp_delay,
 };
 
 static const struct regulator_ops bd70528_led_ops = {
index 679ad3d..03d79fe 100644 (file)
@@ -1198,6 +1198,10 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
                        return -EINVAL;
                }
 
+               /* no need to loop voltages if range is continuous */
+               if (rdev->desc->continuous_voltage_range)
+                       return 0;
+
                /* initial: [cmin..cmax] valid, [min_uV..max_uV] not */
                for (i = 0; i < count; i++) {
                        int     value;
@@ -1938,8 +1942,8 @@ struct regulator *_regulator_get(struct device *dev, const char *id,
        regulator = create_regulator(rdev, dev, id);
        if (regulator == NULL) {
                regulator = ERR_PTR(-ENOMEM);
-               put_device(&rdev->dev);
                module_put(rdev->owner);
+               put_device(&rdev->dev);
                return regulator;
        }
 
@@ -2063,13 +2067,13 @@ static void _regulator_put(struct regulator *regulator)
 
        rdev->open_count--;
        rdev->exclusive = 0;
-       put_device(&rdev->dev);
        regulator_unlock(rdev);
 
        kfree_const(regulator->supply_name);
        kfree(regulator);
 
        module_put(rdev->owner);
+       put_device(&rdev->dev);
 }
 
 /**
@@ -5002,6 +5006,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
        struct regulator_dev *rdev;
        bool dangling_cfg_gpiod = false;
        bool dangling_of_gpiod = false;
+       bool reg_device_fail = false;
        struct device *dev;
        int ret, i;
 
@@ -5187,7 +5192,7 @@ regulator_register(const struct regulator_desc *regulator_desc,
        dev_set_drvdata(&rdev->dev, rdev);
        ret = device_register(&rdev->dev);
        if (ret != 0) {
-               put_device(&rdev->dev);
+               reg_device_fail = true;
                goto unset_supplies;
        }
 
@@ -5218,7 +5223,10 @@ wash:
 clean:
        if (dangling_of_gpiod)
                gpiod_put(config->ena_gpiod);
-       kfree(rdev);
+       if (reg_device_fail)
+               put_device(&rdev->dev);
+       else
+               kfree(rdev);
        kfree(config);
 rinse:
        if (dangling_cfg_gpiod)
index e57fc91..ac89a41 100644 (file)
@@ -386,9 +386,16 @@ static int max77650_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id max77650_regulator_of_match[] = {
+       { .compatible = "maxim,max77650-regulator" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, max77650_regulator_of_match);
+
 static struct platform_driver max77650_regulator_driver = {
        .driver = {
                .name = "max77650-regulator",
+               .of_match_table = max77650_regulator_of_match,
        },
        .probe = max77650_regulator_probe,
 };
index 4a91be0..5c12d57 100644 (file)
@@ -148,6 +148,7 @@ static struct platform_driver rn5t618_regulator_driver = {
 
 module_platform_driver(rn5t618_regulator_driver);
 
+MODULE_ALIAS("platform:rn5t618-regulator");
 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
 MODULE_DESCRIPTION("RN5T618 regulator driver");
 MODULE_LICENSE("GPL v2");
index bdc0773..12d6b8d 100644 (file)
@@ -588,7 +588,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
                if (of_property_read_u32(reg_np, "op_mode",
                                &rmode->mode)) {
                        dev_warn(iodev->dev,
-                               "no op_mode property property at %pOF\n",
+                               "no op_mode property at %pOF\n",
                                reg_np);
 
                        rmode->mode = S5M8767_OPMODE_NORMAL_MODE;
index ca1d491..7597c70 100644 (file)
@@ -787,7 +787,7 @@ struct reset_control *__devm_reset_control_get(struct device *dev,
                return ERR_PTR(-ENOMEM);
 
        rstc = __reset_control_get(dev, id, index, shared, optional, acquired);
-       if (!IS_ERR(rstc)) {
+       if (!IS_ERR_OR_NULL(rstc)) {
                *ptr = rstc;
                devres_add(dev, ptr);
        } else {
@@ -861,8 +861,7 @@ static int of_reset_control_get_count(struct device_node *node)
  * @acquired: only one reset control may be acquired for a given controller
  *            and ID
  *
- * Returns pointer to allocated reset_control_array on success or
- * error on failure
+ * Returns pointer to allocated reset_control on success or error on failure
  */
 struct reset_control *
 of_reset_control_array_get(struct device_node *np, bool shared, bool optional,
@@ -915,8 +914,7 @@ EXPORT_SYMBOL_GPL(of_reset_control_array_get);
  * that just have to be asserted or deasserted, without any
  * requirements on the order.
  *
- * Returns pointer to allocated reset_control_array on success or
- * error on failure
+ * Returns pointer to allocated reset_control on success or error on failure
  */
 struct reset_control *
 devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
@@ -930,7 +928,7 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
                return ERR_PTR(-ENOMEM);
 
        rstc = of_reset_control_array_get(dev->of_node, shared, optional, true);
-       if (IS_ERR(rstc)) {
+       if (IS_ERR_OR_NULL(rstc)) {
                devres_free(devres);
                return rstc;
        }
index a608f44..f213264 100644 (file)
@@ -91,12 +91,6 @@ static int brcmstb_reset_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!IS_ALIGNED(res->start, SW_INIT_BANK_SIZE) ||
-           !IS_ALIGNED(resource_size(res), SW_INIT_BANK_SIZE)) {
-               dev_err(kdev, "incorrect register range\n");
-               return -EINVAL;
-       }
-
        priv->base = devm_ioremap_resource(kdev, res);
        if (IS_ERR(priv->base))
                return PTR_ERR(priv->base);
index df2829d..2ecd875 100644 (file)
@@ -172,20 +172,7 @@ int mc146818_set_time(struct rtc_time *time)
        save_control = CMOS_READ(RTC_CONTROL);
        CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL);
        save_freq_select = CMOS_READ(RTC_FREQ_SELECT);
-
-#ifdef CONFIG_X86
-       if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
-            boot_cpu_data.x86 == 0x17) ||
-            boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
-               CMOS_WRITE((save_freq_select & (~RTC_DIV_RESET2)),
-                       RTC_FREQ_SELECT);
-               save_freq_select &= ~RTC_DIV_RESET2;
-       } else
-               CMOS_WRITE((save_freq_select | RTC_DIV_RESET2),
-                       RTC_FREQ_SELECT);
-#else
-       CMOS_WRITE((save_freq_select | RTC_DIV_RESET2), RTC_FREQ_SELECT);
-#endif
+       CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT);
 
 #ifdef CONFIG_MACH_DECSTATION
        CMOS_WRITE(real_yrs, RTC_DEC_YEAR);
index 5249fc9..9135e21 100644 (file)
@@ -47,7 +47,7 @@ static irqreturn_t mtk_rtc_irq_handler_thread(int irq, void *data)
                irqen = irqsta & ~RTC_IRQ_EN_AL;
                mutex_lock(&rtc->lock);
                if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN,
-                                irqen) < 0)
+                                irqen) == 0)
                        mtk_rtc_write_trigger(rtc);
                mutex_unlock(&rtc->lock);
 
@@ -169,12 +169,12 @@ static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
        alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM);
        mutex_unlock(&rtc->lock);
 
-       tm->tm_sec = data[RTC_OFFSET_SEC];
-       tm->tm_min = data[RTC_OFFSET_MIN];
-       tm->tm_hour = data[RTC_OFFSET_HOUR];
-       tm->tm_mday = data[RTC_OFFSET_DOM];
-       tm->tm_mon = data[RTC_OFFSET_MTH];
-       tm->tm_year = data[RTC_OFFSET_YEAR];
+       tm->tm_sec = data[RTC_OFFSET_SEC] & RTC_AL_SEC_MASK;
+       tm->tm_min = data[RTC_OFFSET_MIN] & RTC_AL_MIN_MASK;
+       tm->tm_hour = data[RTC_OFFSET_HOUR] & RTC_AL_HOU_MASK;
+       tm->tm_mday = data[RTC_OFFSET_DOM] & RTC_AL_DOM_MASK;
+       tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_AL_MTH_MASK;
+       tm->tm_year = data[RTC_OFFSET_YEAR] & RTC_AL_YEA_MASK;
 
        tm->tm_year += RTC_MIN_YEAR_OFFSET;
        tm->tm_mon--;
@@ -195,14 +195,25 @@ static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
        tm->tm_year -= RTC_MIN_YEAR_OFFSET;
        tm->tm_mon++;
 
-       data[RTC_OFFSET_SEC] = tm->tm_sec;
-       data[RTC_OFFSET_MIN] = tm->tm_min;
-       data[RTC_OFFSET_HOUR] = tm->tm_hour;
-       data[RTC_OFFSET_DOM] = tm->tm_mday;
-       data[RTC_OFFSET_MTH] = tm->tm_mon;
-       data[RTC_OFFSET_YEAR] = tm->tm_year;
-
        mutex_lock(&rtc->lock);
+       ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC,
+                              data, RTC_OFFSET_COUNT);
+       if (ret < 0)
+               goto exit;
+
+       data[RTC_OFFSET_SEC] = ((data[RTC_OFFSET_SEC] & ~(RTC_AL_SEC_MASK)) |
+                               (tm->tm_sec & RTC_AL_SEC_MASK));
+       data[RTC_OFFSET_MIN] = ((data[RTC_OFFSET_MIN] & ~(RTC_AL_MIN_MASK)) |
+                               (tm->tm_min & RTC_AL_MIN_MASK));
+       data[RTC_OFFSET_HOUR] = ((data[RTC_OFFSET_HOUR] & ~(RTC_AL_HOU_MASK)) |
+                               (tm->tm_hour & RTC_AL_HOU_MASK));
+       data[RTC_OFFSET_DOM] = ((data[RTC_OFFSET_DOM] & ~(RTC_AL_DOM_MASK)) |
+                               (tm->tm_mday & RTC_AL_DOM_MASK));
+       data[RTC_OFFSET_MTH] = ((data[RTC_OFFSET_MTH] & ~(RTC_AL_MTH_MASK)) |
+                               (tm->tm_mon & RTC_AL_MTH_MASK));
+       data[RTC_OFFSET_YEAR] = ((data[RTC_OFFSET_YEAR] & ~(RTC_AL_YEA_MASK)) |
+                               (tm->tm_year & RTC_AL_YEA_MASK));
+
        if (alm->enabled) {
                ret = regmap_bulk_write(rtc->regmap,
                                        rtc->addr_base + RTC_AL_SEC,
index 8dcd20b..852f5f3 100644 (file)
@@ -379,6 +379,22 @@ static void __init sun50i_h6_rtc_clk_init(struct device_node *node)
 CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc",
                      sun50i_h6_rtc_clk_init);
 
+/*
+ * The R40 user manual is self-conflicting on whether the prescaler is
+ * fixed or configurable. The clock diagram shows it as fixed, but there
+ * is also a configurable divider in the RTC block.
+ */
+static const struct sun6i_rtc_clk_data sun8i_r40_rtc_data = {
+       .rc_osc_rate = 16000000,
+       .fixed_prescaler = 512,
+};
+static void __init sun8i_r40_rtc_clk_init(struct device_node *node)
+{
+       sun6i_rtc_clk_init(node, &sun8i_r40_rtc_data);
+}
+CLK_OF_DECLARE_DRIVER(sun8i_r40_rtc_clk, "allwinner,sun8i-r40-rtc",
+                     sun8i_r40_rtc_clk_init);
+
 static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = {
        .rc_osc_rate = 32000,
        .has_out_clk = 1,
index c94184d..a28b9ff 100644 (file)
@@ -1128,7 +1128,8 @@ static u32 get_fcx_max_data(struct dasd_device *device)
 {
        struct dasd_eckd_private *private = device->private;
        int fcx_in_css, fcx_in_gneq, fcx_in_features;
-       int tpm, mdc;
+       unsigned int mdc;
+       int tpm;
 
        if (dasd_nofcx)
                return 0;
@@ -1142,7 +1143,7 @@ static u32 get_fcx_max_data(struct dasd_device *device)
                return 0;
 
        mdc = ccw_device_get_mdc(device->cdev, 0);
-       if (mdc < 0) {
+       if (mdc == 0) {
                dev_warn(&device->cdev->dev, "Detecting the maximum supported data size for zHPF requests failed\n");
                return 0;
        } else {
@@ -1153,12 +1154,12 @@ static u32 get_fcx_max_data(struct dasd_device *device)
 static int verify_fcx_max_data(struct dasd_device *device, __u8 lpm)
 {
        struct dasd_eckd_private *private = device->private;
-       int mdc;
+       unsigned int mdc;
        u32 fcx_max_data;
 
        if (private->fcx_max_data) {
                mdc = ccw_device_get_mdc(device->cdev, lpm);
-               if ((mdc < 0)) {
+               if (mdc == 0) {
                        dev_warn(&device->cdev->dev,
                                 "Detecting the maximum data size for zHPF "
                                 "requests failed (rc=%d) for a new path %x\n",
@@ -2073,7 +2074,7 @@ out_err2:
        dasd_free_block(device->block);
        device->block = NULL;
 out_err1:
-       kfree(private->conf_data);
+       dasd_eckd_clear_conf_data(device);
        kfree(device->private);
        device->private = NULL;
        return rc;
@@ -2082,7 +2083,6 @@ out_err1:
 static void dasd_eckd_uncheck_device(struct dasd_device *device)
 {
        struct dasd_eckd_private *private = device->private;
-       int i;
 
        if (!private)
                return;
@@ -2092,21 +2092,7 @@ static void dasd_eckd_uncheck_device(struct dasd_device *device)
        private->sneq = NULL;
        private->vdsneq = NULL;
        private->gneq = NULL;
-       private->conf_len = 0;
-       for (i = 0; i < 8; i++) {
-               kfree(device->path[i].conf_data);
-               if ((__u8 *)device->path[i].conf_data ==
-                   private->conf_data) {
-                       private->conf_data = NULL;
-                       private->conf_len = 0;
-               }
-               device->path[i].conf_data = NULL;
-               device->path[i].cssid = 0;
-               device->path[i].ssid = 0;
-               device->path[i].chpid = 0;
-       }
-       kfree(private->conf_data);
-       private->conf_data = NULL;
+       dasd_eckd_clear_conf_data(device);
 }
 
 static struct dasd_ccw_req *
index 8f75df0..45ddabe 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * Coypright IBM Corp. 1999, 2000
+ * Copyright IBM Corp. 1999, 2000
  *
  */
 
index 1770b99..8d4d69e 100644 (file)
@@ -5,7 +5,7 @@
  *                 Carsten Otte <Cotte@de.ibm.com>
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * Coypright IBM Corp. 1999, 2002
+ * Copyright IBM Corp. 1999, 2002
  *
  * /proc interface for the dasd driver.
  *
index 65841af..ccecf6b 100644 (file)
@@ -635,7 +635,7 @@ EXPORT_SYMBOL(ccw_device_tm_start_timeout);
  * @mask: mask of paths to use
  *
  * Return the number of 64K-bytes blocks all paths at least support
- * for a transport command. Return values <= 0 indicate failures.
+ * for a transport command. Return value 0 indicates failure.
  */
 int ccw_device_get_mdc(struct ccw_device *cdev, u8 mask)
 {
index a191506..5256e3c 100644 (file)
@@ -793,8 +793,6 @@ static int ap_device_probe(struct device *dev)
                drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;
                if (!!devres != !!drvres)
                        return -ENODEV;
-               /* (re-)init queue's state machine */
-               ap_queue_reinit_state(to_ap_queue(dev));
        }
 
        /* Add queue/card to list of active queues/cards */
index 433b7b6..bb35ba4 100644 (file)
@@ -261,7 +261,7 @@ void ap_queue_prepare_remove(struct ap_queue *aq);
 void ap_queue_remove(struct ap_queue *aq);
 void ap_queue_suspend(struct ap_device *ap_dev);
 void ap_queue_resume(struct ap_device *ap_dev);
-void ap_queue_reinit_state(struct ap_queue *aq);
+void ap_queue_init_state(struct ap_queue *aq);
 
 struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,
                               int comp_device_type, unsigned int functions);
index dad2be3..37c3bdc 100644 (file)
@@ -638,7 +638,7 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type)
        aq->ap_dev.device.type = &ap_queue_type;
        aq->ap_dev.device_type = device_type;
        aq->qid = qid;
-       aq->state = AP_STATE_RESET_START;
+       aq->state = AP_STATE_UNBOUND;
        aq->interrupt = AP_INTR_DISABLED;
        spin_lock_init(&aq->lock);
        INIT_LIST_HEAD(&aq->list);
@@ -771,10 +771,11 @@ void ap_queue_remove(struct ap_queue *aq)
        spin_unlock_bh(&aq->lock);
 }
 
-void ap_queue_reinit_state(struct ap_queue *aq)
+void ap_queue_init_state(struct ap_queue *aq)
 {
        spin_lock_bh(&aq->lock);
        aq->state = AP_STATE_RESET_START;
        ap_wait(ap_sm_event(aq, AP_EVENT_POLL));
        spin_unlock_bh(&aq->lock);
 }
+EXPORT_SYMBOL(ap_queue_init_state);
index c1db64a..110fe9d 100644 (file)
@@ -1037,8 +1037,8 @@ static int _ip_cprb_helper(u16 cardnr, u16 domain,
        prepparm = (struct iprepparm *) prepcblk->rpl_parmb;
 
        /* do some plausibility checks on the key block */
-       if (prepparm->kb.len < 120 + 5 * sizeof(uint16_t) ||
-           prepparm->kb.len > 136 + 5 * sizeof(uint16_t)) {
+       if (prepparm->kb.len < 120 + 3 * sizeof(uint16_t) ||
+           prepparm->kb.len > 136 + 3 * sizeof(uint16_t)) {
                DEBUG_ERR("%s reply with invalid or unknown key block\n",
                          __func__);
                rc = -EIO;
index c50f3e8..7cbb384 100644 (file)
@@ -175,6 +175,7 @@ static int zcrypt_cex2a_queue_probe(struct ap_device *ap_dev)
        zq->queue = aq;
        zq->online = 1;
        atomic_set(&zq->load, 0);
+       ap_queue_init_state(aq);
        ap_queue_init_reply(aq, &zq->reply);
        aq->request_timeout = CEX2A_CLEANUP_TIME,
        aq->private = zq;
index 35c7c66..c78c0d1 100644 (file)
@@ -220,6 +220,7 @@ static int zcrypt_cex2c_queue_probe(struct ap_device *ap_dev)
        zq->queue = aq;
        zq->online = 1;
        atomic_set(&zq->load, 0);
+       ap_rapq(aq->qid);
        rc = zcrypt_cex2c_rng_supported(aq);
        if (rc < 0) {
                zcrypt_queue_free(zq);
@@ -231,6 +232,7 @@ static int zcrypt_cex2c_queue_probe(struct ap_device *ap_dev)
        else
                zq->ops = zcrypt_msgtype(MSGTYPE06_NAME,
                                         MSGTYPE06_VARIANT_NORNG);
+       ap_queue_init_state(aq);
        ap_queue_init_reply(aq, &zq->reply);
        aq->request_timeout = CEX2C_CLEANUP_TIME;
        aq->private = zq;
index 442e3d6..6fabc90 100644 (file)
@@ -381,6 +381,7 @@ static int zcrypt_cex4_queue_probe(struct ap_device *ap_dev)
        zq->queue = aq;
        zq->online = 1;
        atomic_set(&zq->load, 0);
+       ap_queue_init_state(aq);
        ap_queue_init_reply(aq, &zq->reply);
        aq->request_timeout = CEX4_CLEANUP_TIME,
        aq->private = zq;
index b9a2349..29facb9 100644 (file)
@@ -655,17 +655,17 @@ static int qeth_check_idx_response(struct qeth_card *card,
        unsigned char *buffer)
 {
        QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN);
-       if ((buffer[2] & 0xc0) == 0xc0) {
+       if ((buffer[2] & QETH_IDX_TERMINATE_MASK) == QETH_IDX_TERMINATE) {
                QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#04x\n",
                                 buffer[4]);
                QETH_CARD_TEXT(card, 2, "ckidxres");
                QETH_CARD_TEXT(card, 2, " idxterm");
-               QETH_CARD_TEXT_(card, 2, "  rc%d", -EIO);
-               if (buffer[4] == 0xf6) {
+               QETH_CARD_TEXT_(card, 2, "rc%x", buffer[4]);
+               if (buffer[4] == QETH_IDX_TERM_BAD_TRANSPORT ||
+                   buffer[4] == QETH_IDX_TERM_BAD_TRANSPORT_VM) {
                        dev_err(&card->gdev->dev,
-                       "The qeth device is not configured "
-                       "for the OSI layer required by z/VM\n");
-                       return -EPERM;
+                               "The device does not support the configured transport mode\n");
+                       return -EPROTONOSUPPORT;
                }
                return -EIO;
        }
@@ -742,10 +742,10 @@ static void qeth_issue_next_read_cb(struct qeth_card *card,
        case 0:
                break;
        case -EIO:
-               qeth_clear_ipacmd_list(card);
                qeth_schedule_recovery(card);
                /* fall through */
        default:
+               qeth_clear_ipacmd_list(card);
                goto out;
        }
 
@@ -2482,50 +2482,46 @@ static int qeth_mpc_initialize(struct qeth_card *card)
        rc = qeth_cm_enable(card);
        if (rc) {
                QETH_CARD_TEXT_(card, 2, "2err%d", rc);
-               goto out_qdio;
+               return rc;
        }
        rc = qeth_cm_setup(card);
        if (rc) {
                QETH_CARD_TEXT_(card, 2, "3err%d", rc);
-               goto out_qdio;
+               return rc;
        }
        rc = qeth_ulp_enable(card);
        if (rc) {
                QETH_CARD_TEXT_(card, 2, "4err%d", rc);
-               goto out_qdio;
+               return rc;
        }
        rc = qeth_ulp_setup(card);
        if (rc) {
                QETH_CARD_TEXT_(card, 2, "5err%d", rc);
-               goto out_qdio;
+               return rc;
        }
        rc = qeth_alloc_qdio_queues(card);
        if (rc) {
                QETH_CARD_TEXT_(card, 2, "5err%d", rc);
-               goto out_qdio;
+               return rc;
        }
        rc = qeth_qdio_establish(card);
        if (rc) {
                QETH_CARD_TEXT_(card, 2, "6err%d", rc);
                qeth_free_qdio_queues(card);
-               goto out_qdio;
+               return rc;
        }
        rc = qeth_qdio_activate(card);
        if (rc) {
                QETH_CARD_TEXT_(card, 2, "7err%d", rc);
-               goto out_qdio;
+               return rc;
        }
        rc = qeth_dm_act(card);
        if (rc) {
                QETH_CARD_TEXT_(card, 2, "8err%d", rc);
-               goto out_qdio;
+               return rc;
        }
 
        return 0;
-out_qdio:
-       qeth_qdio_clear_card(card, !IS_IQD(card));
-       qdio_free(CARD_DDEV(card));
-       return rc;
 }
 
 void qeth_print_status_message(struct qeth_card *card)
@@ -3429,11 +3425,6 @@ int qeth_configure_cq(struct qeth_card *card, enum qeth_cq cq)
                        goto out;
                }
 
-               if (card->state != CARD_STATE_DOWN) {
-                       rc = -1;
-                       goto out;
-               }
-
                qeth_free_qdio_queues(card);
                card->options.cq = cq;
                rc = 0;
@@ -4779,7 +4770,7 @@ static int qeth_qdio_establish(struct qeth_card *card)
 
        QETH_CARD_TEXT(card, 2, "qdioest");
 
-       qib_param_field = kzalloc(FIELD_SIZEOF(struct qib, parm), GFP_KERNEL);
+       qib_param_field = kzalloc(sizeof_field(struct qib, parm), GFP_KERNEL);
        if (!qib_param_field) {
                rc =  -ENOMEM;
                goto out_free_nothing;
@@ -5035,10 +5026,8 @@ retriable:
        }
        if (qeth_adp_supported(card, IPA_SETADP_SET_DIAG_ASSIST)) {
                rc = qeth_query_setdiagass(card);
-               if (rc < 0) {
+               if (rc)
                        QETH_CARD_TEXT_(card, 2, "8err%d", rc);
-                       goto out;
-               }
        }
 
        if (!qeth_is_diagass_supported(card, QETH_DIAGS_CMD_TRAP) ||
index 88f4dc1..458db34 100644 (file)
@@ -421,7 +421,7 @@ struct qeth_ipacmd_setassparms {
        } data;
 } __attribute__ ((packed));
 
-#define SETASS_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setassparms,\
+#define SETASS_DATA_SIZEOF(field) sizeof_field(struct qeth_ipacmd_setassparms,\
                                               data.field)
 
 /* SETRTG IPA Command:    ****************************************************/
@@ -535,7 +535,7 @@ struct qeth_ipacmd_setadpparms {
        } data;
 } __attribute__ ((packed));
 
-#define SETADP_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setadpparms,\
+#define SETADP_DATA_SIZEOF(field) sizeof_field(struct qeth_ipacmd_setadpparms,\
                                               data.field)
 
 /* CREATE_ADDR IPA Command:    ***********************************************/
@@ -648,7 +648,7 @@ struct qeth_ipacmd_vnicc {
        } data;
 };
 
-#define VNICC_DATA_SIZEOF(field)       FIELD_SIZEOF(struct qeth_ipacmd_vnicc,\
+#define VNICC_DATA_SIZEOF(field)       sizeof_field(struct qeth_ipacmd_vnicc,\
                                                     data.field)
 
 /* SETBRIDGEPORT IPA Command:   *********************************************/
@@ -729,7 +729,7 @@ struct qeth_ipacmd_setbridgeport {
        } data;
 } __packed;
 
-#define SBP_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipacmd_setbridgeport,\
+#define SBP_DATA_SIZEOF(field) sizeof_field(struct qeth_ipacmd_setbridgeport,\
                                             data.field)
 
 /* ADDRESS_CHANGE_NOTIFICATION adapter-initiated "command" *******************/
@@ -790,7 +790,7 @@ struct qeth_ipa_cmd {
        } data;
 } __attribute__ ((packed));
 
-#define IPA_DATA_SIZEOF(field) FIELD_SIZEOF(struct qeth_ipa_cmd, data.field)
+#define IPA_DATA_SIZEOF(field) sizeof_field(struct qeth_ipa_cmd, data.field)
 
 /*
  * special command for ARP processing.
@@ -899,6 +899,11 @@ extern unsigned char IDX_ACTIVATE_WRITE[];
 #define QETH_IDX_ACT_ERR_AUTH          0x1E
 #define QETH_IDX_ACT_ERR_AUTH_USER     0x20
 
+#define QETH_IDX_TERMINATE             0xc0
+#define QETH_IDX_TERMINATE_MASK                0xc0
+#define QETH_IDX_TERM_BAD_TRANSPORT    0x41
+#define QETH_IDX_TERM_BAD_TRANSPORT_VM 0xf6
+
 #define PDU_ENCAPSULATION(buffer) \
        (buffer + *(buffer + (*(buffer + 0x0b)) + \
         *(buffer + *(buffer + 0x0b) + 0x11) + 0x07))
index e81170a..7bd8602 100644 (file)
@@ -207,7 +207,7 @@ static ssize_t qeth_dev_prioqing_store(struct device *dev,
                card->qdio.default_out_queue = QETH_DEFAULT_QUEUE;
        } else if (sysfs_streq(buf, "prio_queueing_vlan")) {
                if (IS_LAYER3(card)) {
-                       rc = -ENOTSUPP;
+                       rc = -EOPNOTSUPP;
                        goto out;
                }
                card->qdio.do_prio_queueing = QETH_PRIO_Q_ING_VLAN;
index 9086bc0..47d37e7 100644 (file)
@@ -287,14 +287,15 @@ static void qeth_l2_stop_card(struct qeth_card *card)
                card->state = CARD_STATE_HARDSETUP;
        }
        if (card->state == CARD_STATE_HARDSETUP) {
-               qeth_qdio_clear_card(card, 0);
                qeth_drain_output_queues(card);
                qeth_clear_working_pool_list(card);
                card->state = CARD_STATE_DOWN;
        }
 
+       qeth_qdio_clear_card(card, 0);
        flush_workqueue(card->event_wq);
        card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
+       card->info.promisc_mode = 0;
 }
 
 static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
@@ -1951,8 +1952,7 @@ int qeth_l2_vnicc_get_timeout(struct qeth_card *card, u32 *timeout)
 /* check if VNICC is currently enabled */
 bool qeth_l2_vnicc_is_in_use(struct qeth_card *card)
 {
-       /* if everything is turned off, VNICC is not active */
-       if (!card->options.vnicc.cur_chars)
+       if (!card->options.vnicc.sup_chars)
                return false;
        /* default values are only OK if rx_bcast was not enabled by user
         * or the card is offline.
@@ -2039,8 +2039,9 @@ static void qeth_l2_vnicc_init(struct qeth_card *card)
        /* enforce assumed default values and recover settings, if changed  */
        error |= qeth_l2_vnicc_recover_timeout(card, QETH_VNICC_LEARNING,
                                               timeout);
-       chars_tmp = card->options.vnicc.wanted_chars ^ QETH_VNICC_DEFAULT;
-       chars_tmp |= QETH_VNICC_BRIDGE_INVISIBLE;
+       /* Change chars, if necessary  */
+       chars_tmp = card->options.vnicc.wanted_chars ^
+                   card->options.vnicc.cur_chars;
        chars_len = sizeof(card->options.vnicc.wanted_chars) * BITS_PER_BYTE;
        for_each_set_bit(i, &chars_tmp, chars_len) {
                vnicc = BIT(i);
index f70c7aa..7fa325c 100644 (file)
@@ -262,7 +262,8 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
                return;
 
        mutex_lock(&card->sbp_lock);
-       if (card->options.sbp.role != QETH_SBP_ROLE_NONE) {
+       if (!card->options.sbp.reflect_promisc &&
+           card->options.sbp.role != QETH_SBP_ROLE_NONE) {
                /* Conditional to avoid spurious error messages */
                qeth_bridgeport_setrole(card, card->options.sbp.role);
                /* Let the callback function refresh the stored role value. */
index 2712633..5508ab8 100644 (file)
@@ -1307,13 +1307,14 @@ static void qeth_l3_stop_card(struct qeth_card *card)
                card->state = CARD_STATE_HARDSETUP;
        }
        if (card->state == CARD_STATE_HARDSETUP) {
-               qeth_qdio_clear_card(card, 0);
                qeth_drain_output_queues(card);
                qeth_clear_working_pool_list(card);
                card->state = CARD_STATE_DOWN;
        }
 
+       qeth_qdio_clear_card(card, 0);
        flush_workqueue(card->event_wq);
+       card->info.promisc_mode = 0;
 }
 
 static void qeth_l3_set_promisc_mode(struct qeth_card *card)
index f9067ed..e8c848f 100644 (file)
@@ -242,21 +242,33 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t count)
 {
        struct qeth_card *card = dev_get_drvdata(dev);
+       int rc = 0;
        char *tmp;
-       int rc;
 
        if (!IS_IQD(card))
                return -EPERM;
-       if (card->state != CARD_STATE_DOWN)
-               return -EPERM;
-       if (card->options.sniffer)
-               return -EPERM;
-       if (card->options.cq == QETH_CQ_NOTAVAILABLE)
-               return -EPERM;
+
+       mutex_lock(&card->conf_mutex);
+       if (card->state != CARD_STATE_DOWN) {
+               rc = -EPERM;
+               goto out;
+       }
+
+       if (card->options.sniffer) {
+               rc = -EPERM;
+               goto out;
+       }
+
+       if (card->options.cq == QETH_CQ_NOTAVAILABLE) {
+               rc = -EPERM;
+               goto out;
+       }
 
        tmp = strsep((char **)&buf, "\n");
-       if (strlen(tmp) > 8)
-               return -EINVAL;
+       if (strlen(tmp) > 8) {
+               rc = -EINVAL;
+               goto out;
+       }
 
        if (card->options.hsuid[0])
                /* delete old ip address */
@@ -267,11 +279,13 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
                card->options.hsuid[0] = '\0';
                memcpy(card->dev->perm_addr, card->options.hsuid, 9);
                qeth_configure_cq(card, QETH_CQ_DISABLED);
-               return count;
+               goto out;
        }
 
-       if (qeth_configure_cq(card, QETH_CQ_ENABLED))
-               return -EPERM;
+       if (qeth_configure_cq(card, QETH_CQ_ENABLED)) {
+               rc = -EPERM;
+               goto out;
+       }
 
        snprintf(card->options.hsuid, sizeof(card->options.hsuid),
                 "%-8s", tmp);
@@ -280,6 +294,8 @@ static ssize_t qeth_l3_dev_hsuid_store(struct device *dev,
 
        rc = qeth_l3_modify_hsuid(card, true);
 
+out:
+       mutex_unlock(&card->conf_mutex);
        return rc ? rc : count;
 }
 
index e36608c..33dbc05 100644 (file)
@@ -535,7 +535,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
        if ((le32_to_cpu(get_name_reply->status) == CT_OK)
         && (get_name_reply->data[0] != '\0')) {
                char *sp = get_name_reply->data;
-               int data_size = FIELD_SIZEOF(struct aac_get_name_resp, data);
+               int data_size = sizeof_field(struct aac_get_name_resp, data);
 
                sp[data_size - 1] = '\0';
                while (*sp == ' ')
@@ -574,7 +574,7 @@ static int aac_get_container_name(struct scsi_cmnd * scsicmd)
 
        dev = (struct aac_dev *)scsicmd->device->host->hostdata;
 
-       data_size = FIELD_SIZEOF(struct aac_get_name_resp, data);
+       data_size = sizeof_field(struct aac_get_name_resp, data);
 
        cmd_fibcontext = aac_fib_alloc_tag(dev, scsicmd);
 
index 063dccc..5f9f0b1 100644 (file)
@@ -1300,7 +1300,7 @@ struct be_cmd_get_port_name {
 
 /* Returns the number of items in the field array. */
 #define BE_NUMBER_OF_FIELD(_type_, _field_)    \
-       (FIELD_SIZEOF(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
+       (sizeof_field(_type_, _field_)/sizeof((((_type_ *)0)->_field_[0])))\
 
 /**
  * Different types of iSCSI completions to host driver for both initiator
index 0d044c1..4bc794d 100644 (file)
@@ -121,7 +121,8 @@ static inline void cxgbi_device_destroy(struct cxgbi_device *cdev)
                "cdev 0x%p, p# %u.\n", cdev, cdev->nports);
        cxgbi_hbas_remove(cdev);
        cxgbi_device_portmap_cleanup(cdev);
-       cxgbi_ppm_release(cdev->cdev2ppm(cdev));
+       if (cdev->cdev2ppm)
+               cxgbi_ppm_release(cdev->cdev2ppm(cdev));
        if (cdev->pmap.max_connect)
                cxgbi_free_big_mem(cdev->pmap.port_csk);
        kfree(cdev);
@@ -2746,7 +2747,7 @@ static int __init libcxgbi_init_module(void)
 {
        pr_info("%s", version);
 
-       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) <
+       BUILD_BUG_ON(sizeof_field(struct sk_buff, cb) <
                     sizeof(struct cxgbi_skb_cb));
        return 0;
 }
index 1f55b9e..1b88a3b 100644 (file)
@@ -688,26 +688,26 @@ int vnic_dev_soft_reset_done(struct vnic_dev *vdev, int *done)
 
 int vnic_dev_hang_notify(struct vnic_dev *vdev)
 {
-       u64 a0, a1;
+       u64 a0 = 0, a1 = 0;
        int wait = 1000;
        return vnic_dev_cmd(vdev, CMD_HANG_NOTIFY, &a0, &a1, wait);
 }
 
 int vnic_dev_mac_addr(struct vnic_dev *vdev, u8 *mac_addr)
 {
-       u64 a0, a1;
+       u64 a[2] = {};
        int wait = 1000;
        int err, i;
 
        for (i = 0; i < ETH_ALEN; i++)
                mac_addr[i] = 0;
 
-       err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a0, &a1, wait);
+       err = vnic_dev_cmd(vdev, CMD_MAC_ADDR, &a[0], &a[1], wait);
        if (err)
                return err;
 
        for (i = 0; i < ETH_ALEN; i++)
-               mac_addr[i] = ((u8 *)&a0)[i];
+               mac_addr[i] = ((u8 *)&a)[i];
 
        return 0;
 }
@@ -732,30 +732,30 @@ void vnic_dev_packet_filter(struct vnic_dev *vdev, int directed, int multicast,
 
 void vnic_dev_add_addr(struct vnic_dev *vdev, u8 *addr)
 {
-       u64 a0 = 0, a1 = 0;
+       u64 a[2] = {};
        int wait = 1000;
        int err;
        int i;
 
        for (i = 0; i < ETH_ALEN; i++)
-               ((u8 *)&a0)[i] = addr[i];
+               ((u8 *)&a)[i] = addr[i];
 
-       err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a0, &a1, wait);
+       err = vnic_dev_cmd(vdev, CMD_ADDR_ADD, &a[0], &a[1], wait);
        if (err)
                pr_err("Can't add addr [%pM], %d\n", addr, err);
 }
 
 void vnic_dev_del_addr(struct vnic_dev *vdev, u8 *addr)
 {
-       u64 a0 = 0, a1 = 0;
+       u64 a[2] = {};
        int wait = 1000;
        int err;
        int i;
 
        for (i = 0; i < ETH_ALEN; i++)
-               ((u8 *)&a0)[i] = addr[i];
+               ((u8 *)&a)[i] = addr[i];
 
-       err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a0, &a1, wait);
+       err = vnic_dev_cmd(vdev, CMD_ADDR_DEL, &a[0], &a[1], wait);
        if (err)
                pr_err("Can't del addr [%pM], %d\n", addr, err);
 }
index ebd47c0..70b99c0 100644 (file)
@@ -1945,7 +1945,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 
        ISCSI_DBG_EH(session, "scsi cmd %p timedout\n", sc);
 
-       spin_lock(&session->frwd_lock);
+       spin_lock_bh(&session->frwd_lock);
        task = (struct iscsi_task *)sc->SCp.ptr;
        if (!task) {
                /*
@@ -2072,7 +2072,7 @@ enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *sc)
 done:
        if (task)
                task->last_timeout = jiffies;
-       spin_unlock(&session->frwd_lock);
+       spin_unlock_bh(&session->frwd_lock);
        ISCSI_DBG_EH(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
                     "timer reset" : "shutdown or nh");
        return rc;
index f47b4b2..d7302c2 100644 (file)
@@ -81,12 +81,21 @@ static int sas_get_port_device(struct asd_sas_port *port)
                else
                        dev->dev_type = SAS_SATA_DEV;
                dev->tproto = SAS_PROTOCOL_SATA;
-       } else {
+       } else if (port->oob_mode == SAS_OOB_MODE) {
                struct sas_identify_frame *id =
                        (struct sas_identify_frame *) dev->frame_rcvd;
                dev->dev_type = id->dev_type;
                dev->iproto = id->initiator_bits;
                dev->tproto = id->target_bits;
+       } else {
+               /* If the oob mode is OOB_NOT_CONNECTED, the port is
+                * disconnected due to race with PHY down. We cannot
+                * continue to discover this port
+                */
+               sas_put_device(dev);
+               pr_warn("Port %016llx is disconnected when discovering\n",
+                       SAS_ADDR(port->attached_sas_addr));
+               return -ENODEV;
        }
 
        sas_init_dev(dev);
index d4e1b12..0ea03ae 100644 (file)
@@ -4489,12 +4489,6 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,
        phba->mbox_ext_buf_ctx.seqNum++;
        nemb_tp = phba->mbox_ext_buf_ctx.nembType;
 
-       dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
-       if (!dd_data) {
-               rc = -ENOMEM;
-               goto job_error;
-       }
-
        pbuf = (uint8_t *)dmabuf->virt;
        size = job->request_payload.payload_len;
        sg_copy_to_buffer(job->request_payload.sg_list,
@@ -4531,6 +4525,13 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,
                                "2968 SLI_CONFIG ext-buffer wr all %d "
                                "ebuffers received\n",
                                phba->mbox_ext_buf_ctx.numBuf);
+
+               dd_data = kmalloc(sizeof(struct bsg_job_data), GFP_KERNEL);
+               if (!dd_data) {
+                       rc = -ENOMEM;
+                       goto job_error;
+               }
+
                /* mailbox command structure for base driver */
                pmboxq = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
                if (!pmboxq) {
@@ -4579,6 +4580,8 @@ lpfc_bsg_write_ebuf_set(struct lpfc_hba *phba, struct bsg_job *job,
        return SLI_CONFIG_HANDLED;
 
 job_error:
+       if (pmboxq)
+               mempool_free(pmboxq, phba->mbox_mem_pool);
        lpfc_bsg_dma_page_free(phba, dmabuf);
        kfree(dd_data);
 
index 2e6a68d..a5ecbce 100644 (file)
@@ -5385,7 +5385,6 @@ static const struct file_operations lpfc_debugfs_ras_log = {
        .read =         lpfc_debugfs_read,
        .release =      lpfc_debugfs_ras_log_release,
 };
-#endif
 
 #undef lpfc_debugfs_op_dumpHBASlim
 static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
@@ -5557,7 +5556,7 @@ static const struct file_operations lpfc_idiag_op_extAcc = {
        .write =        lpfc_idiag_extacc_write,
        .release =      lpfc_idiag_cmd_release,
 };
-
+#endif
 
 /* lpfc_idiag_mbxacc_dump_bsg_mbox - idiag debugfs dump bsg mailbox command
  * @phba: Pointer to HBA context object.
index 6298b17..6a04fdb 100644 (file)
@@ -5883,7 +5883,7 @@ void lpfc_sli4_async_event_proc(struct lpfc_hba *phba)
                        break;
                default:
                        lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-                                       "1804 Invalid asynchrous event code: "
+                                       "1804 Invalid asynchronous event code: "
                                        "x%x\n", bf_get(lpfc_trailer_code,
                                        &cq_event->cqe.mcqe_cmpl));
                        break;
index db4a04a..f6c8963 100644 (file)
@@ -1985,6 +1985,8 @@ out_unlock:
 
 /* Declare and initialization an instance of the FC NVME template. */
 static struct nvme_fc_port_template lpfc_nvme_template = {
+       .module = THIS_MODULE,
+
        /* initiator-based functions */
        .localport_delete  = lpfc_nvme_localport_delete,
        .remoteport_delete = lpfc_nvme_remoteport_delete,
index c82b579..625c046 100644 (file)
@@ -8555,7 +8555,7 @@ lpfc_sli4_async_mbox_unblock(struct lpfc_hba *phba)
        psli->sli_flag &= ~LPFC_SLI_ASYNC_MBX_BLK;
        spin_unlock_irq(&phba->hbalock);
 
-       /* wake up worker thread to post asynchronlous mailbox command */
+       /* wake up worker thread to post asynchronous mailbox command */
        lpfc_worker_wake_up(phba);
 }
 
@@ -8823,7 +8823,7 @@ lpfc_sli_issue_mbox_s4(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
                return rc;
        }
 
-       /* Now, interrupt mode asynchrous mailbox command */
+       /* Now, interrupt mode asynchronous mailbox command */
        rc = lpfc_mbox_cmd_check(phba, mboxq);
        if (rc) {
                lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
@@ -13112,11 +13112,11 @@ lpfc_cq_event_setup(struct lpfc_hba *phba, void *entry, int size)
 }
 
 /**
- * lpfc_sli4_sp_handle_async_event - Handle an asynchroous event
+ * lpfc_sli4_sp_handle_async_event - Handle an asynchronous event
  * @phba: Pointer to HBA context object.
  * @cqe: Pointer to mailbox completion queue entry.
  *
- * This routine process a mailbox completion queue entry with asynchrous
+ * This routine process a mailbox completion queue entry with asynchronous
  * event.
  *
  * Return: true if work posted to worker thread, otherwise false.
@@ -13270,7 +13270,7 @@ out_no_mqe_complete:
  * @cqe: Pointer to mailbox completion queue entry.
  *
  * This routine process a mailbox completion queue entry, it invokes the
- * proper mailbox complete handling or asynchrous event handling routine
+ * proper mailbox complete handling or asynchronous event handling routine
  * according to the MCQE's async bit.
  *
  * Return: true if work posted to worker thread, otherwise false.
index 848fbec..45fd8df 100644 (file)
@@ -5248,7 +5248,6 @@ _base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc)
                                        &ct->chain_buffer_dma);
                        if (!ct->chain_buffer) {
                                ioc_err(ioc, "chain_lookup: pci_pool_alloc failed\n");
-                               _base_release_memory_pools(ioc);
                                goto out;
                        }
                }
index ae97e2f..d7e7043 100644 (file)
@@ -178,6 +178,7 @@ qla2x00_sysfs_read_nvram(struct file *filp, struct kobject *kobj,
 
        faddr = ha->flt_region_nvram;
        if (IS_QLA28XX(ha)) {
+               qla28xx_get_aux_images(vha, &active_regions);
                if (active_regions.aux.vpd_nvram == QLA27XX_SECONDARY_IMAGE)
                        faddr = ha->flt_region_nvram_sec;
        }
index 99f0a1a..cbaf178 100644 (file)
@@ -2399,7 +2399,7 @@ qla2x00_get_flash_image_status(struct bsg_job *bsg_job)
        struct qla_active_regions regions = { };
        struct active_regions active_regions = { };
 
-       qla28xx_get_aux_images(vha, &active_regions);
+       qla27xx_get_active_image(vha, &active_regions);
        regions.global_image = active_regions.global;
 
        if (IS_QLA28XX(ha)) {
index 460f443..2edd9f7 100644 (file)
@@ -2401,6 +2401,7 @@ typedef struct fc_port {
        unsigned int id_changed:1;
        unsigned int scan_needed:1;
        unsigned int n2n_flag:1;
+       unsigned int explicit_logout:1;
 
        struct completion nvme_del_done;
        uint32_t nvme_prli_service_param;
index 59f6903..9dc09c1 100644 (file)
@@ -1523,6 +1523,10 @@ struct qla_flt_header {
 #define FLT_REG_NVRAM_SEC_28XX_1       0x10F
 #define FLT_REG_NVRAM_SEC_28XX_2       0x111
 #define FLT_REG_NVRAM_SEC_28XX_3       0x113
+#define FLT_REG_MPI_PRI_28XX           0xD3
+#define FLT_REG_MPI_SEC_28XX           0xF0
+#define FLT_REG_PEP_PRI_28XX           0xD1
+#define FLT_REG_PEP_SEC_28XX           0xF1
 
 struct qla_flt_region {
        uint16_t code;
index 6c28f38..aa52041 100644 (file)
@@ -533,6 +533,7 @@ static int qla_post_els_plogi_work(struct scsi_qla_host *vha, fc_port_t *fcport)
 
        e->u.fcport.fcport = fcport;
        fcport->flags |= FCF_ASYNC_ACTIVE;
+       fcport->disc_state = DSC_LOGIN_PEND;
        return qla2x00_post_work(vha, e);
 }
 
@@ -1526,8 +1527,8 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host *vha, fc_port_t *fcport)
                }
        }
 
-       /* for pure Target Mode. Login will not be initiated */
-       if (vha->host->active_mode == MODE_TARGET)
+       /* Target won't initiate port login if fabric is present */
+       if (vha->host->active_mode == MODE_TARGET && !N2N_TOPO(vha->hw))
                return 0;
 
        if (fcport->flags & FCF_ASYNC_SENT) {
@@ -1719,6 +1720,10 @@ void qla24xx_handle_relogin_event(scsi_qla_host_t *vha,
 void qla_handle_els_plogi_done(scsi_qla_host_t *vha,
                                      struct event_arg *ea)
 {
+       /* for pure Target Mode, PRLI will not be initiated */
+       if (vha->host->active_mode == MODE_TARGET)
+               return;
+
        ql_dbg(ql_dbg_disc, vha, 0x2118,
            "%s %d %8phC post PRLI\n",
            __func__, __LINE__, ea->fcport->port_name);
@@ -4852,6 +4857,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
        }
 
        INIT_WORK(&fcport->del_work, qla24xx_delete_sess_fn);
+       INIT_WORK(&fcport->free_work, qlt_free_session_done);
        INIT_WORK(&fcport->reg_work, qla_register_fcport_fn);
        INIT_LIST_HEAD(&fcport->gnl_entry);
        INIT_LIST_HEAD(&fcport->list);
@@ -4930,14 +4936,8 @@ qla2x00_configure_loop(scsi_qla_host_t *vha)
                set_bit(RSCN_UPDATE, &flags);
                clear_bit(LOCAL_LOOP_UPDATE, &flags);
 
-       } else if (ha->current_topology == ISP_CFG_N) {
-               clear_bit(RSCN_UPDATE, &flags);
-               if (qla_tgt_mode_enabled(vha)) {
-                       /* allow the other side to start the login */
-                       clear_bit(LOCAL_LOOP_UPDATE, &flags);
-                       set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
-               }
-       } else if (ha->current_topology == ISP_CFG_NL) {
+       } else if (ha->current_topology == ISP_CFG_NL ||
+                  ha->current_topology == ISP_CFG_N) {
                clear_bit(RSCN_UPDATE, &flags);
                set_bit(LOCAL_LOOP_UPDATE, &flags);
        } else if (!vha->flags.online ||
@@ -5054,7 +5054,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
                                memcpy(&ha->plogi_els_payld.data,
                                    (void *)ha->init_cb,
                                    sizeof(ha->plogi_els_payld.data));
-                               set_bit(RELOGIN_NEEDED, &vha->dpc_flags);
                        } else {
                                ql_dbg(ql_dbg_init, vha, 0x00d1,
                                    "PLOGI ELS param read fail.\n");
index b25f87f..8b050f0 100644 (file)
@@ -2405,11 +2405,19 @@ qla2x00_login_iocb(srb_t *sp, struct mbx_entry *mbx)
 static void
 qla24xx_logout_iocb(srb_t *sp, struct logio_entry_24xx *logio)
 {
+       u16 control_flags = LCF_COMMAND_LOGO;
        logio->entry_type = LOGINOUT_PORT_IOCB_TYPE;
-       logio->control_flags =
-           cpu_to_le16(LCF_COMMAND_LOGO|LCF_IMPL_LOGO);
-       if (!sp->fcport->keep_nport_handle)
-               logio->control_flags |= cpu_to_le16(LCF_FREE_NPORT);
+
+       if (sp->fcport->explicit_logout) {
+               control_flags |= LCF_EXPL_LOGO|LCF_FREE_NPORT;
+       } else {
+               control_flags |= LCF_IMPL_LOGO;
+
+               if (!sp->fcport->keep_nport_handle)
+                       control_flags |= LCF_FREE_NPORT;
+       }
+
+       logio->control_flags = cpu_to_le16(control_flags);
        logio->nport_handle = cpu_to_le16(sp->fcport->loop_id);
        logio->port_id[0] = sp->fcport->d_id.b.al_pa;
        logio->port_id[1] = sp->fcport->d_id.b.area;
@@ -2617,6 +2625,10 @@ qla24xx_els_dcmd_iocb(scsi_qla_host_t *vha, int els_opcode,
 
        memcpy(elsio->u.els_logo.els_logo_pyld, &logo_pyld,
            sizeof(struct els_logo_payload));
+       ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3075, "LOGO buffer:");
+       ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x010a,
+                      elsio->u.els_logo.els_logo_pyld,
+                      sizeof(*elsio->u.els_logo.els_logo_pyld));
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
@@ -2676,7 +2688,8 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
                ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3073,
                    "PLOGI ELS IOCB:\n");
                ql_dump_buffer(ql_log_info, vha, 0x0109,
-                   (uint8_t *)els_iocb, 0x70);
+                   (uint8_t *)els_iocb,
+                   sizeof(*els_iocb));
        } else {
                els_iocb->control_flags = 1 << 13;
                els_iocb->tx_byte_count =
@@ -2688,6 +2701,11 @@ qla24xx_els_logo_iocb(srb_t *sp, struct els_entry_24xx *els_iocb)
                els_iocb->rx_byte_count = 0;
                els_iocb->rx_address = 0;
                els_iocb->rx_len = 0;
+               ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3076,
+                      "LOGO ELS IOCB:");
+               ql_dump_buffer(ql_log_info, vha, 0x010b,
+                              els_iocb,
+                              sizeof(*els_iocb));
        }
 
        sp->vha->qla_stats.control_requests++;
@@ -2934,7 +2952,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
 
        ql_dbg(ql_dbg_disc + ql_dbg_buffer, vha, 0x3073, "PLOGI buffer:\n");
        ql_dump_buffer(ql_dbg_disc + ql_dbg_buffer, vha, 0x0109,
-           (uint8_t *)elsio->u.els_plogi.els_plogi_pyld, 0x70);
+           (uint8_t *)elsio->u.els_plogi.els_plogi_pyld,
+           sizeof(*elsio->u.els_plogi.els_plogi_pyld));
 
        rval = qla2x00_start_sp(sp);
        if (rval != QLA_SUCCESS) {
index 2601d76..7b8a6bf 100644 (file)
@@ -1061,8 +1061,6 @@ global_port_update:
                        ql_dbg(ql_dbg_async, vha, 0x5011,
                            "Asynchronous PORT UPDATE ignored %04x/%04x/%04x.\n",
                            mb[1], mb[2], mb[3]);
-
-                       qlt_async_event(mb[0], vha, mb);
                        break;
                }
 
@@ -1079,8 +1077,6 @@ global_port_update:
                set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
                set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
                set_bit(VP_CONFIG_OK, &vha->vp_flags);
-
-               qlt_async_event(mb[0], vha, mb);
                break;
 
        case MBA_RSCN_UPDATE:           /* State Change Registration */
index 0cf94f0..b7c1108 100644 (file)
@@ -3921,6 +3921,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                                        vha->d_id.b24 = 0;
                                        vha->d_id.b.al_pa = 1;
                                        ha->flags.n2n_bigger = 1;
+                                       ha->flags.n2n_ae = 0;
 
                                        id.b.al_pa = 2;
                                        ql_dbg(ql_dbg_async, vha, 0x5075,
@@ -3931,6 +3932,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                                            "Format 1: Remote login - Waiting for WWPN %8phC.\n",
                                            rptid_entry->u.f1.port_name);
                                        ha->flags.n2n_bigger = 0;
+                                       ha->flags.n2n_ae = 1;
                                }
                                qla24xx_post_newsess_work(vha, &id,
                                    rptid_entry->u.f1.port_name,
@@ -3942,7 +3944,6 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
                        /* if our portname is higher then initiate N2N login */
 
                        set_bit(N2N_LOGIN_NEEDED, &vha->dpc_flags);
-                       ha->flags.n2n_ae = 1;
                        return;
                        break;
                case TOPO_FL:
index 941aa53..bfcd02f 100644 (file)
@@ -610,6 +610,7 @@ static void qla_nvme_remoteport_delete(struct nvme_fc_remote_port *rport)
 }
 
 static struct nvme_fc_port_template qla_nvme_fc_transport = {
+       .module = THIS_MODULE,
        .localport_delete = qla_nvme_localport_delete,
        .remoteport_delete = qla_nvme_remoteport_delete,
        .create_queue   = qla_nvme_alloc_queue,
index f2d5115..bbe9035 100644 (file)
@@ -847,15 +847,15 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
                                ha->flt_region_img_status_pri = start;
                        break;
                case FLT_REG_IMG_SEC_27XX:
-                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+                       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                                ha->flt_region_img_status_sec = start;
                        break;
                case FLT_REG_FW_SEC_27XX:
-                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+                       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                                ha->flt_region_fw_sec = start;
                        break;
                case FLT_REG_BOOTLOAD_SEC_27XX:
-                       if (IS_QLA27XX(ha) && !IS_QLA28XX(ha))
+                       if (IS_QLA27XX(ha) || IS_QLA28XX(ha))
                                ha->flt_region_boot_sec = start;
                        break;
                case FLT_REG_AUX_IMG_PRI_28XX:
@@ -2725,8 +2725,11 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
                    "Region %x is secure\n", region.code);
 
-               if (region.code == FLT_REG_FW ||
-                   region.code == FLT_REG_FW_SEC_27XX) {
+               switch (region.code) {
+               case FLT_REG_FW:
+               case FLT_REG_FW_SEC_27XX:
+               case FLT_REG_MPI_PRI_28XX:
+               case FLT_REG_MPI_SEC_28XX:
                        fw_array = dwptr;
 
                        /* 1st fw array */
@@ -2757,9 +2760,23 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                                buf_size_without_sfub += risc_size;
                                fw_array += risc_size;
                        }
-               } else {
-                       ql_log(ql_log_warn + ql_dbg_verbose, vha, 0xffff,
-                           "Secure region %x not supported\n",
+                       break;
+
+               case FLT_REG_PEP_PRI_28XX:
+               case FLT_REG_PEP_SEC_28XX:
+                       fw_array = dwptr;
+
+                       /* 1st fw array */
+                       risc_size = be32_to_cpu(fw_array[3]);
+                       risc_attr = be32_to_cpu(fw_array[9]);
+
+                       buf_size_without_sfub = risc_size;
+                       fw_array += risc_size;
+                       break;
+
+               default:
+                       ql_log(ql_log_warn + ql_dbg_verbose, vha,
+                           0xffff, "Secure region %x not supported\n",
                            region.code);
                        rval = QLA_COMMAND_ERROR;
                        goto done;
@@ -2880,7 +2897,7 @@ qla28xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
                            "Sending Secure Flash MB Cmd\n");
                        rval = qla28xx_secure_flash_update(vha, 0, region.code,
                                buf_size_without_sfub, sfub_dma,
-                               sizeof(struct secure_flash_update_block));
+                               sizeof(struct secure_flash_update_block) >> 2);
                        if (rval != QLA_SUCCESS) {
                                ql_log(ql_log_warn, vha, 0xffff,
                                    "Secure Flash MB Cmd failed %x.", rval);
index 51b275a..68c1414 100644 (file)
@@ -1104,6 +1104,7 @@ void qlt_free_session_done(struct work_struct *work)
                }
        }
 
+       sess->explicit_logout = 0;
        spin_unlock_irqrestore(&ha->tgt.sess_lock, flags);
        sess->free_pending = 0;
 
@@ -1160,7 +1161,6 @@ void qlt_unreg_sess(struct fc_port *sess)
        sess->last_rscn_gen = sess->rscn_gen;
        sess->last_login_gen = sess->login_gen;
 
-       INIT_WORK(&sess->free_work, qlt_free_session_done);
        queue_work(sess->vha->hw->wq, &sess->free_work);
 }
 EXPORT_SYMBOL(qlt_unreg_sess);
@@ -1265,7 +1265,6 @@ void qlt_schedule_sess_for_deletion(struct fc_port *sess)
            "Scheduling sess %p for deletion %8phC\n",
            sess, sess->port_name);
 
-       INIT_WORK(&sess->del_work, qla24xx_delete_sess_fn);
        WARN_ON(!queue_work(sess->vha->hw->wq, &sess->del_work));
 }
 
@@ -4804,6 +4803,7 @@ static int qlt_handle_login(struct scsi_qla_host *vha,
 
        switch (sess->disc_state) {
        case DSC_DELETED:
+       case DSC_LOGIN_PEND:
                qlt_plogi_ack_unref(vha, pla);
                break;
 
index 042a243..abe7f79 100644 (file)
@@ -246,6 +246,8 @@ static void tcm_qla2xxx_complete_mcmd(struct work_struct *work)
  */
 static void tcm_qla2xxx_free_mcmd(struct qla_tgt_mgmt_cmd *mcmd)
 {
+       if (!mcmd)
+               return;
        INIT_WORK(&mcmd->free_work, tcm_qla2xxx_complete_mcmd);
        queue_work(tcm_qla2xxx_free_wq, &mcmd->free_work);
 }
@@ -348,6 +350,7 @@ static void tcm_qla2xxx_close_session(struct se_session *se_sess)
        target_sess_cmd_list_set_waiting(se_sess);
        spin_unlock_irqrestore(&vha->hw->tgt.sess_lock, flags);
 
+       sess->explicit_logout = 1;
        tcm_qla2xxx_put_sess(sess);
 }
 
index 8c674ec..2323432 100644 (file)
@@ -4275,7 +4275,6 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
        return QLA_SUCCESS;
 
 mem_alloc_error_exit:
-       qla4xxx_mem_free(ha);
        return QLA_ERROR;
 }
 
index 417b868..ed8d970 100644 (file)
@@ -24,6 +24,8 @@
 
 #define ISCSI_TRANSPORT_VERSION "2.0-870"
 
+#define ISCSI_SEND_MAX_ALLOWED  10
+
 #define CREATE_TRACE_POINTS
 #include <trace/events/iscsi.h>
 
@@ -3682,6 +3684,7 @@ iscsi_if_rx(struct sk_buff *skb)
                struct nlmsghdr *nlh;
                struct iscsi_uevent *ev;
                uint32_t group;
+               int retries = ISCSI_SEND_MAX_ALLOWED;
 
                nlh = nlmsg_hdr(skb);
                if (nlh->nlmsg_len < sizeof(*nlh) + sizeof(*ev) ||
@@ -3712,6 +3715,10 @@ iscsi_if_rx(struct sk_buff *skb)
                                break;
                        err = iscsi_if_send_reply(portid, nlh->nlmsg_type,
                                                  ev, sizeof(*ev));
+                       if (err == -EAGAIN && --retries < 0) {
+                               printk(KERN_WARNING "Send reply failed, error %d\n", err);
+                               break;
+                       }
                } while (err < 0 && err != -ECONNREFUSED && err != -ESRCH);
                skb_pull(skb, rlen);
        }
index cea6259..65ce10c 100644 (file)
@@ -2211,8 +2211,10 @@ static int sd_read_protection_type(struct scsi_disk *sdkp, unsigned char *buffer
        u8 type;
        int ret = 0;
 
-       if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0)
+       if (scsi_device_protection(sdp) == 0 || (buffer[12] & 1) == 0) {
+               sdkp->protection_type = 0;
                return ret;
+       }
 
        type = ((buffer[12] >> 1) & 7) + 1; /* P_TYPE 0 = Type 1 */
 
index 7b7ef3a..412ac56 100644 (file)
@@ -8689,11 +8689,11 @@ static void __attribute__((unused)) verify_structures(void)
        BUILD_BUG_ON(offsetof(struct pqi_general_admin_request,
                data.delete_operational_queue.queue_id) != 12);
        BUILD_BUG_ON(sizeof(struct pqi_general_admin_request) != 64);
-       BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+       BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
                data.create_operational_iq) != 64 - 11);
-       BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+       BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
                data.create_operational_oq) != 64 - 11);
-       BUILD_BUG_ON(FIELD_SIZEOF(struct pqi_general_admin_request,
+       BUILD_BUG_ON(sizeof_field(struct pqi_general_admin_request,
                data.delete_operational_queue) != 64 - 11);
 
        BUILD_BUG_ON(offsetof(struct pqi_general_admin_response,
index f8faf8b..fb41636 100644 (file)
@@ -1842,9 +1842,11 @@ static int storvsc_probe(struct hv_device *device,
         */
        host->sg_tablesize = (stor_device->max_transfer_bytes >> PAGE_SHIFT);
        /*
+        * For non-IDE disks, the host supports multiple channels.
         * Set the number of HW queues we are supporting.
         */
-       host->nr_hw_queues = num_present_cpus();
+       if (!dev_is_ide)
+               host->nr_hw_queues = num_present_cpus();
 
        /*
         * Set the error handler work queue.
index b2af04c..6feeb0f 100644 (file)
@@ -99,6 +99,12 @@ static int cdns_ufs_link_startup_notify(struct ufs_hba *hba,
         */
        ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0);
 
+       /*
+        * Disabling Autohibern8 feature in cadence UFS
+        * to mask unexpected interrupt trigger.
+        */
+       hba->ahit = 0;
+
        return 0;
 }
 
index baeecee..53dd876 100644 (file)
@@ -203,7 +203,7 @@ int ufs_bsg_probe(struct ufs_hba *hba)
        bsg_dev->parent = get_device(parent);
        bsg_dev->release = ufs_bsg_node_release;
 
-       dev_set_name(bsg_dev, "ufs-bsg");
+       dev_set_name(bsg_dev, "ufs-bsg%u", shost->host_no);
 
        ret = device_add(bsg_dev);
        if (ret)
index 833e04a..1778f8c 100644 (file)
@@ -14,6 +14,7 @@ source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/renesas/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
 source "drivers/soc/samsung/Kconfig"
+source "drivers/soc/sifive/Kconfig"
 source "drivers/soc/sunxi/Kconfig"
 source "drivers/soc/tegra/Kconfig"
 source "drivers/soc/ti/Kconfig"
index 2ec3550..8b49d78 100644 (file)
@@ -20,6 +20,7 @@ obj-y                         += qcom/
 obj-y                          += renesas/
 obj-$(CONFIG_ARCH_ROCKCHIP)    += rockchip/
 obj-$(CONFIG_SOC_SAMSUNG)      += samsung/
+obj-$(CONFIG_SOC_SIFIVE)       += sifive/
 obj-y                          += sunxi/
 obj-$(CONFIG_ARCH_TEGRA)       += tegra/
 obj-y                          += ti/
index 5823f5b..3f0261d 100644 (file)
@@ -323,6 +323,8 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
                                     struct meson_ee_pwrc *pwrc,
                                     struct meson_ee_pwrc_domain *dom)
 {
+       int ret;
+
        dom->pwrc = pwrc;
        dom->num_rstc = dom->desc.reset_names_count;
        dom->num_clks = dom->desc.clk_names_count;
@@ -368,15 +370,21 @@ static int meson_ee_pwrc_init_domain(struct platform_device *pdev,
          * prepare/enable counters won't be in sync.
          */
        if (dom->num_clks && dom->desc.get_power && !dom->desc.get_power(dom)) {
-               int ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
+               ret = clk_bulk_prepare_enable(dom->num_clks, dom->clks);
                if (ret)
                        return ret;
 
-               pm_genpd_init(&dom->base, &pm_domain_always_on_gov, false);
-       } else
-               pm_genpd_init(&dom->base, NULL,
-                             (dom->desc.get_power ?
-                              dom->desc.get_power(dom) : true));
+               ret = pm_genpd_init(&dom->base, &pm_domain_always_on_gov,
+                                   false);
+               if (ret)
+                       return ret;
+       } else {
+               ret = pm_genpd_init(&dom->base, NULL,
+                                   (dom->desc.get_power ?
+                                    dom->desc.get_power(dom) : true));
+               if (ret)
+                       return ret;
+       }
 
        return 0;
 }
@@ -441,9 +449,7 @@ static int meson_ee_pwrc_probe(struct platform_device *pdev)
                pwrc->xlate.domains[i] = &dom->base;
        }
 
-       of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
-
-       return 0;
+       return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
 }
 
 static void meson_ee_pwrc_shutdown(struct platform_device *pdev)
diff --git a/drivers/soc/sifive/Kconfig b/drivers/soc/sifive/Kconfig
new file mode 100644 (file)
index 0000000..58cf8c4
--- /dev/null
@@ -0,0 +1,10 @@
+# SPDX-License-Identifier: GPL-2.0
+
+if SOC_SIFIVE
+
+config SIFIVE_L2
+       bool "Sifive L2 Cache controller"
+       help
+         Support for the L2 cache controller on SiFive platforms.
+
+endif
diff --git a/drivers/soc/sifive/Makefile b/drivers/soc/sifive/Makefile
new file mode 100644 (file)
index 0000000..b5caff7
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+
+obj-$(CONFIG_SIFIVE_L2)        += sifive_l2_cache.o
similarity index 99%
rename from arch/riscv/mm/sifive_l2_cache.c
rename to drivers/soc/sifive/sifive_l2_cache.c
index a9ffff3..a506939 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/interrupt.h>
 #include <linux/of_irq.h>
 #include <linux/of_address.h>
-#include <asm/sifive_l2_cache.h>
+#include <soc/sifive/sifive_l2_cache.h>
 
 #define SIFIVE_L2_DIRECCFIX_LOW 0x100
 #define SIFIVE_L2_DIRECCFIX_HIGH 0x104
index 378369d..e9ece45 100644 (file)
@@ -419,6 +419,8 @@ static void wkup_m3_rproc_boot_thread(struct wkup_m3_ipc *m3_ipc)
        ret = rproc_boot(m3_ipc->rproc);
        if (ret)
                dev_err(dev, "rproc_boot failed\n");
+       else
+               m3_ipc_state = m3_ipc;
 
        do_exit(0);
 }
@@ -505,8 +507,6 @@ static int wkup_m3_ipc_probe(struct platform_device *pdev)
                goto err_put_rproc;
        }
 
-       m3_ipc_state = m3_ipc;
-
        return 0;
 
 err_put_rproc:
index c36587b..82a0ee0 100644 (file)
@@ -168,16 +168,16 @@ static void cdns_spi_init_hw(struct cdns_spi *xspi)
 /**
  * cdns_spi_chipselect - Select or deselect the chip select line
  * @spi:       Pointer to the spi_device structure
- * @enable:    Select (1) or deselect (0) the chip select line
+ * @is_high:   Select(0) or deselect (1) the chip select line
  */
-static void cdns_spi_chipselect(struct spi_device *spi, bool enable)
+static void cdns_spi_chipselect(struct spi_device *spi, bool is_high)
 {
        struct cdns_spi *xspi = spi_master_get_devdata(spi->master);
        u32 ctrl_reg;
 
        ctrl_reg = cdns_spi_read(xspi, CDNS_SPI_CR);
 
-       if (!enable) {
+       if (is_high) {
                /* Deselect the slave */
                ctrl_reg |= CDNS_SPI_CR_SSCTRL;
        } else {
index d12e149..fd6b9ca 100644 (file)
@@ -82,6 +82,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev,
 
 error:
        clk_disable_unprepare(p->clk);
+       pci_release_regions(pdev);
        spi_master_put(master);
        return ret;
 }
@@ -96,6 +97,7 @@ static void thunderx_spi_remove(struct pci_dev *pdev)
                return;
 
        clk_disable_unprepare(p->clk);
+       pci_release_regions(pdev);
        /* Put everything in a known state. */
        writeq(0, p->register_base + OCTEON_SPI_CFG(p));
 }
index a92aa5c..5a25da3 100644 (file)
@@ -129,10 +129,11 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable)
        struct dw_spi *dws = spi_controller_get_devdata(spi->controller);
        struct chip_data *chip = spi_get_ctldata(spi);
 
+       /* Chip select logic is inverted from spi_set_cs() */
        if (chip && chip->cs_control)
-               chip->cs_control(enable);
+               chip->cs_control(!enable);
 
-       if (enable)
+       if (!enable)
                dw_writel(dws, DW_SPI_SER, BIT(spi->chip_select));
        else if (dws->cs_override)
                dw_writel(dws, DW_SPI_SER, 0);
@@ -171,9 +172,11 @@ static inline u32 rx_max(struct dw_spi *dws)
 
 static void dw_writer(struct dw_spi *dws)
 {
-       u32 max = tx_max(dws);
+       u32 max;
        u16 txw = 0;
 
+       spin_lock(&dws->buf_lock);
+       max = tx_max(dws);
        while (max--) {
                /* Set the tx word if the transfer's original "tx" is not null */
                if (dws->tx_end - dws->len) {
@@ -185,13 +188,16 @@ static void dw_writer(struct dw_spi *dws)
                dw_write_io_reg(dws, DW_SPI_DR, txw);
                dws->tx += dws->n_bytes;
        }
+       spin_unlock(&dws->buf_lock);
 }
 
 static void dw_reader(struct dw_spi *dws)
 {
-       u32 max = rx_max(dws);
+       u32 max;
        u16 rxw;
 
+       spin_lock(&dws->buf_lock);
+       max = rx_max(dws);
        while (max--) {
                rxw = dw_read_io_reg(dws, DW_SPI_DR);
                /* Care rx only if the transfer's original "rx" is not null */
@@ -203,6 +209,7 @@ static void dw_reader(struct dw_spi *dws)
                }
                dws->rx += dws->n_bytes;
        }
+       spin_unlock(&dws->buf_lock);
 }
 
 static void int_error_stop(struct dw_spi *dws, const char *msg)
@@ -275,18 +282,20 @@ static int dw_spi_transfer_one(struct spi_controller *master,
 {
        struct dw_spi *dws = spi_controller_get_devdata(master);
        struct chip_data *chip = spi_get_ctldata(spi);
+       unsigned long flags;
        u8 imask = 0;
        u16 txlevel = 0;
        u32 cr0;
        int ret;
 
        dws->dma_mapped = 0;
-
+       spin_lock_irqsave(&dws->buf_lock, flags);
        dws->tx = (void *)transfer->tx_buf;
        dws->tx_end = dws->tx + transfer->len;
        dws->rx = transfer->rx_buf;
        dws->rx_end = dws->rx + transfer->len;
        dws->len = transfer->len;
+       spin_unlock_irqrestore(&dws->buf_lock, flags);
 
        spi_enable_chip(dws, 0);
 
@@ -470,6 +479,7 @@ int dw_spi_add_host(struct device *dev, struct dw_spi *dws)
        dws->type = SSI_MOTO_SPI;
        dws->dma_inited = 0;
        dws->dma_addr = (dma_addr_t)(dws->paddr + DW_SPI_DR);
+       spin_lock_init(&dws->buf_lock);
 
        spi_controller_set_devdata(master, dws);
 
index 38c7de1..1bf5713 100644 (file)
@@ -119,6 +119,7 @@ struct dw_spi {
        size_t                  len;
        void                    *tx;
        void                    *tx_end;
+       spinlock_t              buf_lock;
        void                    *rx;
        void                    *rx_end;
        int                     dma_mapped;
index 442cff7..8428b69 100644 (file)
@@ -185,6 +185,7 @@ struct fsl_dspi {
        struct spi_transfer                     *cur_transfer;
        struct spi_message                      *cur_msg;
        struct chip_data                        *cur_chip;
+       size_t                                  progress;
        size_t                                  len;
        const void                              *tx;
        void                                    *rx;
@@ -586,21 +587,14 @@ static void dspi_tcfq_write(struct fsl_dspi *dspi)
        dspi->tx_cmd |= SPI_PUSHR_CMD_CTCNT;
 
        if (dspi->devtype_data->xspi_mode && dspi->bits_per_word > 16) {
-               /* Write two TX FIFO entries first, and then the corresponding
-                * CMD FIFO entry.
+               /* Write the CMD FIFO entry first, and then the two
+                * corresponding TX FIFO entries.
                 */
                u32 data = dspi_pop_tx(dspi);
 
-               if (dspi->cur_chip->ctar_val & SPI_CTAR_LSBFE) {
-                       /* LSB */
-                       tx_fifo_write(dspi, data & 0xFFFF);
-                       tx_fifo_write(dspi, data >> 16);
-               } else {
-                       /* MSB */
-                       tx_fifo_write(dspi, data >> 16);
-                       tx_fifo_write(dspi, data & 0xFFFF);
-               }
                cmd_fifo_write(dspi);
+               tx_fifo_write(dspi, data & 0xFFFF);
+               tx_fifo_write(dspi, data >> 16);
        } else {
                /* Write one entry to both TX FIFO and CMD FIFO
                 * simultaneously.
@@ -658,7 +652,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
        u32 spi_tcr;
 
        spi_take_timestamp_post(dspi->ctlr, dspi->cur_transfer,
-                               dspi->tx - dspi->bytes_per_word, !dspi->irq);
+                               dspi->progress, !dspi->irq);
 
        /* Get transfer counter (in number of SPI transfers). It was
         * reset to 0 when transfer(s) were started.
@@ -667,6 +661,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
        spi_tcnt = SPI_TCR_GET_TCNT(spi_tcr);
        /* Update total number of bytes that were transferred */
        msg->actual_length += spi_tcnt * dspi->bytes_per_word;
+       dspi->progress += spi_tcnt;
 
        trans_mode = dspi->devtype_data->trans_mode;
        if (trans_mode == DSPI_EOQ_MODE)
@@ -679,7 +674,7 @@ static int dspi_rxtx(struct fsl_dspi *dspi)
                return 0;
 
        spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
-                              dspi->tx, !dspi->irq);
+                              dspi->progress, !dspi->irq);
 
        if (trans_mode == DSPI_EOQ_MODE)
                dspi_eoq_write(dspi);
@@ -768,6 +763,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
                dspi->rx = transfer->rx_buf;
                dspi->rx_end = dspi->rx + transfer->len;
                dspi->len = transfer->len;
+               dspi->progress = 0;
                /* Validated transfer specific frame size (defaults applied) */
                dspi->bits_per_word = transfer->bits_per_word;
                if (transfer->bits_per_word <= 8)
@@ -789,7 +785,7 @@ static int dspi_transfer_one_message(struct spi_controller *ctlr,
                                     SPI_CTARE_DTCP(1));
 
                spi_take_timestamp_pre(dspi->ctlr, dspi->cur_transfer,
-                                      dspi->tx, !dspi->irq);
+                                      dspi->progress, !dspi->irq);
 
                trans_mode = dspi->devtype_data->trans_mode;
                switch (trans_mode) {
index 114801a..fb4159a 100644 (file)
@@ -611,6 +611,7 @@ static struct spi_master * fsl_spi_probe(struct device *dev,
        master->setup = fsl_spi_setup;
        master->cleanup = fsl_spi_cleanup;
        master->transfer_one_message = fsl_spi_do_one_msg;
+       master->use_gpio_descriptors = true;
 
        mpc8xxx_spi = spi_master_get_devdata(master);
        mpc8xxx_spi->max_bits_per_word = 32;
@@ -727,17 +728,27 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
                        }
                }
 #endif
-
-               pdata->cs_control = fsl_spi_cs_control;
+               /*
+                * Handle the case where we have one hardwired (always selected)
+                * device on the first "chipselect". Else we let the core code
+                * handle any GPIOs or native chip selects and assign the
+                * appropriate callback for dealing with the CS lines. This isn't
+                * supported on the GRLIB variant.
+                */
+               ret = gpiod_count(dev, "cs");
+               if (ret <= 0)
+                       pdata->max_chipselect = 1;
+               else
+                       pdata->cs_control = fsl_spi_cs_control;
        }
 
        ret = of_address_to_resource(np, 0, &mem);
        if (ret)
                goto err;
 
-       irq = irq_of_parse_and_map(np, 0);
-       if (!irq) {
-               ret = -EINVAL;
+       irq = platform_get_irq(ofdev, 0);
+       if (irq < 0) {
+               ret = irq;
                goto err;
        }
 
@@ -750,7 +761,6 @@ static int of_fsl_spi_probe(struct platform_device *ofdev)
        return 0;
 
 err:
-       irq_dispose_mapping(irq);
        return ret;
 }
 
index c36bb1b..8c5084a 100644 (file)
@@ -439,7 +439,7 @@ static bool nxp_fspi_supports_op(struct spi_mem *mem,
            op->data.nbytes > f->devtype_data->txfifo)
                return false;
 
-       return true;
+       return spi_mem_default_supports_op(mem, op);
 }
 
 /* Instead of busy looping invoke readl_poll_timeout functionality. */
index 16b6b2a..9071333 100644 (file)
@@ -1443,6 +1443,10 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
        { PCI_VDEVICE(INTEL, 0x4b2a), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x4b2b), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x4b37), LPSS_BXT_SSP },
+       /* JSL */
+       { PCI_VDEVICE(INTEL, 0x4daa), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x4dab), LPSS_CNL_SSP },
+       { PCI_VDEVICE(INTEL, 0x4dfb), LPSS_CNL_SSP },
        /* APL */
        { PCI_VDEVICE(INTEL, 0x5ac2), LPSS_BXT_SSP },
        { PCI_VDEVICE(INTEL, 0x5ac4), LPSS_BXT_SSP },
index 2ee1feb..6678f1c 100644 (file)
@@ -678,7 +678,7 @@ static int sprd_spi_init_hw(struct sprd_spi *ss, struct spi_transfer *t)
        if (d->unit != SPI_DELAY_UNIT_SCK)
                return -EINVAL;
 
-       val = readl_relaxed(ss->base + SPRD_SPI_CTL7);
+       val = readl_relaxed(ss->base + SPRD_SPI_CTL0);
        val &= ~(SPRD_SPI_SCK_REV | SPRD_SPI_NG_TX | SPRD_SPI_NG_RX);
        /* Set default chip selection, clock phase and clock polarity */
        val |= ss->hw_mode & SPI_CPHA ? SPRD_SPI_NG_RX : SPRD_SPI_NG_TX;
index 3cb6537..66dcb61 100644 (file)
@@ -62,6 +62,7 @@ struct ti_qspi {
        u32 dc;
 
        bool mmap_enabled;
+       int current_cs;
 };
 
 #define QSPI_PID                       (0x0)
@@ -487,6 +488,7 @@ static void ti_qspi_enable_memory_map(struct spi_device *spi)
                                   MEM_CS_EN(spi->chip_select));
        }
        qspi->mmap_enabled = true;
+       qspi->current_cs = spi->chip_select;
 }
 
 static void ti_qspi_disable_memory_map(struct spi_device *spi)
@@ -498,6 +500,7 @@ static void ti_qspi_disable_memory_map(struct spi_device *spi)
                regmap_update_bits(qspi->ctrl_base, qspi->ctrl_reg,
                                   MEM_CS_MASK, 0);
        qspi->mmap_enabled = false;
+       qspi->current_cs = -1;
 }
 
 static void ti_qspi_setup_mmap_read(struct spi_device *spi, u8 opcode,
@@ -543,7 +546,7 @@ static int ti_qspi_exec_mem_op(struct spi_mem *mem,
 
        mutex_lock(&qspi->list_lock);
 
-       if (!qspi->mmap_enabled)
+       if (!qspi->mmap_enabled || qspi->current_cs != mem->spi->chip_select)
                ti_qspi_enable_memory_map(mem->spi);
        ti_qspi_setup_mmap_read(mem->spi, op->cmd.opcode, op->data.buswidth,
                                op->addr.nbytes, op->dummy.nbytes);
@@ -799,6 +802,7 @@ no_dma:
                }
        }
        qspi->mmap_enabled = false;
+       qspi->current_cs = -1;
 
        ret = devm_spi_register_master(&pdev->dev, master);
        if (!ret)
index 47cde18..ce9b301 100644 (file)
@@ -290,25 +290,32 @@ static void uniphier_spi_recv(struct uniphier_spi_priv *priv)
        }
 }
 
-static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
+static void uniphier_spi_set_fifo_threshold(struct uniphier_spi_priv *priv,
+                                           unsigned int threshold)
 {
-       unsigned int fifo_threshold, fill_bytes;
        u32 val;
 
-       fifo_threshold = DIV_ROUND_UP(priv->rx_bytes,
-                               bytes_per_word(priv->bits_per_word));
-       fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
-
-       fill_bytes = fifo_threshold - (priv->rx_bytes - priv->tx_bytes);
-
-       /* set fifo threshold */
        val = readl(priv->base + SSI_FC);
        val &= ~(SSI_FC_TXFTH_MASK | SSI_FC_RXFTH_MASK);
-       val |= FIELD_PREP(SSI_FC_TXFTH_MASK, fifo_threshold);
-       val |= FIELD_PREP(SSI_FC_RXFTH_MASK, fifo_threshold);
+       val |= FIELD_PREP(SSI_FC_TXFTH_MASK, SSI_FIFO_DEPTH - threshold);
+       val |= FIELD_PREP(SSI_FC_RXFTH_MASK, threshold);
        writel(val, priv->base + SSI_FC);
+}
+
+static void uniphier_spi_fill_tx_fifo(struct uniphier_spi_priv *priv)
+{
+       unsigned int fifo_threshold, fill_words;
+       unsigned int bpw = bytes_per_word(priv->bits_per_word);
+
+       fifo_threshold = DIV_ROUND_UP(priv->rx_bytes, bpw);
+       fifo_threshold = min(fifo_threshold, SSI_FIFO_DEPTH);
+
+       uniphier_spi_set_fifo_threshold(priv, fifo_threshold);
+
+       fill_words = fifo_threshold -
+               DIV_ROUND_UP(priv->rx_bytes - priv->tx_bytes, bpw);
 
-       while (fill_bytes--)
+       while (fill_words--)
                uniphier_spi_send(priv);
 }
 
index 5e4c453..8994545 100644 (file)
@@ -1499,8 +1499,7 @@ static void spi_pump_messages(struct kthread_work *work)
  *                         advances its @tx buffer pointer monotonically.
  * @ctlr: Pointer to the spi_controller structure of the driver
  * @xfer: Pointer to the transfer being timestamped
- * @tx: Pointer to the current word within the xfer->tx_buf that the driver is
- *     preparing to transmit right now.
+ * @progress: How many words (not bytes) have been transferred so far
  * @irqs_off: If true, will disable IRQs and preemption for the duration of the
  *           transfer, for less jitter in time measurement. Only compatible
  *           with PIO drivers. If true, must follow up with
@@ -1510,21 +1509,19 @@ static void spi_pump_messages(struct kthread_work *work)
  */
 void spi_take_timestamp_pre(struct spi_controller *ctlr,
                            struct spi_transfer *xfer,
-                           const void *tx, bool irqs_off)
+                           size_t progress, bool irqs_off)
 {
-       u8 bytes_per_word = DIV_ROUND_UP(xfer->bits_per_word, 8);
-
        if (!xfer->ptp_sts)
                return;
 
        if (xfer->timestamped_pre)
                return;
 
-       if (tx < (xfer->tx_buf + xfer->ptp_sts_word_pre * bytes_per_word))
+       if (progress < xfer->ptp_sts_word_pre)
                return;
 
        /* Capture the resolution of the timestamp */
-       xfer->ptp_sts_word_pre = (tx - xfer->tx_buf) / bytes_per_word;
+       xfer->ptp_sts_word_pre = progress;
 
        xfer->timestamped_pre = true;
 
@@ -1546,23 +1543,20 @@ EXPORT_SYMBOL_GPL(spi_take_timestamp_pre);
  *                          timestamped.
  * @ctlr: Pointer to the spi_controller structure of the driver
  * @xfer: Pointer to the transfer being timestamped
- * @tx: Pointer to the current word within the xfer->tx_buf that the driver has
- *     just transmitted.
+ * @progress: How many words (not bytes) have been transferred so far
  * @irqs_off: If true, will re-enable IRQs and preemption for the local CPU.
  */
 void spi_take_timestamp_post(struct spi_controller *ctlr,
                             struct spi_transfer *xfer,
-                            const void *tx, bool irqs_off)
+                            size_t progress, bool irqs_off)
 {
-       u8 bytes_per_word = DIV_ROUND_UP(xfer->bits_per_word, 8);
-
        if (!xfer->ptp_sts)
                return;
 
        if (xfer->timestamped_post)
                return;
 
-       if (tx < (xfer->tx_buf + xfer->ptp_sts_word_post * bytes_per_word))
+       if (progress < xfer->ptp_sts_word_post)
                return;
 
        ptp_read_system_postts(xfer->ptp_sts);
@@ -1573,7 +1567,7 @@ void spi_take_timestamp_post(struct spi_controller *ctlr,
        }
 
        /* Capture the resolution of the timestamp */
-       xfer->ptp_sts_word_post = (tx - xfer->tx_buf) / bytes_per_word;
+       xfer->ptp_sts_word_post = progress;
 
        xfer->timestamped_post = true;
 }
index 3fffe4d..f180a8e 100644 (file)
@@ -4,7 +4,7 @@
 #
 config XIL_AXIS_FIFO
        tristate "Xilinx AXI-Stream FIFO IP core driver"
-       depends on OF
+       depends on OF && HAS_IOMEM
        help
          This adds support for the Xilinx AXI-Stream FIFO IP core driver.
          The AXI Streaming FIFO allows memory mapped access to a AXI Streaming
index dbff0f7..ddc0dc9 100644 (file)
@@ -46,8 +46,8 @@
 #define PCI171X_RANGE_UNI      BIT(4)
 #define PCI171X_RANGE_GAIN(x)  (((x) & 0x7) << 0)
 #define PCI171X_MUX_REG                0x04    /* W:   A/D multiplexor control */
-#define PCI171X_MUX_CHANH(x)   (((x) & 0xf) << 8)
-#define PCI171X_MUX_CHANL(x)   (((x) & 0xf) << 0)
+#define PCI171X_MUX_CHANH(x)   (((x) & 0xff) << 8)
+#define PCI171X_MUX_CHANL(x)   (((x) & 0xff) << 0)
 #define PCI171X_MUX_CHAN(x)    (PCI171X_MUX_CHANH(x) | PCI171X_MUX_CHANL(x))
 #define PCI171X_STATUS_REG     0x06    /* R:   status register */
 #define PCI171X_STATUS_IRQ     BIT(11) /* 1=IRQ occurred */
index 4bdf44d..dc62db1 100644 (file)
@@ -623,6 +623,11 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev,
                    dma_alloc_coherent(&pcidev->dev, DMA_BUFFER_SIZE,
                                       &devpriv->dio_buffer_phys_addr[i],
                                       GFP_KERNEL);
+               if (!devpriv->dio_buffer[i]) {
+                       dev_warn(dev->class_dev,
+                                "failed to allocate DMA buffer\n");
+                       return -ENOMEM;
+               }
        }
        /* allocate dma descriptors */
        devpriv->dma_desc = dma_alloc_coherent(&pcidev->dev,
@@ -630,6 +635,11 @@ static int gsc_hpdi_auto_attach(struct comedi_device *dev,
                                               NUM_DMA_DESCRIPTORS,
                                               &devpriv->dma_desc_phys_addr,
                                               GFP_KERNEL);
+       if (!devpriv->dma_desc) {
+               dev_warn(dev->class_dev,
+                        "failed to allocate DMA descriptors\n");
+               return -ENOMEM;
+       }
        if (devpriv->dma_desc_phys_addr & 0xf) {
                dev_warn(dev->class_dev,
                         " dma descriptors not quad-word aligned (bug)\n");
index 673d732..8f398b3 100644 (file)
@@ -72,9 +72,6 @@ static int ni_find_device_routes(const char *device_family,
                }
        }
 
-       if (!rv)
-               return -ENODATA;
-
        /* Second, find the set of routes valid for this device. */
        for (i = 0; ni_device_routes_list[i]; ++i) {
                if (memcmp(ni_device_routes_list[i]->device, board_name,
@@ -84,12 +81,12 @@ static int ni_find_device_routes(const char *device_family,
                }
        }
 
-       if (!dr)
-               return -ENODATA;
-
        tables->route_values = rv;
        tables->valid_routes = dr;
 
+       if (!rv || !dr)
+               return -ENODATA;
+
        return 0;
 }
 
@@ -487,6 +484,9 @@ int ni_find_route_source(const u8 src_sel_reg_value, int dest,
 {
        int src;
 
+       if (!tables->route_values)
+               return -EINVAL;
+
        dest = B(dest); /* subtract NI names offset */
        /* ensure we are not going to under/over run the route value table */
        if (dest < 0 || dest >= NI_NUM_NAMES)
index 2aac1e0..51c665a 100644 (file)
@@ -805,8 +805,8 @@ s32 create_dir(struct inode *inode, struct chain_t *p_dir,
 s32 create_file(struct inode *inode, struct chain_t *p_dir,
                struct uni_name_t *p_uniname, u8 mode, struct file_id_t *fid);
 void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry);
-s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry,
-               struct uni_name_t *p_uniname, struct file_id_t *fid);
+s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 old_entry,
+                     struct uni_name_t *p_uniname, struct file_id_t *fid);
 s32 move_file(struct inode *inode, struct chain_t *p_olddir, s32 oldentry,
              struct chain_t *p_newdir, struct uni_name_t *p_uniname,
              struct file_id_t *fid);
index d2d3447..794000e 100644 (file)
@@ -192,8 +192,6 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
 
        exfat_bitmap_clear((u8 *)p_fs->vol_amap[i]->b_data, b);
 
-       return sector_write(sb, sector, p_fs->vol_amap[i], 0);
-
 #ifdef CONFIG_EXFAT_DISCARD
        if (opts->discard) {
                ret = sb_issue_discard(sb, START_SECTOR(clu),
@@ -202,9 +200,13 @@ static s32 clr_alloc_bitmap(struct super_block *sb, u32 clu)
                if (ret == -EOPNOTSUPP) {
                        pr_warn("discard not supported by device, disabling");
                        opts->discard = 0;
+               } else {
+                       return ret;
                }
        }
 #endif /* CONFIG_EXFAT_DISCARD */
+
+       return sector_write(sb, sector, p_fs->vol_amap[i], 0);
 }
 
 static u32 test_alloc_bitmap(struct super_block *sb, u32 clu)
@@ -2322,8 +2324,8 @@ void remove_file(struct inode *inode, struct chain_t *p_dir, s32 entry)
        fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries);
 }
 
-s32 rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
-               struct uni_name_t *p_uniname, struct file_id_t *fid)
+s32 exfat_rename_file(struct inode *inode, struct chain_t *p_dir, s32 oldentry,
+                     struct uni_name_t *p_uniname, struct file_id_t *fid)
 {
        s32 ret, newentry = -1, num_old_entries, num_new_entries;
        sector_t sector_old, sector_new;
index 6e48190..9f91853 100644 (file)
@@ -1262,8 +1262,8 @@ static int ffsMoveFile(struct inode *old_parent_inode, struct file_id_t *fid,
        fs_set_vol_flags(sb, VOL_DIRTY);
 
        if (olddir.dir == newdir.dir)
-               ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name,
-                                 fid);
+               ret = exfat_rename_file(new_parent_inode, &olddir, dentry,
+                                       &uni_name, fid);
        else
                ret = move_file(new_parent_inode, &olddir, dentry, &newdir,
                                &uni_name, fid);
index e763205..f61e373 100644 (file)
@@ -63,11 +63,17 @@ static int init_display(struct fbtft_par *par)
 {
        int ret;
 
-       /* Set CS active high */
-       par->spi->mode |= SPI_CS_HIGH;
+       /*
+        * Set CS active inverse polarity: just setting SPI_CS_HIGH does not
+        * work with GPIO based chip selects that are logically active high
+        * but inverted inside the GPIO library, so enforce inverted
+        * semantics.
+        */
+       par->spi->mode ^= SPI_CS_HIGH;
        ret = spi_setup(par->spi);
        if (ret) {
-               dev_err(par->info->device, "Could not set SPI_CS_HIGH\n");
+               dev_err(par->info->device,
+                       "Could not set inverse CS polarity\n");
                return ret;
        }
 
index 27cc8ea..76b25df 100644 (file)
@@ -150,10 +150,17 @@ static int init_display(struct fbtft_par *par)
 
        /* enable SPI interface by having CS and MOSI low during reset */
        save_mode = par->spi->mode;
-       par->spi->mode |= SPI_CS_HIGH;
-       ret = spi_setup(par->spi); /* set CS inactive low */
+       /*
+        * Set CS active inverse polarity: just setting SPI_CS_HIGH does not
+        * work with GPIO based chip selects that are logically active high
+        * but inverted inside the GPIO library, so enforce inverted
+        * semantics.
+        */
+       par->spi->mode ^= SPI_CS_HIGH;
+       ret = spi_setup(par->spi);
        if (ret) {
-               dev_err(par->info->device, "Could not set SPI_CS_HIGH\n");
+               dev_err(par->info->device,
+                       "Could not set inverse CS polarity\n");
                return ret;
        }
        write_reg(par, 0x00); /* make sure mode is set */
index ffb8498..d3e098b 100644 (file)
@@ -913,7 +913,7 @@ static int fbtft_init_display_from_property(struct fbtft_par *par)
        if (count == 0)
                return -EINVAL;
 
-       values = kmalloc_array(count, sizeof(*values), GFP_KERNEL);
+       values = kmalloc_array(count + 1, sizeof(*values), GFP_KERNEL);
        if (!values)
                return -ENOMEM;
 
@@ -926,9 +926,9 @@ static int fbtft_init_display_from_property(struct fbtft_par *par)
                gpiod_set_value(par->gpio.cs, 0);  /* Activate chip */
 
        index = -1;
-       while (index < count) {
-               val = values[++index];
+       val = values[++index];
 
+       while (index < count) {
                if (val & FBTFT_OF_INIT_CMD) {
                        val &= 0xFFFF;
                        i = 0;
index fb395cf..f20ab21 100644 (file)
@@ -6,6 +6,7 @@
 config NET_VENDOR_HP
        bool "HP devices"
        default y
+       depends on ETHERNET
        depends on ISA || EISA || PCI
        ---help---
          If you have a network (Ethernet) card belonging to this class, say Y.
index 1b9b436..a20c0bf 100644 (file)
@@ -571,8 +571,7 @@ static int gigaset_initcshw(struct cardstate *cs)
 {
        struct usb_cardstate *ucs;
 
-       cs->hw.usb = ucs =
-               kmalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
+       cs->hw.usb = ucs = kzalloc(sizeof(struct usb_cardstate), GFP_KERNEL);
        if (!ucs) {
                pr_err("out of memory\n");
                return -ENOMEM;
@@ -584,9 +583,6 @@ static int gigaset_initcshw(struct cardstate *cs)
        ucs->bchars[3] = 0;
        ucs->bchars[4] = 0x11;
        ucs->bchars[5] = 0x13;
-       ucs->bulk_out_buffer = NULL;
-       ucs->bulk_out_urb = NULL;
-       ucs->read_urb = NULL;
        tasklet_init(&cs->write_tasklet,
                     gigaset_modem_fill, (unsigned long) cs);
 
@@ -685,6 +681,11 @@ static int gigaset_probe(struct usb_interface *interface,
                return -ENODEV;
        }
 
+       if (hostif->desc.bNumEndpoints < 2) {
+               dev_err(&interface->dev, "missing endpoints\n");
+               return -ENODEV;
+       }
+
        dev_info(&udev->dev, "%s: Device matched ... !\n", __func__);
 
        /* allocate memory for our device state and initialize it */
@@ -704,6 +705,12 @@ static int gigaset_probe(struct usb_interface *interface,
 
        endpoint = &hostif->endpoint[0].desc;
 
+       if (!usb_endpoint_is_bulk_out(endpoint)) {
+               dev_err(&interface->dev, "missing bulk-out endpoint\n");
+               retval = -ENODEV;
+               goto error;
+       }
+
        buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
        ucs->bulk_out_size = buffer_size;
        ucs->bulk_out_epnum = usb_endpoint_num(endpoint);
@@ -723,6 +730,12 @@ static int gigaset_probe(struct usb_interface *interface,
 
        endpoint = &hostif->endpoint[1].desc;
 
+       if (!usb_endpoint_is_int_in(endpoint)) {
+               dev_err(&interface->dev, "missing int-in endpoint\n");
+               retval = -ENODEV;
+               goto error;
+       }
+
        ucs->busy = 0;
 
        ucs->read_urb = usb_alloc_urb(0, GFP_KERNEL);
index 08eaa0b..1c9c3ba 100644 (file)
@@ -449,7 +449,7 @@ struct ipu3_uapi_awb_fr_config_s {
        __u16 reserved1;
        __u32 bayer_sign;
        __u8 bayer_nf;
-       __u8 reserved2[3];
+       __u8 reserved2[7];
 } __attribute__((aligned(32))) __packed;
 
 /**
index 5319909..e7f4ddc 100644 (file)
@@ -3,6 +3,7 @@ config OCTEON_ETHERNET
        tristate "Cavium Networks Octeon Ethernet support"
        depends on CAVIUM_OCTEON_SOC || COMPILE_TEST
        depends on NETDEVICES
+       depends on BROKEN
        select PHYLIB
        select MDIO_OCTEON
        help
index a6886cc..56d116d 100644 (file)
@@ -41,7 +41,7 @@ struct ql_stats {
        int stat_offset;
 };
 
-#define QL_SIZEOF(m) FIELD_SIZEOF(struct ql_adapter, m)
+#define QL_SIZEOF(m) sizeof_field(struct ql_adapter, m)
 #define QL_OFF(m) offsetof(struct ql_adapter, m)
 
 static const struct ql_stats ql_gstrings_stats[] = {
index 4fac9dc..b5d42f4 100644 (file)
@@ -37,6 +37,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
        {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
        {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
+       {USB_DEVICE(0x2357, 0x0111)}, /* TP-Link TL-WN727N v5.21 */
        {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
        {}      /* Terminating entry */
@@ -70,7 +71,7 @@ static struct dvobj_priv *usb_dvobj_init(struct usb_interface *usb_intf)
        phost_conf = pusbd->actconfig;
        pconf_desc = &phost_conf->desc;
 
-       phost_iface = &usb_intf->altsetting[0];
+       phost_iface = usb_intf->cur_altsetting;
        piface_desc = &phost_iface->desc;
 
        pdvobjpriv->NumInterfaces = pconf_desc->bNumInterfaces;
index ba12882..a87562f 100644 (file)
@@ -247,7 +247,7 @@ static uint r8712_usb_dvobj_init(struct _adapter *padapter)
 
        pdvobjpriv->padapter = padapter;
        padapter->eeprom_address_size = 6;
-       phost_iface = &pintf->altsetting[0];
+       phost_iface = pintf->cur_altsetting;
        piface_desc = &phost_iface->desc;
        pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
        if (pusbd->speed == USB_SPEED_HIGH) {
index 02148a2..4458c1e 100644 (file)
@@ -3309,7 +3309,7 @@ static int __init vchiq_driver_init(void)
        return 0;
 
 region_unregister:
-       platform_driver_unregister(&vchiq_driver);
+       unregister_chrdev_region(vchiq_devid, 1);
 
 class_destroy:
        class_destroy(vchiq_class);
index 8d19ae7..4e651b6 100644 (file)
@@ -449,8 +449,8 @@ int vnt_vt3184_init(struct vnt_private *priv)
 
        memcpy(array, addr, length);
 
-       ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
-                             MESSAGE_REQUEST_BBREG, length, array);
+       ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
+                                    MESSAGE_REQUEST_BBREG, length, array);
        if (ret)
                goto end;
 
index 56cd77f..7958fc1 100644 (file)
@@ -719,7 +719,7 @@ end:
  */
 int vnt_radio_power_on(struct vnt_private *priv)
 {
-       int ret = true;
+       int ret = 0;
 
        vnt_exit_deep_sleep(priv);
 
index 6074ced..50e1c89 100644 (file)
@@ -259,6 +259,7 @@ struct vnt_private {
        u8 mac_hw;
        /* netdev */
        struct usb_device *usb;
+       struct usb_interface *intf;
 
        u64 tsf_time;
        u8 rx_rate;
index 4ac85ec..9cb924c 100644 (file)
@@ -949,7 +949,7 @@ static const struct ieee80211_ops vnt_mac_ops = {
 
 int vnt_init(struct vnt_private *priv)
 {
-       if (!(vnt_init_registers(priv)))
+       if (vnt_init_registers(priv))
                return -EAGAIN;
 
        SET_IEEE80211_PERM_ADDR(priv->hw, priv->permanent_net_addr);
@@ -992,6 +992,7 @@ vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
        priv = hw->priv;
        priv->hw = hw;
        priv->usb = udev;
+       priv->intf = intf;
 
        vnt_set_options(priv);
 
index d3304df..d977d47 100644 (file)
@@ -59,7 +59,9 @@ int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
 
        kfree(usb_buffer);
 
-       if (ret >= 0 && ret < (int)length)
+       if (ret == (int)length)
+               ret = 0;
+       else
                ret = -EIO;
 
 end_unlock:
@@ -74,6 +76,23 @@ int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
                               reg_off, reg, sizeof(u8), &data);
 }
 
+int vnt_control_out_blocks(struct vnt_private *priv,
+                          u16 block, u8 reg, u16 length, u8 *data)
+{
+       int ret = 0, i;
+
+       for (i = 0; i < length; i += block) {
+               u16 len = min_t(int, length - i, block);
+
+               ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE,
+                                     i, reg, len, data + i);
+               if (ret)
+                       goto end;
+       }
+end:
+       return ret;
+}
+
 int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
                   u16 index, u16 length, u8 *buffer)
 {
@@ -103,7 +122,9 @@ int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
 
        kfree(usb_buffer);
 
-       if (ret >= 0 && ret < (int)length)
+       if (ret == (int)length)
+               ret = 0;
+       else
                ret = -EIO;
 
 end_unlock:
index 95147ec..b65d9c0 100644 (file)
@@ -18,6 +18,8 @@
 
 #include "device.h"
 
+#define VNT_REG_BLOCK_SIZE     64
+
 int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
                    u16 index, u16 length, u8 *buffer);
 int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
@@ -26,6 +28,9 @@ int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
 int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 ref_off, u8 data);
 int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data);
 
+int vnt_control_out_blocks(struct vnt_private *priv,
+                          u16 block, u8 reg, u16 len, u8 *data);
+
 int vnt_start_interrupt_urb(struct vnt_private *priv);
 int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb);
 int vnt_tx_context(struct vnt_private *priv,
index 3eb2f11..2c5250c 100644 (file)
@@ -99,6 +99,7 @@ void vnt_run_command(struct work_struct *work)
                if (vnt_init(priv)) {
                        /* If fail all ends TODO retry */
                        dev_err(&priv->usb->dev, "failed to start\n");
+                       usb_set_intfdata(priv->intf, NULL);
                        ieee80211_free_hw(priv->hw);
                        return;
                }
index b722e97..b13d734 100644 (file)
@@ -16,7 +16,7 @@
 #include "traces.h"
 #include "hif_tx_mib.h"
 
-#define WFX_INVALID_RATE_ID (0xFF)
+#define WFX_INVALID_RATE_ID    15
 #define WFX_LINK_ID_NO_ASSOC   15
 #define WFX_LINK_ID_GC_TIMEOUT ((unsigned long)(10 * HZ))
 
@@ -184,7 +184,7 @@ static int wfx_tx_policy_get(struct wfx_vif *wvif,
                 */
                entry = list_entry(cache->free.prev, struct tx_policy, link);
                memcpy(entry->rates, wanted.rates, sizeof(entry->rates));
-               entry->uploaded = 0;
+               entry->uploaded = false;
                entry->usage_count = 0;
                idx = entry - cache->cache;
        }
@@ -202,6 +202,8 @@ static void wfx_tx_policy_put(struct wfx_vif *wvif, int idx)
        int usage, locked;
        struct tx_policy_cache *cache = &wvif->tx_policy_cache;
 
+       if (idx == WFX_INVALID_RATE_ID)
+               return;
        spin_lock_bh(&cache->lock);
        locked = list_empty(&cache->free);
        usage = wfx_tx_policy_release(cache, &cache->cache[idx]);
@@ -239,7 +241,7 @@ static int wfx_tx_policy_upload(struct wfx_vif *wvif)
                        dst->terminate = 1;
                        dst->count_init = 1;
                        memcpy(&dst->rates, src->rates, sizeof(src->rates));
-                       src->uploaded = 1;
+                       src->uploaded = true;
                        arg->num_tx_rate_policies++;
                }
        }
@@ -249,7 +251,7 @@ static int wfx_tx_policy_upload(struct wfx_vif *wvif)
        return 0;
 }
 
-static void wfx_tx_policy_upload_work(struct work_struct *work)
+void wfx_tx_policy_upload_work(struct work_struct *work)
 {
        struct wfx_vif *wvif =
                container_of(work, struct wfx_vif, tx_policy_upload_work);
@@ -270,7 +272,6 @@ void wfx_tx_policy_init(struct wfx_vif *wvif)
        spin_lock_init(&cache->lock);
        INIT_LIST_HEAD(&cache->used);
        INIT_LIST_HEAD(&cache->free);
-       INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
 
        for (i = 0; i < HIF_MIB_NUM_TX_RATE_RETRY_POLICIES; ++i)
                list_add(&cache->cache[i].link, &cache->free);
@@ -523,9 +524,9 @@ static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates)
                for (i = 0; i < IEEE80211_TX_MAX_RATES - 1; i++) {
                        if (rates[i + 1].idx == rates[i].idx &&
                            rates[i].idx != -1) {
-                               rates[i].count =
-                                       max_t(int, rates[i].count,
-                                             rates[i + 1].count);
+                               rates[i].count += rates[i + 1].count;
+                               if (rates[i].count > 15)
+                                       rates[i].count = 15;
                                rates[i + 1].idx = -1;
                                rates[i + 1].count = 0;
 
@@ -537,6 +538,17 @@ static void wfx_tx_fixup_rates(struct ieee80211_tx_rate *rates)
                        }
                }
        } while (!finished);
+       // Ensure that MCS0 or 1Mbps is present at the end of the retry list
+       for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+               if (rates[i].idx == 0)
+                       break;
+               if (rates[i].idx == -1) {
+                       rates[i].idx = 0;
+                       rates[i].count = 8; // == hw->max_rate_tries
+                       rates[i].flags = rates[i - 1].flags & IEEE80211_TX_RC_MCS;
+                       break;
+               }
+       }
        // All retries use long GI
        for (i = 1; i < IEEE80211_TX_MAX_RATES; i++)
                rates[i].flags &= ~IEEE80211_TX_RC_SHORT_GI;
@@ -550,7 +562,8 @@ static u8 wfx_tx_get_rate_id(struct wfx_vif *wvif,
 
        rate_id = wfx_tx_policy_get(wvif,
                                    tx_info->driver_rates, &tx_policy_renew);
-       WARN(rate_id == WFX_INVALID_RATE_ID, "unable to get a valid Tx policy");
+       if (rate_id == WFX_INVALID_RATE_ID)
+               dev_warn(wvif->wdev->dev, "unable to get a valid Tx policy");
 
        if (tx_policy_renew) {
                /* FIXME: It's not so optimal to stop TX queues every now and
@@ -679,7 +692,7 @@ void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
        struct ieee80211_sta *sta = control ? control->sta : NULL;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       size_t driver_data_room = FIELD_SIZEOF(struct ieee80211_tx_info,
+       size_t driver_data_room = sizeof_field(struct ieee80211_tx_info,
                                               rate_driver_data);
 
        compiletime_assert(sizeof(struct wfx_tx_priv) <= driver_data_room,
@@ -735,7 +748,9 @@ void wfx_tx_confirm_cb(struct wfx_vif *wvif, struct hif_cnf_tx *arg)
                rate = &tx_info->status.rates[i];
                if (rate->idx < 0)
                        break;
-               if (tx_count < rate->count && arg->status && arg->ack_failures)
+               if (tx_count < rate->count &&
+                   arg->status == HIF_STATUS_RETRY_EXCEEDED &&
+                   arg->ack_failures)
                        dev_dbg(wvif->wdev->dev, "all retries were not consumed: %d != %d\n",
                                rate->count, tx_count);
                if (tx_count <= rate->count && tx_count &&
index 29faa56..0fc388d 100644 (file)
@@ -39,9 +39,9 @@ struct wfx_link_entry {
 
 struct tx_policy {
        struct list_head link;
+       int usage_count;
        u8 rates[12];
-       u8 usage_count;
-       u8 uploaded;
+       bool uploaded;
 };
 
 struct tx_policy_cache {
@@ -61,6 +61,7 @@ struct wfx_tx_priv {
 } __packed;
 
 void wfx_tx_policy_init(struct wfx_vif *wvif);
+void wfx_tx_policy_upload_work(struct work_struct *work);
 
 void wfx_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
            struct sk_buff *skb);
index bb091e3..9be7488 100644 (file)
@@ -147,7 +147,6 @@ static inline int hif_set_mfp(struct wfx_vif *wvif, bool capable, bool required)
        }
        if (!required)
                val.unpmf_allowed = 1;
-       cpu_to_le32s((u32 *) &val);
        return hif_write_mib(wvif->wdev, wvif->id,
                             HIF_MIB_ID_PROTECTED_MGMT_POLICY,
                             &val, sizeof(val));
index 986a2ef..3b47b6c 100644 (file)
@@ -289,7 +289,7 @@ struct wfx_dev *wfx_init_common(struct device *dev,
        hw->sta_data_size = sizeof(struct wfx_sta_priv);
        hw->queues = 4;
        hw->max_rates = 8;
-       hw->max_rate_tries = 15;
+       hw->max_rate_tries = 8;
        hw->extra_tx_headroom = sizeof(struct hif_sl_msg_hdr) +
                                sizeof(struct hif_msg)
                                + sizeof(struct hif_req_tx)
index c7ee908..680fed3 100644 (file)
@@ -422,6 +422,7 @@ static bool hif_handle_tx_data(struct wfx_vif *wvif, struct sk_buff *skb,
                break;
        case do_wep:
                wfx_tx_lock(wvif->wdev);
+               WARN_ON(wvif->wep_pending_skb);
                wvif->wep_default_key_id = tx_priv->hw_key->keyidx;
                wvif->wep_pending_skb = skb;
                if (!schedule_work(&wvif->wep_key_work))
index 29848a2..471dd15 100644 (file)
@@ -592,6 +592,7 @@ static void wfx_do_unjoin(struct wfx_vif *wvif)
        wfx_tx_flush(wvif->wdev);
        hif_keep_alive_period(wvif, 0);
        hif_reset(wvif, false);
+       wfx_tx_policy_init(wvif);
        hif_set_output_power(wvif, wvif->wdev->output_power * 10);
        wvif->dtim_period = 0;
        hif_set_macaddr(wvif, wvif->vif->addr);
@@ -880,8 +881,10 @@ static int wfx_update_beaconing(struct wfx_vif *wvif)
                if (wvif->state != WFX_STATE_AP ||
                    wvif->beacon_int != conf->beacon_int) {
                        wfx_tx_lock_flush(wvif->wdev);
-                       if (wvif->state != WFX_STATE_PASSIVE)
+                       if (wvif->state != WFX_STATE_PASSIVE) {
                                hif_reset(wvif, false);
+                               wfx_tx_policy_init(wvif);
+                       }
                        wvif->state = WFX_STATE_PASSIVE;
                        wfx_start_ap(wvif);
                        wfx_tx_unlock(wvif->wdev);
@@ -1567,6 +1570,7 @@ int wfx_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        INIT_WORK(&wvif->set_cts_work, wfx_set_cts_work);
        INIT_WORK(&wvif->unjoin_work, wfx_unjoin_work);
 
+       INIT_WORK(&wvif->tx_policy_upload_work, wfx_tx_policy_upload_work);
        mutex_unlock(&wdev->conf_mutex);
 
        hif_set_macaddr(wvif, vif->addr);
index ac13666..082c16a 100644 (file)
@@ -4,6 +4,7 @@ config PRISM2_USB
        depends on WLAN && USB && CFG80211
        select WIRELESS_EXT
        select WEXT_PRIV
+       select CRC32
        help
          This is the wlan-ng prism 2.5/3 USB driver for a wide range of
          old USB wireless devices.
index e877b91..30ea37e 100644 (file)
@@ -708,7 +708,7 @@ static int __init cxgbit_init(void)
        pr_info("%s dcb enabled.\n", DRV_NAME);
        register_dcbevent_notifier(&cxgbit_dcbevent_nb);
 #endif
-       BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, cb) <
+       BUILD_BUG_ON(sizeof_field(struct sk_buff, cb) <
                     sizeof(union cxgbit_skb_cb));
        return 0;
 }
index 6949ea8..51ffd5c 100644 (file)
@@ -646,7 +646,9 @@ iblock_alloc_bip(struct se_cmd *cmd, struct bio *bio,
        }
 
        bip->bip_iter.bi_size = bio_integrity_bytes(bi, bio_sectors(bio));
-       bip_set_seed(bip, bio->bi_iter.bi_sector);
+       /* virtual start sector must be in integrity interval units */
+       bip_set_seed(bip, bio->bi_iter.bi_sector >>
+                                 (bi->interval_exp - SECTOR_SHIFT));
 
        pr_debug("IBLOCK BIP Size: %u Sector: %llu\n", bip->bip_iter.bi_size,
                 (unsigned long long)bip->bip_iter.bi_sector);
index 0332a53..d767eeb 100644 (file)
@@ -28,9 +28,22 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
        shm->size = PAGE_SIZE << order;
 
        if (shm->flags & TEE_SHM_DMA_BUF) {
+               unsigned int nr_pages = 1 << order, i;
+               struct page **pages;
+
+               pages = kcalloc(nr_pages, sizeof(pages), GFP_KERNEL);
+               if (!pages)
+                       return -ENOMEM;
+
+               for (i = 0; i < nr_pages; i++) {
+                       pages[i] = page;
+                       page++;
+               }
+
                shm->flags |= TEE_SHM_REGISTER;
-               rc = optee_shm_register(shm->ctx, shm, &page, 1 << order,
+               rc = optee_shm_register(shm->ctx, shm, pages, nr_pages,
                                        (unsigned long)shm->kaddr);
+               kfree(pages);
        }
 
        return rc;
index 59b79fc..79b2786 100644 (file)
@@ -108,7 +108,7 @@ config THERMAL_DEFAULT_GOV_USER_SPACE
 
 config THERMAL_DEFAULT_GOV_POWER_ALLOCATOR
        bool "power_allocator"
-       select THERMAL_GOV_POWER_ALLOCATOR
+       depends on THERMAL_GOV_POWER_ALLOCATOR
        help
          Select this if you want to control temperature based on
          system and device power allocation. This governor can only
index 015e7d2..0e7cf52 100644 (file)
@@ -110,6 +110,9 @@ static int tsens_register(struct tsens_priv *priv)
        irq = platform_get_irq_byname(pdev, "uplow");
        if (irq < 0) {
                ret = irq;
+               /* For old DTs with no IRQ defined */
+               if (irq == -ENXIO)
+                       ret = 0;
                goto err_put_device;
        }
 
index 226adee..ce5309d 100644 (file)
@@ -663,6 +663,12 @@ static acpi_status acpi_serdev_register_device(struct serdev_controller *ctrl,
        return AE_OK;
 }
 
+static const struct acpi_device_id serdev_acpi_devices_blacklist[] = {
+       { "INT3511", 0 },
+       { "INT3512", 0 },
+       { },
+};
+
 static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
                                          void *data, void **return_value)
 {
@@ -675,6 +681,10 @@ static acpi_status acpi_serdev_add_device(acpi_handle handle, u32 level,
        if (acpi_device_enumerated(adev))
                return AE_OK;
 
+       /* Skip if black listed */
+       if (!acpi_match_device_ids(adev, serdev_acpi_devices_blacklist))
+               return AE_OK;
+
        if (acpi_serdev_check_resources(ctrl, adev))
                return AE_OK;
 
index a8dc8af..1ba9bc6 100644 (file)
@@ -2270,27 +2270,6 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
                mode |= ATMEL_US_USMODE_NORMAL;
        }
 
-       /* set the mode, clock divisor, parity, stop bits and data size */
-       atmel_uart_writel(port, ATMEL_US_MR, mode);
-
-       /*
-        * when switching the mode, set the RTS line state according to the
-        * new mode, otherwise keep the former state
-        */
-       if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
-               unsigned int rts_state;
-
-               if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
-                       /* let the hardware control the RTS line */
-                       rts_state = ATMEL_US_RTSDIS;
-               } else {
-                       /* force RTS line to low level */
-                       rts_state = ATMEL_US_RTSEN;
-               }
-
-               atmel_uart_writel(port, ATMEL_US_CR, rts_state);
-       }
-
        /*
         * Set the baud rate:
         * Fractional baudrate allows to setup output frequency more
@@ -2317,6 +2296,28 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
        if (!(port->iso7816.flags & SER_ISO7816_ENABLED))
                atmel_uart_writel(port, ATMEL_US_BRGR, quot);
+
+       /* set the mode, clock divisor, parity, stop bits and data size */
+       atmel_uart_writel(port, ATMEL_US_MR, mode);
+
+       /*
+        * when switching the mode, set the RTS line state according to the
+        * new mode, otherwise keep the former state
+        */
+       if ((old_mode & ATMEL_US_USMODE) != (mode & ATMEL_US_USMODE)) {
+               unsigned int rts_state;
+
+               if ((mode & ATMEL_US_USMODE) == ATMEL_US_USMODE_HWHS) {
+                       /* let the hardware control the RTS line */
+                       rts_state = ATMEL_US_RTSDIS;
+               } else {
+                       /* force RTS line to low level */
+                       rts_state = ATMEL_US_RTSEN;
+               }
+
+               atmel_uart_writel(port, ATMEL_US_CR, rts_state);
+       }
+
        atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
        atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
        atmel_port->tx_stopped = false;
index 1cbae07..f6c45a7 100644 (file)
@@ -1580,6 +1580,7 @@ static void __msm_console_write(struct uart_port *port, const char *s,
        int num_newlines = 0;
        bool replaced = false;
        void __iomem *tf;
+       int locked = 1;
 
        if (is_uartdm)
                tf = port->membase + UARTDM_TF;
@@ -1592,7 +1593,13 @@ static void __msm_console_write(struct uart_port *port, const char *s,
                        num_newlines++;
        count += num_newlines;
 
-       spin_lock(&port->lock);
+       if (port->sysrq)
+               locked = 0;
+       else if (oops_in_progress)
+               locked = spin_trylock(&port->lock);
+       else
+               spin_lock(&port->lock);
+
        if (is_uartdm)
                msm_reset_dm_count(port, count);
 
@@ -1628,7 +1635,9 @@ static void __msm_console_write(struct uart_port *port, const char *s,
                iowrite32_rep(tf, buf, 1);
                i += num_chars;
        }
-       spin_unlock(&port->lock);
+
+       if (locked)
+               spin_unlock(&port->lock);
 }
 
 static void msm_console_write(struct console *co, const char *s,
index b0a6eb1..7c27827 100644 (file)
@@ -2834,6 +2834,7 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
        if (uport->cons && uport->dev)
                of_console_check(uport->dev->of_node, uport->cons->name, uport->line);
 
+       tty_port_link_device(port, drv->tty_driver, uport->line);
        uart_configure_port(drv, state, uport);
 
        port->console = uart_console(uport);
index 31df235..f60a59d 100644 (file)
@@ -679,6 +679,9 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
        if (ims & SPRD_IMSR_TIMEOUT)
                serial_out(port, SPRD_ICLR, SPRD_ICLR_TIMEOUT);
 
+       if (ims & SPRD_IMSR_BREAK_DETECT)
+               serial_out(port, SPRD_ICLR, SPRD_IMSR_BREAK_DETECT);
+
        if (ims & (SPRD_IMSR_RX_FIFO_FULL | SPRD_IMSR_BREAK_DETECT |
                   SPRD_IMSR_TIMEOUT))
                sprd_rx(port);
index 8b0ea8c..635cf04 100644 (file)
@@ -2124,10 +2124,11 @@ resubmit:
 /*
  * Start the modem : init the data and start kernel thread
  */
-static int uea_boot(struct uea_softc *sc)
+static int uea_boot(struct uea_softc *sc, struct usb_interface *intf)
 {
-       int ret, size;
        struct intr_pkt *intr;
+       int ret = -ENOMEM;
+       int size;
 
        uea_enters(INS_TO_USBDEV(sc));
 
@@ -2152,6 +2153,11 @@ static int uea_boot(struct uea_softc *sc)
        if (UEA_CHIP_VERSION(sc) == ADI930)
                load_XILINX_firmware(sc);
 
+       if (intf->cur_altsetting->desc.bNumEndpoints < 1) {
+               ret = -ENODEV;
+               goto err0;
+       }
+
        intr = kmalloc(size, GFP_KERNEL);
        if (!intr)
                goto err0;
@@ -2163,8 +2169,7 @@ static int uea_boot(struct uea_softc *sc)
        usb_fill_int_urb(sc->urb_int, sc->usb_dev,
                         usb_rcvintpipe(sc->usb_dev, UEA_INTR_PIPE),
                         intr, size, uea_intr, sc,
-                        sc->usb_dev->actconfig->interface[0]->altsetting[0].
-                        endpoint[0].desc.bInterval);
+                        intf->cur_altsetting->endpoint[0].desc.bInterval);
 
        ret = usb_submit_urb(sc->urb_int, GFP_KERNEL);
        if (ret < 0) {
@@ -2179,6 +2184,7 @@ static int uea_boot(struct uea_softc *sc)
        sc->kthread = kthread_create(uea_kthread, sc, "ueagle-atm");
        if (IS_ERR(sc->kthread)) {
                uea_err(INS_TO_USBDEV(sc), "failed to create thread\n");
+               ret = PTR_ERR(sc->kthread);
                goto err2;
        }
 
@@ -2193,7 +2199,7 @@ err1:
        kfree(intr);
 err0:
        uea_leaves(INS_TO_USBDEV(sc));
-       return -ENOMEM;
+       return ret;
 }
 
 /*
@@ -2548,7 +2554,7 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
                }
        }
 
-       ret = uea_boot(sc);
+       ret = uea_boot(sc, intf);
        if (ret < 0)
                goto error;
 
index dbea284..4e12a32 100644 (file)
@@ -1275,7 +1275,7 @@ EXPORT_SYMBOL_GPL(usbatm_usb_disconnect);
 
 static int __init usbatm_usb_init(void)
 {
-       if (sizeof(struct usbatm_control) > FIELD_SIZEOF(struct sk_buff, cb)) {
+       if (sizeof(struct usbatm_control) > sizeof_field(struct sk_buff, cb)) {
                printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name);
                return -EIO;
        }
index 4c1e755..02f6ca2 100644 (file)
@@ -1375,13 +1375,10 @@ static void cdns3_check_usb_interrupt_proceed(struct cdns3_device *priv_dev,
  */
 static irqreturn_t cdns3_device_irq_handler(int irq, void *data)
 {
-       struct cdns3_device *priv_dev;
-       struct cdns3 *cdns = data;
+       struct cdns3_device *priv_dev = data;
        irqreturn_t ret = IRQ_NONE;
        u32 reg;
 
-       priv_dev = cdns->gadget_dev;
-
        /* check USB device interrupt */
        reg = readl(&priv_dev->regs->usb_ists);
        if (reg) {
@@ -1419,14 +1416,12 @@ static irqreturn_t cdns3_device_irq_handler(int irq, void *data)
  */
 static irqreturn_t cdns3_device_thread_irq_handler(int irq, void *data)
 {
-       struct cdns3_device *priv_dev;
-       struct cdns3 *cdns = data;
+       struct cdns3_device *priv_dev = data;
        irqreturn_t ret = IRQ_NONE;
        unsigned long flags;
        int bit;
        u32 reg;
 
-       priv_dev = cdns->gadget_dev;
        spin_lock_irqsave(&priv_dev->lock, flags);
 
        reg = readl(&priv_dev->regs->usb_ists);
@@ -2539,7 +2534,7 @@ void cdns3_gadget_exit(struct cdns3 *cdns)
 
        priv_dev = cdns->gadget_dev;
 
-       devm_free_irq(cdns->dev, cdns->dev_irq, cdns);
+       devm_free_irq(cdns->dev, cdns->dev_irq, priv_dev);
 
        pm_runtime_mark_last_busy(cdns->dev);
        pm_runtime_put_autosuspend(cdns->dev);
@@ -2710,7 +2705,8 @@ static int __cdns3_gadget_init(struct cdns3 *cdns)
        ret = devm_request_threaded_irq(cdns->dev, cdns->dev_irq,
                                        cdns3_device_irq_handler,
                                        cdns3_device_thread_irq_handler,
-                                       IRQF_SHARED, dev_name(cdns->dev), cdns);
+                                       IRQF_SHARED, dev_name(cdns->dev),
+                                       cdns->gadget_dev);
 
        if (ret)
                goto err0;
index b45ceb9..48e4a5c 100644 (file)
@@ -26,6 +26,7 @@ static int (*orig_bus_suspend)(struct usb_hcd *hcd);
 
 struct ehci_ci_priv {
        struct regulator *reg_vbus;
+       bool enabled;
 };
 
 static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
@@ -37,7 +38,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
        int ret = 0;
        int port = HCS_N_PORTS(ehci->hcs_params);
 
-       if (priv->reg_vbus) {
+       if (priv->reg_vbus && enable != priv->enabled) {
                if (port > 1) {
                        dev_warn(dev,
                                "Not support multi-port regulator control\n");
@@ -53,6 +54,7 @@ static int ehci_ci_portpower(struct usb_hcd *hcd, int portnum, bool enable)
                                enable ? "enable" : "disable", ret);
                        return ret;
                }
+               priv->enabled = enable;
        }
 
        if (enable && (ci->platdata->phy_mode == USBPHY_INTERFACE_MODE_HSIC)) {
index 87338f9..ed204cb 100644 (file)
@@ -156,7 +156,8 @@ static int usb_conn_probe(struct platform_device *pdev)
 
        info->vbus = devm_regulator_get(dev, "vbus");
        if (IS_ERR(info->vbus)) {
-               dev_err(dev, "failed to get vbus\n");
+               if (PTR_ERR(info->vbus) != -EPROBE_DEFER)
+                       dev_err(dev, "failed to get vbus\n");
                return PTR_ERR(info->vbus);
        }
 
index 5f40117..26bc05e 100644 (file)
@@ -203,9 +203,58 @@ static const unsigned short super_speed_maxpacket_maxes[4] = {
        [USB_ENDPOINT_XFER_INT] = 1024,
 };
 
-static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
-    int asnum, struct usb_host_interface *ifp, int num_ep,
-    unsigned char *buffer, int size)
+static bool endpoint_is_duplicate(struct usb_endpoint_descriptor *e1,
+               struct usb_endpoint_descriptor *e2)
+{
+       if (e1->bEndpointAddress == e2->bEndpointAddress)
+               return true;
+
+       if (usb_endpoint_xfer_control(e1) || usb_endpoint_xfer_control(e2)) {
+               if (usb_endpoint_num(e1) == usb_endpoint_num(e2))
+                       return true;
+       }
+
+       return false;
+}
+
+/*
+ * Check for duplicate endpoint addresses in other interfaces and in the
+ * altsetting currently being parsed.
+ */
+static bool config_endpoint_is_duplicate(struct usb_host_config *config,
+               int inum, int asnum, struct usb_endpoint_descriptor *d)
+{
+       struct usb_endpoint_descriptor *epd;
+       struct usb_interface_cache *intfc;
+       struct usb_host_interface *alt;
+       int i, j, k;
+
+       for (i = 0; i < config->desc.bNumInterfaces; ++i) {
+               intfc = config->intf_cache[i];
+
+               for (j = 0; j < intfc->num_altsetting; ++j) {
+                       alt = &intfc->altsetting[j];
+
+                       if (alt->desc.bInterfaceNumber == inum &&
+                                       alt->desc.bAlternateSetting != asnum)
+                               continue;
+
+                       for (k = 0; k < alt->desc.bNumEndpoints; ++k) {
+                               epd = &alt->endpoint[k].desc;
+
+                               if (endpoint_is_duplicate(epd, d))
+                                       return true;
+                       }
+               }
+       }
+
+       return false;
+}
+
+static int usb_parse_endpoint(struct device *ddev, int cfgno,
+               struct usb_host_config *config, int inum, int asnum,
+               struct usb_host_interface *ifp, int num_ep,
+               unsigned char *buffer, int size)
 {
        unsigned char *buffer0 = buffer;
        struct usb_endpoint_descriptor *d;
@@ -242,13 +291,10 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
                goto skip_to_next_endpoint_or_interface_descriptor;
 
        /* Check for duplicate endpoint addresses */
-       for (i = 0; i < ifp->desc.bNumEndpoints; ++i) {
-               if (ifp->endpoint[i].desc.bEndpointAddress ==
-                   d->bEndpointAddress) {
-                       dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
-                           cfgno, inum, asnum, d->bEndpointAddress);
-                       goto skip_to_next_endpoint_or_interface_descriptor;
-               }
+       if (config_endpoint_is_duplicate(config, inum, asnum, d)) {
+               dev_warn(ddev, "config %d interface %d altsetting %d has a duplicate endpoint with address 0x%X, skipping\n",
+                               cfgno, inum, asnum, d->bEndpointAddress);
+               goto skip_to_next_endpoint_or_interface_descriptor;
        }
 
        endpoint = &ifp->endpoint[ifp->desc.bNumEndpoints];
@@ -346,12 +392,16 @@ static int usb_parse_endpoint(struct device *ddev, int cfgno, int inum,
                        endpoint->desc.wMaxPacketSize = cpu_to_le16(8);
        }
 
-       /* Validate the wMaxPacketSize field */
+       /*
+        * Validate the wMaxPacketSize field.
+        * Some devices have isochronous endpoints in altsetting 0;
+        * the USB-2 spec requires such endpoints to have wMaxPacketSize = 0
+        * (see the end of section 5.6.3), so don't warn about them.
+        */
        maxp = usb_endpoint_maxp(&endpoint->desc);
-       if (maxp == 0) {
-               dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has wMaxPacketSize 0, skipping\n",
+       if (maxp == 0 && !(usb_endpoint_xfer_isoc(d) && asnum == 0)) {
+               dev_warn(ddev, "config %d interface %d altsetting %d endpoint 0x%X has invalid wMaxPacketSize 0\n",
                    cfgno, inum, asnum, d->bEndpointAddress);
-               goto skip_to_next_endpoint_or_interface_descriptor;
        }
 
        /* Find the highest legal maxpacket size for this endpoint */
@@ -522,8 +572,8 @@ static int usb_parse_interface(struct device *ddev, int cfgno,
                if (((struct usb_descriptor_header *) buffer)->bDescriptorType
                     == USB_DT_INTERFACE)
                        break;
-               retval = usb_parse_endpoint(ddev, cfgno, inum, asnum, alt,
-                   num_ep, buffer, size);
+               retval = usb_parse_endpoint(ddev, cfgno, config, inum, asnum,
+                               alt, num_ep, buffer, size);
                if (retval < 0)
                        return retval;
                ++n;
index 281568d..aa45840 100644 (file)
@@ -1409,7 +1409,17 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
        if (usb_endpoint_xfer_control(&urb->ep->desc)) {
                if (hcd->self.uses_pio_for_control)
                        return ret;
-               if (hcd_uses_dma(hcd)) {
+               if (hcd->localmem_pool) {
+                       ret = hcd_alloc_coherent(
+                                       urb->dev->bus, mem_flags,
+                                       &urb->setup_dma,
+                                       (void **)&urb->setup_packet,
+                                       sizeof(struct usb_ctrlrequest),
+                                       DMA_TO_DEVICE);
+                       if (ret)
+                               return ret;
+                       urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
+               } else if (hcd_uses_dma(hcd)) {
                        if (object_is_on_stack(urb->setup_packet)) {
                                WARN_ONCE(1, "setup packet is on stack\n");
                                return -EAGAIN;
@@ -1424,23 +1434,22 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
                                                urb->setup_dma))
                                return -EAGAIN;
                        urb->transfer_flags |= URB_SETUP_MAP_SINGLE;
-               } else if (hcd->localmem_pool) {
-                       ret = hcd_alloc_coherent(
-                                       urb->dev->bus, mem_flags,
-                                       &urb->setup_dma,
-                                       (void **)&urb->setup_packet,
-                                       sizeof(struct usb_ctrlrequest),
-                                       DMA_TO_DEVICE);
-                       if (ret)
-                               return ret;
-                       urb->transfer_flags |= URB_SETUP_MAP_LOCAL;
                }
        }
 
        dir = usb_urb_dir_in(urb) ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
        if (urb->transfer_buffer_length != 0
            && !(urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) {
-               if (hcd_uses_dma(hcd)) {
+               if (hcd->localmem_pool) {
+                       ret = hcd_alloc_coherent(
+                                       urb->dev->bus, mem_flags,
+                                       &urb->transfer_dma,
+                                       &urb->transfer_buffer,
+                                       urb->transfer_buffer_length,
+                                       dir);
+                       if (ret == 0)
+                               urb->transfer_flags |= URB_MAP_LOCAL;
+               } else if (hcd_uses_dma(hcd)) {
                        if (urb->num_sgs) {
                                int n;
 
@@ -1491,15 +1500,6 @@ int usb_hcd_map_urb_for_dma(struct usb_hcd *hcd, struct urb *urb,
                                else
                                        urb->transfer_flags |= URB_DMA_MAP_SINGLE;
                        }
-               } else if (hcd->localmem_pool) {
-                       ret = hcd_alloc_coherent(
-                                       urb->dev->bus, mem_flags,
-                                       &urb->transfer_dma,
-                                       &urb->transfer_buffer,
-                                       urb->transfer_buffer_length,
-                                       dir);
-                       if (ret == 0)
-                               urb->transfer_flags |= URB_MAP_LOCAL;
                }
                if (ret && (urb->transfer_flags & (URB_SETUP_MAP_SINGLE |
                                URB_SETUP_MAP_LOCAL)))
index f229ad6..3405b14 100644 (file)
@@ -1192,6 +1192,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type)
                         * PORT_OVER_CURRENT is not. So check for any of them.
                         */
                        if (udev || (portstatus & USB_PORT_STAT_CONNECTION) ||
+                           (portchange & USB_PORT_STAT_C_CONNECTION) ||
                            (portstatus & USB_PORT_STAT_OVERCURRENT) ||
                            (portchange & USB_PORT_STAT_C_OVERCURRENT))
                                set_bit(port1, hub->change_bits);
@@ -2692,7 +2693,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub)
 #define SET_ADDRESS_TRIES      2
 #define GET_DESCRIPTOR_TRIES   2
 #define SET_CONFIG_TRIES       (2 * (use_both_schemes + 1))
-#define USE_NEW_SCHEME(i, scheme)      ((i) / 2 == (int)scheme)
+#define USE_NEW_SCHEME(i, scheme)      ((i) / 2 == (int)(scheme))
 
 #define HUB_ROOT_RESET_TIME    60      /* times are in msec */
 #define HUB_SHORT_RESET_TIME   10
index 0eab79f..da923ec 100644 (file)
@@ -45,6 +45,7 @@ void usb_init_urb(struct urb *urb)
        if (urb) {
                memset(urb, 0, sizeof(*urb));
                kref_init(&urb->kref);
+               INIT_LIST_HEAD(&urb->urb_list);
                INIT_LIST_HEAD(&urb->anchor_list);
        }
 }
index 023f035..294276f 100644 (file)
@@ -29,7 +29,8 @@
 #define PCI_DEVICE_ID_INTEL_BXT_M              0x1aaa
 #define PCI_DEVICE_ID_INTEL_APL                        0x5aaa
 #define PCI_DEVICE_ID_INTEL_KBP                        0xa2b0
-#define PCI_DEVICE_ID_INTEL_CMLH               0x02ee
+#define PCI_DEVICE_ID_INTEL_CMLLP              0x02ee
+#define PCI_DEVICE_ID_INTEL_CMLH               0x06ee
 #define PCI_DEVICE_ID_INTEL_GLK                        0x31aa
 #define PCI_DEVICE_ID_INTEL_CNPLP              0x9dee
 #define PCI_DEVICE_ID_INTEL_CNPH               0xa36e
@@ -308,6 +309,9 @@ static const struct pci_device_id dwc3_pci_id_table[] = {
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_MRFLD),
          (kernel_ulong_t) &dwc3_pci_mrfld_properties, },
 
+       { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLLP),
+         (kernel_ulong_t) &dwc3_pci_intel_properties, },
+
        { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_CMLH),
          (kernel_ulong_t) &dwc3_pci_intel_properties, },
 
index 3996b9c..fd1b100 100644 (file)
@@ -1117,6 +1117,9 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
 void dwc3_ep0_interrupt(struct dwc3 *dwc,
                const struct dwc3_event_depevt *event)
 {
+       struct dwc3_ep  *dep = dwc->eps[event->endpoint_number];
+       u8              cmd;
+
        switch (event->endpoint_event) {
        case DWC3_DEPEVT_XFERCOMPLETE:
                dwc3_ep0_xfer_complete(dwc, event);
@@ -1129,7 +1132,12 @@ void dwc3_ep0_interrupt(struct dwc3 *dwc,
        case DWC3_DEPEVT_XFERINPROGRESS:
        case DWC3_DEPEVT_RXTXFIFOEVT:
        case DWC3_DEPEVT_STREAMEVT:
+               break;
        case DWC3_DEPEVT_EPCMDCMPLT:
+               cmd = DEPEVT_PARAMETER_CMD(event->parameters);
+
+               if (cmd == DWC3_DEPCMD_ENDTRANSFER)
+                       dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
                break;
        }
 }
index a9aba71..154f3f3 100644 (file)
@@ -2467,6 +2467,13 @@ static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep,
 
 static bool dwc3_gadget_ep_request_completed(struct dwc3_request *req)
 {
+       /*
+        * For OUT direction, host may send less than the setup
+        * length. Return true for all OUT requests.
+        */
+       if (!req->direction)
+               return true;
+
        return req->request.actual == req->request.length;
 }
 
@@ -2491,7 +2498,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
 
        req->request.actual = req->request.length - req->remaining;
 
-       if (!dwc3_gadget_ep_request_completed(req) &&
+       if (!dwc3_gadget_ep_request_completed(req) ||
                        req->num_pending_sgs) {
                __dwc3_gadget_kick_transfer(dep);
                goto out;
@@ -2719,6 +2726,9 @@ static void dwc3_stop_active_transfer(struct dwc3_ep *dep, bool force,
        WARN_ON_ONCE(ret);
        dep->resource_index = 0;
 
+       if (!interrupt)
+               dep->flags &= ~DWC3_EP_TRANSFER_STARTED;
+
        if (dwc3_is_usb31(dwc) || dwc->revision < DWC3_REVISION_310A)
                udelay(100);
 }
index 6ce0440..460d5d7 100644 (file)
@@ -621,8 +621,12 @@ static void ecm_disable(struct usb_function *f)
 
        DBG(cdev, "ecm deactivated\n");
 
-       if (ecm->port.in_ep->enabled)
+       if (ecm->port.in_ep->enabled) {
                gether_disconnect(&ecm->port);
+       } else {
+               ecm->port.in_ep->desc = NULL;
+               ecm->port.out_ep->desc = NULL;
+       }
 
        usb_ep_disable(ecm->notify);
        ecm->notify->desc = NULL;
index ce1d023..0bbccac 100644 (file)
@@ -3509,7 +3509,7 @@ static void ffs_free_inst(struct usb_function_instance *f)
 
 static int ffs_set_inst_name(struct usb_function_instance *fi, const char *name)
 {
-       if (strlen(name) >= FIELD_SIZEOF(struct ffs_dev, name))
+       if (strlen(name) >= sizeof_field(struct ffs_dev, name))
                return -ENAMETOOLONG;
        return ffs_name_dev(to_f_fs_opts(fi)->dev, name);
 }
index d48df36..0d8e4a3 100644 (file)
@@ -618,6 +618,7 @@ static void rndis_disable(struct usb_function *f)
        gether_disconnect(&rndis->port);
 
        usb_ep_disable(rndis->notify);
+       rndis->notify->desc = NULL;
 }
 
 /*-------------------------------------------------------------------------*/
index ae70ce2..797d6ac 100644 (file)
@@ -445,6 +445,7 @@ config USB_TEGRA_XUDC
        tristate "NVIDIA Tegra Superspeed USB 3.0 Device Controller"
        depends on ARCH_TEGRA || COMPILE_TEST
        depends on PHY_TEGRA_XUSB
+       select USB_ROLE_SWITCH
        help
         Enables NVIDIA Tegra USB 3.0 device mode controller driver.
 
index aa2f77f..8a5c9b3 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
+/* PID Codes that are used here, from EHCI specification, Table 3-16. */
+#define PID_CODE_IN    1
+#define PID_CODE_SETUP 2
+
 /* fill a qtd, returning how much of the buffer we were able to queue up */
 
 static int
@@ -190,7 +194,7 @@ static int qtd_copy_status (
        int     status = -EINPROGRESS;
 
        /* count IN/OUT bytes, not SETUP (even short packets) */
-       if (likely (QTD_PID (token) != 2))
+       if (likely(QTD_PID(token) != PID_CODE_SETUP))
                urb->actual_length += length - QTD_LENGTH (token);
 
        /* don't modify error codes */
@@ -206,6 +210,13 @@ static int qtd_copy_status (
                if (token & QTD_STS_BABBLE) {
                        /* FIXME "must" disable babbling device's port too */
                        status = -EOVERFLOW;
+               /*
+                * When MMF is active and PID Code is IN, queue is halted.
+                * EHCI Specification, Table 4-13.
+                */
+               } else if ((token & QTD_STS_MMF) &&
+                                       (QTD_PID(token) == PID_CODE_IN)) {
+                       status = -EPROTO;
                /* CERR nonzero + halt --> stall */
                } else if (QTD_CERR(token)) {
                        status = -EPIPE;
index 38183ac..1371b0c 100644 (file)
@@ -415,13 +415,17 @@ static int ohci_da8xx_probe(struct platform_device *pdev)
        }
 
        da8xx_ohci->oc_gpio = devm_gpiod_get_optional(dev, "oc", GPIOD_IN);
-       if (IS_ERR(da8xx_ohci->oc_gpio))
+       if (IS_ERR(da8xx_ohci->oc_gpio)) {
+               error = PTR_ERR(da8xx_ohci->oc_gpio);
                goto err;
+       }
 
        if (da8xx_ohci->oc_gpio) {
                oc_irq = gpiod_to_irq(da8xx_ohci->oc_gpio);
-               if (oc_irq < 0)
+               if (oc_irq < 0) {
+                       error = oc_irq;
                        goto err;
+               }
 
                error = devm_request_threaded_irq(dev, oc_irq, NULL,
                                ohci_da8xx_oc_thread, IRQF_TRIGGER_RISING |
index b7d23c4..7a3a29e 100644 (file)
@@ -806,7 +806,7 @@ static void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status,
 
 static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
                                             u32 *status, u32 portsc,
-                                            unsigned long flags)
+                                            unsigned long *flags)
 {
        struct xhci_bus_state *bus_state;
        struct xhci_hcd *xhci;
@@ -860,11 +860,11 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
                xhci_test_and_clear_bit(xhci, port, PORT_PLC);
                xhci_set_link_state(xhci, port, XDEV_U0);
 
-               spin_unlock_irqrestore(&xhci->lock, flags);
+               spin_unlock_irqrestore(&xhci->lock, *flags);
                time_left = wait_for_completion_timeout(
                        &bus_state->rexit_done[wIndex],
                        msecs_to_jiffies(XHCI_MAX_REXIT_TIMEOUT_MS));
-               spin_lock_irqsave(&xhci->lock, flags);
+               spin_lock_irqsave(&xhci->lock, *flags);
 
                if (time_left) {
                        slot_id = xhci_find_slot_id_by_port(hcd, xhci,
@@ -920,11 +920,13 @@ static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
 {
        struct xhci_bus_state *bus_state;
        struct xhci_hcd *xhci;
+       struct usb_hcd *hcd;
        u32 link_state;
        u32 portnum;
 
        bus_state = &port->rhub->bus_state;
        xhci = hcd_to_xhci(port->rhub->hcd);
+       hcd = port->rhub->hcd;
        link_state = portsc & PORT_PLS_MASK;
        portnum = port->hcd_portnum;
 
@@ -952,12 +954,20 @@ static void xhci_get_usb3_port_status(struct xhci_port *port, u32 *status,
                        bus_state->suspended_ports &= ~(1 << portnum);
        }
 
+       /* remote wake resume signaling complete */
+       if (bus_state->port_remote_wakeup & (1 << portnum) &&
+           link_state != XDEV_RESUME &&
+           link_state != XDEV_RECOVERY) {
+               bus_state->port_remote_wakeup &= ~(1 << portnum);
+               usb_hcd_end_port_resume(&hcd->self, portnum);
+       }
+
        xhci_hub_report_usb3_link_state(xhci, status, portsc);
        xhci_del_comp_mod_timer(xhci, portsc, portnum);
 }
 
 static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
-                                     u32 portsc, unsigned long flags)
+                                     u32 portsc, unsigned long *flags)
 {
        struct xhci_bus_state *bus_state;
        u32 link_state;
@@ -1007,7 +1017,7 @@ static void xhci_get_usb2_port_status(struct xhci_port *port, u32 *status,
 static u32 xhci_get_port_status(struct usb_hcd *hcd,
                struct xhci_bus_state *bus_state,
        u16 wIndex, u32 raw_port_status,
-               unsigned long flags)
+               unsigned long *flags)
        __releases(&xhci->lock)
        __acquires(&xhci->lock)
 {
@@ -1130,7 +1140,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                }
                trace_xhci_get_port_status(wIndex, temp);
                status = xhci_get_port_status(hcd, bus_state, wIndex, temp,
-                                             flags);
+                                             &flags);
                if (status == 0xffffffff)
                        goto error;
 
index e16eda6..3b1388f 100644 (file)
@@ -1909,13 +1909,17 @@ no_bw:
        xhci->usb3_rhub.num_ports = 0;
        xhci->num_active_eps = 0;
        kfree(xhci->usb2_rhub.ports);
+       kfree(xhci->usb2_rhub.psi);
        kfree(xhci->usb3_rhub.ports);
+       kfree(xhci->usb3_rhub.psi);
        kfree(xhci->hw_ports);
        kfree(xhci->rh_bw);
        kfree(xhci->ext_caps);
 
        xhci->usb2_rhub.ports = NULL;
+       xhci->usb2_rhub.psi = NULL;
        xhci->usb3_rhub.ports = NULL;
+       xhci->usb3_rhub.psi = NULL;
        xhci->hw_ports = NULL;
        xhci->rh_bw = NULL;
        xhci->ext_caps = NULL;
index a0025d2..4917c5b 100644 (file)
@@ -519,6 +519,18 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
        retval = xhci_resume(xhci, hibernated);
        return retval;
 }
+
+static void xhci_pci_shutdown(struct usb_hcd *hcd)
+{
+       struct xhci_hcd         *xhci = hcd_to_xhci(hcd);
+       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+
+       xhci_shutdown(hcd);
+
+       /* Yet another workaround for spurious wakeups at shutdown with HSW */
+       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
+               pci_set_power_state(pdev, PCI_D3hot);
+}
 #endif /* CONFIG_PM */
 
 /*-------------------------------------------------------------------------*/
@@ -556,6 +568,7 @@ static int __init xhci_pci_init(void)
 #ifdef CONFIG_PM
        xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
        xhci_pci_hc_driver.pci_resume = xhci_pci_resume;
+       xhci_pci_hc_driver.shutdown = xhci_pci_shutdown;
 #endif
        return pci_register_driver(&xhci_pci_driver);
 }
index 6475c3d..d23f740 100644 (file)
@@ -1628,7 +1628,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
                slot_id = xhci_find_slot_id_by_port(hcd, xhci, hcd_portnum + 1);
                if (slot_id && xhci->devs[slot_id])
                        xhci->devs[slot_id]->flags |= VDEV_PORT_ERROR;
-               bus_state->port_remote_wakeup &= ~(1 << hcd_portnum);
        }
 
        if ((portsc & PORT_PLC) && (portsc & PORT_PLS_MASK) == XDEV_RESUME) {
@@ -1648,6 +1647,7 @@ static void handle_port_status(struct xhci_hcd *xhci,
                         */
                        bus_state->port_remote_wakeup |= 1 << hcd_portnum;
                        xhci_test_and_clear_bit(xhci, port, PORT_PLC);
+                       usb_hcd_start_port_resume(&hcd->self, hcd_portnum);
                        xhci_set_link_state(xhci, port, XDEV_U0);
                        /* Need to wait until the next link state change
                         * indicates the device is actually in U0.
@@ -1688,7 +1688,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
                if (slot_id && xhci->devs[slot_id])
                        xhci_ring_device(xhci, slot_id);
                if (bus_state->port_remote_wakeup & (1 << hcd_portnum)) {
-                       bus_state->port_remote_wakeup &= ~(1 << hcd_portnum);
                        xhci_test_and_clear_bit(xhci, port, PORT_PLC);
                        usb_wakeup_notification(hcd->self.root_hub,
                                        hcd_portnum + 1);
@@ -2382,7 +2381,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
        case COMP_SUCCESS:
                if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
                        break;
-               if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
+               if (xhci->quirks & XHCI_TRUST_TX_LENGTH ||
+                   ep_ring->last_td_was_short)
                        trb_comp_code = COMP_SHORT_PACKET;
                else
                        xhci_warn_ratelimited(xhci,
index 6721d05..dbac0fa 100644 (file)
@@ -770,7 +770,7 @@ static void xhci_stop(struct usb_hcd *hcd)
  *
  * This will only ever be called with the main usb_hcd (the USB3 roothub).
  */
-static void xhci_shutdown(struct usb_hcd *hcd)
+void xhci_shutdown(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
@@ -789,11 +789,8 @@ static void xhci_shutdown(struct usb_hcd *hcd)
        xhci_dbg_trace(xhci, trace_xhci_dbg_init,
                        "xhci_shutdown completed - status = %x",
                        readl(&xhci->op_regs->status));
-
-       /* Yet another workaround for spurious wakeups at shutdown with HSW */
-       if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
-               pci_set_power_state(to_pci_dev(hcd->self.sysdev), PCI_D3hot);
 }
+EXPORT_SYMBOL_GPL(xhci_shutdown);
 
 #ifdef CONFIG_PM
 static void xhci_save_registers(struct xhci_hcd *xhci)
@@ -973,7 +970,7 @@ static bool xhci_pending_portevent(struct xhci_hcd *xhci)
 int xhci_suspend(struct xhci_hcd *xhci, bool do_wakeup)
 {
        int                     rc = 0;
-       unsigned int            delay = XHCI_MAX_HALT_USEC;
+       unsigned int            delay = XHCI_MAX_HALT_USEC * 2;
        struct usb_hcd          *hcd = xhci_to_hcd(xhci);
        u32                     command;
        u32                     res;
index dc6f62a..13d8838 100644 (file)
@@ -2050,6 +2050,7 @@ int xhci_start(struct xhci_hcd *xhci);
 int xhci_reset(struct xhci_hcd *xhci);
 int xhci_run(struct usb_hcd *hcd);
 int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks);
+void xhci_shutdown(struct usb_hcd *hcd);
 void xhci_init_driver(struct hc_driver *drv,
                      const struct xhci_driver_overrides *over);
 int xhci_disable_slot(struct xhci_hcd *xhci, u32 slot_id);
index 6f5edb9..d8d157c 100644 (file)
@@ -669,7 +669,7 @@ static int adu_probe(struct usb_interface *interface,
        init_waitqueue_head(&dev->read_wait);
        init_waitqueue_head(&dev->write_wait);
 
-       res = usb_find_common_endpoints_reverse(&interface->altsetting[0],
+       res = usb_find_common_endpoints_reverse(interface->cur_altsetting,
                        NULL, NULL,
                        &dev->interrupt_in_endpoint,
                        &dev->interrupt_out_endpoint);
index 4afb5dd..e9437a1 100644 (file)
@@ -322,7 +322,7 @@ static int idmouse_probe(struct usb_interface *interface,
        int result;
 
        /* check if we have gotten the data or the hid interface */
-       iface_desc = &interface->altsetting[0];
+       iface_desc = interface->cur_altsetting;
        if (iface_desc->desc.bInterfaceClass != 0x0A)
                return -ENODEV;
 
index ac2b4fc..f48a23a 100644 (file)
@@ -1039,12 +1039,18 @@ static long mon_bin_ioctl(struct file *file, unsigned int cmd, unsigned long arg
 
                mutex_lock(&rp->fetch_lock);
                spin_lock_irqsave(&rp->b_lock, flags);
-               mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
-               kfree(rp->b_vec);
-               rp->b_vec  = vec;
-               rp->b_size = size;
-               rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
-               rp->cnt_lost = 0;
+               if (rp->mmap_active) {
+                       mon_free_buff(vec, size/CHUNK_SIZE);
+                       kfree(vec);
+                       ret = -EBUSY;
+               } else {
+                       mon_free_buff(rp->b_vec, rp->b_size/CHUNK_SIZE);
+                       kfree(rp->b_vec);
+                       rp->b_vec  = vec;
+                       rp->b_size = size;
+                       rp->b_read = rp->b_in = rp->b_out = rp->b_cnt = 0;
+                       rp->cnt_lost = 0;
+               }
                spin_unlock_irqrestore(&rp->b_lock, flags);
                mutex_unlock(&rp->fetch_lock);
                }
@@ -1216,13 +1222,21 @@ mon_bin_poll(struct file *file, struct poll_table_struct *wait)
 static void mon_bin_vma_open(struct vm_area_struct *vma)
 {
        struct mon_reader_bin *rp = vma->vm_private_data;
+       unsigned long flags;
+
+       spin_lock_irqsave(&rp->b_lock, flags);
        rp->mmap_active++;
+       spin_unlock_irqrestore(&rp->b_lock, flags);
 }
 
 static void mon_bin_vma_close(struct vm_area_struct *vma)
 {
+       unsigned long flags;
+
        struct mon_reader_bin *rp = vma->vm_private_data;
+       spin_lock_irqsave(&rp->b_lock, flags);
        rp->mmap_active--;
+       spin_unlock_irqrestore(&rp->b_lock, flags);
 }
 
 /*
@@ -1234,16 +1248,12 @@ static vm_fault_t mon_bin_vma_fault(struct vm_fault *vmf)
        unsigned long offset, chunk_idx;
        struct page *pageptr;
 
-       mutex_lock(&rp->fetch_lock);
        offset = vmf->pgoff << PAGE_SHIFT;
-       if (offset >= rp->b_size) {
-               mutex_unlock(&rp->fetch_lock);
+       if (offset >= rp->b_size)
                return VM_FAULT_SIGBUS;
-       }
        chunk_idx = offset / CHUNK_SIZE;
        pageptr = rp->b_vec[chunk_idx].pg;
        get_page(pageptr);
-       mutex_unlock(&rp->fetch_lock);
        vmf->page = pageptr;
        return 0;
 }
index 5261f8d..e3b8c84 100644 (file)
@@ -75,14 +75,17 @@ static struct musb_hdrc_platform_data jz4740_musb_platform_data = {
 static int jz4740_musb_init(struct musb *musb)
 {
        struct device *dev = musb->controller->parent;
+       int err;
 
        if (dev->of_node)
                musb->xceiv = devm_usb_get_phy_by_phandle(dev, "phys", 0);
        else
                musb->xceiv = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2);
        if (IS_ERR(musb->xceiv)) {
-               dev_err(dev, "No transceiver configured\n");
-               return PTR_ERR(musb->xceiv);
+               err = PTR_ERR(musb->xceiv);
+               if (err != -EPROBE_DEFER)
+                       dev_err(dev, "No transceiver configured: %d", err);
+               return err;
        }
 
        /* Silicon does not implement ConfigData register.
index 15cca91..5ebf30b 100644 (file)
@@ -1840,6 +1840,9 @@ ATTRIBUTE_GROUPS(musb);
 #define MUSB_QUIRK_B_INVALID_VBUS_91   (MUSB_DEVCTL_BDEVICE | \
                                         (2 << MUSB_DEVCTL_VBUS_SHIFT) | \
                                         MUSB_DEVCTL_SESSION)
+#define MUSB_QUIRK_B_DISCONNECT_99     (MUSB_DEVCTL_BDEVICE | \
+                                        (3 << MUSB_DEVCTL_VBUS_SHIFT) | \
+                                        MUSB_DEVCTL_SESSION)
 #define MUSB_QUIRK_A_DISCONNECT_19     ((3 << MUSB_DEVCTL_VBUS_SHIFT) | \
                                         MUSB_DEVCTL_SESSION)
 
@@ -1862,6 +1865,11 @@ static void musb_pm_runtime_check_session(struct musb *musb)
        s = MUSB_DEVCTL_FSDEV | MUSB_DEVCTL_LSDEV |
                MUSB_DEVCTL_HR;
        switch (devctl & ~s) {
+       case MUSB_QUIRK_B_DISCONNECT_99:
+               musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n");
+               schedule_delayed_work(&musb->irq_work,
+                                     msecs_to_jiffies(1000));
+               break;
        case MUSB_QUIRK_B_INVALID_VBUS_91:
                if (musb->quirk_retries && !musb->flush_irq_work) {
                        musb_dbg(musb,
@@ -2310,6 +2318,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        musb_disable_interrupts(musb);
        musb_writeb(musb->mregs, MUSB_DEVCTL, 0);
 
+       /* MUSB_POWER_SOFTCONN might be already set, JZ4740 does this. */
+       musb_writeb(musb->mregs, MUSB_POWER, 0);
+
        /* Init IRQ workqueue before request_irq */
        INIT_DELAYED_WORK(&musb->irq_work, musb_irq_work);
        INIT_DELAYED_WORK(&musb->deassert_reset_work, musb_deassert_reset);
index 5fc6825..2d3751d 100644 (file)
@@ -425,7 +425,7 @@ struct dma_controller *musbhs_dma_controller_create(struct musb *musb,
        controller->controller.channel_abort = dma_channel_abort;
 
        if (request_irq(irq, dma_controller_irq, 0,
-                       dev_name(musb->controller), &controller->controller)) {
+                       dev_name(musb->controller), controller)) {
                dev_err(dev, "request_irq %d failed!\n", irq);
                musb_dma_controller_destroy(&controller->controller);
 
index 8273126..63a00ff 100644 (file)
@@ -169,8 +169,8 @@ EXPORT_SYMBOL_GPL(fwnode_usb_role_switch_get);
 void usb_role_switch_put(struct usb_role_switch *sw)
 {
        if (!IS_ERR_OR_NULL(sw)) {
-               put_device(&sw->dev);
                module_put(sw->dev.parent->driver->owner);
+               put_device(&sw->dev);
        }
 }
 EXPORT_SYMBOL_GPL(usb_role_switch_put);
index df582fe..d3f420f 100644 (file)
@@ -642,9 +642,13 @@ static int ch341_tiocmget(struct tty_struct *tty)
 static int ch341_reset_resume(struct usb_serial *serial)
 {
        struct usb_serial_port *port = serial->port[0];
-       struct ch341_private *priv = usb_get_serial_port_data(port);
+       struct ch341_private *priv;
        int ret;
 
+       priv = usb_get_serial_port_data(port);
+       if (!priv)
+               return 0;
+
        /* reconfigure ch341 serial port after bus-reset */
        ch341_configure(serial->dev, priv);
 
index 48a4392..5737add 100644 (file)
@@ -716,7 +716,7 @@ static void edge_interrupt_callback(struct urb *urb)
                        if (txCredits) {
                                port = edge_serial->serial->port[portNumber];
                                edge_port = usb_get_serial_port_data(port);
-                               if (edge_port->open) {
+                               if (edge_port && edge_port->open) {
                                        spin_lock_irqsave(&edge_port->ep_lock,
                                                          flags);
                                        edge_port->txCredits += txCredits;
@@ -1725,7 +1725,8 @@ static void edge_break(struct tty_struct *tty, int break_state)
 static void process_rcvd_data(struct edgeport_serial *edge_serial,
                                unsigned char *buffer, __u16 bufferLength)
 {
-       struct device *dev = &edge_serial->serial->dev->dev;
+       struct usb_serial *serial = edge_serial->serial;
+       struct device *dev = &serial->dev->dev;
        struct usb_serial_port *port;
        struct edgeport_port *edge_port;
        __u16 lastBufferLength;
@@ -1821,11 +1822,10 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
 
                        /* spit this data back into the tty driver if this
                           port is open */
-                       if (rxLen) {
-                               port = edge_serial->serial->port[
-                                                       edge_serial->rxPort];
+                       if (rxLen && edge_serial->rxPort < serial->num_ports) {
+                               port = serial->port[edge_serial->rxPort];
                                edge_port = usb_get_serial_port_data(port);
-                               if (edge_port->open) {
+                               if (edge_port && edge_port->open) {
                                        dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n",
                                                __func__, rxLen,
                                                edge_serial->rxPort);
@@ -1833,8 +1833,8 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial,
                                                        rxLen);
                                        edge_port->port->icount.rx += rxLen;
                                }
-                               buffer += rxLen;
                        }
+                       buffer += rxLen;
                        break;
 
                case EXPECT_HDR3:       /* Expect 3rd byte of status header */
@@ -1869,6 +1869,8 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial,
        __u8 code = edge_serial->rxStatusCode;
 
        /* switch the port pointer to the one being currently talked about */
+       if (edge_serial->rxPort >= edge_serial->serial->num_ports)
+               return;
        port = edge_serial->serial->port[edge_serial->rxPort];
        edge_port = usb_get_serial_port_data(port);
        if (edge_port == NULL) {
@@ -2901,16 +2903,18 @@ static int edge_startup(struct usb_serial *serial)
        response = 0;
 
        if (edge_serial->is_epic) {
+               struct usb_host_interface *alt;
+
+               alt = serial->interface->cur_altsetting;
+
                /* EPIC thing, set up our interrupt polling now and our read
                 * urb, so that the device knows it really is connected. */
                interrupt_in_found = bulk_in_found = bulk_out_found = false;
-               for (i = 0; i < serial->interface->altsetting[0]
-                                               .desc.bNumEndpoints; ++i) {
+               for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
                        struct usb_endpoint_descriptor *endpoint;
                        int buffer_size;
 
-                       endpoint = &serial->interface->altsetting[0].
-                                                       endpoint[i].desc;
+                       endpoint = &alt->endpoint[i].desc;
                        buffer_size = usb_endpoint_maxp(endpoint);
                        if (!interrupt_in_found &&
                            (usb_endpoint_is_int_in(endpoint))) {
index e66a59e..aa3dbce 100644 (file)
@@ -1058,6 +1058,8 @@ static void       usa49_glocont_callback(struct urb *urb)
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                p_priv = usb_get_serial_port_data(port);
+               if (!p_priv)
+                       continue;
 
                if (p_priv->resend_cont) {
                        dev_dbg(&port->dev, "%s - sending setup\n", __func__);
@@ -1459,6 +1461,8 @@ static void usa67_glocont_callback(struct urb *urb)
        for (i = 0; i < serial->num_ports; ++i) {
                port = serial->port[i];
                p_priv = usb_get_serial_port_data(port);
+               if (!p_priv)
+                       continue;
 
                if (p_priv->resend_cont) {
                        dev_dbg(&port->dev, "%s - sending setup\n", __func__);
index cb7aac9..ed2b4e6 100644 (file)
@@ -113,7 +113,7 @@ static int send_control_msg(struct usb_serial_port *port, u8 requesttype,
        retval = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0),
                                requesttype,
                                USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
-                               0, 0, buffer, 1, 0);
+                               0, 0, buffer, 1, USB_CTRL_SET_TIMEOUT);
        kfree(buffer);
 
        if (retval < 0)
index e9491d4..084cc2f 100644 (file)
@@ -248,6 +248,7 @@ static void option_instat_callback(struct urb *urb);
 #define QUECTEL_PRODUCT_BG96                   0x0296
 #define QUECTEL_PRODUCT_EP06                   0x0306
 #define QUECTEL_PRODUCT_EM12                   0x0512
+#define QUECTEL_PRODUCT_RM500Q                 0x0800
 
 #define CMOTECH_VENDOR_ID                      0x16d8
 #define CMOTECH_PRODUCT_6001                   0x6001
@@ -567,6 +568,9 @@ static void option_instat_callback(struct urb *urb);
 /* Interface must have two endpoints */
 #define NUMEP2         BIT(16)
 
+/* Device needs ZLP */
+#define ZLP            BIT(17)
+
 
 static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
@@ -1101,6 +1105,11 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) | RSVD(2) | RSVD(3) | RSVD(4) | NUMEP2 },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM12, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x30) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0, 0) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM500Q, 0xff, 0xff, 0x10),
+         .driver_info = ZLP },
+
        { 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),
@@ -1172,6 +1181,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(0) | RSVD(3) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1102, 0xff),    /* Telit ME910 (ECM) */
          .driver_info = NCTRL(0) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x110a, 0xff),    /* Telit ME910G1 */
+         .driver_info = NCTRL(0) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910_USBCFG4),
@@ -1196,6 +1207,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(0) | RSVD(1) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff),    /* Telit LN940 (MBIM) */
          .driver_info = NCTRL(0) },
+       { USB_DEVICE(TELIT_VENDOR_ID, 0x9010),                          /* Telit SBL FN980 flashing device */
+         .driver_info = NCTRL(0) | ZLP },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff),
          .driver_info = RSVD(1) },
@@ -2097,6 +2110,9 @@ static int option_attach(struct usb_serial *serial)
        if (!(device_flags & NCTRL(iface_desc->bInterfaceNumber)))
                data->use_send_setup = 1;
 
+       if (device_flags & ZLP)
+               data->use_zlp = 1;
+
        spin_lock_init(&data->susp_lock);
 
        usb_set_serial_data(serial, data);
index a62981c..f93b81a 100644 (file)
@@ -841,7 +841,10 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
        u8 newMSR = (u8) *ch;
        unsigned long flags;
 
+       /* May be called from qt2_process_read_urb() for an unbound port. */
        port_priv = usb_get_serial_port_data(port);
+       if (!port_priv)
+               return;
 
        spin_lock_irqsave(&port_priv->lock, flags);
        port_priv->shadowMSR = newMSR;
@@ -869,7 +872,10 @@ static void qt2_update_lsr(struct usb_serial_port *port, unsigned char *ch)
        unsigned long flags;
        u8 newLSR = (u8) *ch;
 
+       /* May be called from qt2_process_read_urb() for an unbound port. */
        port_priv = usb_get_serial_port_data(port);
+       if (!port_priv)
+               return;
 
        if (newLSR & UART_LSR_BI)
                newLSR &= (u8) (UART_LSR_OE | UART_LSR_BI);
index edbbb13..bd23a7c 100644 (file)
@@ -86,6 +86,8 @@ DEVICE(moto_modem, MOTO_IDS);
 #define MOTOROLA_TETRA_IDS()                   \
        { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
        { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
+       { USB_DEVICE(0x0cad, 0x9013) }, /* MTP3xxx */ \
+       { USB_DEVICE(0x0cad, 0x9015) }, /* MTP85xx */ \
        { USB_DEVICE(0x0cad, 0x9016) }  /* TPG2200 */
 DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
 
index 8f066bb..dc7a65b 100644 (file)
@@ -1317,6 +1317,9 @@ static int usb_serial_register(struct usb_serial_driver *driver)
                return -EINVAL;
        }
 
+       /* Prevent individual ports from being unbound. */
+       driver->driver.suppress_bind_attrs = true;
+
        usb_serial_operations_init(driver);
 
        /* Add this device to our list of devices */
index 1c120ea..934e936 100644 (file)
@@ -38,6 +38,7 @@ struct usb_wwan_intf_private {
        spinlock_t susp_lock;
        unsigned int suspended:1;
        unsigned int use_send_setup:1;
+       unsigned int use_zlp:1;
        int in_flight;
        unsigned int open_ports;
        void *private;
index 7e855c8..13be21a 100644 (file)
@@ -461,6 +461,7 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
                                      void (*callback) (struct urb *))
 {
        struct usb_serial *serial = port->serial;
+       struct usb_wwan_intf_private *intfdata = usb_get_serial_data(serial);
        struct urb *urb;
 
        urb = usb_alloc_urb(0, GFP_KERNEL);     /* No ISO */
@@ -471,6 +472,9 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
                          usb_sndbulkpipe(serial->dev, endpoint) | dir,
                          buf, len, callback, ctx);
 
+       if (intfdata->use_zlp && dir == USB_DIR_OUT)
+               urb->transfer_flags |= URB_ZERO_PACKET;
+
        return urb;
 }
 
index 66a4dcb..f4c2359 100644 (file)
@@ -135,7 +135,8 @@ static int slave_configure(struct scsi_device *sdev)
         * For such controllers we need to make sure the block layer sets
         * up bounce buffers in addressable memory.
         */
-       if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)))
+       if (!hcd_uses_dma(bus_to_hcd(us->pusb_dev->bus)) ||
+                       (bus_to_hcd(us->pusb_dev->bus)->localmem_pool != NULL))
                blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_HIGH);
 
        /*
index 7ece6ca..91d6227 100644 (file)
@@ -1612,14 +1612,16 @@ struct typec_port *typec_register_port(struct device *parent,
 
        port->sw = typec_switch_get(&port->dev);
        if (IS_ERR(port->sw)) {
+               ret = PTR_ERR(port->sw);
                put_device(&port->dev);
-               return ERR_CAST(port->sw);
+               return ERR_PTR(ret);
        }
 
        port->mux = typec_mux_get(&port->dev, NULL);
        if (IS_ERR(port->mux)) {
+               ret = PTR_ERR(port->mux);
                put_device(&port->dev);
-               return ERR_CAST(port->mux);
+               return ERR_PTR(ret);
        }
 
        ret = device_add(&port->dev);
index 72481bb..5b986d6 100644 (file)
@@ -32,6 +32,7 @@ endif # TYPEC_TCPCI
 config TYPEC_FUSB302
        tristate "Fairchild FUSB302 Type-C chip driver"
        depends on I2C
+       depends on EXTCON || !EXTCON
        help
          The Fairchild FUSB302 Type-C chip driver that works with
          Type-C Port Controller Manager to provide USB PD and USB
index c1f7073..8b4ff9f 100644 (file)
@@ -432,20 +432,30 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci)
 
        if (status & TCPC_ALERT_RX_STATUS) {
                struct pd_message msg;
-               unsigned int cnt;
+               unsigned int cnt, payload_cnt;
                u16 header;
 
                regmap_read(tcpci->regmap, TCPC_RX_BYTE_CNT, &cnt);
+               /*
+                * 'cnt' corresponds to READABLE_BYTE_COUNT in section 4.4.14
+                * of the TCPCI spec [Rev 2.0 Ver 1.0 October 2017] and is
+                * defined in table 4-36 as one greater than the number of
+                * bytes received. And that number includes the header. So:
+                */
+               if (cnt > 3)
+                       payload_cnt = cnt - (1 + sizeof(msg.header));
+               else
+                       payload_cnt = 0;
 
                tcpci_read16(tcpci, TCPC_RX_HDR, &header);
                msg.header = cpu_to_le16(header);
 
-               if (WARN_ON(cnt > sizeof(msg.payload)))
-                       cnt = sizeof(msg.payload);
+               if (WARN_ON(payload_cnt > sizeof(msg.payload)))
+                       payload_cnt = sizeof(msg.payload);
 
-               if (cnt > 0)
+               if (payload_cnt > 0)
                        regmap_raw_read(tcpci->regmap, TCPC_RX_DATA,
-                                       &msg.payload, cnt);
+                                       &msg.payload, payload_cnt);
 
                /* Read complete, clear RX status alert bit */
                tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
index 8569bbd..831c947 100644 (file)
@@ -94,15 +94,15 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
 #define UCSI_ENABLE_NTFY_CMD_COMPLETE          BIT(16)
 #define UCSI_ENABLE_NTFY_EXT_PWR_SRC_CHANGE    BIT(17)
 #define UCSI_ENABLE_NTFY_PWR_OPMODE_CHANGE     BIT(18)
-#define UCSI_ENABLE_NTFY_CAP_CHANGE            BIT(19)
-#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE      BIT(20)
-#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE     BIT(21)
-#define UCSI_ENABLE_NTFY_CAM_CHANGE            BIT(22)
-#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE     BIT(23)
-#define UCSI_ENABLE_NTFY_PARTNER_CHANGE                BIT(24)
-#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE                BIT(25)
-#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE      BIT(26)
-#define UCSI_ENABLE_NTFY_ERROR                 BIT(27)
+#define UCSI_ENABLE_NTFY_CAP_CHANGE            BIT(21)
+#define UCSI_ENABLE_NTFY_PWR_LEVEL_CHANGE      BIT(22)
+#define UCSI_ENABLE_NTFY_PD_RESET_COMPLETE     BIT(23)
+#define UCSI_ENABLE_NTFY_CAM_CHANGE            BIT(24)
+#define UCSI_ENABLE_NTFY_BAT_STATUS_CHANGE     BIT(25)
+#define UCSI_ENABLE_NTFY_PARTNER_CHANGE                BIT(27)
+#define UCSI_ENABLE_NTFY_PWR_DIR_CHANGE                BIT(28)
+#define UCSI_ENABLE_NTFY_CONNECTOR_CHANGE      BIT(30)
+#define UCSI_ENABLE_NTFY_ERROR                 BIT(31)
 #define UCSI_ENABLE_NTFY_ALL                   0xdbe70000
 
 /* SET_UOR command bits */
index 6532d68..e4b9667 100644 (file)
@@ -727,6 +727,9 @@ int usbip_recv_xbuff(struct usbip_device *ud, struct urb *urb)
 
                        copy -= recv;
                        ret += recv;
+
+                       if (!copy)
+                               break;
                }
 
                if (ret != size)
index 33f8972..00fc987 100644 (file)
@@ -77,16 +77,21 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev,
        usbip_pack_pdu(pdu, urb, USBIP_RET_SUBMIT, 0);
 
        /* recv transfer buffer */
-       if (usbip_recv_xbuff(ud, urb) < 0)
-               return;
+       if (usbip_recv_xbuff(ud, urb) < 0) {
+               urb->status = -EPROTO;
+               goto error;
+       }
 
        /* recv iso_packet_descriptor */
-       if (usbip_recv_iso(ud, urb) < 0)
-               return;
+       if (usbip_recv_iso(ud, urb) < 0) {
+               urb->status = -EPROTO;
+               goto error;
+       }
 
        /* restore the padding in iso packets */
        usbip_pad_iso(ud, urb);
 
+error:
        if (usbip_dbg_flag_vhci_rx)
                usbip_dump_urb(urb);
 
index e05679c..93f995f 100644 (file)
 #define VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG (__GFP_NORETRY | __GFP_NOWARN | \
                                             __GFP_NOMEMALLOC)
 /* The order of free page blocks to report to host */
-#define VIRTIO_BALLOON_FREE_PAGE_ORDER (MAX_ORDER - 1)
+#define VIRTIO_BALLOON_HINT_BLOCK_ORDER (MAX_ORDER - 1)
 /* The size of a free page block in bytes */
-#define VIRTIO_BALLOON_FREE_PAGE_SIZE \
-       (1 << (VIRTIO_BALLOON_FREE_PAGE_ORDER + PAGE_SHIFT))
+#define VIRTIO_BALLOON_HINT_BLOCK_BYTES \
+       (1 << (VIRTIO_BALLOON_HINT_BLOCK_ORDER + PAGE_SHIFT))
+#define VIRTIO_BALLOON_HINT_BLOCK_PAGES (1 << VIRTIO_BALLOON_HINT_BLOCK_ORDER)
 
 #ifdef CONFIG_BALLOON_COMPACTION
 static struct vfsmount *balloon_mnt;
@@ -380,7 +381,7 @@ static unsigned long return_free_pages_to_mm(struct virtio_balloon *vb,
                if (!page)
                        break;
                free_pages((unsigned long)page_address(page),
-                          VIRTIO_BALLOON_FREE_PAGE_ORDER);
+                          VIRTIO_BALLOON_HINT_BLOCK_ORDER);
        }
        vb->num_free_page_blocks -= num_returned;
        spin_unlock_irq(&vb->free_page_list_lock);
@@ -582,7 +583,7 @@ static int get_free_page_and_send(struct virtio_balloon *vb)
                ;
 
        page = alloc_pages(VIRTIO_BALLOON_FREE_PAGE_ALLOC_FLAG,
-                          VIRTIO_BALLOON_FREE_PAGE_ORDER);
+                          VIRTIO_BALLOON_HINT_BLOCK_ORDER);
        /*
         * When the allocation returns NULL, it indicates that we have got all
         * the possible free pages, so return -EINTR to stop.
@@ -591,13 +592,13 @@ static int get_free_page_and_send(struct virtio_balloon *vb)
                return -EINTR;
 
        p = page_address(page);
-       sg_init_one(&sg, p, VIRTIO_BALLOON_FREE_PAGE_SIZE);
+       sg_init_one(&sg, p, VIRTIO_BALLOON_HINT_BLOCK_BYTES);
        /* There is always 1 entry reserved for the cmd id to use. */
        if (vq->num_free > 1) {
                err = virtqueue_add_inbuf(vq, &sg, 1, p, GFP_KERNEL);
                if (unlikely(err)) {
                        free_pages((unsigned long)p,
-                                  VIRTIO_BALLOON_FREE_PAGE_ORDER);
+                                  VIRTIO_BALLOON_HINT_BLOCK_ORDER);
                        return err;
                }
                virtqueue_kick(vq);
@@ -610,7 +611,7 @@ static int get_free_page_and_send(struct virtio_balloon *vb)
                 * The vq has no available entry to add this page block, so
                 * just free it.
                 */
-               free_pages((unsigned long)p, VIRTIO_BALLOON_FREE_PAGE_ORDER);
+               free_pages((unsigned long)p, VIRTIO_BALLOON_HINT_BLOCK_ORDER);
        }
 
        return 0;
@@ -721,6 +722,17 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info,
 
        get_page(newpage); /* balloon reference */
 
+       /*
+         * When we migrate a page to a different zone and adjusted the
+         * managed page count when inflating, we have to fixup the count of
+         * both involved zones.
+         */
+       if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_DEFLATE_ON_OOM) &&
+           page_zone(page) != page_zone(newpage)) {
+               adjust_managed_page_count(page, 1);
+               adjust_managed_page_count(newpage, -1);
+       }
+
        /* balloon's page migration 1st step  -- inflate "newpage" */
        spin_lock_irqsave(&vb_dev_info->pages_lock, flags);
        balloon_page_insert(vb_dev_info, newpage);
@@ -765,11 +777,11 @@ static unsigned long shrink_free_pages(struct virtio_balloon *vb,
        unsigned long blocks_to_free, blocks_freed;
 
        pages_to_free = round_up(pages_to_free,
-                                1 << VIRTIO_BALLOON_FREE_PAGE_ORDER);
-       blocks_to_free = pages_to_free >> VIRTIO_BALLOON_FREE_PAGE_ORDER;
+                                VIRTIO_BALLOON_HINT_BLOCK_PAGES);
+       blocks_to_free = pages_to_free / VIRTIO_BALLOON_HINT_BLOCK_PAGES;
        blocks_freed = return_free_pages_to_mm(vb, blocks_to_free);
 
-       return blocks_freed << VIRTIO_BALLOON_FREE_PAGE_ORDER;
+       return blocks_freed * VIRTIO_BALLOON_HINT_BLOCK_PAGES;
 }
 
 static unsigned long leak_balloon_pages(struct virtio_balloon *vb,
@@ -826,7 +838,7 @@ static unsigned long virtio_balloon_shrinker_count(struct shrinker *shrinker,
        unsigned long count;
 
        count = vb->num_pages / VIRTIO_BALLOON_PAGES_PER_PAGE;
-       count += vb->num_free_page_blocks << VIRTIO_BALLOON_FREE_PAGE_ORDER;
+       count += vb->num_free_page_blocks * VIRTIO_BALLOON_HINT_BLOCK_PAGES;
 
        return count;
 }
index 1679e0d..cec868f 100644 (file)
@@ -687,6 +687,7 @@ config MAX63XX_WATCHDOG
 config MAX77620_WATCHDOG
        tristate "Maxim Max77620 Watchdog Timer"
        depends on MFD_MAX77620 || COMPILE_TEST
+       select WATCHDOG_CORE
        help
         This is the driver for the Max77620 watchdog timer.
         Say 'Y' here to enable the watchdog timer support for
@@ -1444,6 +1445,7 @@ config SMSC37B787_WDT
 config TQMX86_WDT
        tristate "TQ-Systems TQMX86 Watchdog Timer"
        depends on X86
+       select WATCHDOG_CORE
        help
        This is the driver for the hardware watchdog timer in the TQMX86 IO
        controller found on some of their ComExpress Modules.
index 0a87c6f..11b9e7c 100644 (file)
@@ -112,7 +112,7 @@ static int imx7ulp_wdt_restart(struct watchdog_device *wdog,
 {
        struct imx7ulp_wdt_device *wdt = watchdog_get_drvdata(wdog);
 
-       imx7ulp_wdt_enable(wdt->base, true);
+       imx7ulp_wdt_enable(wdog, true);
        imx7ulp_wdt_set_timeout(&wdt->wdd, 1);
 
        /* wait for wdog to fire */
index 1cccf8e..8e6dfe7 100644 (file)
@@ -602,7 +602,7 @@ static int orion_wdt_probe(struct platform_device *pdev)
                set_bit(WDOG_HW_RUNNING, &dev->wdt.status);
 
        /* Request the IRQ only after the watchdog is disabled */
-       irq = platform_get_irq(pdev, 0);
+       irq = platform_get_irq_optional(pdev, 0);
        if (irq > 0) {
                /*
                 * Not all supported platforms specify an interrupt for the
@@ -617,7 +617,7 @@ static int orion_wdt_probe(struct platform_device *pdev)
        }
 
        /* Optional 2nd interrupt for pretimeout */
-       irq = platform_get_irq(pdev, 1);
+       irq = platform_get_irq_optional(pdev, 1);
        if (irq > 0) {
                orion_wdt_info.options |= WDIOF_PRETIMEOUT;
                ret = devm_request_irq(&pdev->dev, irq, orion_wdt_pre_irq,
index 2348760..6e524c8 100644 (file)
@@ -188,6 +188,7 @@ static struct platform_driver rn5t618_wdt_driver = {
 
 module_platform_driver(rn5t618_wdt_driver);
 
+MODULE_ALIAS("platform:rn5t618-wdt");
 MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
 MODULE_DESCRIPTION("RN5T618 watchdog driver");
 MODULE_LICENSE("GPL v2");
index fdf533f..56a4a40 100644 (file)
@@ -420,7 +420,7 @@ static int wdt_find(int addr)
                cr_wdt_csr = NCT6102D_WDT_CSR;
                break;
        case NCT6116_ID:
-               ret = nct6102;
+               ret = nct6116;
                cr_wdt_timeout = NCT6102D_WDT_TIMEOUT;
                cr_wdt_control = NCT6102D_WDT_CONTROL;
                cr_wdt_csr = NCT6102D_WDT_CSR;
index 4f2e78a..0c142bc 100644 (file)
@@ -394,7 +394,8 @@ static struct notifier_block xen_memory_nb = {
 #else
 static enum bp_state reserve_additional_memory(void)
 {
-       balloon_stats.target_pages = balloon_stats.current_pages;
+       balloon_stats.target_pages = balloon_stats.current_pages +
+                                    balloon_stats.target_unpopulated;
        return BP_ECANCELED;
 }
 #endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
index 49b381e..7b36b51 100644 (file)
@@ -664,7 +664,6 @@ static int grow_gnttab_list(unsigned int more_frames)
        unsigned int nr_glist_frames, new_nr_glist_frames;
        unsigned int grefs_per_frame;
 
-       BUG_ON(gnttab_interface == NULL);
        grefs_per_frame = gnttab_interface->grefs_per_grant_frame;
 
        new_nr_grant_frames = nr_grant_frames + more_frames;
@@ -1160,7 +1159,6 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs_sync);
 
 static unsigned int nr_status_frames(unsigned int nr_grant_frames)
 {
-       BUG_ON(gnttab_interface == NULL);
        return gnttab_frames(nr_grant_frames, SPP);
 }
 
@@ -1388,7 +1386,6 @@ static int gnttab_expand(unsigned int req_entries)
        int rc;
        unsigned int cur, extra;
 
-       BUG_ON(gnttab_interface == NULL);
        cur = nr_grant_frames;
        extra = ((req_entries + gnttab_interface->grefs_per_grant_frame - 1) /
                 gnttab_interface->grefs_per_grant_frame);
@@ -1423,7 +1420,6 @@ int gnttab_init(void)
        /* Determine the maximum number of frames required for the
         * grant reference free list on the current hypervisor.
         */
-       BUG_ON(gnttab_interface == NULL);
        max_nr_glist_frames = (max_nr_grant_frames *
                               gnttab_interface->grefs_per_grant_frame / RPP);
 
index d75a238..5f5b8a7 100644 (file)
@@ -116,8 +116,6 @@ int xenbus_probe_devices(struct xen_bus_type *bus);
 
 void xenbus_dev_changed(const char *node, struct xen_bus_type *bus);
 
-void xenbus_dev_shutdown(struct device *_dev);
-
 int xenbus_dev_suspend(struct device *dev);
 int xenbus_dev_resume(struct device *dev);
 int xenbus_dev_cancel(struct device *dev);
index c21be6e..378486b 100644 (file)
@@ -255,7 +255,6 @@ fail_put:
        module_put(drv->driver.owner);
 fail:
        xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->nodename);
-       xenbus_switch_state(dev, XenbusStateClosed);
        return err;
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_probe);
@@ -276,34 +275,20 @@ int xenbus_dev_remove(struct device *_dev)
 
        free_otherend_details(dev);
 
-       xenbus_switch_state(dev, XenbusStateClosed);
+       /*
+        * If the toolstack has forced the device state to closing then set
+        * the state to closed now to allow it to be cleaned up.
+        * Similarly, if the driver does not support re-bind, set the
+        * closed.
+        */
+       if (!drv->allow_rebind ||
+           xenbus_read_driver_state(dev->nodename) == XenbusStateClosing)
+               xenbus_switch_state(dev, XenbusStateClosed);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(xenbus_dev_remove);
 
-void xenbus_dev_shutdown(struct device *_dev)
-{
-       struct xenbus_device *dev = to_xenbus_device(_dev);
-       unsigned long timeout = 5*HZ;
-
-       DPRINTK("%s", dev->nodename);
-
-       get_device(&dev->dev);
-       if (dev->state != XenbusStateConnected) {
-               pr_info("%s: %s: %s != Connected, skipping\n",
-                       __func__, dev->nodename, xenbus_strstate(dev->state));
-               goto out;
-       }
-       xenbus_switch_state(dev, XenbusStateClosing);
-       timeout = wait_for_completion_timeout(&dev->down, timeout);
-       if (!timeout)
-               pr_info("%s: %s timeout closing device\n",
-                       __func__, dev->nodename);
- out:
-       put_device(&dev->dev);
-}
-EXPORT_SYMBOL_GPL(xenbus_dev_shutdown);
-
 int xenbus_register_driver_common(struct xenbus_driver *drv,
                                  struct xen_bus_type *bus,
                                  struct module *owner, const char *mod_name)
index b0bed4f..14876fa 100644 (file)
@@ -198,7 +198,6 @@ static struct xen_bus_type xenbus_backend = {
                .uevent         = xenbus_uevent_backend,
                .probe          = xenbus_dev_probe,
                .remove         = xenbus_dev_remove,
-               .shutdown       = xenbus_dev_shutdown,
                .dev_groups     = xenbus_dev_groups,
        },
 };
index a7d90a7..8a1650b 100644 (file)
@@ -126,6 +126,28 @@ static int xenbus_frontend_dev_probe(struct device *dev)
        return xenbus_dev_probe(dev);
 }
 
+static void xenbus_frontend_dev_shutdown(struct device *_dev)
+{
+       struct xenbus_device *dev = to_xenbus_device(_dev);
+       unsigned long timeout = 5*HZ;
+
+       DPRINTK("%s", dev->nodename);
+
+       get_device(&dev->dev);
+       if (dev->state != XenbusStateConnected) {
+               pr_info("%s: %s: %s != Connected, skipping\n",
+                       __func__, dev->nodename, xenbus_strstate(dev->state));
+               goto out;
+       }
+       xenbus_switch_state(dev, XenbusStateClosing);
+       timeout = wait_for_completion_timeout(&dev->down, timeout);
+       if (!timeout)
+               pr_info("%s: %s timeout closing device\n",
+                       __func__, dev->nodename);
+ out:
+       put_device(&dev->dev);
+}
+
 static const struct dev_pm_ops xenbus_pm_ops = {
        .suspend        = xenbus_dev_suspend,
        .resume         = xenbus_frontend_dev_resume,
@@ -146,7 +168,7 @@ static struct xen_bus_type xenbus_frontend = {
                .uevent         = xenbus_uevent_frontend,
                .probe          = xenbus_frontend_dev_probe,
                .remove         = xenbus_dev_remove,
-               .shutdown       = xenbus_dev_shutdown,
+               .shutdown       = xenbus_frontend_dev_shutdown,
                .dev_groups     = xenbus_dev_groups,
 
                .pm             = &xenbus_pm_ops,
index 497f979..5c794f4 100644 (file)
@@ -908,6 +908,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
                                 unsigned int flags)
 {
        struct afs_vnode *dvnode = AFS_FS_I(dir);
+       struct afs_fid fid = {};
        struct inode *inode;
        struct dentry *d;
        struct key *key;
@@ -951,21 +952,18 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
        afs_stat_v(dvnode, n_lookup);
        inode = afs_do_lookup(dir, dentry, key);
        key_put(key);
-       if (inode == ERR_PTR(-ENOENT)) {
+       if (inode == ERR_PTR(-ENOENT))
                inode = afs_try_auto_mntpt(dentry, dir);
-       } else {
-               dentry->d_fsdata =
-                       (void *)(unsigned long)dvnode->status.data_version;
-       }
+
+       if (!IS_ERR_OR_NULL(inode))
+               fid = AFS_FS_I(inode)->fid;
+
        d = d_splice_alias(inode, dentry);
        if (!IS_ERR_OR_NULL(d)) {
                d->d_fsdata = dentry->d_fsdata;
-               trace_afs_lookup(dvnode, &d->d_name,
-                                inode ? AFS_FS_I(inode) : NULL);
+               trace_afs_lookup(dvnode, &d->d_name, &fid);
        } else {
-               trace_afs_lookup(dvnode, &dentry->d_name,
-                                IS_ERR_OR_NULL(inode) ? NULL
-                                : AFS_FS_I(inode));
+               trace_afs_lookup(dvnode, &dentry->d_name, &fid);
        }
        return d;
 }
index 4150280..7503899 100644 (file)
@@ -136,6 +136,9 @@ static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentr
 
        ASSERTCMP(d_inode(dentry), ==, NULL);
 
+       if (flags & LOOKUP_CREATE)
+               return ERR_PTR(-EOPNOTSUPP);
+
        if (dentry->d_name.len >= AFSNAMEMAX) {
                _leave(" = -ENAMETOOLONG");
                return ERR_PTR(-ENAMETOOLONG);
index f532d6d..79bc5f1 100644 (file)
@@ -126,7 +126,7 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
                if (src_as->cell)
                        ctx->cell = afs_get_cell(src_as->cell);
 
-               if (size > PAGE_SIZE - 1)
+               if (size < 2 || size > PAGE_SIZE - 1)
                        return -EINVAL;
 
                page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
@@ -140,7 +140,9 @@ static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
                }
 
                buf = kmap(page);
-               ret = vfs_parse_fs_string(fc, "source", buf, size);
+               ret = -EINVAL;
+               if (buf[size - 1] == '.')
+                       ret = vfs_parse_fs_string(fc, "source", buf, size - 1);
                kunmap(page);
                put_page(page);
                if (ret < 0)
index fba2ec3..468e171 100644 (file)
@@ -213,13 +213,14 @@ static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
 
        /* Display header on line 1 */
        if (v == &cell->proc_volumes) {
-               seq_puts(m, "USE VID      TY\n");
+               seq_puts(m, "USE VID      TY NAME\n");
                return 0;
        }
 
-       seq_printf(m, "%3d %08llx %s\n",
+       seq_printf(m, "%3d %08llx %s %s\n",
                   atomic_read(&vol->usage), vol->vid,
-                  afs_vol_types[vol->type]);
+                  afs_vol_types[vol->type],
+                  vol->name);
 
        return 0;
 }
index 1686bf1..b7f3cb2 100644 (file)
@@ -32,18 +32,11 @@ static void afs_dec_servers_outstanding(struct afs_net *net)
 struct afs_server *afs_find_server(struct afs_net *net,
                                   const struct sockaddr_rxrpc *srx)
 {
-       const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
        const struct afs_addr_list *alist;
        struct afs_server *server = NULL;
        unsigned int i;
-       bool ipv6 = true;
        int seq = 0, diff;
 
-       if (srx->transport.sin6.sin6_addr.s6_addr32[0] == 0 ||
-           srx->transport.sin6.sin6_addr.s6_addr32[1] == 0 ||
-           srx->transport.sin6.sin6_addr.s6_addr32[2] == htonl(0xffff))
-               ipv6 = false;
-
        rcu_read_lock();
 
        do {
@@ -52,7 +45,8 @@ struct afs_server *afs_find_server(struct afs_net *net,
                server = NULL;
                read_seqbegin_or_lock(&net->fs_addr_lock, &seq);
 
-               if (ipv6) {
+               if (srx->transport.family == AF_INET6) {
+                       const struct sockaddr_in6 *a = &srx->transport.sin6, *b;
                        hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) {
                                alist = rcu_dereference(server->addresses);
                                for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) {
@@ -68,15 +62,16 @@ struct afs_server *afs_find_server(struct afs_net *net,
                                }
                        }
                } else {
+                       const struct sockaddr_in *a = &srx->transport.sin, *b;
                        hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) {
                                alist = rcu_dereference(server->addresses);
                                for (i = 0; i < alist->nr_ipv4; i++) {
-                                       b = &alist->addrs[i].transport.sin6;
-                                       diff = ((u16 __force)a->sin6_port -
-                                               (u16 __force)b->sin6_port);
+                                       b = &alist->addrs[i].transport.sin;
+                                       diff = ((u16 __force)a->sin_port -
+                                               (u16 __force)b->sin_port);
                                        if (diff == 0)
-                                               diff = ((u32 __force)a->sin6_addr.s6_addr32[3] -
-                                                       (u32 __force)b->sin6_addr.s6_addr32[3]);
+                                               diff = ((u32 __force)a->sin_addr.s_addr -
+                                                       (u32 __force)b->sin_addr.s_addr);
                                        if (diff == 0)
                                                goto found;
                                }
index 488641b..7f8a9b3 100644 (file)
@@ -404,6 +404,7 @@ static int afs_test_super(struct super_block *sb, struct fs_context *fc)
        return (as->net_ns == fc->net_ns &&
                as->volume &&
                as->volume->vid == ctx->volume->vid &&
+               as->cell == ctx->cell &&
                !as->dyn_root);
 }
 
@@ -448,7 +449,6 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx)
        /* allocate the root inode and dentry */
        if (as->dyn_root) {
                inode = afs_iget_pseudo_dir(sb, true);
-               sb->s_flags     |= SB_RDONLY;
        } else {
                sprintf(sb->s_id, "%llu", as->volume->vid);
                afs_activate_volume(as->volume);
index 75b6d10..575636f 100644 (file)
@@ -7,6 +7,7 @@ config BTRFS_FS
        select LIBCRC32C
        select CRYPTO_XXHASH
        select CRYPTO_SHA256
+       select CRYPTO_BLAKE2B
        select ZLIB_INFLATE
        select ZLIB_DEFLATE
        select LZO_COMPRESS
index ee834ef..43e1660 100644 (file)
@@ -447,7 +447,7 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start,
 
        if (blkcg_css) {
                bio->bi_opf |= REQ_CGROUP_PUNT;
-               bio_associate_blkg_from_css(bio, blkcg_css);
+               kthread_associate_blkcg(blkcg_css);
        }
        refcount_set(&cb->pending_bios, 1);
 
@@ -491,6 +491,8 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start,
                        bio->bi_opf = REQ_OP_WRITE | write_flags;
                        bio->bi_private = cb;
                        bio->bi_end_io = end_compressed_bio_write;
+                       if (blkcg_css)
+                               bio->bi_opf |= REQ_CGROUP_PUNT;
                        bio_add_page(bio, page, PAGE_SIZE, 0);
                }
                if (bytes_left < PAGE_SIZE) {
@@ -517,6 +519,9 @@ blk_status_t btrfs_submit_compressed_write(struct inode *inode, u64 start,
                bio_endio(bio);
        }
 
+       if (blkcg_css)
+               kthread_associate_blkcg(NULL);
+
        return 0;
 }
 
index 5b6e86a..24658b5 100644 (file)
@@ -379,7 +379,7 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info,
        for (node = rb_first(tm_root); node; node = next) {
                next = rb_next(node);
                tm = rb_entry(node, struct tree_mod_elem, node);
-               if (tm->seq > min_seq)
+               if (tm->seq >= min_seq)
                        continue;
                rb_erase(node, tm_root);
                kfree(tm);
index b2e8fd8..54efb21 100644 (file)
@@ -2787,7 +2787,7 @@ struct btrfs_inode_extref *btrfs_find_name_in_ext_backref(
 /* file-item.c */
 struct btrfs_dio_private;
 int btrfs_del_csums(struct btrfs_trans_handle *trans,
-                   struct btrfs_fs_info *fs_info, u64 bytenr, u64 len);
+                   struct btrfs_root *root, u64 bytenr, u64 len);
 blk_status_t btrfs_lookup_bio_sums(struct inode *inode, struct bio *bio,
                                   u8 *dst);
 blk_status_t btrfs_lookup_bio_sums_dio(struct inode *inode, struct bio *bio,
index 153f71a..274318e 100644 (file)
@@ -1869,8 +1869,8 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
                btrfs_pin_extent(fs_info, head->bytenr,
                                 head->num_bytes, 1);
                if (head->is_data) {
-                       ret = btrfs_del_csums(trans, fs_info, head->bytenr,
-                                             head->num_bytes);
+                       ret = btrfs_del_csums(trans, fs_info->csum_root,
+                                             head->bytenr, head->num_bytes);
                }
        }
 
@@ -3175,7 +3175,8 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
                btrfs_release_path(path);
 
                if (is_data) {
-                       ret = btrfs_del_csums(trans, info, bytenr, num_bytes);
+                       ret = btrfs_del_csums(trans, info->csum_root, bytenr,
+                                             num_bytes);
                        if (ret) {
                                btrfs_abort_transaction(trans, ret);
                                goto out;
@@ -3799,6 +3800,7 @@ static noinline int find_free_extent(struct btrfs_fs_info *fs_info,
                                u64 flags, int delalloc)
 {
        int ret = 0;
+       int cache_block_group_error = 0;
        struct btrfs_free_cluster *last_ptr = NULL;
        struct btrfs_block_group *block_group = NULL;
        struct find_free_extent_ctl ffe_ctl = {0};
@@ -3958,7 +3960,20 @@ have_block_group:
                if (unlikely(!ffe_ctl.cached)) {
                        ffe_ctl.have_caching_bg = true;
                        ret = btrfs_cache_block_group(block_group, 0);
-                       BUG_ON(ret < 0);
+
+                       /*
+                        * If we get ENOMEM here or something else we want to
+                        * try other block groups, because it may not be fatal.
+                        * However if we can't find anything else we need to
+                        * save our return here so that we return the actual
+                        * error that caused problems, not ENOSPC.
+                        */
+                       if (ret < 0) {
+                               if (!cache_block_group_error)
+                                       cache_block_group_error = ret;
+                               ret = 0;
+                               goto loop;
+                       }
                        ret = 0;
                }
 
@@ -4045,7 +4060,7 @@ loop:
        if (ret > 0)
                goto search;
 
-       if (ret == -ENOSPC) {
+       if (ret == -ENOSPC && !cache_block_group_error) {
                /*
                 * Use ffe_ctl->total_free_space as fallback if we can't find
                 * any contiguous hole.
@@ -4056,6 +4071,8 @@ loop:
                space_info->max_extent_size = ffe_ctl.max_extent_size;
                spin_unlock(&space_info->lock);
                ins->offset = ffe_ctl.max_extent_size;
+       } else if (ret == -ENOSPC) {
+               ret = cache_block_group_error;
        }
        return ret;
 }
index eb8bd02..2f4802f 100644 (file)
@@ -5074,12 +5074,14 @@ struct extent_buffer *alloc_test_extent_buffer(struct btrfs_fs_info *fs_info,
                return eb;
        eb = alloc_dummy_extent_buffer(fs_info, start);
        if (!eb)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
        eb->fs_info = fs_info;
 again:
        ret = radix_tree_preload(GFP_NOFS);
-       if (ret)
+       if (ret) {
+               exists = ERR_PTR(ret);
                goto free_eb;
+       }
        spin_lock(&fs_info->buffer_lock);
        ret = radix_tree_insert(&fs_info->buffer_radix,
                                start >> PAGE_SHIFT, eb);
index 3270a40..b1bfdc5 100644 (file)
@@ -590,9 +590,9 @@ static noinline void truncate_one_csum(struct btrfs_fs_info *fs_info,
  * range of bytes.
  */
 int btrfs_del_csums(struct btrfs_trans_handle *trans,
-                   struct btrfs_fs_info *fs_info, u64 bytenr, u64 len)
+                   struct btrfs_root *root, u64 bytenr, u64 len)
 {
-       struct btrfs_root *root = fs_info->csum_root;
+       struct btrfs_fs_info *fs_info = trans->fs_info;
        struct btrfs_path *path;
        struct btrfs_key key;
        u64 end_byte = bytenr + len;
@@ -602,6 +602,9 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
        u16 csum_size = btrfs_super_csum_size(fs_info->super_copy);
        int blocksize_bits = fs_info->sb->s_blocksize_bits;
 
+       ASSERT(root == fs_info->csum_root ||
+              root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID);
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
index 0cb43b6..8d47c76 100644 (file)
@@ -2599,8 +2599,8 @@ int btrfs_punch_hole_range(struct inode *inode, struct btrfs_path *path,
                        }
                }
 
-               if (clone_info) {
-                       u64 clone_len = drop_end - cur_offset;
+               if (clone_info && drop_end > clone_info->file_offset) {
+                       u64 clone_len = drop_end - clone_info->file_offset;
 
                        ret = btrfs_insert_clone_extent(trans, inode, path,
                                                        clone_info, clone_len);
index 56032c5..c70baaf 100644 (file)
@@ -1479,10 +1479,10 @@ next_slot:
                        disk_num_bytes =
                                btrfs_file_extent_disk_num_bytes(leaf, fi);
                        /*
-                        * If extent we got ends before our range starts, skip
-                        * to next extent
+                        * If the extent we got ends before our current offset,
+                        * skip to the next extent.
                         */
-                       if (extent_end <= start) {
+                       if (extent_end <= cur_offset) {
                                path->slots[0]++;
                                goto next_slot;
                        }
@@ -4238,18 +4238,30 @@ out:
 }
 
 static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
-                              struct inode *dir, u64 objectid,
-                              const char *name, int name_len)
+                              struct inode *dir, struct dentry *dentry)
 {
        struct btrfs_root *root = BTRFS_I(dir)->root;
+       struct btrfs_inode *inode = BTRFS_I(d_inode(dentry));
        struct btrfs_path *path;
        struct extent_buffer *leaf;
        struct btrfs_dir_item *di;
        struct btrfs_key key;
+       const char *name = dentry->d_name.name;
+       int name_len = dentry->d_name.len;
        u64 index;
        int ret;
+       u64 objectid;
        u64 dir_ino = btrfs_ino(BTRFS_I(dir));
 
+       if (btrfs_ino(inode) == BTRFS_FIRST_FREE_OBJECTID) {
+               objectid = inode->root->root_key.objectid;
+       } else if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) {
+               objectid = inode->location.objectid;
+       } else {
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
        path = btrfs_alloc_path();
        if (!path)
                return -ENOMEM;
@@ -4271,13 +4283,16 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
        }
        btrfs_release_path(path);
 
-       ret = btrfs_del_root_ref(trans, objectid, root->root_key.objectid,
-                                dir_ino, &index, name, name_len);
-       if (ret < 0) {
-               if (ret != -ENOENT) {
-                       btrfs_abort_transaction(trans, ret);
-                       goto out;
-               }
+       /*
+        * This is a placeholder inode for a subvolume we didn't have a
+        * reference to at the time of the snapshot creation.  In the meantime
+        * we could have renamed the real subvol link into our snapshot, so
+        * depending on btrfs_del_root_ref to return -ENOENT here is incorret.
+        * Instead simply lookup the dir_index_item for this entry so we can
+        * remove it.  Otherwise we know we have a ref to the root and we can
+        * call btrfs_del_root_ref, and it _shouldn't_ fail.
+        */
+       if (btrfs_ino(inode) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID) {
                di = btrfs_search_dir_index_item(root, path, dir_ino,
                                                 name, name_len);
                if (IS_ERR_OR_NULL(di)) {
@@ -4292,8 +4307,16 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
                leaf = path->nodes[0];
                btrfs_item_key_to_cpu(leaf, &key, path->slots[0]);
                index = key.offset;
+               btrfs_release_path(path);
+       } else {
+               ret = btrfs_del_root_ref(trans, objectid,
+                                        root->root_key.objectid, dir_ino,
+                                        &index, name, name_len);
+               if (ret) {
+                       btrfs_abort_transaction(trans, ret);
+                       goto out;
+               }
        }
-       btrfs_release_path(path);
 
        ret = btrfs_delete_delayed_dir_index(trans, BTRFS_I(dir), index);
        if (ret) {
@@ -4487,8 +4510,7 @@ int btrfs_delete_subvolume(struct inode *dir, struct dentry *dentry)
 
        btrfs_record_snapshot_destroy(trans, BTRFS_I(dir));
 
-       ret = btrfs_unlink_subvol(trans, dir, dest->root_key.objectid,
-                                 dentry->d_name.name, dentry->d_name.len);
+       ret = btrfs_unlink_subvol(trans, dir, dentry);
        if (ret) {
                err = ret;
                btrfs_abort_transaction(trans, ret);
@@ -4583,10 +4605,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
                return PTR_ERR(trans);
 
        if (unlikely(btrfs_ino(BTRFS_I(inode)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
-               err = btrfs_unlink_subvol(trans, dir,
-                                         BTRFS_I(inode)->location.objectid,
-                                         dentry->d_name.name,
-                                         dentry->d_name.len);
+               err = btrfs_unlink_subvol(trans, dir, dentry);
                goto out;
        }
 
@@ -5728,7 +5747,6 @@ static void inode_tree_add(struct inode *inode)
 
 static void inode_tree_del(struct inode *inode)
 {
-       struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_root *root = BTRFS_I(inode)->root;
        int empty = 0;
 
@@ -5741,7 +5759,6 @@ static void inode_tree_del(struct inode *inode)
        spin_unlock(&root->inode_lock);
 
        if (empty && btrfs_root_refs(&root->root_item) == 0) {
-               synchronize_srcu(&fs_info->subvol_srcu);
                spin_lock(&root->inode_lock);
                empty = RB_EMPTY_ROOT(&root->inode_tree);
                spin_unlock(&root->inode_lock);
@@ -9538,7 +9555,6 @@ static int btrfs_rename_exchange(struct inode *old_dir,
        u64 new_ino = btrfs_ino(BTRFS_I(new_inode));
        u64 old_idx = 0;
        u64 new_idx = 0;
-       u64 root_objectid;
        int ret;
        bool root_log_pinned = false;
        bool dest_log_pinned = false;
@@ -9556,9 +9572,8 @@ static int btrfs_rename_exchange(struct inode *old_dir,
        btrfs_init_log_ctx(&ctx_dest, new_inode);
 
        /* close the race window with snapshot create/destroy ioctl */
-       if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
-               down_read(&fs_info->subvol_sem);
-       if (new_ino == BTRFS_FIRST_FREE_OBJECTID)
+       if (old_ino == BTRFS_FIRST_FREE_OBJECTID ||
+           new_ino == BTRFS_FIRST_FREE_OBJECTID)
                down_read(&fs_info->subvol_sem);
 
        /*
@@ -9645,10 +9660,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
 
        /* src is a subvolume */
        if (old_ino == BTRFS_FIRST_FREE_OBJECTID) {
-               root_objectid = BTRFS_I(old_inode)->root->root_key.objectid;
-               ret = btrfs_unlink_subvol(trans, old_dir, root_objectid,
-                                         old_dentry->d_name.name,
-                                         old_dentry->d_name.len);
+               ret = btrfs_unlink_subvol(trans, old_dir, old_dentry);
        } else { /* src is an inode */
                ret = __btrfs_unlink_inode(trans, root, BTRFS_I(old_dir),
                                           BTRFS_I(old_dentry->d_inode),
@@ -9664,10 +9676,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
 
        /* dest is a subvolume */
        if (new_ino == BTRFS_FIRST_FREE_OBJECTID) {
-               root_objectid = BTRFS_I(new_inode)->root->root_key.objectid;
-               ret = btrfs_unlink_subvol(trans, new_dir, root_objectid,
-                                         new_dentry->d_name.name,
-                                         new_dentry->d_name.len);
+               ret = btrfs_unlink_subvol(trans, new_dir, new_dentry);
        } else { /* dest is an inode */
                ret = __btrfs_unlink_inode(trans, dest, BTRFS_I(new_dir),
                                           BTRFS_I(new_dentry->d_inode),
@@ -9792,9 +9801,8 @@ out_fail:
                ret = ret ? ret : ret2;
        }
 out_notrans:
-       if (new_ino == BTRFS_FIRST_FREE_OBJECTID)
-               up_read(&fs_info->subvol_sem);
-       if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
+       if (new_ino == BTRFS_FIRST_FREE_OBJECTID ||
+           old_ino == BTRFS_FIRST_FREE_OBJECTID)
                up_read(&fs_info->subvol_sem);
 
        ASSERT(list_empty(&ctx_root.list));
@@ -9866,7 +9874,6 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct inode *new_inode = d_inode(new_dentry);
        struct inode *old_inode = d_inode(old_dentry);
        u64 index = 0;
-       u64 root_objectid;
        int ret;
        u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
        bool log_pinned = false;
@@ -9974,10 +9981,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                                BTRFS_I(old_inode), 1);
 
        if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) {
-               root_objectid = BTRFS_I(old_inode)->root->root_key.objectid;
-               ret = btrfs_unlink_subvol(trans, old_dir, root_objectid,
-                                       old_dentry->d_name.name,
-                                       old_dentry->d_name.len);
+               ret = btrfs_unlink_subvol(trans, old_dir, old_dentry);
        } else {
                ret = __btrfs_unlink_inode(trans, root, BTRFS_I(old_dir),
                                        BTRFS_I(d_inode(old_dentry)),
@@ -9996,10 +10000,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                new_inode->i_ctime = current_time(new_inode);
                if (unlikely(btrfs_ino(BTRFS_I(new_inode)) ==
                             BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)) {
-                       root_objectid = BTRFS_I(new_inode)->location.objectid;
-                       ret = btrfs_unlink_subvol(trans, new_dir, root_objectid,
-                                               new_dentry->d_name.name,
-                                               new_dentry->d_name.len);
+                       ret = btrfs_unlink_subvol(trans, new_dir, new_dentry);
                        BUG_ON(new_inode->i_nlink == 0);
                } else {
                        ret = btrfs_unlink_inode(trans, dest, BTRFS_I(new_dir),
index a1ee0b7..12ae31e 100644 (file)
@@ -704,11 +704,17 @@ static noinline int create_subvol(struct inode *dir,
 
        btrfs_i_size_write(BTRFS_I(dir), dir->i_size + namelen * 2);
        ret = btrfs_update_inode(trans, root, dir);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, ret);
+               goto fail;
+       }
 
        ret = btrfs_add_root_ref(trans, objectid, root->root_key.objectid,
                                 btrfs_ino(BTRFS_I(dir)), index, name, namelen);
-       BUG_ON(ret);
+       if (ret) {
+               btrfs_abort_transaction(trans, ret);
+               goto fail;
+       }
 
        ret = btrfs_uuid_tree_add(trans, root_item->uuid,
                                  BTRFS_UUID_KEY_SUBVOL, objectid);
@@ -3720,24 +3726,18 @@ process_slot:
        ret = 0;
 
        if (last_dest_end < destoff + len) {
-               struct btrfs_clone_extent_info clone_info = { 0 };
                /*
-                * We have an implicit hole (NO_HOLES feature is enabled) that
-                * fully or partially overlaps our cloning range at its end.
+                * We have an implicit hole that fully or partially overlaps our
+                * cloning range at its end. This means that we either have the
+                * NO_HOLES feature enabled or the implicit hole happened due to
+                * mixing buffered and direct IO writes against this file.
                 */
                btrfs_release_path(path);
                path->leave_spinning = 0;
 
-               /*
-                * We are dealing with a hole and our clone_info already has a
-                * disk_offset of 0, we only need to fill the data length and
-                * file offset.
-                */
-               clone_info.data_len = destoff + len - last_dest_end;
-               clone_info.file_offset = last_dest_end;
                ret = btrfs_punch_hole_range(inode, path,
                                             last_dest_end, destoff + len - 1,
-                                            &clone_info, &trans);
+                                            NULL, &trans);
                if (ret)
                        goto out;
 
@@ -4252,7 +4252,19 @@ static long btrfs_ioctl_scrub(struct file *file, void __user *arg)
                              &sa->progress, sa->flags & BTRFS_SCRUB_READONLY,
                              0);
 
-       if (ret == 0 && copy_to_user(arg, sa, sizeof(*sa)))
+       /*
+        * Copy scrub args to user space even if btrfs_scrub_dev() returned an
+        * error. This is important as it allows user space to know how much
+        * progress scrub has done. For example, if scrub is canceled we get
+        * -ECANCELED from btrfs_scrub_dev() and return that error back to user
+        * space. Later user space can inspect the progress from the structure
+        * btrfs_ioctl_scrub_args and resume scrub from where it left off
+        * previously (btrfs-progs does this).
+        * If we fail to copy the btrfs_ioctl_scrub_args structure to user space
+        * then return -EFAULT to signal the structure was not copied or it may
+        * be corrupt and unreliable due to a partial copy.
+        */
+       if (copy_to_user(arg, sa, sizeof(*sa)))
                ret = -EFAULT;
 
        if (!(sa->flags & BTRFS_SCRUB_READONLY))
index 93aeb2e..39fc8c3 100644 (file)
@@ -2423,8 +2423,12 @@ int btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,
        u64 nr_old_roots = 0;
        int ret = 0;
 
+       /*
+        * If quotas get disabled meanwhile, the resouces need to be freed and
+        * we can't just exit here.
+        */
        if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
-               return 0;
+               goto out_free;
 
        if (new_roots) {
                if (!maybe_fs_roots(new_roots))
@@ -3232,12 +3236,12 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
                if (!(fs_info->qgroup_flags &
                      BTRFS_QGROUP_STATUS_FLAG_RESCAN)) {
                        btrfs_warn(fs_info,
-                       "qgroup rescan init failed, qgroup is not enabled");
+                       "qgroup rescan init failed, qgroup rescan is not queued");
                        ret = -EINVAL;
                } else if (!(fs_info->qgroup_flags &
                             BTRFS_QGROUP_STATUS_FLAG_ON)) {
                        btrfs_warn(fs_info,
-                       "qgroup rescan init failed, qgroup rescan is not queued");
+                       "qgroup rescan init failed, qgroup is not enabled");
                        ret = -EINVAL;
                }
 
index d897a8e..da5abd6 100644 (file)
@@ -517,6 +517,34 @@ static int update_backref_cache(struct btrfs_trans_handle *trans,
        return 1;
 }
 
+static bool reloc_root_is_dead(struct btrfs_root *root)
+{
+       /*
+        * Pair with set_bit/clear_bit in clean_dirty_subvols and
+        * btrfs_update_reloc_root. We need to see the updated bit before
+        * trying to access reloc_root
+        */
+       smp_rmb();
+       if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
+               return true;
+       return false;
+}
+
+/*
+ * Check if this subvolume tree has valid reloc tree.
+ *
+ * Reloc tree after swap is considered dead, thus not considered as valid.
+ * This is enough for most callers, as they don't distinguish dead reloc root
+ * from no reloc root.  But should_ignore_root() below is a special case.
+ */
+static bool have_reloc_root(struct btrfs_root *root)
+{
+       if (reloc_root_is_dead(root))
+               return false;
+       if (!root->reloc_root)
+               return false;
+       return true;
+}
 
 static int should_ignore_root(struct btrfs_root *root)
 {
@@ -525,6 +553,10 @@ static int should_ignore_root(struct btrfs_root *root)
        if (!test_bit(BTRFS_ROOT_REF_COWS, &root->state))
                return 0;
 
+       /* This root has been merged with its reloc tree, we can ignore it */
+       if (reloc_root_is_dead(root))
+               return 1;
+
        reloc_root = root->reloc_root;
        if (!reloc_root)
                return 0;
@@ -1439,7 +1471,7 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
         * The subvolume has reloc tree but the swap is finished, no need to
         * create/update the dead reloc tree
         */
-       if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state))
+       if (reloc_root_is_dead(root))
                return 0;
 
        if (root->reloc_root) {
@@ -1478,8 +1510,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
        struct btrfs_root_item *root_item;
        int ret;
 
-       if (test_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state) ||
-           !root->reloc_root)
+       if (!have_reloc_root(root))
                goto out;
 
        reloc_root = root->reloc_root;
@@ -1489,6 +1520,11 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans,
        if (fs_info->reloc_ctl->merge_reloc_tree &&
            btrfs_root_refs(root_item) == 0) {
                set_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state);
+               /*
+                * Mark the tree as dead before we change reloc_root so
+                * have_reloc_root will not touch it from now on.
+                */
+               smp_wmb();
                __del_reloc_root(reloc_root);
        }
 
@@ -2201,6 +2237,11 @@ static int clean_dirty_subvols(struct reloc_control *rc)
                                if (ret2 < 0 && !ret)
                                        ret = ret2;
                        }
+                       /*
+                        * Need barrier to ensure clear_bit() only happens after
+                        * root->reloc_root = NULL. Pairs with have_reloc_root.
+                        */
+                       smp_wmb();
                        clear_bit(BTRFS_ROOT_DEAD_RELOC_TREE, &root->state);
                        btrfs_put_fs_root(root);
                } else {
@@ -4552,6 +4593,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
                fs_root = read_fs_root(fs_info, reloc_root->root_key.offset);
                if (IS_ERR(fs_root)) {
                        err = PTR_ERR(fs_root);
+                       list_add_tail(&reloc_root->root_list, &reloc_roots);
                        goto out_free;
                }
 
@@ -4717,7 +4759,7 @@ void btrfs_reloc_pre_snapshot(struct btrfs_pending_snapshot *pending,
        struct btrfs_root *root = pending->root;
        struct reloc_control *rc = root->fs_info->reloc_ctl;
 
-       if (!root->reloc_root || !rc)
+       if (!rc || !have_reloc_root(root))
                return;
 
        if (!rc->merge_reloc_tree)
@@ -4751,7 +4793,7 @@ int btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
        struct reloc_control *rc = root->fs_info->reloc_ctl;
        int ret;
 
-       if (!root->reloc_root || !rc)
+       if (!rc || !have_reloc_root(root))
                return 0;
 
        rc = root->fs_info->reloc_ctl;
index 3b17b64..612411c 100644 (file)
@@ -376,11 +376,13 @@ again:
                leaf = path->nodes[0];
                ref = btrfs_item_ptr(leaf, path->slots[0],
                                     struct btrfs_root_ref);
-
-               WARN_ON(btrfs_root_ref_dirid(leaf, ref) != dirid);
-               WARN_ON(btrfs_root_ref_name_len(leaf, ref) != name_len);
                ptr = (unsigned long)(ref + 1);
-               WARN_ON(memcmp_extent_buffer(leaf, name, ptr, name_len));
+               if ((btrfs_root_ref_dirid(leaf, ref) != dirid) ||
+                   (btrfs_root_ref_name_len(leaf, ref) != name_len) ||
+                   memcmp_extent_buffer(leaf, name, ptr, name_len)) {
+                       err = -ENOENT;
+                       goto out;
+               }
                *sequence = btrfs_root_ref_sequence(leaf, ref);
 
                ret = btrfs_del_item(trans, tree_root, path);
index ae2db5e..091e5bc 100644 (file)
@@ -7084,12 +7084,6 @@ long btrfs_ioctl_send(struct file *mnt_file, struct btrfs_ioctl_send_args *arg)
        spin_unlock(&send_root->root_item_lock);
 
        /*
-        * This is done when we lookup the root, it should already be complete
-        * by the time we get here.
-        */
-       WARN_ON(send_root->orphan_cleanup_state != ORPHAN_CLEANUP_DONE);
-
-       /*
         * Userspace tools do the checks and warn the user if it's
         * not RO.
         */
index 1a846bf..914eea5 100644 (file)
@@ -452,9 +452,9 @@ static int run_test(test_func_t test_func, int bitmaps, u32 sectorsize,
        root->fs_info->tree_root = root;
 
        root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
-       if (!root->node) {
+       if (IS_ERR(root->node)) {
                test_std_err(TEST_ALLOC_EXTENT_BUFFER);
-               ret = -ENOMEM;
+               ret = PTR_ERR(root->node);
                goto out;
        }
        btrfs_set_header_level(root->node, 0);
index 09aaca1..ac035a6 100644 (file)
@@ -484,9 +484,9 @@ int btrfs_test_qgroups(u32 sectorsize, u32 nodesize)
         * *cough*backref walking code*cough*
         */
        root->node = alloc_test_extent_buffer(root->fs_info, nodesize);
-       if (!root->node) {
+       if (IS_ERR(root->node)) {
                test_err("couldn't allocate dummy buffer");
-               ret = -ENOMEM;
+               ret = PTR_ERR(root->node);
                goto out;
        }
        btrfs_set_header_level(root->node, 0);
index 493d4d9..97f3520 100644 (file)
@@ -227,7 +227,7 @@ static int check_extent_data_item(struct extent_buffer *leaf,
         */
        if (item_size < BTRFS_FILE_EXTENT_INLINE_DATA_START) {
                file_extent_err(leaf, slot,
-                               "invalid item size, have %u expect [%lu, %u)",
+                               "invalid item size, have %u expect [%zu, %u)",
                                item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START,
                                SZ_4K);
                return -EUCLEAN;
@@ -332,7 +332,7 @@ static int check_extent_data_item(struct extent_buffer *leaf,
 }
 
 static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key,
-                          int slot)
+                          int slot, struct btrfs_key *prev_key)
 {
        struct btrfs_fs_info *fs_info = leaf->fs_info;
        u32 sectorsize = fs_info->sectorsize;
@@ -356,6 +356,20 @@ static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key,
                        btrfs_item_size_nr(leaf, slot), csumsize);
                return -EUCLEAN;
        }
+       if (slot > 0 && prev_key->type == BTRFS_EXTENT_CSUM_KEY) {
+               u64 prev_csum_end;
+               u32 prev_item_size;
+
+               prev_item_size = btrfs_item_size_nr(leaf, slot - 1);
+               prev_csum_end = (prev_item_size / csumsize) * sectorsize;
+               prev_csum_end += prev_key->offset;
+               if (prev_csum_end > key->offset) {
+                       generic_err(leaf, slot - 1,
+"csum end range (%llu) goes beyond the start range (%llu) of the next csum item",
+                                   prev_csum_end, key->offset);
+                       return -EUCLEAN;
+               }
+       }
        return 0;
 }
 
@@ -1355,7 +1369,7 @@ static int check_leaf_item(struct extent_buffer *leaf,
                ret = check_extent_data_item(leaf, key, slot, prev_key);
                break;
        case BTRFS_EXTENT_CSUM_KEY:
-               ret = check_csum_item(leaf, key, slot);
+               ret = check_csum_item(leaf, key, slot, prev_key);
                break;
        case BTRFS_DIR_ITEM_KEY:
        case BTRFS_DIR_INDEX_KEY:
index 6f75736..d3f1159 100644 (file)
@@ -808,7 +808,8 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans,
                                                struct btrfs_ordered_sum,
                                                list);
                                if (!ret)
-                                       ret = btrfs_del_csums(trans, fs_info,
+                                       ret = btrfs_del_csums(trans,
+                                                             fs_info->csum_root,
                                                              sums->bytenr,
                                                              sums->len);
                                if (!ret)
@@ -3909,6 +3910,28 @@ static int log_inode_item(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static int log_csums(struct btrfs_trans_handle *trans,
+                    struct btrfs_root *log_root,
+                    struct btrfs_ordered_sum *sums)
+{
+       int ret;
+
+       /*
+        * Due to extent cloning, we might have logged a csum item that covers a
+        * subrange of a cloned extent, and later we can end up logging a csum
+        * item for a larger subrange of the same extent or the entire range.
+        * This would leave csum items in the log tree that cover the same range
+        * and break the searches for checksums in the log tree, resulting in
+        * some checksums missing in the fs/subvolume tree. So just delete (or
+        * trim and adjust) any existing csum items in the log for this range.
+        */
+       ret = btrfs_del_csums(trans, log_root, sums->bytenr, sums->len);
+       if (ret)
+               return ret;
+
+       return btrfs_csum_file_blocks(trans, log_root, sums);
+}
+
 static noinline int copy_items(struct btrfs_trans_handle *trans,
                               struct btrfs_inode *inode,
                               struct btrfs_path *dst_path,
@@ -4054,7 +4077,7 @@ static noinline int copy_items(struct btrfs_trans_handle *trans,
                                                   struct btrfs_ordered_sum,
                                                   list);
                if (!ret)
-                       ret = btrfs_csum_file_blocks(trans, log, sums);
+                       ret = log_csums(trans, log, sums);
                list_del(&sums->list);
                kfree(sums);
        }
@@ -4274,7 +4297,7 @@ static int log_extent_csums(struct btrfs_trans_handle *trans,
                                                   struct btrfs_ordered_sum,
                                                   list);
                if (!ret)
-                       ret = btrfs_csum_file_blocks(trans, log_root, sums);
+                       ret = log_csums(trans, log_root, sums);
                list_del(&sums->list);
                kfree(sums);
        }
@@ -6294,9 +6317,28 @@ again:
                wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key);
                if (IS_ERR(wc.replay_dest)) {
                        ret = PTR_ERR(wc.replay_dest);
+
+                       /*
+                        * We didn't find the subvol, likely because it was
+                        * deleted.  This is ok, simply skip this log and go to
+                        * the next one.
+                        *
+                        * We need to exclude the root because we can't have
+                        * other log replays overwriting this log as we'll read
+                        * it back in a few more times.  This will keep our
+                        * block from being modified, and we'll just bail for
+                        * each subsequent pass.
+                        */
+                       if (ret == -ENOENT)
+                               ret = btrfs_pin_extent_for_log_replay(fs_info,
+                                                       log->node->start,
+                                                       log->node->len);
                        free_extent_buffer(log->node);
                        free_extent_buffer(log->commit_root);
                        kfree(log);
+
+                       if (!ret)
+                               goto next;
                        btrfs_handle_fs_error(fs_info, ret,
                                "Couldn't read target root for tree log recovery.");
                        goto error;
@@ -6328,7 +6370,6 @@ again:
                                                  &root->highest_objectid);
                }
 
-               key.offset = found_key.offset - 1;
                wc.replay_dest->log_root = NULL;
                free_extent_buffer(log->node);
                free_extent_buffer(log->commit_root);
@@ -6336,9 +6377,10 @@ again:
 
                if (ret)
                        goto error;
-
+next:
                if (found_key.offset == 0)
                        break;
+               key.offset = found_key.offset - 1;
        }
        btrfs_release_path(path);
 
index 91caab6..76b84f2 100644 (file)
@@ -324,6 +324,8 @@ again_search_slot:
                                }
                                if (ret < 0 && ret != -ENOENT)
                                        goto out;
+                               key.offset++;
+                               goto again_search_slot;
                        }
                        item_size -= sizeof(subid_le);
                        offset += sizeof(subid_le);
index d8e5560..9b78e72 100644 (file)
@@ -61,7 +61,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        [BTRFS_RAID_RAID1C3] = {
                .sub_stripes    = 1,
                .dev_stripes    = 1,
-               .devs_max       = 0,
+               .devs_max       = 3,
                .devs_min       = 3,
                .tolerated_failures = 2,
                .devs_increment = 3,
@@ -73,7 +73,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
        [BTRFS_RAID_RAID1C4] = {
                .sub_stripes    = 1,
                .dev_stripes    = 1,
-               .devs_max       = 0,
+               .devs_max       = 4,
                .devs_min       = 4,
                .tolerated_failures = 3,
                .devs_increment = 4,
@@ -3881,7 +3881,11 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
                }
        }
 
-       num_devices = btrfs_num_devices(fs_info);
+       /*
+        * rw_devices will not change at the moment, device add/delete/replace
+        * are excluded by EXCL_OP
+        */
+       num_devices = fs_info->fs_devices->rw_devices;
 
        /*
         * SINGLE profile on-disk has no profile bit, but in-memory we have a
index d8c7242..18a87ec 100644 (file)
@@ -3031,11 +3031,9 @@ static void end_bio_bh_io_sync(struct bio *bio)
  * errors, this only handles the "we need to be able to
  * do IO at the final sector" case.
  */
-void guard_bio_eod(int op, struct bio *bio)
+void guard_bio_eod(struct bio *bio)
 {
        sector_t maxsector;
-       struct bio_vec *bvec = bio_last_bvec_all(bio);
-       unsigned truncated_bytes;
        struct hd_struct *part;
 
        rcu_read_lock();
@@ -3061,28 +3059,7 @@ void guard_bio_eod(int op, struct bio *bio)
        if (likely((bio->bi_iter.bi_size >> 9) <= maxsector))
                return;
 
-       /* Uhhuh. We've got a bio that straddles the device size! */
-       truncated_bytes = bio->bi_iter.bi_size - (maxsector << 9);
-
-       /*
-        * The bio contains more than one segment which spans EOD, just return
-        * and let IO layer turn it into an EIO
-        */
-       if (truncated_bytes > bvec->bv_len)
-               return;
-
-       /* Truncate the bio.. */
-       bio->bi_iter.bi_size -= truncated_bytes;
-       bvec->bv_len -= truncated_bytes;
-
-       /* ..and clear the end of the buffer for reads */
-       if (op == REQ_OP_READ) {
-               struct bio_vec bv;
-
-               mp_bvec_last_segment(bvec, &bv);
-               zero_user(bv.bv_page, bv.bv_offset + bv.bv_len,
-                               truncated_bytes);
-       }
+       bio_truncate(bio, maxsector << 9);
 }
 
 static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
@@ -3118,15 +3095,15 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
        bio->bi_end_io = end_bio_bh_io_sync;
        bio->bi_private = bh;
 
-       /* Take care of bh's that straddle the end of the device */
-       guard_bio_eod(op, bio);
-
        if (buffer_meta(bh))
                op_flags |= REQ_META;
        if (buffer_prio(bh))
                op_flags |= REQ_PRIO;
        bio_set_op_attrs(bio, op, op_flags);
 
+       /* Take care of bh's that straddle the end of the device */
+       guard_bio_eod(bio);
+
        if (wbc) {
                wbc_init_bio(wbc, bio);
                wbc_account_cgroup_owner(wbc, bh->b_page, bh->b_size);
index f5a3891..9d09bb5 100644 (file)
@@ -1011,18 +1011,13 @@ static int __ceph_is_single_caps(struct ceph_inode_info *ci)
        return rb_first(&ci->i_caps) == rb_last(&ci->i_caps);
 }
 
-static int __ceph_is_any_caps(struct ceph_inode_info *ci)
-{
-       return !RB_EMPTY_ROOT(&ci->i_caps);
-}
-
 int ceph_is_any_caps(struct inode *inode)
 {
        struct ceph_inode_info *ci = ceph_inode(inode);
        int ret;
 
        spin_lock(&ci->i_ceph_lock);
-       ret = __ceph_is_any_caps(ci);
+       ret = __ceph_is_any_real_caps(ci);
        spin_unlock(&ci->i_ceph_lock);
 
        return ret;
@@ -1099,15 +1094,16 @@ void __ceph_remove_cap(struct ceph_cap *cap, bool queue_release)
        if (removed)
                ceph_put_cap(mdsc, cap);
 
-       /* when reconnect denied, we remove session caps forcibly,
-        * i_wr_ref can be non-zero. If there are ongoing write,
-        * keep i_snap_realm.
-        */
-       if (!__ceph_is_any_caps(ci) && ci->i_wr_ref == 0 && ci->i_snap_realm)
-               drop_inode_snap_realm(ci);
+       if (!__ceph_is_any_real_caps(ci)) {
+               /* when reconnect denied, we remove session caps forcibly,
+                * i_wr_ref can be non-zero. If there are ongoing write,
+                * keep i_snap_realm.
+                */
+               if (ci->i_wr_ref == 0 && ci->i_snap_realm)
+                       drop_inode_snap_realm(ci);
 
-       if (!__ceph_is_any_real_caps(ci))
                __cap_delay_cancel(mdsc, ci);
+       }
 }
 
 struct cap_msg_args {
@@ -2764,7 +2760,19 @@ int ceph_get_caps(struct file *filp, int need, int want,
                if (ret == -EAGAIN)
                        continue;
                if (!ret) {
+                       struct ceph_mds_client *mdsc = fsc->mdsc;
+                       struct cap_wait cw;
                        DEFINE_WAIT_FUNC(wait, woken_wake_function);
+
+                       cw.ino = inode->i_ino;
+                       cw.tgid = current->tgid;
+                       cw.need = need;
+                       cw.want = want;
+
+                       spin_lock(&mdsc->caps_list_lock);
+                       list_add(&cw.list, &mdsc->cap_wait_list);
+                       spin_unlock(&mdsc->caps_list_lock);
+
                        add_wait_queue(&ci->i_cap_wq, &wait);
 
                        flags |= NON_BLOCKING;
@@ -2778,6 +2786,11 @@ int ceph_get_caps(struct file *filp, int need, int want,
                        }
 
                        remove_wait_queue(&ci->i_cap_wq, &wait);
+
+                       spin_lock(&mdsc->caps_list_lock);
+                       list_del(&cw.list);
+                       spin_unlock(&mdsc->caps_list_lock);
+
                        if (ret == -EAGAIN)
                                continue;
                }
@@ -2928,7 +2941,7 @@ void ceph_put_cap_refs(struct ceph_inode_info *ci, int had)
                                ci->i_head_snapc = NULL;
                        }
                        /* see comment in __ceph_remove_cap() */
-                       if (!__ceph_is_any_caps(ci) && ci->i_snap_realm)
+                       if (!__ceph_is_any_real_caps(ci) && ci->i_snap_realm)
                                drop_inode_snap_realm(ci);
                }
        spin_unlock(&ci->i_ceph_lock);
index facb387..c281f32 100644 (file)
@@ -139,6 +139,7 @@ static int caps_show(struct seq_file *s, void *p)
        struct ceph_fs_client *fsc = s->private;
        struct ceph_mds_client *mdsc = fsc->mdsc;
        int total, avail, used, reserved, min, i;
+       struct cap_wait *cw;
 
        ceph_reservation_status(fsc, &total, &avail, &used, &reserved, &min);
        seq_printf(s, "total\t\t%d\n"
@@ -166,6 +167,18 @@ static int caps_show(struct seq_file *s, void *p)
        }
        mutex_unlock(&mdsc->mutex);
 
+       seq_printf(s, "\n\nWaiters:\n--------\n");
+       seq_printf(s, "tgid         ino                need             want\n");
+       seq_printf(s, "-----------------------------------------------------\n");
+
+       spin_lock(&mdsc->caps_list_lock);
+       list_for_each_entry(cw, &mdsc->cap_wait_list, list) {
+               seq_printf(s, "%-13d0x%-17lx%-17s%-17s\n", cw->tgid, cw->ino,
+                               ceph_cap_string(cw->need),
+                               ceph_cap_string(cw->want));
+       }
+       spin_unlock(&mdsc->caps_list_lock);
+
        return 0;
 }
 
index 068b029..374db1b 100644 (file)
@@ -2015,7 +2015,7 @@ void ceph_reclaim_caps_nr(struct ceph_mds_client *mdsc, int nr)
        if (!nr)
                return;
        val = atomic_add_return(nr, &mdsc->cap_reclaim_pending);
-       if (!(val % CEPH_CAPS_PER_RELEASE)) {
+       if ((val % CEPH_CAPS_PER_RELEASE) < nr) {
                atomic_set(&mdsc->cap_reclaim_pending, 0);
                ceph_queue_cap_reclaim_work(mdsc);
        }
@@ -2032,12 +2032,13 @@ int ceph_alloc_readdir_reply_buffer(struct ceph_mds_request *req,
        struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info;
        struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options;
        size_t size = sizeof(struct ceph_mds_reply_dir_entry);
-       int order, num_entries;
+       unsigned int num_entries;
+       int order;
 
        spin_lock(&ci->i_ceph_lock);
        num_entries = ci->i_files + ci->i_subdirs;
        spin_unlock(&ci->i_ceph_lock);
-       num_entries = max(num_entries, 1);
+       num_entries = max(num_entries, 1U);
        num_entries = min(num_entries, opt->max_readdir);
 
        order = get_order(size * num_entries);
@@ -4168,6 +4169,7 @@ int ceph_mdsc_init(struct ceph_fs_client *fsc)
        INIT_DELAYED_WORK(&mdsc->delayed_work, delayed_work);
        mdsc->last_renew_caps = jiffies;
        INIT_LIST_HEAD(&mdsc->cap_delay_list);
+       INIT_LIST_HEAD(&mdsc->cap_wait_list);
        spin_lock_init(&mdsc->cap_delay_lock);
        INIT_LIST_HEAD(&mdsc->snap_flush_list);
        spin_lock_init(&mdsc->snap_flush_lock);
index 5cd131b..14c7e8c 100644 (file)
@@ -340,6 +340,14 @@ struct ceph_quotarealm_inode {
        struct inode *inode;
 };
 
+struct cap_wait {
+       struct list_head        list;
+       unsigned long           ino;
+       pid_t                   tgid;
+       int                     need;
+       int                     want;
+};
+
 /*
  * mds client state
  */
@@ -416,6 +424,7 @@ struct ceph_mds_client {
        spinlock_t      caps_list_lock;
        struct          list_head caps_list; /* unused (reserved or
                                                unreserved) */
+       struct          list_head cap_wait_list;
        int             caps_total_count;    /* total caps allocated */
        int             caps_use_count;      /* in use */
        int             caps_use_max;        /* max used caps */
index aeec1d6..471bac3 100644 (file)
@@ -158,6 +158,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                void *pexport_targets = NULL;
                struct ceph_timespec laggy_since;
                struct ceph_mds_info *info;
+               bool laggy;
 
                ceph_decode_need(p, end, sizeof(u64) + 1, bad);
                global_id = ceph_decode_64(p);
@@ -190,6 +191,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                if (err)
                        goto corrupt;
                ceph_decode_copy(p, &laggy_since, sizeof(laggy_since));
+               laggy = laggy_since.tv_sec != 0 || laggy_since.tv_nsec != 0;
                *p += sizeof(u32);
                ceph_decode_32_safe(p, end, namelen, bad);
                *p += namelen;
@@ -207,10 +209,11 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                        *p = info_end;
                }
 
-               dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s\n",
+               dout("mdsmap_decode %d/%d %lld mds%d.%d %s %s%s\n",
                     i+1, n, global_id, mds, inc,
                     ceph_pr_addr(&addr),
-                    ceph_mds_state_name(state));
+                    ceph_mds_state_name(state),
+                    laggy ? "(laggy)" : "");
 
                if (mds < 0 || state <= 0)
                        continue;
@@ -230,8 +233,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                info->global_id = global_id;
                info->state = state;
                info->addr = addr;
-               info->laggy = (laggy_since.tv_sec != 0 ||
-                              laggy_since.tv_nsec != 0);
+               info->laggy = laggy;
                info->num_export_targets = num_export_targets;
                if (num_export_targets) {
                        info->export_targets = kcalloc(num_export_targets,
@@ -355,6 +357,8 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                m->m_damaged = false;
        }
 bad_ext:
+       dout("mdsmap_decode m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n",
+            !!m->m_enabled, !!m->m_damaged, m->m_num_laggy);
        *p = end;
        dout("mdsmap_decode success epoch %u\n", m->m_epoch);
        return m;
index 9c9a7c6..29a795f 100644 (file)
@@ -172,10 +172,10 @@ static const struct fs_parameter_enum ceph_mount_param_enums[] = {
 static const struct fs_parameter_spec ceph_mount_param_specs[] = {
        fsparam_flag_no ("acl",                         Opt_acl),
        fsparam_flag_no ("asyncreaddir",                Opt_asyncreaddir),
-       fsparam_u32     ("caps_max",                    Opt_caps_max),
+       fsparam_s32     ("caps_max",                    Opt_caps_max),
        fsparam_u32     ("caps_wanted_delay_max",       Opt_caps_wanted_delay_max),
        fsparam_u32     ("caps_wanted_delay_min",       Opt_caps_wanted_delay_min),
-       fsparam_s32     ("write_congestion_kb",         Opt_congestion_kb),
+       fsparam_u32     ("write_congestion_kb",         Opt_congestion_kb),
        fsparam_flag_no ("copyfrom",                    Opt_copyfrom),
        fsparam_flag_no ("dcache",                      Opt_dcache),
        fsparam_flag_no ("dirstat",                     Opt_dirstat),
@@ -187,8 +187,8 @@ static const struct fs_parameter_spec ceph_mount_param_specs[] = {
        fsparam_flag_no ("quotadf",                     Opt_quotadf),
        fsparam_u32     ("rasize",                      Opt_rasize),
        fsparam_flag_no ("rbytes",                      Opt_rbytes),
-       fsparam_s32     ("readdir_max_bytes",           Opt_readdir_max_bytes),
-       fsparam_s32     ("readdir_max_entries",         Opt_readdir_max_entries),
+       fsparam_u32     ("readdir_max_bytes",           Opt_readdir_max_bytes),
+       fsparam_u32     ("readdir_max_entries",         Opt_readdir_max_entries),
        fsparam_enum    ("recover_session",             Opt_recover_session),
        fsparam_flag_no ("require_active_mds",          Opt_require_active_mds),
        fsparam_u32     ("rsize",                       Opt_rsize),
@@ -328,7 +328,9 @@ static int ceph_parse_mount_param(struct fs_context *fc,
                fsopt->caps_wanted_delay_max = result.uint_32;
                break;
        case Opt_caps_max:
-               fsopt->caps_max = result.uint_32;
+               if (result.int_32 < 0)
+                       goto out_of_range;
+               fsopt->caps_max = result.int_32;
                break;
        case Opt_readdir_max_entries:
                if (result.uint_32 < 1)
@@ -547,25 +549,25 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
                seq_show_option(m, "recover_session", "clean");
 
        if (fsopt->wsize != CEPH_MAX_WRITE_SIZE)
-               seq_printf(m, ",wsize=%d", fsopt->wsize);
+               seq_printf(m, ",wsize=%u", fsopt->wsize);
        if (fsopt->rsize != CEPH_MAX_READ_SIZE)
-               seq_printf(m, ",rsize=%d", fsopt->rsize);
+               seq_printf(m, ",rsize=%u", fsopt->rsize);
        if (fsopt->rasize != CEPH_RASIZE_DEFAULT)
-               seq_printf(m, ",rasize=%d", fsopt->rasize);
+               seq_printf(m, ",rasize=%u", fsopt->rasize);
        if (fsopt->congestion_kb != default_congestion_kb())
-               seq_printf(m, ",write_congestion_kb=%d", fsopt->congestion_kb);
+               seq_printf(m, ",write_congestion_kb=%u", fsopt->congestion_kb);
        if (fsopt->caps_max)
                seq_printf(m, ",caps_max=%d", fsopt->caps_max);
        if (fsopt->caps_wanted_delay_min != CEPH_CAPS_WANTED_DELAY_MIN_DEFAULT)
-               seq_printf(m, ",caps_wanted_delay_min=%d",
+               seq_printf(m, ",caps_wanted_delay_min=%u",
                         fsopt->caps_wanted_delay_min);
        if (fsopt->caps_wanted_delay_max != CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT)
-               seq_printf(m, ",caps_wanted_delay_max=%d",
+               seq_printf(m, ",caps_wanted_delay_max=%u",
                           fsopt->caps_wanted_delay_max);
        if (fsopt->max_readdir != CEPH_MAX_READDIR_DEFAULT)
-               seq_printf(m, ",readdir_max_entries=%d", fsopt->max_readdir);
+               seq_printf(m, ",readdir_max_entries=%u", fsopt->max_readdir);
        if (fsopt->max_readdir_bytes != CEPH_MAX_READDIR_BYTES_DEFAULT)
-               seq_printf(m, ",readdir_max_bytes=%d", fsopt->max_readdir_bytes);
+               seq_printf(m, ",readdir_max_bytes=%u", fsopt->max_readdir_bytes);
        if (strcmp(fsopt->snapdir_name, CEPH_SNAPDIRNAME_DEFAULT))
                seq_show_option(m, "snapdirname", fsopt->snapdir_name);
 
index f0f9cb7..3bf1a01 100644 (file)
 #define CEPH_CAPS_WANTED_DELAY_MAX_DEFAULT     60  /* cap release delay */
 
 struct ceph_mount_options {
-       int flags;
+       unsigned int flags;
 
-       int wsize;            /* max write size */
-       int rsize;            /* max read size */
-       int rasize;           /* max readahead */
-       int congestion_kb;    /* max writeback in flight */
-       int caps_wanted_delay_min, caps_wanted_delay_max;
+       unsigned int wsize;            /* max write size */
+       unsigned int rsize;            /* max read size */
+       unsigned int rasize;           /* max readahead */
+       unsigned int congestion_kb;    /* max writeback in flight */
+       unsigned int caps_wanted_delay_min, caps_wanted_delay_max;
        int caps_max;
-       int max_readdir;       /* max readdir result (entires) */
-       int max_readdir_bytes; /* max readdir result (bytes) */
+       unsigned int max_readdir;       /* max readdir result (entries) */
+       unsigned int max_readdir_bytes; /* max readdir result (bytes) */
 
        /*
         * everything above this point can be memcmp'd; everything below
index 00dfe17..c5e6eff 100644 (file)
@@ -352,7 +352,7 @@ static struct kobject *cdev_get(struct cdev *p)
 
        if (owner && !try_module_get(owner))
                return NULL;
-       kobj = kobject_get(&p->kobj);
+       kobj = kobject_get_unless_zero(&p->kobj);
        if (!kobj)
                module_put(owner);
        return kobj;
index fd0262c..40705e8 100644 (file)
@@ -1061,7 +1061,7 @@ cap_unix(struct cifs_ses *ses)
 struct cached_fid {
        bool is_valid:1;        /* Do we have a useable root fid */
        bool file_all_info_is_valid:1;
-
+       bool has_lease:1;
        struct kref refcount;
        struct cifs_fid *fid;
        struct mutex fid_mutex;
@@ -1693,6 +1693,7 @@ struct cifs_fattr {
        struct timespec64 cf_atime;
        struct timespec64 cf_mtime;
        struct timespec64 cf_ctime;
+       u32             cf_cifstag;
 };
 
 static inline void free_dfs_info_param(struct dfs_info3_param *param)
index 4f554f0..cc86a67 100644 (file)
@@ -42,6 +42,7 @@
 #include "cifsproto.h"
 #include "cifs_unicode.h"
 #include "cifs_debug.h"
+#include "smb2proto.h"
 #include "fscache.h"
 #include "smbdirect.h"
 #ifdef CONFIG_CIFS_DFS_UPCALL
@@ -112,6 +113,8 @@ cifs_mark_open_files_invalid(struct cifs_tcon *tcon)
 
        mutex_lock(&tcon->crfid.fid_mutex);
        tcon->crfid.is_valid = false;
+       /* cached handle is not valid, so SMB2_CLOSE won't be sent below */
+       close_shroot_lease_locked(&tcon->crfid);
        memset(tcon->crfid.fid, 0, sizeof(struct cifs_fid));
        mutex_unlock(&tcon->crfid.fid_mutex);
 
index 3925a7b..d17587c 100644 (file)
@@ -139,6 +139,28 @@ retry:
        dput(dentry);
 }
 
+static bool reparse_file_needs_reval(const struct cifs_fattr *fattr)
+{
+       if (!(fattr->cf_cifsattrs & ATTR_REPARSE))
+               return false;
+       /*
+        * The DFS tags should be only intepreted by server side as per
+        * MS-FSCC 2.1.2.1, but let's include them anyway.
+        *
+        * Besides, if cf_cifstag is unset (0), then we still need it to be
+        * revalidated to know exactly what reparse point it is.
+        */
+       switch (fattr->cf_cifstag) {
+       case IO_REPARSE_TAG_DFS:
+       case IO_REPARSE_TAG_DFSR:
+       case IO_REPARSE_TAG_SYMLINK:
+       case IO_REPARSE_TAG_NFS:
+       case 0:
+               return true;
+       }
+       return false;
+}
+
 static void
 cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
 {
@@ -158,7 +180,7 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
         * is a symbolic link, DFS referral or a reparse point with a direct
         * access like junctions, deduplicated files, NFS symlinks.
         */
-       if (fattr->cf_cifsattrs & ATTR_REPARSE)
+       if (reparse_file_needs_reval(fattr))
                fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
 
        /* non-unix readdir doesn't provide nlink */
@@ -194,19 +216,37 @@ cifs_fill_common_info(struct cifs_fattr *fattr, struct cifs_sb_info *cifs_sb)
        }
 }
 
+static void __dir_info_to_fattr(struct cifs_fattr *fattr, const void *info)
+{
+       const FILE_DIRECTORY_INFO *fi = info;
+
+       memset(fattr, 0, sizeof(*fattr));
+       fattr->cf_cifsattrs = le32_to_cpu(fi->ExtFileAttributes);
+       fattr->cf_eof = le64_to_cpu(fi->EndOfFile);
+       fattr->cf_bytes = le64_to_cpu(fi->AllocationSize);
+       fattr->cf_createtime = le64_to_cpu(fi->CreationTime);
+       fattr->cf_atime = cifs_NTtimeToUnix(fi->LastAccessTime);
+       fattr->cf_ctime = cifs_NTtimeToUnix(fi->ChangeTime);
+       fattr->cf_mtime = cifs_NTtimeToUnix(fi->LastWriteTime);
+}
+
 void
 cifs_dir_info_to_fattr(struct cifs_fattr *fattr, FILE_DIRECTORY_INFO *info,
                       struct cifs_sb_info *cifs_sb)
 {
-       memset(fattr, 0, sizeof(*fattr));
-       fattr->cf_cifsattrs = le32_to_cpu(info->ExtFileAttributes);
-       fattr->cf_eof = le64_to_cpu(info->EndOfFile);
-       fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
-       fattr->cf_createtime = le64_to_cpu(info->CreationTime);
-       fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
-       fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
-       fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
+       __dir_info_to_fattr(fattr, info);
+       cifs_fill_common_info(fattr, cifs_sb);
+}
 
+static void cifs_fulldir_info_to_fattr(struct cifs_fattr *fattr,
+                                      SEARCH_ID_FULL_DIR_INFO *info,
+                                      struct cifs_sb_info *cifs_sb)
+{
+       __dir_info_to_fattr(fattr, info);
+
+       /* See MS-FSCC 2.4.18 FileIdFullDirectoryInformation */
+       if (fattr->cf_cifsattrs & ATTR_REPARSE)
+               fattr->cf_cifstag = le32_to_cpu(info->EaSize);
        cifs_fill_common_info(fattr, cifs_sb);
 }
 
@@ -755,6 +795,11 @@ static int cifs_filldir(char *find_entry, struct file *file,
                                       (FIND_FILE_STANDARD_INFO *)find_entry,
                                       cifs_sb);
                break;
+       case SMB_FIND_FILE_ID_FULL_DIR_INFO:
+               cifs_fulldir_info_to_fattr(&fattr,
+                                          (SEARCH_ID_FULL_DIR_INFO *)find_entry,
+                                          cifs_sb);
+               break;
        default:
                cifs_dir_info_to_fattr(&fattr,
                                       (FILE_DIRECTORY_INFO *)find_entry,
index 8b0b512..afe1f03 100644 (file)
@@ -67,7 +67,7 @@ smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms,
                goto out;
 
 
-        if (oparms->tcon->use_resilient) {
+       if (oparms->tcon->use_resilient) {
                /* default timeout is 0, servers pick default (120 seconds) */
                nr_ioctl_req.Timeout =
                        cpu_to_le32(oparms->tcon->handle_timeout);
index 18c7a33..5ef5e97 100644 (file)
@@ -95,6 +95,7 @@ smb2_compound_op(const unsigned int xid, struct cifs_tcon *tcon,
                goto finished;
        }
 
+       memset(&oparms, 0, sizeof(struct cifs_open_parms));
        oparms.tcon = tcon;
        oparms.desired_access = desired_access;
        oparms.disposition = create_disposition;
index a5c96bc..6250370 100644 (file)
@@ -616,6 +616,7 @@ smb2_close_cached_fid(struct kref *ref)
                           cfid->fid->volatile_fid);
                cfid->is_valid = false;
                cfid->file_all_info_is_valid = false;
+               cfid->has_lease = false;
        }
 }
 
@@ -626,13 +627,28 @@ void close_shroot(struct cached_fid *cfid)
        mutex_unlock(&cfid->fid_mutex);
 }
 
+void close_shroot_lease_locked(struct cached_fid *cfid)
+{
+       if (cfid->has_lease) {
+               cfid->has_lease = false;
+               kref_put(&cfid->refcount, smb2_close_cached_fid);
+       }
+}
+
+void close_shroot_lease(struct cached_fid *cfid)
+{
+       mutex_lock(&cfid->fid_mutex);
+       close_shroot_lease_locked(cfid);
+       mutex_unlock(&cfid->fid_mutex);
+}
+
 void
 smb2_cached_lease_break(struct work_struct *work)
 {
        struct cached_fid *cfid = container_of(work,
                                struct cached_fid, lease_break);
 
-       close_shroot(cfid);
+       close_shroot_lease(cfid);
 }
 
 /*
@@ -773,6 +789,7 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid *pfid)
        /* BB TBD check to see if oplock level check can be removed below */
        if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) {
                kref_get(&tcon->crfid.refcount);
+               tcon->crfid.has_lease = true;
                smb2_parse_contexts(server, o_rsp,
                                &oparms.fid->epoch,
                                oparms.fid->lease_key, &oplock, NULL);
index 0ab6b12..9434f6d 100644 (file)
@@ -1847,7 +1847,7 @@ SMB2_tdis(const unsigned int xid, struct cifs_tcon *tcon)
        if ((tcon->need_reconnect) || (tcon->ses->need_reconnect))
                return 0;
 
-       close_shroot(&tcon->crfid);
+       close_shroot_lease(&tcon->crfid);
 
        rc = smb2_plain_req_init(SMB2_TREE_DISCONNECT, tcon, (void **) &req,
                             &total_len);
index a18272c..27d29f2 100644 (file)
@@ -70,6 +70,8 @@ extern int smb3_handle_read_data(struct TCP_Server_Info *server,
 extern int open_shroot(unsigned int xid, struct cifs_tcon *tcon,
                        struct cifs_fid *pfid);
 extern void close_shroot(struct cached_fid *cfid);
+extern void close_shroot_lease(struct cached_fid *cfid);
+extern void close_shroot_lease_locked(struct cached_fid *cfid);
 extern void move_smb2_info_to_cifs(FILE_ALL_INFO *dst,
                                   struct smb2_file_all_info *src);
 extern int smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
index 040df1f..40cca35 100644 (file)
@@ -151,7 +151,7 @@ static struct key *search_fscrypt_keyring(struct key *keyring,
 }
 
 #define FSCRYPT_FS_KEYRING_DESCRIPTION_SIZE    \
-       (CONST_STRLEN("fscrypt-") + FIELD_SIZEOF(struct super_block, s_id))
+       (CONST_STRLEN("fscrypt-") + sizeof_field(struct super_block, s_id))
 
 #define FSCRYPT_MK_DESCRIPTION_SIZE    (2 * FSCRYPT_KEY_IDENTIFIER_SIZE + 1)
 
index 0ec4f27..00b4d15 100644 (file)
@@ -39,6 +39,8 @@
 #include <linux/atomic.h>
 #include <linux/prefetch.h>
 
+#include "internal.h"
+
 /*
  * How many user pages to map in one call to get_user_pages().  This determines
  * the size of a structure in the slab cache
index d31b6c7..dc1a1d5 100644 (file)
@@ -35,11 +35,11 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
                spin_unlock(&inode->i_lock);
                spin_unlock(&sb->s_inode_list_lock);
 
-               cond_resched();
                invalidate_mapping_pages(inode->i_mapping, 0, -1);
                iput(toput_inode);
                toput_inode = inode;
 
+               cond_resched();
                spin_lock(&sb->s_inode_list_lock);
        }
        spin_unlock(&sb->s_inode_list_lock);
index a13a787..b766c3e 100644 (file)
@@ -649,6 +649,8 @@ ssize_t erofs_listxattr(struct dentry *dentry,
        struct listxattr_iter it;
 
        ret = init_inode_xattrs(d_inode(dentry));
+       if (ret == -ENOATTR)
+               return 0;
        if (ret)
                return ret;
 
index d4d4fdf..1ee04e7 100644 (file)
@@ -133,10 +133,13 @@ static void debug_print_tree(struct ext4_sb_info *sbi)
 {
        struct rb_node *node;
        struct ext4_system_zone *entry;
+       struct ext4_system_blocks *system_blks;
        int first = 1;
 
        printk(KERN_INFO "System zones: ");
-       node = rb_first(&sbi->system_blks->root);
+       rcu_read_lock();
+       system_blks = rcu_dereference(sbi->system_blks);
+       node = rb_first(&system_blks->root);
        while (node) {
                entry = rb_entry(node, struct ext4_system_zone, node);
                printk(KERN_CONT "%s%llu-%llu", first ? "" : ", ",
@@ -144,6 +147,7 @@ static void debug_print_tree(struct ext4_sb_info *sbi)
                first = 0;
                node = rb_next(node);
        }
+       rcu_read_unlock();
        printk(KERN_CONT "\n");
 }
 
index 9fdd2b2..9f00fc0 100644 (file)
@@ -72,6 +72,7 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
        const char *error_msg = NULL;
        const int rlen = ext4_rec_len_from_disk(de->rec_len,
                                                dir->i_sb->s_blocksize);
+       const int next_offset = ((char *) de - buf) + rlen;
 
        if (unlikely(rlen < EXT4_DIR_REC_LEN(1)))
                error_msg = "rec_len is smaller than minimal";
@@ -79,8 +80,11 @@ int __ext4_check_dir_entry(const char *function, unsigned int line,
                error_msg = "rec_len % 4 != 0";
        else if (unlikely(rlen < EXT4_DIR_REC_LEN(de->name_len)))
                error_msg = "rec_len is too small for name_len";
-       else if (unlikely(((char *) de - buf) + rlen > size))
+       else if (unlikely(next_offset > size))
                error_msg = "directory entry overrun";
+       else if (unlikely(next_offset > size - EXT4_DIR_REC_LEN(1) &&
+                         next_offset != size))
+               error_msg = "directory entry too close to block end";
        else if (unlikely(le32_to_cpu(de->inode) >
                        le32_to_cpu(EXT4_SB(dir->i_sb)->s_es->s_inodes_count)))
                error_msg = "inode out of bounds";
index dc333e8..8ca4a23 100644 (file)
@@ -921,8 +921,8 @@ repeat_in_this_group:
                if (!handle) {
                        BUG_ON(nblocks <= 0);
                        handle = __ext4_journal_start_sb(dir->i_sb, line_no,
-                                                        handle_type, nblocks,
-                                                        0, 0);
+                                handle_type, nblocks, 0,
+                                ext4_trans_default_revoke_credits(sb));
                        if (IS_ERR(handle)) {
                                err = PTR_ERR(handle);
                                ext4_std_error(sb, err);
index 92a9da1..bbce1c3 100644 (file)
@@ -25,7 +25,7 @@
  * For constructing the negative timestamp lower bound value.
  * binary: 10000000 00000000 00000000 00000000
  */
-#define LOWER_MSB_1 (-0x80000000L)
+#define LOWER_MSB_1 (-(UPPER_MSB_0) - 1L)  /* avoid overflow */
 /*
  * For constructing the negative timestamp upper bound value.
  * binary: 11111111 11111111 11111111 11111111
index 28f28de..629a25d 100644 (file)
@@ -5692,7 +5692,7 @@ int ext4_expand_extra_isize(struct inode *inode,
        error = ext4_journal_get_write_access(handle, iloc->bh);
        if (error) {
                brelse(iloc->bh);
-               goto out_stop;
+               goto out_unlock;
        }
 
        error = __ext4_expand_extra_isize(inode, new_extra_isize, iloc,
@@ -5702,8 +5702,8 @@ int ext4_expand_extra_isize(struct inode *inode,
        if (!error)
                error = rc;
 
+out_unlock:
        ext4_write_unlock_xattr(inode, &no_expand);
-out_stop:
        ext4_journal_stop(handle);
        return error;
 }
index a856997..1cb42d9 100644 (file)
@@ -2164,7 +2164,9 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
        struct buffer_head *bh = NULL;
        struct ext4_dir_entry_2 *de;
        struct super_block *sb;
+#ifdef CONFIG_UNICODE
        struct ext4_sb_info *sbi;
+#endif
        struct ext4_filename fname;
        int     retval;
        int     dx_fallback=0;
@@ -2176,12 +2178,12 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
                csum_size = sizeof(struct ext4_dir_entry_tail);
 
        sb = dir->i_sb;
-       sbi = EXT4_SB(sb);
        blocksize = sb->s_blocksize;
        if (!dentry->d_name.len)
                return -EINVAL;
 
 #ifdef CONFIG_UNICODE
+       sbi = EXT4_SB(sb);
        if (ext4_has_strict_mode(sbi) && IS_CASEFOLDED(dir) &&
            sbi->s_encoding && utf8_validate(sbi->s_encoding, &dentry->d_name))
                return -EINVAL;
@@ -2822,7 +2824,7 @@ bool ext4_empty_dir(struct inode *inode)
 {
        unsigned int offset;
        struct buffer_head *bh;
-       struct ext4_dir_entry_2 *de, *de1;
+       struct ext4_dir_entry_2 *de;
        struct super_block *sb;
 
        if (ext4_has_inline_data(inode)) {
@@ -2847,19 +2849,25 @@ bool ext4_empty_dir(struct inode *inode)
                return true;
 
        de = (struct ext4_dir_entry_2 *) bh->b_data;
-       de1 = ext4_next_entry(de, sb->s_blocksize);
-       if (le32_to_cpu(de->inode) != inode->i_ino ||
-                       le32_to_cpu(de1->inode) == 0 ||
-                       strcmp(".", de->name) || strcmp("..", de1->name)) {
-               ext4_warning_inode(inode, "directory missing '.' and/or '..'");
+       if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size,
+                                0) ||
+           le32_to_cpu(de->inode) != inode->i_ino || strcmp(".", de->name)) {
+               ext4_warning_inode(inode, "directory missing '.'");
+               brelse(bh);
+               return true;
+       }
+       offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
+       de = ext4_next_entry(de, sb->s_blocksize);
+       if (ext4_check_dir_entry(inode, NULL, de, bh, bh->b_data, bh->b_size,
+                                offset) ||
+           le32_to_cpu(de->inode) == 0 || strcmp("..", de->name)) {
+               ext4_warning_inode(inode, "directory missing '..'");
                brelse(bh);
                return true;
        }
-       offset = ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize) +
-                ext4_rec_len_from_disk(de1->rec_len, sb->s_blocksize);
-       de = ext4_next_entry(de1, sb->s_blocksize);
+       offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
        while (offset < inode->i_size) {
-               if ((void *) de >= (void *) (bh->b_data+sb->s_blocksize)) {
+               if (!(offset & (sb->s_blocksize - 1))) {
                        unsigned int lblock;
                        brelse(bh);
                        lblock = offset >> EXT4_BLOCK_SIZE_BITS(sb);
@@ -2870,12 +2878,11 @@ bool ext4_empty_dir(struct inode *inode)
                        }
                        if (IS_ERR(bh))
                                return true;
-                       de = (struct ext4_dir_entry_2 *) bh->b_data;
                }
+               de = (struct ext4_dir_entry_2 *) (bh->b_data +
+                                       (offset & (sb->s_blocksize - 1)));
                if (ext4_check_dir_entry(inode, NULL, de, bh,
                                         bh->b_data, bh->b_size, offset)) {
-                       de = (struct ext4_dir_entry_2 *)(bh->b_data +
-                                                        sb->s_blocksize);
                        offset = (offset | (sb->s_blocksize - 1)) + 1;
                        continue;
                }
@@ -2884,7 +2891,6 @@ bool ext4_empty_dir(struct inode *inode)
                        return false;
                }
                offset += ext4_rec_len_from_disk(de->rec_len, sb->s_blocksize);
-               de = ext4_next_entry(de, sb->s_blocksize);
        }
        brelse(bh);
        return true;
index 1d82b56..2937a88 100644 (file)
@@ -1900,6 +1900,13 @@ static int handle_mount_opt(struct super_block *sb, char *opt, int token,
                }
                sbi->s_commit_interval = HZ * arg;
        } else if (token == Opt_debug_want_extra_isize) {
+               if ((arg & 1) ||
+                   (arg < 4) ||
+                   (arg > (sbi->s_inode_size - EXT4_GOOD_OLD_INODE_SIZE))) {
+                       ext4_msg(sb, KERN_ERR,
+                                "Invalid want_extra_isize %d", arg);
+                       return -1;
+               }
                sbi->s_want_extra_isize = arg;
        } else if (token == Opt_max_batch_time) {
                sbi->s_max_batch_time = arg;
@@ -3554,40 +3561,6 @@ int ext4_calculate_overhead(struct super_block *sb)
        return 0;
 }
 
-static void ext4_clamp_want_extra_isize(struct super_block *sb)
-{
-       struct ext4_sb_info *sbi = EXT4_SB(sb);
-       struct ext4_super_block *es = sbi->s_es;
-       unsigned def_extra_isize = sizeof(struct ext4_inode) -
-                                               EXT4_GOOD_OLD_INODE_SIZE;
-
-       if (sbi->s_inode_size == EXT4_GOOD_OLD_INODE_SIZE) {
-               sbi->s_want_extra_isize = 0;
-               return;
-       }
-       if (sbi->s_want_extra_isize < 4) {
-               sbi->s_want_extra_isize = def_extra_isize;
-               if (ext4_has_feature_extra_isize(sb)) {
-                       if (sbi->s_want_extra_isize <
-                           le16_to_cpu(es->s_want_extra_isize))
-                               sbi->s_want_extra_isize =
-                                       le16_to_cpu(es->s_want_extra_isize);
-                       if (sbi->s_want_extra_isize <
-                           le16_to_cpu(es->s_min_extra_isize))
-                               sbi->s_want_extra_isize =
-                                       le16_to_cpu(es->s_min_extra_isize);
-               }
-       }
-       /* Check if enough inode space is available */
-       if ((sbi->s_want_extra_isize > sbi->s_inode_size) ||
-           (EXT4_GOOD_OLD_INODE_SIZE + sbi->s_want_extra_isize >
-                                                       sbi->s_inode_size)) {
-               sbi->s_want_extra_isize = def_extra_isize;
-               ext4_msg(sb, KERN_INFO,
-                        "required extra inode space not available");
-       }
-}
-
 static void ext4_set_resv_clusters(struct super_block *sb)
 {
        ext4_fsblk_t resv_clusters;
@@ -3795,6 +3768,68 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
         */
        sbi->s_li_wait_mult = EXT4_DEF_LI_WAIT_MULT;
 
+       if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
+               sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
+               sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
+       } else {
+               sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
+               sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
+               if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
+                       ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
+                                sbi->s_first_ino);
+                       goto failed_mount;
+               }
+               if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
+                   (!is_power_of_2(sbi->s_inode_size)) ||
+                   (sbi->s_inode_size > blocksize)) {
+                       ext4_msg(sb, KERN_ERR,
+                              "unsupported inode size: %d",
+                              sbi->s_inode_size);
+                       goto failed_mount;
+               }
+               /*
+                * i_atime_extra is the last extra field available for
+                * [acm]times in struct ext4_inode. Checking for that
+                * field should suffice to ensure we have extra space
+                * for all three.
+                */
+               if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
+                       sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
+                       sb->s_time_gran = 1;
+                       sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
+               } else {
+                       sb->s_time_gran = NSEC_PER_SEC;
+                       sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
+               }
+               sb->s_time_min = EXT4_TIMESTAMP_MIN;
+       }
+       if (sbi->s_inode_size > EXT4_GOOD_OLD_INODE_SIZE) {
+               sbi->s_want_extra_isize = sizeof(struct ext4_inode) -
+                       EXT4_GOOD_OLD_INODE_SIZE;
+               if (ext4_has_feature_extra_isize(sb)) {
+                       unsigned v, max = (sbi->s_inode_size -
+                                          EXT4_GOOD_OLD_INODE_SIZE);
+
+                       v = le16_to_cpu(es->s_want_extra_isize);
+                       if (v > max) {
+                               ext4_msg(sb, KERN_ERR,
+                                        "bad s_want_extra_isize: %d", v);
+                               goto failed_mount;
+                       }
+                       if (sbi->s_want_extra_isize < v)
+                               sbi->s_want_extra_isize = v;
+
+                       v = le16_to_cpu(es->s_min_extra_isize);
+                       if (v > max) {
+                               ext4_msg(sb, KERN_ERR,
+                                        "bad s_min_extra_isize: %d", v);
+                               goto failed_mount;
+                       }
+                       if (sbi->s_want_extra_isize < v)
+                               sbi->s_want_extra_isize = v;
+               }
+       }
+
        if (sbi->s_es->s_mount_opts[0]) {
                char *s_mount_opts = kstrndup(sbi->s_es->s_mount_opts,
                                              sizeof(sbi->s_es->s_mount_opts),
@@ -4033,42 +4068,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                                                      has_huge_files);
        sb->s_maxbytes = ext4_max_size(sb->s_blocksize_bits, has_huge_files);
 
-       if (le32_to_cpu(es->s_rev_level) == EXT4_GOOD_OLD_REV) {
-               sbi->s_inode_size = EXT4_GOOD_OLD_INODE_SIZE;
-               sbi->s_first_ino = EXT4_GOOD_OLD_FIRST_INO;
-       } else {
-               sbi->s_inode_size = le16_to_cpu(es->s_inode_size);
-               sbi->s_first_ino = le32_to_cpu(es->s_first_ino);
-               if (sbi->s_first_ino < EXT4_GOOD_OLD_FIRST_INO) {
-                       ext4_msg(sb, KERN_ERR, "invalid first ino: %u",
-                                sbi->s_first_ino);
-                       goto failed_mount;
-               }
-               if ((sbi->s_inode_size < EXT4_GOOD_OLD_INODE_SIZE) ||
-                   (!is_power_of_2(sbi->s_inode_size)) ||
-                   (sbi->s_inode_size > blocksize)) {
-                       ext4_msg(sb, KERN_ERR,
-                              "unsupported inode size: %d",
-                              sbi->s_inode_size);
-                       goto failed_mount;
-               }
-               /*
-                * i_atime_extra is the last extra field available for [acm]times in
-                * struct ext4_inode. Checking for that field should suffice to ensure
-                * we have extra space for all three.
-                */
-               if (sbi->s_inode_size >= offsetof(struct ext4_inode, i_atime_extra) +
-                       sizeof(((struct ext4_inode *)0)->i_atime_extra)) {
-                       sb->s_time_gran = 1;
-                       sb->s_time_max = EXT4_EXTRA_TIMESTAMP_MAX;
-               } else {
-                       sb->s_time_gran = NSEC_PER_SEC;
-                       sb->s_time_max = EXT4_NON_EXTRA_TIMESTAMP_MAX;
-               }
-
-               sb->s_time_min = EXT4_TIMESTAMP_MIN;
-       }
-
        sbi->s_desc_size = le16_to_cpu(es->s_desc_size);
        if (ext4_has_feature_64bit(sb)) {
                if (sbi->s_desc_size < EXT4_MIN_DESC_SIZE_64BIT ||
@@ -4517,8 +4516,6 @@ no_journal:
        } else if (ret)
                goto failed_mount4a;
 
-       ext4_clamp_want_extra_isize(sb);
-
        ext4_set_resv_clusters(sb);
 
        err = ext4_setup_system_zone(sb);
@@ -5306,8 +5303,6 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
-       ext4_clamp_want_extra_isize(sb);
-
        if ((old_opts.s_mount_opt & EXT4_MOUNT_JOURNAL_CHECKSUM) ^
            test_opt(sb, JOURNAL_CHECKSUM)) {
                ext4_msg(sb, KERN_ERR, "changing journal_checksum "
index a63d779..ce71538 100644 (file)
@@ -882,6 +882,7 @@ static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
        struct fuse_args_pages *ap = &ia->ap;
        loff_t pos = page_offset(ap->pages[0]);
        size_t count = ap->num_pages << PAGE_SHIFT;
+       ssize_t res;
        int err;
 
        ap->args.out_pages = true;
@@ -896,7 +897,8 @@ static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
                if (!err)
                        return;
        } else {
-               err = fuse_simple_request(fc, &ap->args);
+               res = fuse_simple_request(fc, &ap->args);
+               err = res < 0 ? res : 0;
        }
        fuse_readpages_end(fc, &ap->args, err);
 }
index d5c2a31..a66e425 100644 (file)
@@ -1498,8 +1498,10 @@ static int __init init_hugetlbfs_fs(void)
        /* other hstates are optional */
        i = 0;
        for_each_hstate(h) {
-               if (i == default_hstate_idx)
+               if (i == default_hstate_idx) {
+                       i++;
                        continue;
+               }
 
                mnt = mount_one_hugetlbfs(h);
                if (IS_ERR(mnt))
index fef457a..96d62d9 100644 (file)
@@ -676,6 +676,7 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
        struct inode *inode, *next;
        LIST_HEAD(dispose);
 
+again:
        spin_lock(&sb->s_inode_list_lock);
        list_for_each_entry_safe(inode, next, &sb->s_inodes, i_sb_list) {
                spin_lock(&inode->i_lock);
@@ -698,6 +699,12 @@ int invalidate_inodes(struct super_block *sb, bool kill_dirty)
                inode_lru_list_del(inode);
                spin_unlock(&inode->i_lock);
                list_add(&inode->i_lru, &dispose);
+               if (need_resched()) {
+                       spin_unlock(&sb->s_inode_list_lock);
+                       cond_resched();
+                       dispose_list(&dispose);
+                       goto again;
+               }
        }
        spin_unlock(&sb->s_inode_list_lock);
 
index 4a7da1d..e3fa695 100644 (file)
@@ -38,7 +38,7 @@ static inline int __sync_blockdev(struct block_device *bdev, int wait)
 /*
  * buffer.c
  */
-extern void guard_bio_eod(int rw, struct bio *bio);
+extern void guard_bio_eod(struct bio *bio);
 extern int __block_write_begin_int(struct page *page, loff_t pos, unsigned len,
                get_block_t *get_block, struct iomap *iomap);
 
index 74b4050..5147d22 100644 (file)
@@ -49,7 +49,6 @@ struct io_worker {
        struct hlist_nulls_node nulls_node;
        struct list_head all_list;
        struct task_struct *task;
-       wait_queue_head_t wait;
        struct io_wqe *wqe;
 
        struct io_wq_work *cur_work;
@@ -93,7 +92,6 @@ struct io_wqe {
        struct io_wqe_acct acct[2];
 
        struct hlist_nulls_head free_list;
-       struct hlist_nulls_head busy_list;
        struct list_head all_list;
 
        struct io_wq *wq;
@@ -258,7 +256,7 @@ static bool io_wqe_activate_free_worker(struct io_wqe *wqe)
 
        worker = hlist_nulls_entry(n, struct io_worker, nulls_node);
        if (io_worker_get(worker)) {
-               wake_up(&worker->wait);
+               wake_up_process(worker->task);
                io_worker_release(worker);
                return true;
        }
@@ -328,7 +326,6 @@ static void __io_worker_busy(struct io_wqe *wqe, struct io_worker *worker,
        if (worker->flags & IO_WORKER_F_FREE) {
                worker->flags &= ~IO_WORKER_F_FREE;
                hlist_nulls_del_init_rcu(&worker->nulls_node);
-               hlist_nulls_add_head_rcu(&worker->nulls_node, &wqe->busy_list);
        }
 
        /*
@@ -366,7 +363,6 @@ static bool __io_worker_idle(struct io_wqe *wqe, struct io_worker *worker)
 {
        if (!(worker->flags & IO_WORKER_F_FREE)) {
                worker->flags |= IO_WORKER_F_FREE;
-               hlist_nulls_del_init_rcu(&worker->nulls_node);
                hlist_nulls_add_head_rcu(&worker->nulls_node, &wqe->free_list);
        }
 
@@ -433,6 +429,8 @@ next:
                if (signal_pending(current))
                        flush_signals(current);
 
+               cond_resched();
+
                spin_lock_irq(&worker->lock);
                worker->cur_work = work;
                spin_unlock_irq(&worker->lock);
@@ -447,10 +445,14 @@ next:
                        task_unlock(current);
                }
                if ((work->flags & IO_WQ_WORK_NEEDS_USER) && !worker->mm &&
-                   wq->mm && mmget_not_zero(wq->mm)) {
-                       use_mm(wq->mm);
-                       set_fs(USER_DS);
-                       worker->mm = wq->mm;
+                   wq->mm) {
+                       if (mmget_not_zero(wq->mm)) {
+                               use_mm(wq->mm);
+                               set_fs(USER_DS);
+                               worker->mm = wq->mm;
+                       } else {
+                               work->flags |= IO_WQ_WORK_CANCEL;
+                       }
                }
                if (!worker->creds)
                        worker->creds = override_creds(wq->creds);
@@ -492,28 +494,46 @@ next:
        } while (1);
 }
 
+static inline void io_worker_spin_for_work(struct io_wqe *wqe)
+{
+       int i = 0;
+
+       while (++i < 1000) {
+               if (io_wqe_run_queue(wqe))
+                       break;
+               if (need_resched())
+                       break;
+               cpu_relax();
+       }
+}
+
 static int io_wqe_worker(void *data)
 {
        struct io_worker *worker = data;
        struct io_wqe *wqe = worker->wqe;
        struct io_wq *wq = wqe->wq;
-       DEFINE_WAIT(wait);
+       bool did_work;
 
        io_worker_start(wqe, worker);
 
+       did_work = false;
        while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
-               prepare_to_wait(&worker->wait, &wait, TASK_INTERRUPTIBLE);
-
+               set_current_state(TASK_INTERRUPTIBLE);
+loop:
+               if (did_work)
+                       io_worker_spin_for_work(wqe);
                spin_lock_irq(&wqe->lock);
                if (io_wqe_run_queue(wqe)) {
                        __set_current_state(TASK_RUNNING);
                        io_worker_handle_work(worker);
-                       continue;
+                       did_work = true;
+                       goto loop;
                }
+               did_work = false;
                /* drops the lock on success, retry */
                if (__io_worker_idle(wqe, worker)) {
                        __release(&wqe->lock);
-                       continue;
+                       goto loop;
                }
                spin_unlock_irq(&wqe->lock);
                if (signal_pending(current))
@@ -526,8 +546,6 @@ static int io_wqe_worker(void *data)
                        break;
        }
 
-       finish_wait(&worker->wait, &wait);
-
        if (test_bit(IO_WQ_BIT_EXIT, &wq->state)) {
                spin_lock_irq(&wqe->lock);
                if (!wq_list_empty(&wqe->work_list))
@@ -589,7 +607,6 @@ static bool create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index)
 
        refcount_set(&worker->ref, 1);
        worker->nulls_node.pprev = NULL;
-       init_waitqueue_head(&worker->wait);
        worker->wqe = wqe;
        spin_lock_init(&worker->lock);
 
@@ -784,10 +801,6 @@ void io_wq_cancel_all(struct io_wq *wq)
 
        set_bit(IO_WQ_BIT_CANCEL, &wq->state);
 
-       /*
-        * Browse both lists, as there's a gap between handing work off
-        * to a worker and the worker putting itself on the busy_list
-        */
        rcu_read_lock();
        for_each_node(node) {
                struct io_wqe *wqe = wq->wqes[node];
@@ -934,7 +947,7 @@ static enum io_wq_cancel io_wqe_cancel_work(struct io_wqe *wqe,
        /*
         * Now check if a free (going busy) or busy worker has the work
         * currently running. If we find it there, we'll return CANCEL_RUNNING
-        * as an indication that we attempte to signal cancellation. The
+        * as an indication that we attempt to signal cancellation. The
         * completion will run normally in this case.
         */
        rcu_read_lock();
@@ -1035,7 +1048,6 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
                spin_lock_init(&wqe->lock);
                INIT_WQ_LIST(&wqe->work_list);
                INIT_HLIST_NULLS_HEAD(&wqe->free_list, 0);
-               INIT_HLIST_NULLS_HEAD(&wqe->busy_list, 1);
                INIT_LIST_HEAD(&wqe->all_list);
        }
 
index 7c333a2..3f5e356 100644 (file)
@@ -35,7 +35,8 @@ static inline void wq_list_add_tail(struct io_wq_work_node *node,
                                    struct io_wq_work_list *list)
 {
        if (!list->first) {
-               list->first = list->last = node;
+               list->last = node;
+               WRITE_ONCE(list->first, node);
        } else {
                list->last->next = node;
                list->last = node;
@@ -47,7 +48,7 @@ static inline void wq_node_del(struct io_wq_work_list *list,
                               struct io_wq_work_node *prev)
 {
        if (node == list->first)
-               list->first = node->next;
+               WRITE_ONCE(list->first, node->next);
        if (node == list->last)
                list->last = prev;
        if (prev)
@@ -58,7 +59,7 @@ static inline void wq_node_del(struct io_wq_work_list *list,
 #define wq_list_for_each(pos, prv, head)                       \
        for (pos = (head)->first, prv = NULL; pos; prv = pos, pos = (pos)->next)
 
-#define wq_list_empty(list)    ((list)->first == NULL)
+#define wq_list_empty(list)    (READ_ONCE((list)->first) == NULL)
 #define INIT_WQ_LIST(list)     do {                            \
        (list)->first = NULL;                                   \
        (list)->last = NULL;                                    \
@@ -119,6 +120,10 @@ static inline void io_wq_worker_sleeping(struct task_struct *tsk)
 static inline void io_wq_worker_running(struct task_struct *tsk)
 {
 }
-#endif /* CONFIG_IO_WQ */
+#endif
 
-#endif /* INTERNAL_IO_WQ_H */
+static inline bool io_wq_current_is_worker(void)
+{
+       return in_task() && (current->flags & PF_IO_WORKER);
+}
+#endif
index 405be10..187dd94 100644 (file)
@@ -289,11 +289,14 @@ struct io_ring_ctx {
  */
 struct io_poll_iocb {
        struct file                     *file;
-       struct wait_queue_head          *head;
+       union {
+               struct wait_queue_head  *head;
+               u64                     addr;
+       };
        __poll_t                        events;
        bool                            done;
        bool                            canceled;
-       struct wait_queue_entry         *wait;
+       struct wait_queue_entry         wait;
 };
 
 struct io_timeout_data {
@@ -304,6 +307,51 @@ struct io_timeout_data {
        u32                             seq_offset;
 };
 
+struct io_accept {
+       struct file                     *file;
+       struct sockaddr __user          *addr;
+       int __user                      *addr_len;
+       int                             flags;
+};
+
+struct io_sync {
+       struct file                     *file;
+       loff_t                          len;
+       loff_t                          off;
+       int                             flags;
+};
+
+struct io_cancel {
+       struct file                     *file;
+       u64                             addr;
+};
+
+struct io_timeout {
+       struct file                     *file;
+       u64                             addr;
+       int                             flags;
+       unsigned                        count;
+};
+
+struct io_rw {
+       /* NOTE: kiocb has the file as the first member, so don't do it here */
+       struct kiocb                    kiocb;
+       u64                             addr;
+       u64                             len;
+};
+
+struct io_connect {
+       struct file                     *file;
+       struct sockaddr __user          *addr;
+       int                             addr_len;
+};
+
+struct io_sr_msg {
+       struct file                     *file;
+       struct user_msghdr __user       *msg;
+       int                             msg_flags;
+};
+
 struct io_async_connect {
        struct sockaddr_storage         address;
 };
@@ -323,7 +371,6 @@ struct io_async_rw {
 };
 
 struct io_async_ctx {
-       struct io_uring_sqe             sqe;
        union {
                struct io_async_rw      rw;
                struct io_async_msghdr  msg;
@@ -341,17 +388,23 @@ struct io_async_ctx {
 struct io_kiocb {
        union {
                struct file             *file;
-               struct kiocb            rw;
+               struct io_rw            rw;
                struct io_poll_iocb     poll;
+               struct io_accept        accept;
+               struct io_sync          sync;
+               struct io_cancel        cancel;
+               struct io_timeout       timeout;
+               struct io_connect       connect;
+               struct io_sr_msg        sr_msg;
        };
 
-       const struct io_uring_sqe       *sqe;
        struct io_async_ctx             *io;
        struct file                     *ring_file;
        int                             ring_fd;
        bool                            has_user;
        bool                            in_async;
        bool                            needs_fixed_file;
+       u8                              opcode;
 
        struct io_ring_ctx      *ctx;
        union {
@@ -377,6 +430,7 @@ struct io_kiocb {
 #define REQ_F_TIMEOUT_NOSEQ    8192    /* no timeout sequence */
 #define REQ_F_INFLIGHT         16384   /* on inflight list */
 #define REQ_F_COMP_LOCKED      32768   /* completion under lock */
+#define REQ_F_HARDLINK         65536   /* doesn't sever on completion < 0 */
        u64                     user_data;
        u32                     result;
        u32                     sequence;
@@ -563,12 +617,10 @@ static void __io_commit_cqring(struct io_ring_ctx *ctx)
        }
 }
 
-static inline bool io_sqe_needs_user(const struct io_uring_sqe *sqe)
+static inline bool io_req_needs_user(struct io_kiocb *req)
 {
-       u8 opcode = READ_ONCE(sqe->opcode);
-
-       return !(opcode == IORING_OP_READ_FIXED ||
-                opcode == IORING_OP_WRITE_FIXED);
+       return !(req->opcode == IORING_OP_READ_FIXED ||
+                req->opcode == IORING_OP_WRITE_FIXED);
 }
 
 static inline bool io_prep_async_work(struct io_kiocb *req,
@@ -576,31 +628,31 @@ static inline bool io_prep_async_work(struct io_kiocb *req,
 {
        bool do_hashed = false;
 
-       if (req->sqe) {
-               switch (req->sqe->opcode) {
-               case IORING_OP_WRITEV:
-               case IORING_OP_WRITE_FIXED:
+       switch (req->opcode) {
+       case IORING_OP_WRITEV:
+       case IORING_OP_WRITE_FIXED:
+               /* only regular files should be hashed for writes */
+               if (req->flags & REQ_F_ISREG)
                        do_hashed = true;
-                       /* fall-through */
-               case IORING_OP_READV:
-               case IORING_OP_READ_FIXED:
-               case IORING_OP_SENDMSG:
-               case IORING_OP_RECVMSG:
-               case IORING_OP_ACCEPT:
-               case IORING_OP_POLL_ADD:
-               case IORING_OP_CONNECT:
-                       /*
-                        * We know REQ_F_ISREG is not set on some of these
-                        * opcodes, but this enables us to keep the check in
-                        * just one place.
-                        */
-                       if (!(req->flags & REQ_F_ISREG))
-                               req->work.flags |= IO_WQ_WORK_UNBOUND;
-                       break;
-               }
-               if (io_sqe_needs_user(req->sqe))
-                       req->work.flags |= IO_WQ_WORK_NEEDS_USER;
+               /* fall-through */
+       case IORING_OP_READV:
+       case IORING_OP_READ_FIXED:
+       case IORING_OP_SENDMSG:
+       case IORING_OP_RECVMSG:
+       case IORING_OP_ACCEPT:
+       case IORING_OP_POLL_ADD:
+       case IORING_OP_CONNECT:
+               /*
+                * We know REQ_F_ISREG is not set on some of these
+                * opcodes, but this enables us to keep the check in
+                * just one place.
+                */
+               if (!(req->flags & REQ_F_ISREG))
+                       req->work.flags |= IO_WQ_WORK_UNBOUND;
+               break;
        }
+       if (io_req_needs_user(req))
+               req->work.flags |= IO_WQ_WORK_NEEDS_USER;
 
        *link = io_prep_linked_timeout(req);
        return do_hashed;
@@ -969,7 +1021,7 @@ static void io_fail_links(struct io_kiocb *req)
                trace_io_uring_fail_link(req, link);
 
                if ((req->flags & REQ_F_LINK_TIMEOUT) &&
-                   link->sqe->opcode == IORING_OP_LINK_TIMEOUT) {
+                   link->opcode == IORING_OP_LINK_TIMEOUT) {
                        io_link_cancel_timeout(link);
                } else {
                        io_cqring_fill_event(link, -ECANCELED);
@@ -1145,7 +1197,7 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
 
        ret = 0;
        list_for_each_entry_safe(req, tmp, &ctx->poll_list, list) {
-               struct kiocb *kiocb = &req->rw;
+               struct kiocb *kiocb = &req->rw.kiocb;
 
                /*
                 * Move completed entries to our local list. If we find a
@@ -1175,7 +1227,7 @@ static int io_do_iopoll(struct io_ring_ctx *ctx, unsigned int *nr_events,
 }
 
 /*
- * Poll for a mininum of 'min' events. Note that if min == 0 we consider that a
+ * Poll for a minimum of 'min' events. Note that if min == 0 we consider that a
  * non-spinning poll check - we'll still enter the driver poll loop, but only
  * as a non-spinning completion check.
  */
@@ -1292,21 +1344,27 @@ static void kiocb_end_write(struct io_kiocb *req)
        file_end_write(req->file);
 }
 
+static inline void req_set_fail_links(struct io_kiocb *req)
+{
+       if ((req->flags & (REQ_F_LINK | REQ_F_HARDLINK)) == REQ_F_LINK)
+               req->flags |= REQ_F_FAIL_LINK;
+}
+
 static void io_complete_rw_common(struct kiocb *kiocb, long res)
 {
-       struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw);
+       struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb);
 
        if (kiocb->ki_flags & IOCB_WRITE)
                kiocb_end_write(req);
 
-       if ((req->flags & REQ_F_LINK) && res != req->result)
-               req->flags |= REQ_F_FAIL_LINK;
+       if (res != req->result)
+               req_set_fail_links(req);
        io_cqring_add_event(req, res);
 }
 
 static void io_complete_rw(struct kiocb *kiocb, long res, long res2)
 {
-       struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw);
+       struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb);
 
        io_complete_rw_common(kiocb, res);
        io_put_req(req);
@@ -1314,7 +1372,7 @@ static void io_complete_rw(struct kiocb *kiocb, long res, long res2)
 
 static struct io_kiocb *__io_complete_rw(struct kiocb *kiocb, long res)
 {
-       struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw);
+       struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb);
        struct io_kiocb *nxt = NULL;
 
        io_complete_rw_common(kiocb, res);
@@ -1325,13 +1383,13 @@ static struct io_kiocb *__io_complete_rw(struct kiocb *kiocb, long res)
 
 static void io_complete_rw_iopoll(struct kiocb *kiocb, long res, long res2)
 {
-       struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw);
+       struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb);
 
        if (kiocb->ki_flags & IOCB_WRITE)
                kiocb_end_write(req);
 
-       if ((req->flags & REQ_F_LINK) && res != req->result)
-               req->flags |= REQ_F_FAIL_LINK;
+       if (res != req->result)
+               req_set_fail_links(req);
        req->result = res;
        if (res != -EAGAIN)
                req->flags |= REQ_F_IOPOLL_COMPLETED;
@@ -1359,7 +1417,7 @@ static void io_iopoll_req_issued(struct io_kiocb *req)
 
                list_req = list_first_entry(&ctx->poll_list, struct io_kiocb,
                                                list);
-               if (list_req->rw.ki_filp != req->rw.ki_filp)
+               if (list_req->file != req->file)
                        ctx->poll_multi_file = true;
        }
 
@@ -1422,7 +1480,7 @@ static bool io_file_supports_async(struct file *file)
 {
        umode_t mode = file_inode(file)->i_mode;
 
-       if (S_ISBLK(mode) || S_ISCHR(mode))
+       if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISSOCK(mode))
                return true;
        if (S_ISREG(mode) && file->f_op != &io_uring_fops)
                return true;
@@ -1430,11 +1488,11 @@ static bool io_file_supports_async(struct file *file)
        return false;
 }
 
-static int io_prep_rw(struct io_kiocb *req, bool force_nonblock)
+static int io_prep_rw(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+                     bool force_nonblock)
 {
-       const struct io_uring_sqe *sqe = req->sqe;
        struct io_ring_ctx *ctx = req->ctx;
-       struct kiocb *kiocb = &req->rw;
+       struct kiocb *kiocb = &req->rw.kiocb;
        unsigned ioprio;
        int ret;
 
@@ -1483,6 +1541,12 @@ static int io_prep_rw(struct io_kiocb *req, bool force_nonblock)
                        return -EINVAL;
                kiocb->ki_complete = io_complete_rw;
        }
+
+       req->rw.addr = READ_ONCE(sqe->addr);
+       req->rw.len = READ_ONCE(sqe->len);
+       /* we own ->private, reuse it for the buffer index */
+       req->rw.kiocb.private = (void *) (unsigned long)
+                                       READ_ONCE(sqe->buf_index);
        return 0;
 }
 
@@ -1516,11 +1580,11 @@ static void kiocb_done(struct kiocb *kiocb, ssize_t ret, struct io_kiocb **nxt,
                io_rw_done(kiocb, ret);
 }
 
-static ssize_t io_import_fixed(struct io_ring_ctx *ctx, int rw,
-                              const struct io_uring_sqe *sqe,
+static ssize_t io_import_fixed(struct io_kiocb *req, int rw,
                               struct iov_iter *iter)
 {
-       size_t len = READ_ONCE(sqe->len);
+       struct io_ring_ctx *ctx = req->ctx;
+       size_t len = req->rw.len;
        struct io_mapped_ubuf *imu;
        unsigned index, buf_index;
        size_t offset;
@@ -1530,13 +1594,13 @@ static ssize_t io_import_fixed(struct io_ring_ctx *ctx, int rw,
        if (unlikely(!ctx->user_bufs))
                return -EFAULT;
 
-       buf_index = READ_ONCE(sqe->buf_index);
+       buf_index = (unsigned long) req->rw.kiocb.private;
        if (unlikely(buf_index >= ctx->nr_user_bufs))
                return -EFAULT;
 
        index = array_index_nospec(buf_index, ctx->nr_user_bufs);
        imu = &ctx->user_bufs[index];
-       buf_addr = READ_ONCE(sqe->addr);
+       buf_addr = req->rw.addr;
 
        /* overflow */
        if (buf_addr + len < buf_addr)
@@ -1593,25 +1657,20 @@ static ssize_t io_import_fixed(struct io_ring_ctx *ctx, int rw,
 static ssize_t io_import_iovec(int rw, struct io_kiocb *req,
                               struct iovec **iovec, struct iov_iter *iter)
 {
-       const struct io_uring_sqe *sqe = req->sqe;
-       void __user *buf = u64_to_user_ptr(READ_ONCE(sqe->addr));
-       size_t sqe_len = READ_ONCE(sqe->len);
+       void __user *buf = u64_to_user_ptr(req->rw.addr);
+       size_t sqe_len = req->rw.len;
        u8 opcode;
 
-       /*
-        * We're reading ->opcode for the second time, but the first read
-        * doesn't care whether it's _FIXED or not, so it doesn't matter
-        * whether ->opcode changes concurrently. The first read does care
-        * about whether it is a READ or a WRITE, so we don't trust this read
-        * for that purpose and instead let the caller pass in the read/write
-        * flag.
-        */
-       opcode = READ_ONCE(sqe->opcode);
+       opcode = req->opcode;
        if (opcode == IORING_OP_READ_FIXED || opcode == IORING_OP_WRITE_FIXED) {
                *iovec = NULL;
-               return io_import_fixed(req->ctx, rw, sqe, iter);
+               return io_import_fixed(req, rw, iter);
        }
 
+       /* buffer index only valid with fixed read/write */
+       if (req->rw.kiocb.private)
+               return -EINVAL;
+
        if (req->io) {
                struct io_async_rw *iorw = &req->io->rw;
 
@@ -1692,7 +1751,7 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,
        return ret;
 }
 
-static void io_req_map_io(struct io_kiocb *req, ssize_t io_size,
+static void io_req_map_rw(struct io_kiocb *req, ssize_t io_size,
                          struct iovec *iovec, struct iovec *fast_iov,
                          struct iov_iter *iter)
 {
@@ -1706,57 +1765,85 @@ static void io_req_map_io(struct io_kiocb *req, ssize_t io_size,
        }
 }
 
-static int io_setup_async_io(struct io_kiocb *req, ssize_t io_size,
+static int io_alloc_async_ctx(struct io_kiocb *req)
+{
+       req->io = kmalloc(sizeof(*req->io), GFP_KERNEL);
+       return req->io == NULL;
+}
+
+static void io_rw_async(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       struct iovec *iov = NULL;
+
+       if (req->io->rw.iov != req->io->rw.fast_iov)
+               iov = req->io->rw.iov;
+       io_wq_submit_work(workptr);
+       kfree(iov);
+}
+
+static int io_setup_async_rw(struct io_kiocb *req, ssize_t io_size,
                             struct iovec *iovec, struct iovec *fast_iov,
                             struct iov_iter *iter)
 {
-       req->io = kmalloc(sizeof(*req->io), GFP_KERNEL);
-       if (req->io) {
-               io_req_map_io(req, io_size, iovec, fast_iov, iter);
-               memcpy(&req->io->sqe, req->sqe, sizeof(req->io->sqe));
-               req->sqe = &req->io->sqe;
+       if (req->opcode == IORING_OP_READ_FIXED ||
+           req->opcode == IORING_OP_WRITE_FIXED)
                return 0;
-       }
+       if (!req->io && io_alloc_async_ctx(req))
+               return -ENOMEM;
 
-       return -ENOMEM;
+       io_req_map_rw(req, io_size, iovec, fast_iov, iter);
+       req->work.func = io_rw_async;
+       return 0;
 }
 
-static int io_read_prep(struct io_kiocb *req, struct iovec **iovec,
-                       struct iov_iter *iter, bool force_nonblock)
+static int io_read_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+                       bool force_nonblock)
 {
+       struct io_async_ctx *io;
+       struct iov_iter iter;
        ssize_t ret;
 
-       ret = io_prep_rw(req, force_nonblock);
+       ret = io_prep_rw(req, sqe, force_nonblock);
        if (ret)
                return ret;
 
        if (unlikely(!(req->file->f_mode & FMODE_READ)))
                return -EBADF;
 
-       return io_import_iovec(READ, req, iovec, iter);
+       if (!req->io)
+               return 0;
+
+       io = req->io;
+       io->rw.iov = io->rw.fast_iov;
+       req->io = NULL;
+       ret = io_import_iovec(READ, req, &io->rw.iov, &iter);
+       req->io = io;
+       if (ret < 0)
+               return ret;
+
+       io_req_map_rw(req, ret, io->rw.iov, io->rw.fast_iov, &iter);
+       return 0;
 }
 
 static int io_read(struct io_kiocb *req, struct io_kiocb **nxt,
                   bool force_nonblock)
 {
        struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
-       struct kiocb *kiocb = &req->rw;
+       struct kiocb *kiocb = &req->rw.kiocb;
        struct iov_iter iter;
-       struct file *file;
        size_t iov_count;
        ssize_t io_size, ret;
 
-       if (!req->io) {
-               ret = io_read_prep(req, &iovec, &iter, force_nonblock);
-               if (ret < 0)
-                       return ret;
-       } else {
-               ret = io_import_iovec(READ, req, &iovec, &iter);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = io_import_iovec(READ, req, &iovec, &iter);
+       if (ret < 0)
+               return ret;
 
-       file = req->file;
+       /* Ensure we clear previously set non-block flag */
+       if (!force_nonblock)
+               req->rw.kiocb.ki_flags &= ~IOCB_NOWAIT;
+
+       req->result = 0;
        io_size = ret;
        if (req->flags & REQ_F_LINK)
                req->result = io_size;
@@ -1765,39 +1852,27 @@ static int io_read(struct io_kiocb *req, struct io_kiocb **nxt,
         * If the file doesn't support async, mark it as REQ_F_MUST_PUNT so
         * we know to async punt it even if it was opened O_NONBLOCK
         */
-       if (force_nonblock && !io_file_supports_async(file)) {
+       if (force_nonblock && !io_file_supports_async(req->file)) {
                req->flags |= REQ_F_MUST_PUNT;
                goto copy_iov;
        }
 
        iov_count = iov_iter_count(&iter);
-       ret = rw_verify_area(READ, file, &kiocb->ki_pos, iov_count);
+       ret = rw_verify_area(READ, req->file, &kiocb->ki_pos, iov_count);
        if (!ret) {
                ssize_t ret2;
 
-               if (file->f_op->read_iter)
-                       ret2 = call_read_iter(file, kiocb, &iter);
+               if (req->file->f_op->read_iter)
+                       ret2 = call_read_iter(req->file, kiocb, &iter);
                else
-                       ret2 = loop_rw_iter(READ, file, kiocb, &iter);
+                       ret2 = loop_rw_iter(READ, req->file, kiocb, &iter);
 
-               /*
-                * In case of a short read, punt to async. This can happen
-                * if we have data partially cached. Alternatively we can
-                * return the short read, in which case the application will
-                * need to issue another SQE and wait for it. That SQE will
-                * need async punt anyway, so it's more efficient to do it
-                * here.
-                */
-               if (force_nonblock && !(req->flags & REQ_F_NOWAIT) &&
-                   (req->flags & REQ_F_ISREG) &&
-                   ret2 > 0 && ret2 < io_size)
-                       ret2 = -EAGAIN;
                /* Catch -EAGAIN return for forced non-blocking submission */
                if (!force_nonblock || ret2 != -EAGAIN) {
                        kiocb_done(kiocb, ret2, nxt, req->in_async);
                } else {
 copy_iov:
-                       ret = io_setup_async_io(req, io_size, iovec,
+                       ret = io_setup_async_rw(req, io_size, iovec,
                                                inline_vecs, &iter);
                        if (ret)
                                goto out_free;
@@ -1805,46 +1880,58 @@ copy_iov:
                }
        }
 out_free:
-       kfree(iovec);
+       if (!io_wq_current_is_worker())
+               kfree(iovec);
        return ret;
 }
 
-static int io_write_prep(struct io_kiocb *req, struct iovec **iovec,
-                        struct iov_iter *iter, bool force_nonblock)
+static int io_write_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+                        bool force_nonblock)
 {
+       struct io_async_ctx *io;
+       struct iov_iter iter;
        ssize_t ret;
 
-       ret = io_prep_rw(req, force_nonblock);
+       ret = io_prep_rw(req, sqe, force_nonblock);
        if (ret)
                return ret;
 
        if (unlikely(!(req->file->f_mode & FMODE_WRITE)))
                return -EBADF;
 
-       return io_import_iovec(WRITE, req, iovec, iter);
+       if (!req->io)
+               return 0;
+
+       io = req->io;
+       io->rw.iov = io->rw.fast_iov;
+       req->io = NULL;
+       ret = io_import_iovec(WRITE, req, &io->rw.iov, &iter);
+       req->io = io;
+       if (ret < 0)
+               return ret;
+
+       io_req_map_rw(req, ret, io->rw.iov, io->rw.fast_iov, &iter);
+       return 0;
 }
 
 static int io_write(struct io_kiocb *req, struct io_kiocb **nxt,
                    bool force_nonblock)
 {
        struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
-       struct kiocb *kiocb = &req->rw;
+       struct kiocb *kiocb = &req->rw.kiocb;
        struct iov_iter iter;
-       struct file *file;
        size_t iov_count;
        ssize_t ret, io_size;
 
-       if (!req->io) {
-               ret = io_write_prep(req, &iovec, &iter, force_nonblock);
-               if (ret < 0)
-                       return ret;
-       } else {
-               ret = io_import_iovec(WRITE, req, &iovec, &iter);
-               if (ret < 0)
-                       return ret;
-       }
+       ret = io_import_iovec(WRITE, req, &iovec, &iter);
+       if (ret < 0)
+               return ret;
 
-       file = kiocb->ki_filp;
+       /* Ensure we clear previously set non-block flag */
+       if (!force_nonblock)
+               req->rw.kiocb.ki_flags &= ~IOCB_NOWAIT;
+
+       req->result = 0;
        io_size = ret;
        if (req->flags & REQ_F_LINK)
                req->result = io_size;
@@ -1858,11 +1945,13 @@ static int io_write(struct io_kiocb *req, struct io_kiocb **nxt,
                goto copy_iov;
        }
 
-       if (force_nonblock && !(kiocb->ki_flags & IOCB_DIRECT))
+       /* file path doesn't support NOWAIT for non-direct_IO */
+       if (force_nonblock && !(kiocb->ki_flags & IOCB_DIRECT) &&
+           (req->flags & REQ_F_ISREG))
                goto copy_iov;
 
        iov_count = iov_iter_count(&iter);
-       ret = rw_verify_area(WRITE, file, &kiocb->ki_pos, iov_count);
+       ret = rw_verify_area(WRITE, req->file, &kiocb->ki_pos, iov_count);
        if (!ret) {
                ssize_t ret2;
 
@@ -1874,22 +1963,22 @@ static int io_write(struct io_kiocb *req, struct io_kiocb **nxt,
                 * we return to userspace.
                 */
                if (req->flags & REQ_F_ISREG) {
-                       __sb_start_write(file_inode(file)->i_sb,
+                       __sb_start_write(file_inode(req->file)->i_sb,
                                                SB_FREEZE_WRITE, true);
-                       __sb_writers_release(file_inode(file)->i_sb,
+                       __sb_writers_release(file_inode(req->file)->i_sb,
                                                SB_FREEZE_WRITE);
                }
                kiocb->ki_flags |= IOCB_WRITE;
 
-               if (file->f_op->write_iter)
-                       ret2 = call_write_iter(file, kiocb, &iter);
+               if (req->file->f_op->write_iter)
+                       ret2 = call_write_iter(req->file, kiocb, &iter);
                else
-                       ret2 = loop_rw_iter(WRITE, file, kiocb, &iter);
+                       ret2 = loop_rw_iter(WRITE, req->file, kiocb, &iter);
                if (!force_nonblock || ret2 != -EAGAIN) {
                        kiocb_done(kiocb, ret2, nxt, req->in_async);
                } else {
 copy_iov:
-                       ret = io_setup_async_io(req, io_size, iovec,
+                       ret = io_setup_async_rw(req, io_size, iovec,
                                                inline_vecs, &iter);
                        if (ret)
                                goto out_free;
@@ -1897,7 +1986,8 @@ copy_iov:
                }
        }
 out_free:
-       kfree(iovec);
+       if (!io_wq_current_is_worker())
+               kfree(iovec);
        return ret;
 }
 
@@ -1928,45 +2018,92 @@ static int io_prep_fsync(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        if (unlikely(sqe->addr || sqe->ioprio || sqe->buf_index))
                return -EINVAL;
 
+       req->sync.flags = READ_ONCE(sqe->fsync_flags);
+       if (unlikely(req->sync.flags & ~IORING_FSYNC_DATASYNC))
+               return -EINVAL;
+
+       req->sync.off = READ_ONCE(sqe->off);
+       req->sync.len = READ_ONCE(sqe->len);
        return 0;
 }
 
-static int io_fsync(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                   struct io_kiocb **nxt, bool force_nonblock)
+static bool io_req_cancelled(struct io_kiocb *req)
 {
-       loff_t sqe_off = READ_ONCE(sqe->off);
-       loff_t sqe_len = READ_ONCE(sqe->len);
-       loff_t end = sqe_off + sqe_len;
-       unsigned fsync_flags;
+       if (req->work.flags & IO_WQ_WORK_CANCEL) {
+               req_set_fail_links(req);
+               io_cqring_add_event(req, -ECANCELED);
+               io_put_req(req);
+               return true;
+       }
+
+       return false;
+}
+
+static void io_link_work_cb(struct io_wq_work **workptr)
+{
+       struct io_wq_work *work = *workptr;
+       struct io_kiocb *link = work->data;
+
+       io_queue_linked_timeout(link);
+       work->func = io_wq_submit_work;
+}
+
+static void io_wq_assign_next(struct io_wq_work **workptr, struct io_kiocb *nxt)
+{
+       struct io_kiocb *link;
+
+       io_prep_async_work(nxt, &link);
+       *workptr = &nxt->work;
+       if (link) {
+               nxt->work.flags |= IO_WQ_WORK_CB;
+               nxt->work.func = io_link_work_cb;
+               nxt->work.data = link;
+       }
+}
+
+static void io_fsync_finish(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       loff_t end = req->sync.off + req->sync.len;
+       struct io_kiocb *nxt = NULL;
        int ret;
 
-       fsync_flags = READ_ONCE(sqe->fsync_flags);
-       if (unlikely(fsync_flags & ~IORING_FSYNC_DATASYNC))
-               return -EINVAL;
+       if (io_req_cancelled(req))
+               return;
 
-       ret = io_prep_fsync(req, sqe);
-       if (ret)
-               return ret;
+       ret = vfs_fsync_range(req->file, req->sync.off,
+                               end > 0 ? end : LLONG_MAX,
+                               req->sync.flags & IORING_FSYNC_DATASYNC);
+       if (ret < 0)
+               req_set_fail_links(req);
+       io_cqring_add_event(req, ret);
+       io_put_req_find_next(req, &nxt);
+       if (nxt)
+               io_wq_assign_next(workptr, nxt);
+}
+
+static int io_fsync(struct io_kiocb *req, struct io_kiocb **nxt,
+                   bool force_nonblock)
+{
+       struct io_wq_work *work, *old_work;
 
        /* fsync always requires a blocking context */
-       if (force_nonblock)
+       if (force_nonblock) {
+               io_put_req(req);
+               req->work.func = io_fsync_finish;
                return -EAGAIN;
+       }
 
-       ret = vfs_fsync_range(req->rw.ki_filp, sqe_off,
-                               end > 0 ? end : LLONG_MAX,
-                               fsync_flags & IORING_FSYNC_DATASYNC);
-
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
-       io_cqring_add_event(req, ret);
-       io_put_req_find_next(req, nxt);
+       work = old_work = &req->work;
+       io_fsync_finish(&work);
+       if (work && work != old_work)
+               *nxt = container_of(work, struct io_kiocb, work);
        return 0;
 }
 
 static int io_prep_sfr(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_ring_ctx *ctx = req->ctx;
-       int ret = 0;
 
        if (!req->file)
                return -EBADF;
@@ -1976,59 +2113,88 @@ static int io_prep_sfr(struct io_kiocb *req, const struct io_uring_sqe *sqe)
        if (unlikely(sqe->addr || sqe->ioprio || sqe->buf_index))
                return -EINVAL;
 
-       return ret;
+       req->sync.off = READ_ONCE(sqe->off);
+       req->sync.len = READ_ONCE(sqe->len);
+       req->sync.flags = READ_ONCE(sqe->sync_range_flags);
+       return 0;
 }
 
-static int io_sync_file_range(struct io_kiocb *req,
-                             const struct io_uring_sqe *sqe,
-                             struct io_kiocb **nxt,
-                             bool force_nonblock)
+static void io_sync_file_range_finish(struct io_wq_work **workptr)
 {
-       loff_t sqe_off;
-       loff_t sqe_len;
-       unsigned flags;
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       struct io_kiocb *nxt = NULL;
        int ret;
 
-       ret = io_prep_sfr(req, sqe);
-       if (ret)
-               return ret;
+       if (io_req_cancelled(req))
+               return;
+
+       ret = sync_file_range(req->file, req->sync.off, req->sync.len,
+                               req->sync.flags);
+       if (ret < 0)
+               req_set_fail_links(req);
+       io_cqring_add_event(req, ret);
+       io_put_req_find_next(req, &nxt);
+       if (nxt)
+               io_wq_assign_next(workptr, nxt);
+}
+
+static int io_sync_file_range(struct io_kiocb *req, struct io_kiocb **nxt,
+                             bool force_nonblock)
+{
+       struct io_wq_work *work, *old_work;
 
        /* sync_file_range always requires a blocking context */
-       if (force_nonblock)
+       if (force_nonblock) {
+               io_put_req(req);
+               req->work.func = io_sync_file_range_finish;
                return -EAGAIN;
+       }
 
-       sqe_off = READ_ONCE(sqe->off);
-       sqe_len = READ_ONCE(sqe->len);
-       flags = READ_ONCE(sqe->sync_range_flags);
+       work = old_work = &req->work;
+       io_sync_file_range_finish(&work);
+       if (work && work != old_work)
+               *nxt = container_of(work, struct io_kiocb, work);
+       return 0;
+}
 
-       ret = sync_file_range(req->rw.ki_filp, sqe_off, sqe_len, flags);
+#if defined(CONFIG_NET)
+static void io_sendrecv_async(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       struct iovec *iov = NULL;
 
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
-       io_cqring_add_event(req, ret);
-       io_put_req_find_next(req, nxt);
-       return 0;
+       if (req->io->rw.iov != req->io->rw.fast_iov)
+               iov = req->io->msg.iov;
+       io_wq_submit_work(workptr);
+       kfree(iov);
 }
+#endif
 
-static int io_sendmsg_prep(struct io_kiocb *req, struct io_async_ctx *io)
+static int io_sendmsg_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
 #if defined(CONFIG_NET)
-       const struct io_uring_sqe *sqe = req->sqe;
-       struct user_msghdr __user *msg;
-       unsigned flags;
+       struct io_sr_msg *sr = &req->sr_msg;
+       struct io_async_ctx *io = req->io;
+
+       sr->msg_flags = READ_ONCE(sqe->msg_flags);
+       sr->msg = u64_to_user_ptr(READ_ONCE(sqe->addr));
 
-       flags = READ_ONCE(sqe->msg_flags);
-       msg = (struct user_msghdr __user *)(unsigned long) READ_ONCE(sqe->addr);
-       return sendmsg_copy_msghdr(&io->msg.msg, msg, flags, &io->msg.iov);
+       if (!io)
+               return 0;
+
+       io->msg.iov = io->msg.fast_iov;
+       return sendmsg_copy_msghdr(&io->msg.msg, sr->msg, sr->msg_flags,
+                                       &io->msg.iov);
 #else
-       return 0;
+       return -EOPNOTSUPP;
 #endif
 }
 
-static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                     struct io_kiocb **nxt, bool force_nonblock)
+static int io_sendmsg(struct io_kiocb *req, struct io_kiocb **nxt,
+                     bool force_nonblock)
 {
 #if defined(CONFIG_NET)
+       struct io_async_msghdr *kmsg = NULL;
        struct socket *sock;
        int ret;
 
@@ -2037,50 +2203,55 @@ static int io_sendmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 
        sock = sock_from_file(req->file, &ret);
        if (sock) {
-               struct io_async_ctx io, *copy;
+               struct io_async_ctx io;
                struct sockaddr_storage addr;
-               struct msghdr *kmsg;
                unsigned flags;
 
-               flags = READ_ONCE(sqe->msg_flags);
-               if (flags & MSG_DONTWAIT)
-                       req->flags |= REQ_F_NOWAIT;
-               else if (force_nonblock)
-                       flags |= MSG_DONTWAIT;
-
                if (req->io) {
-                       kmsg = &req->io->msg.msg;
-                       kmsg->msg_name = &addr;
+                       kmsg = &req->io->msg;
+                       kmsg->msg.msg_name = &addr;
+                       /* if iov is set, it's allocated already */
+                       if (!kmsg->iov)
+                               kmsg->iov = kmsg->fast_iov;
+                       kmsg->msg.msg_iter.iov = kmsg->iov;
                } else {
-                       kmsg = &io.msg.msg;
-                       kmsg->msg_name = &addr;
+                       struct io_sr_msg *sr = &req->sr_msg;
+
+                       kmsg = &io.msg;
+                       kmsg->msg.msg_name = &addr;
+
                        io.msg.iov = io.msg.fast_iov;
-                       ret = io_sendmsg_prep(req, &io);
+                       ret = sendmsg_copy_msghdr(&io.msg.msg, sr->msg,
+                                       sr->msg_flags, &io.msg.iov);
                        if (ret)
-                               goto out;
+                               return ret;
                }
 
-               ret = __sys_sendmsg_sock(sock, kmsg, flags);
+               flags = req->sr_msg.msg_flags;
+               if (flags & MSG_DONTWAIT)
+                       req->flags |= REQ_F_NOWAIT;
+               else if (force_nonblock)
+                       flags |= MSG_DONTWAIT;
+
+               ret = __sys_sendmsg_sock(sock, &kmsg->msg, flags);
                if (force_nonblock && ret == -EAGAIN) {
-                       copy = kmalloc(sizeof(*copy), GFP_KERNEL);
-                       if (!copy) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       memcpy(&copy->msg, &io.msg, sizeof(copy->msg));
-                       req->io = copy;
-                       memcpy(&req->io->sqe, req->sqe, sizeof(*req->sqe));
-                       req->sqe = &req->io->sqe;
-                       return ret;
+                       if (req->io)
+                               return -EAGAIN;
+                       if (io_alloc_async_ctx(req))
+                               return -ENOMEM;
+                       memcpy(&req->io->msg, &io.msg, sizeof(io.msg));
+                       req->work.func = io_sendrecv_async;
+                       return -EAGAIN;
                }
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
        }
 
-out:
+       if (!io_wq_current_is_worker() && kmsg && kmsg->iov != kmsg->fast_iov)
+               kfree(kmsg->iov);
        io_cqring_add_event(req, ret);
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req_find_next(req, nxt);
        return 0;
 #else
@@ -2088,26 +2259,32 @@ out:
 #endif
 }
 
-static int io_recvmsg_prep(struct io_kiocb *req, struct io_async_ctx *io)
+static int io_recvmsg_prep(struct io_kiocb *req,
+                          const struct io_uring_sqe *sqe)
 {
 #if defined(CONFIG_NET)
-       const struct io_uring_sqe *sqe = req->sqe;
-       struct user_msghdr __user *msg;
-       unsigned flags;
+       struct io_sr_msg *sr = &req->sr_msg;
+       struct io_async_ctx *io = req->io;
 
-       flags = READ_ONCE(sqe->msg_flags);
-       msg = (struct user_msghdr __user *)(unsigned long) READ_ONCE(sqe->addr);
-       return recvmsg_copy_msghdr(&io->msg.msg, msg, flags, &io->msg.uaddr,
-                                       &io->msg.iov);
+       sr->msg_flags = READ_ONCE(sqe->msg_flags);
+       sr->msg = u64_to_user_ptr(READ_ONCE(sqe->addr));
+
+       if (!io)
+               return 0;
+
+       io->msg.iov = io->msg.fast_iov;
+       return recvmsg_copy_msghdr(&io->msg.msg, sr->msg, sr->msg_flags,
+                                       &io->msg.uaddr, &io->msg.iov);
 #else
-       return 0;
+       return -EOPNOTSUPP;
 #endif
 }
 
-static int io_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                     struct io_kiocb **nxt, bool force_nonblock)
+static int io_recvmsg(struct io_kiocb *req, struct io_kiocb **nxt,
+                     bool force_nonblock)
 {
 #if defined(CONFIG_NET)
+       struct io_async_msghdr *kmsg = NULL;
        struct socket *sock;
        int ret;
 
@@ -2116,53 +2293,57 @@ static int io_recvmsg(struct io_kiocb *req, const struct io_uring_sqe *sqe,
 
        sock = sock_from_file(req->file, &ret);
        if (sock) {
-               struct user_msghdr __user *msg;
-               struct io_async_ctx io, *copy;
+               struct io_async_ctx io;
                struct sockaddr_storage addr;
-               struct msghdr *kmsg;
                unsigned flags;
 
-               flags = READ_ONCE(sqe->msg_flags);
-               if (flags & MSG_DONTWAIT)
-                       req->flags |= REQ_F_NOWAIT;
-               else if (force_nonblock)
-                       flags |= MSG_DONTWAIT;
-
-               msg = (struct user_msghdr __user *) (unsigned long)
-                       READ_ONCE(sqe->addr);
                if (req->io) {
-                       kmsg = &req->io->msg.msg;
-                       kmsg->msg_name = &addr;
+                       kmsg = &req->io->msg;
+                       kmsg->msg.msg_name = &addr;
+                       /* if iov is set, it's allocated already */
+                       if (!kmsg->iov)
+                               kmsg->iov = kmsg->fast_iov;
+                       kmsg->msg.msg_iter.iov = kmsg->iov;
                } else {
-                       kmsg = &io.msg.msg;
-                       kmsg->msg_name = &addr;
+                       struct io_sr_msg *sr = &req->sr_msg;
+
+                       kmsg = &io.msg;
+                       kmsg->msg.msg_name = &addr;
+
                        io.msg.iov = io.msg.fast_iov;
-                       ret = io_recvmsg_prep(req, &io);
+                       ret = recvmsg_copy_msghdr(&io.msg.msg, sr->msg,
+                                       sr->msg_flags, &io.msg.uaddr,
+                                       &io.msg.iov);
                        if (ret)
-                               goto out;
+                               return ret;
                }
 
-               ret = __sys_recvmsg_sock(sock, kmsg, msg, io.msg.uaddr, flags);
+               flags = req->sr_msg.msg_flags;
+               if (flags & MSG_DONTWAIT)
+                       req->flags |= REQ_F_NOWAIT;
+               else if (force_nonblock)
+                       flags |= MSG_DONTWAIT;
+
+               ret = __sys_recvmsg_sock(sock, &kmsg->msg, req->sr_msg.msg,
+                                               kmsg->uaddr, flags);
                if (force_nonblock && ret == -EAGAIN) {
-                       copy = kmalloc(sizeof(*copy), GFP_KERNEL);
-                       if (!copy) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
-                       memcpy(copy, &io, sizeof(*copy));
-                       req->io = copy;
-                       memcpy(&req->io->sqe, req->sqe, sizeof(*req->sqe));
-                       req->sqe = &req->io->sqe;
-                       return ret;
+                       if (req->io)
+                               return -EAGAIN;
+                       if (io_alloc_async_ctx(req))
+                               return -ENOMEM;
+                       memcpy(&req->io->msg, &io.msg, sizeof(io.msg));
+                       req->work.func = io_sendrecv_async;
+                       return -EAGAIN;
                }
                if (ret == -ERESTARTSYS)
                        ret = -EINTR;
        }
 
-out:
+       if (!io_wq_current_is_worker() && kmsg && kmsg->iov != kmsg->fast_iov)
+               kfree(kmsg->iov);
        io_cqring_add_event(req, ret);
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req_find_next(req, nxt);
        return 0;
 #else
@@ -2170,101 +2351,141 @@ out:
 #endif
 }
 
-static int io_accept(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                    struct io_kiocb **nxt, bool force_nonblock)
+static int io_accept_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+{
+#if defined(CONFIG_NET)
+       struct io_accept *accept = &req->accept;
+
+       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
+               return -EINVAL;
+       if (sqe->ioprio || sqe->len || sqe->buf_index)
+               return -EINVAL;
+
+       accept->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
+       accept->addr_len = u64_to_user_ptr(READ_ONCE(sqe->addr2));
+       accept->flags = READ_ONCE(sqe->accept_flags);
+       return 0;
+#else
+       return -EOPNOTSUPP;
+#endif
+}
+
+#if defined(CONFIG_NET)
+static int __io_accept(struct io_kiocb *req, struct io_kiocb **nxt,
+                      bool force_nonblock)
+{
+       struct io_accept *accept = &req->accept;
+       unsigned file_flags;
+       int ret;
+
+       file_flags = force_nonblock ? O_NONBLOCK : 0;
+       ret = __sys_accept4_file(req->file, file_flags, accept->addr,
+                                       accept->addr_len, accept->flags);
+       if (ret == -EAGAIN && force_nonblock)
+               return -EAGAIN;
+       if (ret == -ERESTARTSYS)
+               ret = -EINTR;
+       if (ret < 0)
+               req_set_fail_links(req);
+       io_cqring_add_event(req, ret);
+       io_put_req_find_next(req, nxt);
+       return 0;
+}
+
+static void io_accept_finish(struct io_wq_work **workptr)
+{
+       struct io_kiocb *req = container_of(*workptr, struct io_kiocb, work);
+       struct io_kiocb *nxt = NULL;
+
+       if (io_req_cancelled(req))
+               return;
+       __io_accept(req, &nxt, false);
+       if (nxt)
+               io_wq_assign_next(workptr, nxt);
+}
+#endif
+
+static int io_accept(struct io_kiocb *req, struct io_kiocb **nxt,
+                    bool force_nonblock)
 {
 #if defined(CONFIG_NET)
-       struct sockaddr __user *addr;
-       int __user *addr_len;
-       unsigned file_flags;
-       int flags, ret;
-
-       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
-               return -EINVAL;
-       if (sqe->ioprio || sqe->len || sqe->buf_index)
-               return -EINVAL;
-
-       addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
-       addr_len = (int __user *) (unsigned long) READ_ONCE(sqe->addr2);
-       flags = READ_ONCE(sqe->accept_flags);
-       file_flags = force_nonblock ? O_NONBLOCK : 0;
+       int ret;
 
-       ret = __sys_accept4_file(req->file, file_flags, addr, addr_len, flags);
+       ret = __io_accept(req, nxt, force_nonblock);
        if (ret == -EAGAIN && force_nonblock) {
+               req->work.func = io_accept_finish;
                req->work.flags |= IO_WQ_WORK_NEEDS_FILES;
+               io_put_req(req);
                return -EAGAIN;
        }
-       if (ret == -ERESTARTSYS)
-               ret = -EINTR;
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
-       io_cqring_add_event(req, ret);
-       io_put_req_find_next(req, nxt);
        return 0;
 #else
        return -EOPNOTSUPP;
 #endif
 }
 
-static int io_connect_prep(struct io_kiocb *req, struct io_async_ctx *io)
+static int io_connect_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
 #if defined(CONFIG_NET)
-       const struct io_uring_sqe *sqe = req->sqe;
-       struct sockaddr __user *addr;
-       int addr_len;
+       struct io_connect *conn = &req->connect;
+       struct io_async_ctx *io = req->io;
+
+       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
+               return -EINVAL;
+       if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags)
+               return -EINVAL;
+
+       conn->addr = u64_to_user_ptr(READ_ONCE(sqe->addr));
+       conn->addr_len =  READ_ONCE(sqe->addr2);
+
+       if (!io)
+               return 0;
 
-       addr = (struct sockaddr __user *) (unsigned long) READ_ONCE(sqe->addr);
-       addr_len = READ_ONCE(sqe->addr2);
-       return move_addr_to_kernel(addr, addr_len, &io->connect.address);
+       return move_addr_to_kernel(conn->addr, conn->addr_len,
+                                       &io->connect.address);
 #else
-       return 0;
+       return -EOPNOTSUPP;
 #endif
 }
 
-static int io_connect(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                     struct io_kiocb **nxt, bool force_nonblock)
+static int io_connect(struct io_kiocb *req, struct io_kiocb **nxt,
+                     bool force_nonblock)
 {
 #if defined(CONFIG_NET)
        struct io_async_ctx __io, *io;
        unsigned file_flags;
-       int addr_len, ret;
-
-       if (unlikely(req->ctx->flags & (IORING_SETUP_IOPOLL|IORING_SETUP_SQPOLL)))
-               return -EINVAL;
-       if (sqe->ioprio || sqe->len || sqe->buf_index || sqe->rw_flags)
-               return -EINVAL;
-
-       addr_len = READ_ONCE(sqe->addr2);
-       file_flags = force_nonblock ? O_NONBLOCK : 0;
+       int ret;
 
        if (req->io) {
                io = req->io;
        } else {
-               ret = io_connect_prep(req, &__io);
+               ret = move_addr_to_kernel(req->connect.addr,
+                                               req->connect.addr_len,
+                                               &__io.connect.address);
                if (ret)
                        goto out;
                io = &__io;
        }
 
-       ret = __sys_connect_file(req->file, &io->connect.address, addr_len,
-                                       file_flags);
+       file_flags = force_nonblock ? O_NONBLOCK : 0;
+
+       ret = __sys_connect_file(req->file, &io->connect.address,
+                                       req->connect.addr_len, file_flags);
        if ((ret == -EAGAIN || ret == -EINPROGRESS) && force_nonblock) {
-               io = kmalloc(sizeof(*io), GFP_KERNEL);
-               if (!io) {
+               if (req->io)
+                       return -EAGAIN;
+               if (io_alloc_async_ctx(req)) {
                        ret = -ENOMEM;
                        goto out;
                }
-               memcpy(&io->connect, &__io.connect, sizeof(io->connect));
-               req->io = io;
-               memcpy(&io->sqe, req->sqe, sizeof(*req->sqe));
-               req->sqe = &io->sqe;
+               memcpy(&req->io->connect, &__io.connect, sizeof(__io.connect));
                return -EAGAIN;
        }
        if (ret == -ERESTARTSYS)
                ret = -EINTR;
 out:
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_cqring_add_event(req, ret);
        io_put_req_find_next(req, nxt);
        return 0;
@@ -2279,8 +2500,8 @@ static void io_poll_remove_one(struct io_kiocb *req)
 
        spin_lock(&poll->head->lock);
        WRITE_ONCE(poll->canceled, true);
-       if (!list_empty(&poll->wait->entry)) {
-               list_del_init(&poll->wait->entry);
+       if (!list_empty(&poll->wait.entry)) {
+               list_del_init(&poll->wait.entry);
                io_queue_async_work(req);
        }
        spin_unlock(&poll->head->lock);
@@ -2320,28 +2541,37 @@ static int io_poll_cancel(struct io_ring_ctx *ctx, __u64 sqe_addr)
        return -ENOENT;
 }
 
+static int io_poll_remove_prep(struct io_kiocb *req,
+                              const struct io_uring_sqe *sqe)
+{
+       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+               return -EINVAL;
+       if (sqe->ioprio || sqe->off || sqe->len || sqe->buf_index ||
+           sqe->poll_events)
+               return -EINVAL;
+
+       req->poll.addr = READ_ONCE(sqe->addr);
+       return 0;
+}
+
 /*
  * Find a running poll command that matches one specified in sqe->addr,
  * and remove it if found.
  */
-static int io_poll_remove(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+static int io_poll_remove(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
+       u64 addr;
        int ret;
 
-       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
-               return -EINVAL;
-       if (sqe->ioprio || sqe->off || sqe->len || sqe->buf_index ||
-           sqe->poll_events)
-               return -EINVAL;
-
+       addr = req->poll.addr;
        spin_lock_irq(&ctx->completion_lock);
-       ret = io_poll_cancel(ctx, READ_ONCE(sqe->addr));
+       ret = io_poll_cancel(ctx, addr);
        spin_unlock_irq(&ctx->completion_lock);
 
        io_cqring_add_event(req, ret);
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req(req);
        return 0;
 }
@@ -2351,7 +2581,6 @@ static void io_poll_complete(struct io_kiocb *req, __poll_t mask, int error)
        struct io_ring_ctx *ctx = req->ctx;
 
        req->poll.done = true;
-       kfree(req->poll.wait);
        if (error)
                io_cqring_fill_event(req, error);
        else
@@ -2389,7 +2618,7 @@ static void io_poll_complete_work(struct io_wq_work **workptr)
         */
        spin_lock_irq(&ctx->completion_lock);
        if (!mask && ret != -ECANCELED) {
-               add_wait_queue(poll->head, poll->wait);
+               add_wait_queue(poll->head, &poll->wait);
                spin_unlock_irq(&ctx->completion_lock);
                return;
        }
@@ -2399,11 +2628,11 @@ static void io_poll_complete_work(struct io_wq_work **workptr)
 
        io_cqring_ev_posted(ctx);
 
-       if (ret < 0 && req->flags & REQ_F_LINK)
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req_find_next(req, &nxt);
        if (nxt)
-               *workptr = &nxt->work;
+               io_wq_assign_next(workptr, nxt);
 }
 
 static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
@@ -2419,7 +2648,7 @@ static int io_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
        if (mask && !(mask & poll->events))
                return 0;
 
-       list_del_init(&poll->wait->entry);
+       list_del_init(&poll->wait.entry);
 
        /*
         * Run completion inline if we can. We're using trylock here because
@@ -2460,7 +2689,7 @@ static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head,
 
        pt->error = 0;
        pt->req->poll.head = head;
-       add_wait_queue(head, pt->req->poll.wait);
+       add_wait_queue(head, &pt->req->poll.wait);
 }
 
 static void io_poll_req_insert(struct io_kiocb *req)
@@ -2472,14 +2701,9 @@ static void io_poll_req_insert(struct io_kiocb *req)
        hlist_add_head(&req->hash_node, list);
 }
 
-static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                      struct io_kiocb **nxt)
+static int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_poll_iocb *poll = &req->poll;
-       struct io_ring_ctx *ctx = req->ctx;
-       struct io_poll_table ipt;
-       bool cancel = false;
-       __poll_t mask;
        u16 events;
 
        if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
@@ -2489,14 +2713,20 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        if (!poll->file)
                return -EBADF;
 
-       poll->wait = kmalloc(sizeof(*poll->wait), GFP_KERNEL);
-       if (!poll->wait)
-               return -ENOMEM;
-
-       req->io = NULL;
-       INIT_IO_WORK(&req->work, io_poll_complete_work);
        events = READ_ONCE(sqe->poll_events);
        poll->events = demangle_poll(events) | EPOLLERR | EPOLLHUP;
+       return 0;
+}
+
+static int io_poll_add(struct io_kiocb *req, struct io_kiocb **nxt)
+{
+       struct io_poll_iocb *poll = &req->poll;
+       struct io_ring_ctx *ctx = req->ctx;
+       struct io_poll_table ipt;
+       bool cancel = false;
+       __poll_t mask;
+
+       INIT_IO_WORK(&req->work, io_poll_complete_work);
        INIT_HLIST_NODE(&req->hash_node);
 
        poll->head = NULL;
@@ -2509,9 +2739,9 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        ipt.error = -EINVAL; /* same as no support for IOCB_CMD_POLL */
 
        /* initialized the list so that we can do list_empty checks */
-       INIT_LIST_HEAD(&poll->wait->entry);
-       init_waitqueue_func_entry(poll->wait, io_poll_wake);
-       poll->wait->private = poll;
+       INIT_LIST_HEAD(&poll->wait.entry);
+       init_waitqueue_func_entry(&poll->wait, io_poll_wake);
+       poll->wait.private = poll;
 
        INIT_LIST_HEAD(&req->list);
 
@@ -2520,14 +2750,14 @@ static int io_poll_add(struct io_kiocb *req, const struct io_uring_sqe *sqe,
        spin_lock_irq(&ctx->completion_lock);
        if (likely(poll->head)) {
                spin_lock(&poll->head->lock);
-               if (unlikely(list_empty(&poll->wait->entry))) {
+               if (unlikely(list_empty(&poll->wait.entry))) {
                        if (ipt.error)
                                cancel = true;
                        ipt.error = 0;
                        mask = 0;
                }
                if (mask || ipt.error)
-                       list_del_init(&poll->wait->entry);
+                       list_del_init(&poll->wait.entry);
                else if (cancel)
                        WRITE_ONCE(poll->canceled, true);
                else if (!poll->done) /* actually waiting for an event */
@@ -2567,7 +2797,7 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
 
                /*
                 * Adjust the reqs sequence before the current one because it
-                * will consume a slot in the cq_ring and the the cq_tail
+                * will consume a slot in the cq_ring and the cq_tail
                 * pointer will be increased, otherwise other timeout reqs may
                 * return in advance without waiting for enough wait_nr.
                 */
@@ -2582,8 +2812,7 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
 
        io_cqring_ev_posted(ctx);
-       if (req->flags & REQ_F_LINK)
-               req->flags |= REQ_F_FAIL_LINK;
+       req_set_fail_links(req);
        io_put_req(req);
        return HRTIMER_NORESTART;
 }
@@ -2608,48 +2837,52 @@ static int io_timeout_cancel(struct io_ring_ctx *ctx, __u64 user_data)
        if (ret == -1)
                return -EALREADY;
 
-       if (req->flags & REQ_F_LINK)
-               req->flags |= REQ_F_FAIL_LINK;
+       req_set_fail_links(req);
        io_cqring_fill_event(req, -ECANCELED);
        io_put_req(req);
        return 0;
 }
 
+static int io_timeout_remove_prep(struct io_kiocb *req,
+                                 const struct io_uring_sqe *sqe)
+{
+       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
+               return -EINVAL;
+       if (sqe->flags || sqe->ioprio || sqe->buf_index || sqe->len)
+               return -EINVAL;
+
+       req->timeout.addr = READ_ONCE(sqe->addr);
+       req->timeout.flags = READ_ONCE(sqe->timeout_flags);
+       if (req->timeout.flags)
+               return -EINVAL;
+
+       return 0;
+}
+
 /*
  * Remove or update an existing timeout command
  */
-static int io_timeout_remove(struct io_kiocb *req,
-                            const struct io_uring_sqe *sqe)
+static int io_timeout_remove(struct io_kiocb *req)
 {
        struct io_ring_ctx *ctx = req->ctx;
-       unsigned flags;
        int ret;
 
-       if (unlikely(ctx->flags & IORING_SETUP_IOPOLL))
-               return -EINVAL;
-       if (sqe->flags || sqe->ioprio || sqe->buf_index || sqe->len)
-               return -EINVAL;
-       flags = READ_ONCE(sqe->timeout_flags);
-       if (flags)
-               return -EINVAL;
-
        spin_lock_irq(&ctx->completion_lock);
-       ret = io_timeout_cancel(ctx, READ_ONCE(sqe->addr));
+       ret = io_timeout_cancel(ctx, req->timeout.addr);
 
        io_cqring_fill_event(req, ret);
        io_commit_cqring(ctx);
        spin_unlock_irq(&ctx->completion_lock);
        io_cqring_ev_posted(ctx);
-       if (ret < 0 && req->flags & REQ_F_LINK)
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req(req);
        return 0;
 }
 
-static int io_timeout_prep(struct io_kiocb *req, struct io_async_ctx *io,
+static int io_timeout_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe,
                           bool is_timeout_link)
 {
-       const struct io_uring_sqe *sqe = req->sqe;
        struct io_timeout_data *data;
        unsigned flags;
 
@@ -2663,7 +2896,12 @@ static int io_timeout_prep(struct io_kiocb *req, struct io_async_ctx *io,
        if (flags & ~IORING_TIMEOUT_ABS)
                return -EINVAL;
 
-       data = &io->timeout;
+       req->timeout.count = READ_ONCE(sqe->off);
+
+       if (!req->io && io_alloc_async_ctx(req))
+               return -ENOMEM;
+
+       data = &req->io->timeout;
        data->req = req;
        req->flags |= REQ_F_TIMEOUT;
 
@@ -2676,32 +2914,17 @@ static int io_timeout_prep(struct io_kiocb *req, struct io_async_ctx *io,
                data->mode = HRTIMER_MODE_REL;
 
        hrtimer_init(&data->timer, CLOCK_MONOTONIC, data->mode);
-       req->io = io;
        return 0;
 }
 
-static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
+static int io_timeout(struct io_kiocb *req)
 {
        unsigned count;
        struct io_ring_ctx *ctx = req->ctx;
        struct io_timeout_data *data;
-       struct io_async_ctx *io;
        struct list_head *entry;
        unsigned span = 0;
 
-       io = req->io;
-       if (!io) {
-               int ret;
-
-               io = kmalloc(sizeof(*io), GFP_KERNEL);
-               if (!io)
-                       return -ENOMEM;
-               ret = io_timeout_prep(req, io, false);
-               if (ret) {
-                       kfree(io);
-                       return ret;
-               }
-       }
        data = &req->io->timeout;
 
        /*
@@ -2709,7 +2932,7 @@ static int io_timeout(struct io_kiocb *req, const struct io_uring_sqe *sqe)
         * timeout event to be satisfied. If it isn't set, then this is
         * a pure timeout request, sequence isn't used.
         */
-       count = READ_ONCE(sqe->off);
+       count = req->timeout.count;
        if (!count) {
                req->flags |= REQ_F_TIMEOUT_NOSEQ;
                spin_lock_irq(&ctx->completion_lock);
@@ -2822,89 +3045,109 @@ done:
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
        io_cqring_ev_posted(ctx);
 
-       if (ret < 0 && (req->flags & REQ_F_LINK))
-               req->flags |= REQ_F_FAIL_LINK;
+       if (ret < 0)
+               req_set_fail_links(req);
        io_put_req_find_next(req, nxt);
 }
 
-static int io_async_cancel(struct io_kiocb *req, const struct io_uring_sqe *sqe,
-                          struct io_kiocb **nxt)
+static int io_async_cancel_prep(struct io_kiocb *req,
+                               const struct io_uring_sqe *sqe)
 {
-       struct io_ring_ctx *ctx = req->ctx;
-
-       if (unlikely(ctx->flags & IORING_SETUP_IOPOLL))
+       if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL))
                return -EINVAL;
        if (sqe->flags || sqe->ioprio || sqe->off || sqe->len ||
            sqe->cancel_flags)
                return -EINVAL;
 
-       io_async_find_and_cancel(ctx, req, READ_ONCE(sqe->addr), nxt, 0);
+       req->cancel.addr = READ_ONCE(sqe->addr);
        return 0;
 }
 
-static int io_req_defer_prep(struct io_kiocb *req, struct io_async_ctx *io)
+static int io_async_cancel(struct io_kiocb *req, struct io_kiocb **nxt)
 {
-       struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
-       struct iov_iter iter;
-       ssize_t ret;
+       struct io_ring_ctx *ctx = req->ctx;
 
-       memcpy(&io->sqe, req->sqe, sizeof(io->sqe));
-       req->sqe = &io->sqe;
+       io_async_find_and_cancel(ctx, req, req->cancel.addr, nxt, 0);
+       return 0;
+}
+
+static int io_req_defer_prep(struct io_kiocb *req,
+                            const struct io_uring_sqe *sqe)
+{
+       ssize_t ret = 0;
 
-       switch (io->sqe.opcode) {
+       switch (req->opcode) {
+       case IORING_OP_NOP:
+               break;
        case IORING_OP_READV:
        case IORING_OP_READ_FIXED:
-               ret = io_read_prep(req, &iovec, &iter, true);
+               ret = io_read_prep(req, sqe, true);
                break;
        case IORING_OP_WRITEV:
        case IORING_OP_WRITE_FIXED:
-               ret = io_write_prep(req, &iovec, &iter, true);
+               ret = io_write_prep(req, sqe, true);
+               break;
+       case IORING_OP_POLL_ADD:
+               ret = io_poll_add_prep(req, sqe);
+               break;
+       case IORING_OP_POLL_REMOVE:
+               ret = io_poll_remove_prep(req, sqe);
+               break;
+       case IORING_OP_FSYNC:
+               ret = io_prep_fsync(req, sqe);
+               break;
+       case IORING_OP_SYNC_FILE_RANGE:
+               ret = io_prep_sfr(req, sqe);
                break;
        case IORING_OP_SENDMSG:
-               ret = io_sendmsg_prep(req, io);
+               ret = io_sendmsg_prep(req, sqe);
                break;
        case IORING_OP_RECVMSG:
-               ret = io_recvmsg_prep(req, io);
+               ret = io_recvmsg_prep(req, sqe);
                break;
        case IORING_OP_CONNECT:
-               ret = io_connect_prep(req, io);
+               ret = io_connect_prep(req, sqe);
                break;
        case IORING_OP_TIMEOUT:
-               return io_timeout_prep(req, io, false);
+               ret = io_timeout_prep(req, sqe, false);
+               break;
+       case IORING_OP_TIMEOUT_REMOVE:
+               ret = io_timeout_remove_prep(req, sqe);
+               break;
+       case IORING_OP_ASYNC_CANCEL:
+               ret = io_async_cancel_prep(req, sqe);
+               break;
        case IORING_OP_LINK_TIMEOUT:
-               return io_timeout_prep(req, io, true);
+               ret = io_timeout_prep(req, sqe, true);
+               break;
+       case IORING_OP_ACCEPT:
+               ret = io_accept_prep(req, sqe);
+               break;
        default:
-               req->io = io;
-               return 0;
+               printk_once(KERN_WARNING "io_uring: unhandled opcode %d\n",
+                               req->opcode);
+               ret = -EINVAL;
+               break;
        }
 
-       if (ret < 0)
-               return ret;
-
-       req->io = io;
-       io_req_map_io(req, ret, iovec, inline_vecs, &iter);
-       return 0;
+       return ret;
 }
 
-static int io_req_defer(struct io_kiocb *req)
+static int io_req_defer(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        struct io_ring_ctx *ctx = req->ctx;
-       struct io_async_ctx *io;
        int ret;
 
        /* Still need defer if there is pending req in defer list. */
        if (!req_need_defer(req) && list_empty(&ctx->defer_list))
                return 0;
 
-       io = kmalloc(sizeof(*io), GFP_KERNEL);
-       if (!io)
+       if (!req->io && io_alloc_async_ctx(req))
                return -EAGAIN;
 
-       ret = io_req_defer_prep(req, io);
-       if (ret < 0) {
-               kfree(io);
+       ret = io_req_defer_prep(req, sqe);
+       if (ret < 0)
                return ret;
-       }
 
        spin_lock_irq(&ctx->completion_lock);
        if (!req_need_defer(req) && list_empty(&ctx->defer_list)) {
@@ -2918,66 +3161,121 @@ static int io_req_defer(struct io_kiocb *req)
        return -EIOCBQUEUED;
 }
 
-__attribute__((nonnull))
-static int io_issue_sqe(struct io_kiocb *req, struct io_kiocb **nxt,
-                       bool force_nonblock)
+static int io_issue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+                       struct io_kiocb **nxt, bool force_nonblock)
 {
-       int ret, opcode;
        struct io_ring_ctx *ctx = req->ctx;
+       int ret;
 
-       opcode = READ_ONCE(req->sqe->opcode);
-       switch (opcode) {
+       switch (req->opcode) {
        case IORING_OP_NOP:
                ret = io_nop(req);
                break;
        case IORING_OP_READV:
-               if (unlikely(req->sqe->buf_index))
-                       return -EINVAL;
-               ret = io_read(req, nxt, force_nonblock);
-               break;
-       case IORING_OP_WRITEV:
-               if (unlikely(req->sqe->buf_index))
-                       return -EINVAL;
-               ret = io_write(req, nxt, force_nonblock);
-               break;
        case IORING_OP_READ_FIXED:
+               if (sqe) {
+                       ret = io_read_prep(req, sqe, force_nonblock);
+                       if (ret < 0)
+                               break;
+               }
                ret = io_read(req, nxt, force_nonblock);
                break;
+       case IORING_OP_WRITEV:
        case IORING_OP_WRITE_FIXED:
+               if (sqe) {
+                       ret = io_write_prep(req, sqe, force_nonblock);
+                       if (ret < 0)
+                               break;
+               }
                ret = io_write(req, nxt, force_nonblock);
                break;
        case IORING_OP_FSYNC:
-               ret = io_fsync(req, req->sqe, nxt, force_nonblock);
+               if (sqe) {
+                       ret = io_prep_fsync(req, sqe);
+                       if (ret < 0)
+                               break;
+               }
+               ret = io_fsync(req, nxt, force_nonblock);
                break;
        case IORING_OP_POLL_ADD:
-               ret = io_poll_add(req, req->sqe, nxt);
+               if (sqe) {
+                       ret = io_poll_add_prep(req, sqe);
+                       if (ret)
+                               break;
+               }
+               ret = io_poll_add(req, nxt);
                break;
        case IORING_OP_POLL_REMOVE:
-               ret = io_poll_remove(req, req->sqe);
+               if (sqe) {
+                       ret = io_poll_remove_prep(req, sqe);
+                       if (ret < 0)
+                               break;
+               }
+               ret = io_poll_remove(req);
                break;
        case IORING_OP_SYNC_FILE_RANGE:
-               ret = io_sync_file_range(req, req->sqe, nxt, force_nonblock);
+               if (sqe) {
+                       ret = io_prep_sfr(req, sqe);
+                       if (ret < 0)
+                               break;
+               }
+               ret = io_sync_file_range(req, nxt, force_nonblock);
                break;
        case IORING_OP_SENDMSG:
-               ret = io_sendmsg(req, req->sqe, nxt, force_nonblock);
+               if (sqe) {
+                       ret = io_sendmsg_prep(req, sqe);
+                       if (ret < 0)
+                               break;
+               }
+               ret = io_sendmsg(req, nxt, force_nonblock);
                break;
        case IORING_OP_RECVMSG:
-               ret = io_recvmsg(req, req->sqe, nxt, force_nonblock);
+               if (sqe) {
+                       ret = io_recvmsg_prep(req, sqe);
+                       if (ret)
+                               break;
+               }
+               ret = io_recvmsg(req, nxt, force_nonblock);
                break;
        case IORING_OP_TIMEOUT:
-               ret = io_timeout(req, req->sqe);
+               if (sqe) {
+                       ret = io_timeout_prep(req, sqe, false);
+                       if (ret)
+                               break;
+               }
+               ret = io_timeout(req);
                break;
        case IORING_OP_TIMEOUT_REMOVE:
-               ret = io_timeout_remove(req, req->sqe);
+               if (sqe) {
+                       ret = io_timeout_remove_prep(req, sqe);
+                       if (ret)
+                               break;
+               }
+               ret = io_timeout_remove(req);
                break;
        case IORING_OP_ACCEPT:
-               ret = io_accept(req, req->sqe, nxt, force_nonblock);
+               if (sqe) {
+                       ret = io_accept_prep(req, sqe);
+                       if (ret)
+                               break;
+               }
+               ret = io_accept(req, nxt, force_nonblock);
                break;
        case IORING_OP_CONNECT:
-               ret = io_connect(req, req->sqe, nxt, force_nonblock);
+               if (sqe) {
+                       ret = io_connect_prep(req, sqe);
+                       if (ret)
+                               break;
+               }
+               ret = io_connect(req, nxt, force_nonblock);
                break;
        case IORING_OP_ASYNC_CANCEL:
-               ret = io_async_cancel(req, req->sqe, nxt);
+               if (sqe) {
+                       ret = io_async_cancel_prep(req, sqe);
+                       if (ret)
+                               break;
+               }
+               ret = io_async_cancel(req, nxt);
                break;
        default:
                ret = -EINVAL;
@@ -2988,29 +3286,24 @@ static int io_issue_sqe(struct io_kiocb *req, struct io_kiocb **nxt,
                return ret;
 
        if (ctx->flags & IORING_SETUP_IOPOLL) {
+               const bool in_async = io_wq_current_is_worker();
+
                if (req->result == -EAGAIN)
                        return -EAGAIN;
 
                /* workqueue context doesn't hold uring_lock, grab it now */
-               if (req->in_async)
+               if (in_async)
                        mutex_lock(&ctx->uring_lock);
+
                io_iopoll_req_issued(req);
-               if (req->in_async)
+
+               if (in_async)
                        mutex_unlock(&ctx->uring_lock);
        }
 
        return 0;
 }
 
-static void io_link_work_cb(struct io_wq_work **workptr)
-{
-       struct io_wq_work *work = *workptr;
-       struct io_kiocb *link = work->data;
-
-       io_queue_linked_timeout(link);
-       work->func = io_wq_submit_work;
-}
-
 static void io_wq_submit_work(struct io_wq_work **workptr)
 {
        struct io_wq_work *work = *workptr;
@@ -3018,9 +3311,6 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
        struct io_kiocb *nxt = NULL;
        int ret = 0;
 
-       /* Ensure we clear previously set non-block flag */
-       req->rw.ki_flags &= ~IOCB_NOWAIT;
-
        if (work->flags & IO_WQ_WORK_CANCEL)
                ret = -ECANCELED;
 
@@ -3028,7 +3318,7 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
                req->has_user = (work->flags & IO_WQ_WORK_HAS_MM) != 0;
                req->in_async = true;
                do {
-                       ret = io_issue_sqe(req, &nxt, false);
+                       ret = io_issue_sqe(req, NULL, &nxt, false);
                        /*
                         * We can get EAGAIN for polled IO even though we're
                         * forcing a sync submission from here, since we can't
@@ -3044,40 +3334,35 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
        io_put_req(req);
 
        if (ret) {
-               if (req->flags & REQ_F_LINK)
-                       req->flags |= REQ_F_FAIL_LINK;
+               req_set_fail_links(req);
                io_cqring_add_event(req, ret);
                io_put_req(req);
        }
 
        /* if a dependent link is ready, pass it back */
-       if (!ret && nxt) {
-               struct io_kiocb *link;
-
-               io_prep_async_work(nxt, &link);
-               *workptr = &nxt->work;
-               if (link) {
-                       nxt->work.flags |= IO_WQ_WORK_CB;
-                       nxt->work.func = io_link_work_cb;
-                       nxt->work.data = link;
-               }
-       }
+       if (!ret && nxt)
+               io_wq_assign_next(workptr, nxt);
 }
 
-static bool io_op_needs_file(const struct io_uring_sqe *sqe)
+static bool io_req_op_valid(int op)
 {
-       int op = READ_ONCE(sqe->opcode);
+       return op >= IORING_OP_NOP && op < IORING_OP_LAST;
+}
 
-       switch (op) {
+static int io_req_needs_file(struct io_kiocb *req)
+{
+       switch (req->opcode) {
        case IORING_OP_NOP:
        case IORING_OP_POLL_REMOVE:
        case IORING_OP_TIMEOUT:
        case IORING_OP_TIMEOUT_REMOVE:
        case IORING_OP_ASYNC_CANCEL:
        case IORING_OP_LINK_TIMEOUT:
-               return false;
+               return 0;
        default:
-               return true;
+               if (io_req_op_valid(req->opcode))
+                       return 1;
+               return -EINVAL;
        }
 }
 
@@ -3090,20 +3375,22 @@ static inline struct file *io_file_from_index(struct io_ring_ctx *ctx,
        return table->files[index & IORING_FILE_TABLE_MASK];
 }
 
-static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req)
+static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req,
+                          const struct io_uring_sqe *sqe)
 {
        struct io_ring_ctx *ctx = req->ctx;
        unsigned flags;
-       int fd;
+       int fd, ret;
 
-       flags = READ_ONCE(req->sqe->flags);
-       fd = READ_ONCE(req->sqe->fd);
+       flags = READ_ONCE(sqe->flags);
+       fd = READ_ONCE(sqe->fd);
 
        if (flags & IOSQE_IO_DRAIN)
                req->flags |= REQ_F_IO_DRAIN;
 
-       if (!io_op_needs_file(req->sqe))
-               return 0;
+       ret = io_req_needs_file(req);
+       if (ret <= 0)
+               return ret;
 
        if (flags & IOSQE_FIXED_FILE) {
                if (unlikely(!ctx->file_table ||
@@ -3179,8 +3466,7 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer)
        spin_unlock_irqrestore(&ctx->completion_lock, flags);
 
        if (prev) {
-               if (prev->flags & REQ_F_LINK)
-                       prev->flags |= REQ_F_FAIL_LINK;
+               req_set_fail_links(prev);
                io_async_find_and_cancel(ctx, req, prev->user_data, NULL,
                                                -ETIME);
                io_put_req(prev);
@@ -3222,22 +3508,23 @@ static struct io_kiocb *io_prep_linked_timeout(struct io_kiocb *req)
 
        nxt = list_first_entry_or_null(&req->link_list, struct io_kiocb,
                                        link_list);
-       if (!nxt || nxt->sqe->opcode != IORING_OP_LINK_TIMEOUT)
+       if (!nxt || nxt->opcode != IORING_OP_LINK_TIMEOUT)
                return NULL;
 
        req->flags |= REQ_F_LINK_TIMEOUT;
        return nxt;
 }
 
-static void __io_queue_sqe(struct io_kiocb *req)
+static void __io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
-       struct io_kiocb *linked_timeout = io_prep_linked_timeout(req);
+       struct io_kiocb *linked_timeout;
        struct io_kiocb *nxt = NULL;
        int ret;
 
-       ret = io_issue_sqe(req, &nxt, true);
-       if (nxt)
-               io_queue_async_work(nxt);
+again:
+       linked_timeout = io_prep_linked_timeout(req);
+
+       ret = io_issue_sqe(req, sqe, &nxt, true);
 
        /*
         * We async punt it if the file wasn't marked NOWAIT, or if the file
@@ -3256,7 +3543,7 @@ static void __io_queue_sqe(struct io_kiocb *req)
                 * submit reference when the iocb is actually submitted.
                 */
                io_queue_async_work(req);
-               return;
+               goto done_req;
        }
 
 err:
@@ -3273,13 +3560,18 @@ err:
        /* and drop final reference, if we failed */
        if (ret) {
                io_cqring_add_event(req, ret);
-               if (req->flags & REQ_F_LINK)
-                       req->flags |= REQ_F_FAIL_LINK;
+               req_set_fail_links(req);
                io_put_req(req);
        }
+done_req:
+       if (nxt) {
+               req = nxt;
+               nxt = NULL;
+               goto again;
+       }
 }
 
-static void io_queue_sqe(struct io_kiocb *req)
+static void io_queue_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 {
        int ret;
 
@@ -3289,16 +3581,15 @@ static void io_queue_sqe(struct io_kiocb *req)
        }
        req->ctx->drain_next = (req->flags & REQ_F_DRAIN_LINK);
 
-       ret = io_req_defer(req);
+       ret = io_req_defer(req, sqe);
        if (ret) {
                if (ret != -EIOCBQUEUED) {
                        io_cqring_add_event(req, ret);
-                       if (req->flags & REQ_F_LINK)
-                               req->flags |= REQ_F_FAIL_LINK;
+                       req_set_fail_links(req);
                        io_double_put_req(req);
                }
        } else
-               __io_queue_sqe(req);
+               __io_queue_sqe(req, sqe);
 }
 
 static inline void io_queue_link_head(struct io_kiocb *req)
@@ -3307,27 +3598,25 @@ static inline void io_queue_link_head(struct io_kiocb *req)
                io_cqring_add_event(req, -ECANCELED);
                io_double_put_req(req);
        } else
-               io_queue_sqe(req);
+               io_queue_sqe(req, NULL);
 }
 
+#define SQE_VALID_FLAGS        (IOSQE_FIXED_FILE|IOSQE_IO_DRAIN|IOSQE_IO_LINK| \
+                               IOSQE_IO_HARDLINK)
 
-#define SQE_VALID_FLAGS        (IOSQE_FIXED_FILE|IOSQE_IO_DRAIN|IOSQE_IO_LINK)
-
-static bool io_submit_sqe(struct io_kiocb *req, struct io_submit_state *state,
-                         struct io_kiocb **link)
+static bool io_submit_sqe(struct io_kiocb *req, const struct io_uring_sqe *sqe,
+                         struct io_submit_state *state, struct io_kiocb **link)
 {
        struct io_ring_ctx *ctx = req->ctx;
        int ret;
 
-       req->user_data = req->sqe->user_data;
-
        /* enforce forwards compatibility on users */
-       if (unlikely(req->sqe->flags & ~SQE_VALID_FLAGS)) {
+       if (unlikely(sqe->flags & ~SQE_VALID_FLAGS)) {
                ret = -EINVAL;
                goto err_req;
        }
 
-       ret = io_req_set_file(state, req);
+       ret = io_req_set_file(state, req, sqe);
        if (unlikely(ret)) {
 err_req:
                io_cqring_add_event(req, ret);
@@ -3344,32 +3633,38 @@ err_req:
         */
        if (*link) {
                struct io_kiocb *prev = *link;
-               struct io_async_ctx *io;
 
-               if (req->sqe->flags & IOSQE_IO_DRAIN)
+               if (sqe->flags & IOSQE_IO_DRAIN)
                        (*link)->flags |= REQ_F_DRAIN_LINK | REQ_F_IO_DRAIN;
 
-               io = kmalloc(sizeof(*io), GFP_KERNEL);
-               if (!io) {
+               if (sqe->flags & IOSQE_IO_HARDLINK)
+                       req->flags |= REQ_F_HARDLINK;
+
+               if (io_alloc_async_ctx(req)) {
                        ret = -EAGAIN;
                        goto err_req;
                }
 
-               ret = io_req_defer_prep(req, io);
+               ret = io_req_defer_prep(req, sqe);
                if (ret) {
-                       kfree(io);
+                       /* fail even hard links since we don't submit */
                        prev->flags |= REQ_F_FAIL_LINK;
                        goto err_req;
                }
                trace_io_uring_link(ctx, req, prev);
                list_add_tail(&req->link_list, &prev->link_list);
-       } else if (req->sqe->flags & IOSQE_IO_LINK) {
+       } else if (sqe->flags & (IOSQE_IO_LINK|IOSQE_IO_HARDLINK)) {
                req->flags |= REQ_F_LINK;
+               if (sqe->flags & IOSQE_IO_HARDLINK)
+                       req->flags |= REQ_F_HARDLINK;
 
                INIT_LIST_HEAD(&req->link_list);
+               ret = io_req_defer_prep(req, sqe);
+               if (ret)
+                       req->flags |= REQ_F_FAIL_LINK;
                *link = req;
        } else {
-               io_queue_sqe(req);
+               io_queue_sqe(req, sqe);
        }
 
        return true;
@@ -3414,14 +3709,15 @@ static void io_commit_sqring(struct io_ring_ctx *ctx)
 }
 
 /*
- * Fetch an sqe, if one is available. Note that s->sqe will point to memory
+ * Fetch an sqe, if one is available. Note that sqe_ptr will point to memory
  * that is mapped by userspace. This means that care needs to be taken to
  * ensure that reads are stable, as we cannot rely on userspace always
  * being a good citizen. If members of the sqe are validated and then later
  * used, it's important that those reads are done through READ_ONCE() to
  * prevent a re-load down the line.
  */
-static bool io_get_sqring(struct io_ring_ctx *ctx, struct io_kiocb *req)
+static bool io_get_sqring(struct io_ring_ctx *ctx, struct io_kiocb *req,
+                         const struct io_uring_sqe **sqe_ptr)
 {
        struct io_rings *rings = ctx->rings;
        u32 *sq_array = ctx->sq_array;
@@ -3448,7 +3744,9 @@ static bool io_get_sqring(struct io_ring_ctx *ctx, struct io_kiocb *req)
                 * link list.
                 */
                req->sequence = ctx->cached_sq_head;
-               req->sqe = &ctx->sq_sqes[head];
+               *sqe_ptr = &ctx->sq_sqes[head];
+               req->opcode = READ_ONCE((*sqe_ptr)->opcode);
+               req->user_data = READ_ONCE((*sqe_ptr)->user_data);
                ctx->cached_sq_head++;
                return true;
        }
@@ -3480,6 +3778,7 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
        }
 
        for (i = 0; i < nr; i++) {
+               const struct io_uring_sqe *sqe;
                struct io_kiocb *req;
                unsigned int sqe_flags;
 
@@ -3489,12 +3788,12 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
                                submitted = -EAGAIN;
                        break;
                }
-               if (!io_get_sqring(ctx, req)) {
+               if (!io_get_sqring(ctx, req, &sqe)) {
                        __io_free_req(req);
                        break;
                }
 
-               if (io_sqe_needs_user(req->sqe) && !*mm) {
+               if (io_req_needs_user(req) && !*mm) {
                        mm_fault = mm_fault || !mmget_not_zero(ctx->sqo_mm);
                        if (!mm_fault) {
                                use_mm(ctx->sqo_mm);
@@ -3503,22 +3802,21 @@ static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
                }
 
                submitted++;
-               sqe_flags = req->sqe->flags;
+               sqe_flags = sqe->flags;
 
                req->ring_file = ring_file;
                req->ring_fd = ring_fd;
                req->has_user = *mm != NULL;
                req->in_async = async;
                req->needs_fixed_file = async;
-               trace_io_uring_submit_sqe(ctx, req->sqe->user_data,
-                                         true, async);
-               if (!io_submit_sqe(req, statep, &link))
+               trace_io_uring_submit_sqe(ctx, req->user_data, true, async);
+               if (!io_submit_sqe(req, sqe, statep, &link))
                        break;
                /*
                 * If previous wasn't linked and we have a linked command,
                 * that's the end of the chain. Submit the previous link.
                 */
-               if (!(sqe_flags & IOSQE_IO_LINK) && link) {
+               if (!(sqe_flags & (IOSQE_IO_LINK|IOSQE_IO_HARDLINK)) && link) {
                        io_queue_link_head(link);
                        link = NULL;
                }
@@ -3647,7 +3945,9 @@ static int io_sq_thread(void *data)
                }
 
                to_submit = min(to_submit, ctx->sq_entries);
+               mutex_lock(&ctx->uring_lock);
                ret = io_submit_sqes(ctx, to_submit, NULL, -1, &cur_mm, true);
+               mutex_unlock(&ctx->uring_lock);
                if (ret > 0)
                        inflight += ret;
        }
@@ -3676,7 +3976,7 @@ static inline bool io_should_wake(struct io_wait_queue *iowq, bool noflush)
        struct io_ring_ctx *ctx = iowq->ctx;
 
        /*
-        * Wake up if we have enough events, or if a timeout occured since we
+        * Wake up if we have enough events, or if a timeout occurred since we
         * started waiting. For timeouts, we always want to return to userspace,
         * regardless of event count.
         */
@@ -4428,7 +4728,7 @@ static int io_copy_iov(struct io_ring_ctx *ctx, struct iovec *dst,
                if (copy_from_user(&ciov, &ciovs[index], sizeof(ciov)))
                        return -EFAULT;
 
-               dst->iov_base = (void __user *) (unsigned long) ciov.iov_base;
+               dst->iov_base = u64_to_user_ptr((u64)ciov.iov_base);
                dst->iov_len = ciov.iov_len;
                return 0;
        }
@@ -4859,6 +5159,12 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
        } else if (to_submit) {
                struct mm_struct *cur_mm;
 
+               if (current->mm != ctx->sqo_mm ||
+                   current_cred() != ctx->creds) {
+                       ret = -EPERM;
+                       goto out;
+               }
+
                to_submit = min(to_submit, ctx->sq_entries);
                mutex_lock(&ctx->uring_lock);
                /* already have mm, so io_submit_sqes() won't try to grab it */
@@ -4866,6 +5172,9 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                submitted = io_submit_sqes(ctx, to_submit, f.file, fd,
                                           &cur_mm, false);
                mutex_unlock(&ctx->uring_lock);
+
+               if (submitted != to_submit)
+                       goto out;
        }
        if (flags & IORING_ENTER_GETEVENTS) {
                unsigned nr_events = 0;
@@ -4879,6 +5188,7 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
                }
        }
 
+out:
        percpu_ref_put(&ctx->refs);
 out_fput:
        fdput(f);
index 6970f55..44b6da0 100644 (file)
@@ -2853,7 +2853,7 @@ static void lock_get_status(struct seq_file *f, struct file_lock *fl,
        }
        if (inode) {
                /* userspace relies on this representation of dev_t */
-               seq_printf(f, "%d %02x:%02x:%ld ", fl_pid,
+               seq_printf(f, "%d %02x:%02x:%lu ", fl_pid,
                                MAJOR(inode->i_sb->s_dev),
                                MINOR(inode->i_sb->s_dev), inode->i_ino);
        } else {
index a63620c..ccba3c4 100644 (file)
@@ -62,7 +62,7 @@ static struct bio *mpage_bio_submit(int op, int op_flags, struct bio *bio)
 {
        bio->bi_end_io = mpage_end_io;
        bio_set_op_attrs(bio, op, op_flags);
-       guard_bio_eod(op, bio);
+       guard_bio_eod(bio);
        submit_bio(bio);
        return NULL;
 }
index d6c91d1..d2720dc 100644 (file)
@@ -1232,6 +1232,7 @@ static int follow_managed(struct path *path, struct nameidata *nd)
                        BUG_ON(!path->dentry->d_op);
                        BUG_ON(!path->dentry->d_op->d_manage);
                        ret = path->dentry->d_op->d_manage(path, false);
+                       flags = smp_load_acquire(&path->dentry->d_flags);
                        if (ret < 0)
                                break;
                }
@@ -1649,17 +1650,15 @@ again:
        if (IS_ERR(dentry))
                return dentry;
        if (unlikely(!d_in_lookup(dentry))) {
-               if (!(flags & LOOKUP_NO_REVAL)) {
-                       int error = d_revalidate(dentry, flags);
-                       if (unlikely(error <= 0)) {
-                               if (!error) {
-                                       d_invalidate(dentry);
-                                       dput(dentry);
-                                       goto again;
-                               }
+               int error = d_revalidate(dentry, flags);
+               if (unlikely(error <= 0)) {
+                       if (!error) {
+                               d_invalidate(dentry);
                                dput(dentry);
-                               dentry = ERR_PTR(error);
+                               goto again;
                        }
+                       dput(dentry);
+                       dentry = ERR_PTR(error);
                }
        } else {
                old = inode->i_op->lookup(inode, dentry, flags);
@@ -2618,72 +2617,6 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
 EXPORT_SYMBOL(user_path_at_empty);
 
 /**
- * mountpoint_last - look up last component for umount
- * @nd:   pathwalk nameidata - currently pointing at parent directory of "last"
- *
- * This is a special lookup_last function just for umount. In this case, we
- * need to resolve the path without doing any revalidation.
- *
- * The nameidata should be the result of doing a LOOKUP_PARENT pathwalk. Since
- * mountpoints are always pinned in the dcache, their ancestors are too. Thus,
- * in almost all cases, this lookup will be served out of the dcache. The only
- * cases where it won't are if nd->last refers to a symlink or the path is
- * bogus and it doesn't exist.
- *
- * Returns:
- * -error: if there was an error during lookup. This includes -ENOENT if the
- *         lookup found a negative dentry.
- *
- * 0:      if we successfully resolved nd->last and found it to not to be a
- *         symlink that needs to be followed.
- *
- * 1:      if we successfully resolved nd->last and found it to be a symlink
- *         that needs to be followed.
- */
-static int
-mountpoint_last(struct nameidata *nd)
-{
-       int error = 0;
-       struct dentry *dir = nd->path.dentry;
-       struct path path;
-
-       /* If we're in rcuwalk, drop out of it to handle last component */
-       if (nd->flags & LOOKUP_RCU) {
-               if (unlazy_walk(nd))
-                       return -ECHILD;
-       }
-
-       nd->flags &= ~LOOKUP_PARENT;
-
-       if (unlikely(nd->last_type != LAST_NORM)) {
-               error = handle_dots(nd, nd->last_type);
-               if (error)
-                       return error;
-               path.dentry = dget(nd->path.dentry);
-       } else {
-               path.dentry = d_lookup(dir, &nd->last);
-               if (!path.dentry) {
-                       /*
-                        * No cached dentry. Mounted dentries are pinned in the
-                        * cache, so that means that this dentry is probably
-                        * a symlink or the path doesn't actually point
-                        * to a mounted dentry.
-                        */
-                       path.dentry = lookup_slow(&nd->last, dir,
-                                            nd->flags | LOOKUP_NO_REVAL);
-                       if (IS_ERR(path.dentry))
-                               return PTR_ERR(path.dentry);
-               }
-       }
-       if (d_flags_negative(smp_load_acquire(&path.dentry->d_flags))) {
-               dput(path.dentry);
-               return -ENOENT;
-       }
-       path.mnt = nd->path.mnt;
-       return step_into(nd, &path, 0, d_backing_inode(path.dentry), 0);
-}
-
-/**
  * path_mountpoint - look up a path to be umounted
  * @nd:                lookup context
  * @flags:     lookup flags
@@ -2699,14 +2632,17 @@ path_mountpoint(struct nameidata *nd, unsigned flags, struct path *path)
        int err;
 
        while (!(err = link_path_walk(s, nd)) &&
-               (err = mountpoint_last(nd)) > 0) {
+               (err = lookup_last(nd)) > 0) {
                s = trailing_symlink(nd);
        }
+       if (!err && (nd->flags & LOOKUP_RCU))
+               err = unlazy_walk(nd);
+       if (!err)
+               err = handle_lookup_down(nd);
        if (!err) {
                *path = nd->path;
                nd->path.mnt = NULL;
                nd->path.dentry = NULL;
-               follow_mount(path);
        }
        terminate_walk(nd);
        return err;
index 2fd0c8b..5e1bf61 100644 (file)
@@ -1728,7 +1728,7 @@ static bool is_mnt_ns_file(struct dentry *dentry)
               dentry->d_fsdata == &mntns_operations;
 }
 
-struct mnt_namespace *to_mnt_ns(struct ns_common *ns)
+static struct mnt_namespace *to_mnt_ns(struct ns_common *ns)
 {
        return container_of(ns, struct mnt_namespace, ns);
 }
@@ -3325,8 +3325,8 @@ struct dentry *mount_subtree(struct vfsmount *m, const char *name)
 }
 EXPORT_SYMBOL(mount_subtree);
 
-int ksys_mount(const char __user *dev_name, const char __user *dir_name,
-              const char __user *type, unsigned long flags, void __user *data)
+SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
+               char __user *, type, unsigned long, flags, void __user *, data)
 {
        int ret;
        char *kernel_type;
@@ -3359,12 +3359,6 @@ out_type:
        return ret;
 }
 
-SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
-               char __user *, type, unsigned long, flags, void __user *, data)
-{
-       return ksys_mount(dev_name, dir_name, type, flags, data);
-}
-
 /*
  * Create a kernel mount representation for a new, prepared superblock
  * (specified by fs_fd) and attach to an open_tree-like file descriptor.
index f64a33d..2a82dcc 100644 (file)
@@ -206,7 +206,6 @@ TRACE_DEFINE_ENUM(LOOKUP_AUTOMOUNT);
 TRACE_DEFINE_ENUM(LOOKUP_PARENT);
 TRACE_DEFINE_ENUM(LOOKUP_REVAL);
 TRACE_DEFINE_ENUM(LOOKUP_RCU);
-TRACE_DEFINE_ENUM(LOOKUP_NO_REVAL);
 TRACE_DEFINE_ENUM(LOOKUP_OPEN);
 TRACE_DEFINE_ENUM(LOOKUP_CREATE);
 TRACE_DEFINE_ENUM(LOOKUP_EXCL);
@@ -224,7 +223,6 @@ TRACE_DEFINE_ENUM(LOOKUP_DOWN);
                        { LOOKUP_PARENT, "PARENT" }, \
                        { LOOKUP_REVAL, "REVAL" }, \
                        { LOOKUP_RCU, "RCU" }, \
-                       { LOOKUP_NO_REVAL, "NO_REVAL" }, \
                        { LOOKUP_OPEN, "OPEN" }, \
                        { LOOKUP_CREATE, "CREATE" }, \
                        { LOOKUP_EXCL, "EXCL" }, \
index 3e77b72..46f2255 100644 (file)
@@ -57,6 +57,9 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
                 * doing an __iget/iput with SB_ACTIVE clear would actually
                 * evict all inodes with zero i_count from icache which is
                 * unnecessarily violent and may in fact be illegal to do.
+                * However, we should have been called /after/ evict_inodes
+                * removed all zero refcount inodes, in any case.  Test to
+                * be sure.
                 */
                if (!atomic_read(&inode->i_count)) {
                        spin_unlock(&inode->i_lock);
@@ -77,6 +80,7 @@ static void fsnotify_unmount_inodes(struct super_block *sb)
 
                iput_inode = inode;
 
+               cond_resched();
                spin_lock(&sb->s_inode_list_lock);
        }
        spin_unlock(&sb->s_inode_list_lock);
index a043164..f75767b 100644 (file)
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -3,6 +3,7 @@
 #include <linux/pseudo_fs.h>
 #include <linux/file.h>
 #include <linux/fs.h>
+#include <linux/proc_fs.h>
 #include <linux/proc_ns.h>
 #include <linux/magic.h>
 #include <linux/ktime.h>
@@ -11,6 +12,8 @@
 #include <linux/nsfs.h>
 #include <linux/uaccess.h>
 
+#include "internal.h"
+
 static struct vfsmount *nsfs_mnt;
 
 static long ns_ioctl(struct file *filp, unsigned int ioctl,
index 1c4c51f..cda1027 100644 (file)
@@ -3282,6 +3282,7 @@ static void ocfs2_dlm_init_debug(struct ocfs2_super *osb)
 
        debugfs_create_u32("locking_filter", 0600, osb->osb_debug_root,
                           &dlm_debug->d_filter_secs);
+       ocfs2_get_dlm_debug(dlm_debug);
 }
 
 static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb)
index 1afe57f..68ba354 100644 (file)
@@ -1066,6 +1066,14 @@ int ocfs2_journal_load(struct ocfs2_journal *journal, int local, int replayed)
 
        ocfs2_clear_journal_error(osb->sb, journal->j_journal, osb->slot_num);
 
+       if (replayed) {
+               jbd2_journal_lock_updates(journal->j_journal);
+               status = jbd2_journal_flush(journal->j_journal);
+               jbd2_journal_unlock_updates(journal->j_journal);
+               if (status < 0)
+                       mlog_errno(status);
+       }
+
        status = ocfs2_journal_toggle_dirty(osb, 1, replayed);
        if (status < 0) {
                mlog_errno(status);
index b801c63..6220642 100644 (file)
@@ -227,13 +227,17 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
 struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper)
 {
        struct ovl_fh *fh;
-       int fh_type, fh_len, dwords;
-       void *buf;
+       int fh_type, dwords;
        int buflen = MAX_HANDLE_SZ;
        uuid_t *uuid = &real->d_sb->s_uuid;
+       int err;
 
-       buf = kmalloc(buflen, GFP_KERNEL);
-       if (!buf)
+       /* Make sure the real fid stays 32bit aligned */
+       BUILD_BUG_ON(OVL_FH_FID_OFFSET % 4);
+       BUILD_BUG_ON(MAX_HANDLE_SZ + OVL_FH_FID_OFFSET > 255);
+
+       fh = kzalloc(buflen + OVL_FH_FID_OFFSET, GFP_KERNEL);
+       if (!fh)
                return ERR_PTR(-ENOMEM);
 
        /*
@@ -242,27 +246,19 @@ struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper)
         * the price or reconnecting the dentry.
         */
        dwords = buflen >> 2;
-       fh_type = exportfs_encode_fh(real, buf, &dwords, 0);
+       fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0);
        buflen = (dwords << 2);
 
-       fh = ERR_PTR(-EIO);
+       err = -EIO;
        if (WARN_ON(fh_type < 0) ||
            WARN_ON(buflen > MAX_HANDLE_SZ) ||
            WARN_ON(fh_type == FILEID_INVALID))
-               goto out;
+               goto out_err;
 
-       BUILD_BUG_ON(MAX_HANDLE_SZ + offsetof(struct ovl_fh, fid) > 255);
-       fh_len = offsetof(struct ovl_fh, fid) + buflen;
-       fh = kmalloc(fh_len, GFP_KERNEL);
-       if (!fh) {
-               fh = ERR_PTR(-ENOMEM);
-               goto out;
-       }
-
-       fh->version = OVL_FH_VERSION;
-       fh->magic = OVL_FH_MAGIC;
-       fh->type = fh_type;
-       fh->flags = OVL_FH_FLAG_CPU_ENDIAN;
+       fh->fb.version = OVL_FH_VERSION;
+       fh->fb.magic = OVL_FH_MAGIC;
+       fh->fb.type = fh_type;
+       fh->fb.flags = OVL_FH_FLAG_CPU_ENDIAN;
        /*
         * When we will want to decode an overlay dentry from this handle
         * and all layers are on the same fs, if we get a disconncted real
@@ -270,14 +266,15 @@ struct ovl_fh *ovl_encode_real_fh(struct dentry *real, bool is_upper)
         * it to upperdentry or to lowerstack is by checking this flag.
         */
        if (is_upper)
-               fh->flags |= OVL_FH_FLAG_PATH_UPPER;
-       fh->len = fh_len;
-       fh->uuid = *uuid;
-       memcpy(fh->fid, buf, buflen);
+               fh->fb.flags |= OVL_FH_FLAG_PATH_UPPER;
+       fh->fb.len = sizeof(fh->fb) + buflen;
+       fh->fb.uuid = *uuid;
 
-out:
-       kfree(buf);
        return fh;
+
+out_err:
+       kfree(fh);
+       return ERR_PTR(err);
 }
 
 int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
@@ -300,8 +297,8 @@ int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
        /*
         * Do not fail when upper doesn't support xattrs.
         */
-       err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh,
-                                fh ? fh->len : 0, 0);
+       err = ovl_check_setxattr(dentry, upper, OVL_XATTR_ORIGIN, fh->buf,
+                                fh ? fh->fb.len : 0, 0);
        kfree(fh);
 
        return err;
@@ -317,7 +314,7 @@ static int ovl_set_upper_fh(struct dentry *upper, struct dentry *index)
        if (IS_ERR(fh))
                return PTR_ERR(fh);
 
-       err = ovl_do_setxattr(index, OVL_XATTR_UPPER, fh, fh->len, 0);
+       err = ovl_do_setxattr(index, OVL_XATTR_UPPER, fh->buf, fh->fb.len, 0);
 
        kfree(fh);
        return err;
index 702aa63..29abdb1 100644 (file)
@@ -1170,7 +1170,7 @@ static int ovl_rename(struct inode *olddir, struct dentry *old,
        if (newdentry == trap)
                goto out_dput;
 
-       if (WARN_ON(olddentry->d_inode == newdentry->d_inode))
+       if (olddentry->d_inode == newdentry->d_inode)
                goto out_dput;
 
        err = 0;
index 73c9775..70e5558 100644 (file)
@@ -211,10 +211,11 @@ static int ovl_check_encode_origin(struct dentry *dentry)
        return 1;
 }
 
-static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen)
+static int ovl_dentry_to_fid(struct dentry *dentry, u32 *fid, int buflen)
 {
        struct ovl_fh *fh = NULL;
        int err, enc_lower;
+       int len;
 
        /*
         * Check if we should encode a lower or upper file handle and maybe
@@ -231,11 +232,12 @@ static int ovl_d_to_fh(struct dentry *dentry, char *buf, int buflen)
                return PTR_ERR(fh);
 
        err = -EOVERFLOW;
-       if (fh->len > buflen)
+       len = OVL_FH_LEN(fh);
+       if (len > buflen)
                goto fail;
 
-       memcpy(buf, (char *)fh, fh->len);
-       err = fh->len;
+       memcpy(fid, fh, len);
+       err = len;
 
 out:
        kfree(fh);
@@ -243,31 +245,16 @@ out:
 
 fail:
        pr_warn_ratelimited("overlayfs: failed to encode file handle (%pd2, err=%i, buflen=%d, len=%d, type=%d)\n",
-                           dentry, err, buflen, fh ? (int)fh->len : 0,
-                           fh ? fh->type : 0);
+                           dentry, err, buflen, fh ? (int)fh->fb.len : 0,
+                           fh ? fh->fb.type : 0);
        goto out;
 }
 
-static int ovl_dentry_to_fh(struct dentry *dentry, u32 *fid, int *max_len)
-{
-       int res, len = *max_len << 2;
-
-       res = ovl_d_to_fh(dentry, (char *)fid, len);
-       if (res <= 0)
-               return FILEID_INVALID;
-
-       len = res;
-
-       /* Round up to dwords */
-       *max_len = (len + 3) >> 2;
-       return OVL_FILEID;
-}
-
 static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,
                         struct inode *parent)
 {
        struct dentry *dentry;
-       int type;
+       int bytes = *max_len << 2;
 
        /* TODO: encode connectable file handles */
        if (parent)
@@ -277,10 +264,14 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,
        if (WARN_ON(!dentry))
                return FILEID_INVALID;
 
-       type = ovl_dentry_to_fh(dentry, fid, max_len);
-
+       bytes = ovl_dentry_to_fid(dentry, fid, bytes);
        dput(dentry);
-       return type;
+       if (bytes <= 0)
+               return FILEID_INVALID;
+
+       *max_len = bytes >> 2;
+
+       return OVL_FILEID_V1;
 }
 
 /*
@@ -777,24 +768,45 @@ out_err:
        goto out;
 }
 
+static struct ovl_fh *ovl_fid_to_fh(struct fid *fid, int buflen, int fh_type)
+{
+       struct ovl_fh *fh;
+
+       /* If on-wire inner fid is aligned - nothing to do */
+       if (fh_type == OVL_FILEID_V1)
+               return (struct ovl_fh *)fid;
+
+       if (fh_type != OVL_FILEID_V0)
+               return ERR_PTR(-EINVAL);
+
+       fh = kzalloc(buflen, GFP_KERNEL);
+       if (!fh)
+               return ERR_PTR(-ENOMEM);
+
+       /* Copy unaligned inner fh into aligned buffer */
+       memcpy(&fh->fb, fid, buflen - OVL_FH_WIRE_OFFSET);
+       return fh;
+}
+
 static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid,
                                       int fh_len, int fh_type)
 {
        struct dentry *dentry = NULL;
-       struct ovl_fh *fh = (struct ovl_fh *) fid;
+       struct ovl_fh *fh = NULL;
        int len = fh_len << 2;
        unsigned int flags = 0;
        int err;
 
-       err = -EINVAL;
-       if (fh_type != OVL_FILEID)
+       fh = ovl_fid_to_fh(fid, len, fh_type);
+       err = PTR_ERR(fh);
+       if (IS_ERR(fh))
                goto out_err;
 
        err = ovl_check_fh_len(fh, len);
        if (err)
                goto out_err;
 
-       flags = fh->flags;
+       flags = fh->fb.flags;
        dentry = (flags & OVL_FH_FLAG_PATH_UPPER) ?
                 ovl_upper_fh_to_d(sb, fh) :
                 ovl_lower_fh_to_d(sb, fh);
@@ -802,12 +814,18 @@ static struct dentry *ovl_fh_to_dentry(struct super_block *sb, struct fid *fid,
        if (IS_ERR(dentry) && err != -ESTALE)
                goto out_err;
 
+out:
+       /* We may have needed to re-align OVL_FILEID_V0 */
+       if (!IS_ERR_OR_NULL(fh) && fh != (void *)fid)
+               kfree(fh);
+
        return dentry;
 
 out_err:
        pr_warn_ratelimited("overlayfs: failed to decode file handle (len=%d, type=%d, flags=%x, err=%i)\n",
-                           len, fh_type, flags, err);
-       return ERR_PTR(err);
+                           fh_len, fh_type, flags, err);
+       dentry = ERR_PTR(err);
+       goto out;
 }
 
 static struct dentry *ovl_fh_to_parent(struct super_block *sb, struct fid *fid,
index bc14781..b045cf1 100644 (file)
@@ -200,8 +200,14 @@ int ovl_getattr(const struct path *path, struct kstat *stat,
                        if (ovl_test_flag(OVL_INDEX, d_inode(dentry)) ||
                            (!ovl_verify_lower(dentry->d_sb) &&
                             (is_dir || lowerstat.nlink == 1))) {
-                               stat->ino = lowerstat.ino;
                                lower_layer = ovl_layer_lower(dentry);
+                               /*
+                                * Cannot use origin st_dev;st_ino because
+                                * origin inode content may differ from overlay
+                                * inode content.
+                                */
+                               if (samefs || lower_layer->fsid)
+                                       stat->ino = lowerstat.ino;
                        }
 
                        /*
index c269d60..76ff663 100644 (file)
@@ -84,21 +84,21 @@ static int ovl_acceptable(void *ctx, struct dentry *dentry)
  * Return -ENODATA for "origin unknown".
  * Return <0 for an invalid file handle.
  */
-int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
+int ovl_check_fb_len(struct ovl_fb *fb, int fb_len)
 {
-       if (fh_len < sizeof(struct ovl_fh) || fh_len < fh->len)
+       if (fb_len < sizeof(struct ovl_fb) || fb_len < fb->len)
                return -EINVAL;
 
-       if (fh->magic != OVL_FH_MAGIC)
+       if (fb->magic != OVL_FH_MAGIC)
                return -EINVAL;
 
        /* Treat larger version and unknown flags as "origin unknown" */
-       if (fh->version > OVL_FH_VERSION || fh->flags & ~OVL_FH_FLAG_ALL)
+       if (fb->version > OVL_FH_VERSION || fb->flags & ~OVL_FH_FLAG_ALL)
                return -ENODATA;
 
        /* Treat endianness mismatch as "origin unknown" */
-       if (!(fh->flags & OVL_FH_FLAG_ANY_ENDIAN) &&
-           (fh->flags & OVL_FH_FLAG_BIG_ENDIAN) != OVL_FH_FLAG_CPU_ENDIAN)
+       if (!(fb->flags & OVL_FH_FLAG_ANY_ENDIAN) &&
+           (fb->flags & OVL_FH_FLAG_BIG_ENDIAN) != OVL_FH_FLAG_CPU_ENDIAN)
                return -ENODATA;
 
        return 0;
@@ -119,15 +119,15 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
        if (res == 0)
                return NULL;
 
-       fh = kzalloc(res, GFP_KERNEL);
+       fh = kzalloc(res + OVL_FH_WIRE_OFFSET, GFP_KERNEL);
        if (!fh)
                return ERR_PTR(-ENOMEM);
 
-       res = vfs_getxattr(dentry, name, fh, res);
+       res = vfs_getxattr(dentry, name, fh->buf, res);
        if (res < 0)
                goto fail;
 
-       err = ovl_check_fh_len(fh, res);
+       err = ovl_check_fb_len(&fh->fb, res);
        if (err < 0) {
                if (err == -ENODATA)
                        goto out;
@@ -158,12 +158,12 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
         * Make sure that the stored uuid matches the uuid of the lower
         * layer where file handle will be decoded.
         */
-       if (!uuid_equal(&fh->uuid, &mnt->mnt_sb->s_uuid))
+       if (!uuid_equal(&fh->fb.uuid, &mnt->mnt_sb->s_uuid))
                return NULL;
 
-       bytes = (fh->len - offsetof(struct ovl_fh, fid));
-       real = exportfs_decode_fh(mnt, (struct fid *)fh->fid,
-                                 bytes >> 2, (int)fh->type,
+       bytes = (fh->fb.len - offsetof(struct ovl_fb, fid));
+       real = exportfs_decode_fh(mnt, (struct fid *)fh->fb.fid,
+                                 bytes >> 2, (int)fh->fb.type,
                                  connected ? ovl_acceptable : NULL, mnt);
        if (IS_ERR(real)) {
                /*
@@ -173,7 +173,7 @@ struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
                 * index entries correctly.
                 */
                if (real == ERR_PTR(-ESTALE) &&
-                   !(fh->flags & OVL_FH_FLAG_PATH_UPPER))
+                   !(fh->fb.flags & OVL_FH_FLAG_PATH_UPPER))
                        real = NULL;
                return real;
        }
@@ -323,6 +323,14 @@ int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
        int i;
 
        for (i = 0; i < ofs->numlower; i++) {
+               /*
+                * If lower fs uuid is not unique among lower fs we cannot match
+                * fh->uuid to layer.
+                */
+               if (ofs->lower_layers[i].fsid &&
+                   ofs->lower_layers[i].fs->bad_uuid)
+                       continue;
+
                origin = ovl_decode_real_fh(fh, ofs->lower_layers[i].mnt,
                                            connected);
                if (origin)
@@ -400,7 +408,7 @@ static int ovl_verify_fh(struct dentry *dentry, const char *name,
        if (IS_ERR(ofh))
                return PTR_ERR(ofh);
 
-       if (fh->len != ofh->len || memcmp(fh, ofh, fh->len))
+       if (fh->fb.len != ofh->fb.len || memcmp(&fh->fb, &ofh->fb, fh->fb.len))
                err = -ESTALE;
 
        kfree(ofh);
@@ -431,7 +439,7 @@ int ovl_verify_set_fh(struct dentry *dentry, const char *name,
 
        err = ovl_verify_fh(dentry, name, fh);
        if (set && err == -ENODATA)
-               err = ovl_do_setxattr(dentry, name, fh, fh->len, 0);
+               err = ovl_do_setxattr(dentry, name, fh->buf, fh->fb.len, 0);
        if (err)
                goto fail;
 
@@ -505,20 +513,20 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index)
                goto fail;
 
        err = -EINVAL;
-       if (index->d_name.len < sizeof(struct ovl_fh)*2)
+       if (index->d_name.len < sizeof(struct ovl_fb)*2)
                goto fail;
 
        err = -ENOMEM;
        len = index->d_name.len / 2;
-       fh = kzalloc(len, GFP_KERNEL);
+       fh = kzalloc(len + OVL_FH_WIRE_OFFSET, GFP_KERNEL);
        if (!fh)
                goto fail;
 
        err = -EINVAL;
-       if (hex2bin((u8 *)fh, index->d_name.name, len))
+       if (hex2bin(fh->buf, index->d_name.name, len))
                goto fail;
 
-       err = ovl_check_fh_len(fh, len);
+       err = ovl_check_fb_len(&fh->fb, len);
        if (err)
                goto fail;
 
@@ -597,11 +605,11 @@ static int ovl_get_index_name_fh(struct ovl_fh *fh, struct qstr *name)
 {
        char *n, *s;
 
-       n = kcalloc(fh->len, 2, GFP_KERNEL);
+       n = kcalloc(fh->fb.len, 2, GFP_KERNEL);
        if (!n)
                return -ENOMEM;
 
-       s  = bin2hex(n, fh, fh->len);
+       s  = bin2hex(n, fh->buf, fh->fb.len);
        *name = (struct qstr) QSTR_INIT(n, s - n);
 
        return 0;
index 6934bcf..f283b1d 100644 (file)
@@ -71,20 +71,36 @@ enum ovl_entry_flag {
 #error Endianness not defined
 #endif
 
-/* The type returned by overlay exportfs ops when encoding an ovl_fh handle */
-#define OVL_FILEID     0xfb
+/* The type used to be returned by overlay exportfs for misaligned fid */
+#define OVL_FILEID_V0  0xfb
+/* The type returned by overlay exportfs for 32bit aligned fid */
+#define OVL_FILEID_V1  0xf8
 
-/* On-disk and in-memeory format for redirect by file handle */
-struct ovl_fh {
+/* On-disk format for "origin" file handle */
+struct ovl_fb {
        u8 version;     /* 0 */
        u8 magic;       /* 0xfb */
        u8 len;         /* size of this header + size of fid */
        u8 flags;       /* OVL_FH_FLAG_* */
        u8 type;        /* fid_type of fid */
        uuid_t uuid;    /* uuid of filesystem */
-       u8 fid[0];      /* file identifier */
+       u32 fid[0];     /* file identifier should be 32bit aligned in-memory */
 } __packed;
 
+/* In-memory and on-wire format for overlay file handle */
+struct ovl_fh {
+       u8 padding[3];  /* make sure fb.fid is 32bit aligned */
+       union {
+               struct ovl_fb fb;
+               u8 buf[0];
+       };
+} __packed;
+
+#define OVL_FH_WIRE_OFFSET     offsetof(struct ovl_fh, fb)
+#define OVL_FH_LEN(fh)         (OVL_FH_WIRE_OFFSET + (fh)->fb.len)
+#define OVL_FH_FID_OFFSET      (OVL_FH_WIRE_OFFSET + \
+                                offsetof(struct ovl_fb, fid))
+
 static inline int ovl_do_rmdir(struct inode *dir, struct dentry *dentry)
 {
        int err = vfs_rmdir(dir, dentry);
@@ -302,7 +318,13 @@ static inline void ovl_inode_unlock(struct inode *inode)
 
 
 /* namei.c */
-int ovl_check_fh_len(struct ovl_fh *fh, int fh_len);
+int ovl_check_fb_len(struct ovl_fb *fb, int fb_len);
+
+static inline int ovl_check_fh_len(struct ovl_fh *fh, int fh_len)
+{
+       return ovl_check_fb_len(&fh->fb, fh_len - OVL_FH_WIRE_OFFSET);
+}
+
 struct dentry *ovl_decode_real_fh(struct ovl_fh *fh, struct vfsmount *mnt,
                                  bool connected);
 int ovl_check_origin_fh(struct ovl_fs *ofs, struct ovl_fh *fh, bool connected,
index a827928..28348c4 100644 (file)
@@ -22,6 +22,8 @@ struct ovl_config {
 struct ovl_sb {
        struct super_block *sb;
        dev_t pseudo_dev;
+       /* Unusable (conflicting) uuid */
+       bool bad_uuid;
 };
 
 struct ovl_layer {
index afbcb11..7621ff1 100644 (file)
@@ -1255,7 +1255,7 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
 {
        unsigned int i;
 
-       if (!ofs->config.nfs_export && !(ofs->config.index && ofs->upper_mnt))
+       if (!ofs->config.nfs_export && !ofs->upper_mnt)
                return true;
 
        for (i = 0; i < ofs->numlowerfs; i++) {
@@ -1263,9 +1263,13 @@ static bool ovl_lower_uuid_ok(struct ovl_fs *ofs, const uuid_t *uuid)
                 * We use uuid to associate an overlay lower file handle with a
                 * lower layer, so we can accept lower fs with null uuid as long
                 * as all lower layers with null uuid are on the same fs.
+                * if we detect multiple lower fs with the same uuid, we
+                * disable lower file handle decoding on all of them.
                 */
-               if (uuid_equal(&ofs->lower_fs[i].sb->s_uuid, uuid))
+               if (uuid_equal(&ofs->lower_fs[i].sb->s_uuid, uuid)) {
+                       ofs->lower_fs[i].bad_uuid = true;
                        return false;
+               }
        }
        return true;
 }
@@ -1277,6 +1281,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
        unsigned int i;
        dev_t dev;
        int err;
+       bool bad_uuid = false;
 
        /* fsid 0 is reserved for upper fs even with non upper overlay */
        if (ofs->upper_mnt && ofs->upper_mnt->mnt_sb == sb)
@@ -1288,11 +1293,15 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
        }
 
        if (!ovl_lower_uuid_ok(ofs, &sb->s_uuid)) {
-               ofs->config.index = false;
-               ofs->config.nfs_export = false;
-               pr_warn("overlayfs: %s uuid detected in lower fs '%pd2', falling back to index=off,nfs_export=off.\n",
-                       uuid_is_null(&sb->s_uuid) ? "null" : "conflicting",
-                       path->dentry);
+               bad_uuid = true;
+               if (ofs->config.index || ofs->config.nfs_export) {
+                       ofs->config.index = false;
+                       ofs->config.nfs_export = false;
+                       pr_warn("overlayfs: %s uuid detected in lower fs '%pd2', falling back to index=off,nfs_export=off.\n",
+                               uuid_is_null(&sb->s_uuid) ? "null" :
+                                                           "conflicting",
+                               path->dentry);
+               }
        }
 
        err = get_anon_bdev(&dev);
@@ -1303,6 +1312,7 @@ static int ovl_get_fsid(struct ovl_fs *ofs, const struct path *path)
 
        ofs->lower_fs[ofs->numlowerfs].sb = sb;
        ofs->lower_fs[ofs->numlowerfs].pseudo_dev = dev;
+       ofs->lower_fs[ofs->numlowerfs].bad_uuid = bad_uuid;
        ofs->numlowerfs++;
 
        return ofs->numlowerfs;
index 87109e7..57502c3 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -364,17 +364,39 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                        ret = -EAGAIN;
                        break;
                }
-               if (signal_pending(current)) {
-                       if (!ret)
-                               ret = -ERESTARTSYS;
-                       break;
-               }
                __pipe_unlock(pipe);
-               if (was_full) {
+
+               /*
+                * We only get here if we didn't actually read anything.
+                *
+                * However, we could have seen (and removed) a zero-sized
+                * pipe buffer, and might have made space in the buffers
+                * that way.
+                *
+                * You can't make zero-sized pipe buffers by doing an empty
+                * write (not even in packet mode), but they can happen if
+                * the writer gets an EFAULT when trying to fill a buffer
+                * that already got allocated and inserted in the buffer
+                * array.
+                *
+                * So we still need to wake up any pending writers in the
+                * _very_ unlikely case that the pipe was full, but we got
+                * no data.
+                */
+               if (unlikely(was_full)) {
                        wake_up_interruptible_sync_poll(&pipe->wait, EPOLLOUT | EPOLLWRNORM);
                        kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
                }
-               wait_event_interruptible(pipe->wait, pipe_readable(pipe));
+
+               /*
+                * But because we didn't read anything, at this point we can
+                * just return directly with -ERESTARTSYS if we're interrupted,
+                * since we've done any required wakeups and there's no need
+                * to mark anything accessed. And we've dropped the lock.
+                */
+               if (wait_event_interruptible(pipe->wait, pipe_readable(pipe)) < 0)
+                       return -ERESTARTSYS;
+
                __pipe_lock(pipe);
                was_full = pipe_full(pipe->head, pipe->tail, pipe->max_usage);
        }
@@ -559,7 +581,7 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
                }
                wait_event_interruptible(pipe->wait, pipe_writable(pipe));
                __pipe_lock(pipe);
-               was_empty = pipe_empty(head, pipe->tail);
+               was_empty = pipe_empty(pipe->head, pipe->tail);
        }
 out:
        __pipe_unlock(pipe);
index 84ad1c9..249672b 100644 (file)
@@ -631,12 +631,15 @@ EXPORT_SYMBOL_GPL(posix_acl_create);
 
 /**
  * posix_acl_update_mode  -  update mode in set_acl
+ * @inode: target inode
+ * @mode_p: mode (pointer) for update
+ * @acl: acl pointer
  *
  * Update the file mode when setting an ACL: compute the new file permission
  * bits based on the ACL.  In addition, if the ACL is equivalent to the new
- * file mode, set *acl to NULL to indicate that no ACL should be set.
+ * file mode, set *@acl to NULL to indicate that no ACL should be set.
  *
- * As with chmod, clear the setgit bit if the caller is not in the owning group
+ * As with chmod, clear the setgid bit if the caller is not in the owning group
  * or capable of CAP_FSETID (see inode_change_ok).
  *
  * Called from set_acl inode operations.
index 37bdbec..fd931d3 100644 (file)
@@ -134,7 +134,7 @@ static int show_stat(struct seq_file *p, void *v)
                softirq         += cpustat[CPUTIME_SOFTIRQ];
                steal           += cpustat[CPUTIME_STEAL];
                guest           += cpustat[CPUTIME_GUEST];
-               guest_nice      += cpustat[CPUTIME_USER];
+               guest_nice      += cpustat[CPUTIME_GUEST_NICE];
                sum             += kstat_cpu_irqs_sum(i);
                sum             += arch_irq_stat_cpu(i);
 
@@ -175,7 +175,7 @@ static int show_stat(struct seq_file *p, void *v)
                softirq         = cpustat[CPUTIME_SOFTIRQ];
                steal           = cpustat[CPUTIME_STEAL];
                guest           = cpustat[CPUTIME_GUEST];
-               guest_nice      = cpustat[CPUTIME_USER];
+               guest_nice      = cpustat[CPUTIME_GUEST_NICE];
                seq_printf(p, "cpu%d", i);
                seq_put_decimal_ull(p, " ", nsec_to_clock_t(user));
                seq_put_decimal_ull(p, " ", nsec_to_clock_t(nice));
index 8caff83..013486b 100644 (file)
@@ -407,6 +407,17 @@ static int notrace ramoops_pstore_write(struct pstore_record *record)
 
        prz = cxt->dprzs[cxt->dump_write_cnt];
 
+       /*
+        * Since this is a new crash dump, we need to reset the buffer in
+        * case it still has an old dump present. Without this, the new dump
+        * will get appended, which would seriously confuse anything trying
+        * to check dump file contents. Specifically, ramoops_read_kmsg_hdr()
+        * expects to find a dump header in the beginning of buffer data, so
+        * we must to reset the buffer values, in order to ensure that the
+        * header will be written to the beginning of the buffer.
+        */
+       persistent_ram_zap(prz);
+
        /* Build header and append record contents. */
        hlen = ramoops_write_kmsg_hdr(prz, record);
        if (!hlen)
@@ -572,6 +583,7 @@ static int ramoops_init_przs(const char *name,
                prz_ar[i] = persistent_ram_new(*paddr, zone_sz, sig,
                                               &cxt->ecc_info,
                                               cxt->memtype, flags, label);
+               kfree(label);
                if (IS_ERR(prz_ar[i])) {
                        err = PTR_ERR(prz_ar[i]);
                        dev_err(dev, "failed to request %s mem region (0x%zx@0x%llx): %d\n",
@@ -617,6 +629,7 @@ static int ramoops_init_prz(const char *name,
        label = kasprintf(GFP_KERNEL, "ramoops:%s", name);
        *prz = persistent_ram_new(*paddr, sz, sig, &cxt->ecc_info,
                                  cxt->memtype, PRZ_FLAG_ZAP_OLD, label);
+       kfree(label);
        if (IS_ERR(*prz)) {
                int err = PTR_ERR(*prz);
 
index 8823f65..1f4d8c0 100644 (file)
@@ -574,7 +574,7 @@ struct persistent_ram_zone *persistent_ram_new(phys_addr_t start, size_t size,
        /* Initialize general buffer state. */
        raw_spin_lock_init(&prz->buffer_lock);
        prz->flags = flags;
-       prz->label = label;
+       prz->label = kstrdup(label, GFP_KERNEL);
 
        ret = persistent_ram_buffer_map(start, size, prz, memtype);
        if (ret)
index b0688c0..b6a4f69 100644 (file)
@@ -984,6 +984,7 @@ static int add_dquot_ref(struct super_block *sb, int type)
                 * later.
                 */
                old_inode = inode;
+               cond_resched();
                spin_lock(&sb->s_inode_list_lock);
        }
        spin_unlock(&sb->s_inode_list_lock);
index cfadab2..cd35253 100644 (file)
@@ -448,10 +448,12 @@ void generic_shutdown_super(struct super_block *sb)
                sync_filesystem(sb);
                sb->s_flags &= ~SB_ACTIVE;
 
-               fsnotify_sb_delete(sb);
                cgroup_writeback_umount();
 
+               /* evict all inodes with zero refcount */
                evict_inodes(sb);
+               /* only nonzero refcount inodes can have marks */
+               fsnotify_sb_delete(sb);
 
                if (sb->s_dio_done_wq) {
                        destroy_workqueue(sb->s_dio_done_wq);
index eabc6ac..b79e3fd 100644 (file)
@@ -315,7 +315,7 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *uarg)
        if (arg.block_size != PAGE_SIZE)
                return -EINVAL;
 
-       if (arg.salt_size > FIELD_SIZEOF(struct fsverity_descriptor, salt))
+       if (arg.salt_size > sizeof_field(struct fsverity_descriptor, salt))
                return -EMSGSIZE;
 
        if (arg.sig_size > FS_VERITY_MAX_SIGNATURE_SIZE)
index c284e10..fc93fd8 100644 (file)
@@ -2248,24 +2248,32 @@ xfs_alloc_longest_free_extent(
        return pag->pagf_flcount > 0 || pag->pagf_longest > 0;
 }
 
+/*
+ * Compute the minimum length of the AGFL in the given AG.  If @pag is NULL,
+ * return the largest possible minimum length.
+ */
 unsigned int
 xfs_alloc_min_freelist(
        struct xfs_mount        *mp,
        struct xfs_perag        *pag)
 {
+       /* AG btrees have at least 1 level. */
+       static const uint8_t    fake_levels[XFS_BTNUM_AGF] = {1, 1, 1};
+       const uint8_t           *levels = pag ? pag->pagf_levels : fake_levels;
        unsigned int            min_free;
 
+       ASSERT(mp->m_ag_maxlevels > 0);
+
        /* space needed by-bno freespace btree */
-       min_free = min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_BNOi] + 1,
+       min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1,
                                       mp->m_ag_maxlevels);
        /* space needed by-size freespace btree */
-       min_free += min_t(unsigned int, pag->pagf_levels[XFS_BTNUM_CNTi] + 1,
+       min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1,
                                       mp->m_ag_maxlevels);
        /* space needed reverse mapping used space btree */
        if (xfs_sb_version_hasrmapbt(&mp->m_sb))
-               min_free += min_t(unsigned int,
-                                 pag->pagf_levels[XFS_BTNUM_RMAPi] + 1,
-                                 mp->m_rmap_maxlevels);
+               min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1,
+                                               mp->m_rmap_maxlevels);
 
        return min_free;
 }
index a9ad1f9..4c2e046 100644 (file)
@@ -4561,7 +4561,7 @@ xfs_bmapi_convert_delalloc(
        struct xfs_mount        *mp = ip->i_mount;
        xfs_fileoff_t           offset_fsb = XFS_B_TO_FSBT(mp, offset);
        struct xfs_bmalloca     bma = { NULL };
-       u16                     flags = 0;
+       uint16_t                flags = 0;
        struct xfs_trans        *tp;
        int                     error;
 
@@ -5972,8 +5972,7 @@ xfs_bmap_insert_extents(
                goto del_cursor;
        }
 
-       if (XFS_IS_CORRUPT(mp,
-                          stop_fsb >= got.br_startoff + got.br_blockcount)) {
+       if (XFS_IS_CORRUPT(mp, stop_fsb > got.br_startoff)) {
                error = -EFSCORRUPTED;
                goto del_cursor;
        }
index 0aa87cb..dd6fcaa 100644 (file)
@@ -724,3 +724,24 @@ xfs_dir2_namecheck(
        /* There shouldn't be any slashes or nulls here */
        return !memchr(name, '/', length) && !memchr(name, 0, length);
 }
+
+xfs_dahash_t
+xfs_dir2_hashname(
+       struct xfs_mount        *mp,
+       struct xfs_name         *name)
+{
+       if (unlikely(xfs_sb_version_hasasciici(&mp->m_sb)))
+               return xfs_ascii_ci_hashname(name);
+       return xfs_da_hashname(name->name, name->len);
+}
+
+enum xfs_dacmp
+xfs_dir2_compname(
+       struct xfs_da_args      *args,
+       const unsigned char     *name,
+       int                     len)
+{
+       if (unlikely(xfs_sb_version_hasasciici(&args->dp->i_mount->m_sb)))
+               return xfs_ascii_ci_compname(args, name, len);
+       return xfs_da_compname(args, name, len);
+}
index c031c53..01ee0b9 100644 (file)
@@ -175,6 +175,12 @@ extern int xfs_dir2_sf_lookup(struct xfs_da_args *args);
 extern int xfs_dir2_sf_removename(struct xfs_da_args *args);
 extern int xfs_dir2_sf_replace(struct xfs_da_args *args);
 extern xfs_failaddr_t xfs_dir2_sf_verify(struct xfs_inode *ip);
+int xfs_dir2_sf_entsize(struct xfs_mount *mp,
+               struct xfs_dir2_sf_hdr *hdr, int len);
+void xfs_dir2_sf_put_ino(struct xfs_mount *mp, struct xfs_dir2_sf_hdr *hdr,
+               struct xfs_dir2_sf_entry *sfep, xfs_ino_t ino);
+void xfs_dir2_sf_put_ftype(struct xfs_mount *mp,
+               struct xfs_dir2_sf_entry *sfep, uint8_t ftype);
 
 /* xfs_dir2_readdir.c */
 extern int xfs_readdir(struct xfs_trans *tp, struct xfs_inode *dp,
@@ -194,25 +200,8 @@ xfs_dir2_data_entsize(
        return round_up(len, XFS_DIR2_DATA_ALIGN);
 }
 
-static inline xfs_dahash_t
-xfs_dir2_hashname(
-       struct xfs_mount        *mp,
-       struct xfs_name         *name)
-{
-       if (unlikely(xfs_sb_version_hasasciici(&mp->m_sb)))
-               return xfs_ascii_ci_hashname(name);
-       return xfs_da_hashname(name->name, name->len);
-}
-
-static inline enum xfs_dacmp
-xfs_dir2_compname(
-       struct xfs_da_args      *args,
-       const unsigned char     *name,
-       int                     len)
-{
-       if (unlikely(xfs_sb_version_hasasciici(&args->dp->i_mount->m_sb)))
-               return xfs_ascii_ci_compname(args, name, len);
-       return xfs_da_compname(args, name, len);
-}
+xfs_dahash_t xfs_dir2_hashname(struct xfs_mount *mp, struct xfs_name *name);
+enum xfs_dacmp xfs_dir2_compname(struct xfs_da_args *args,
+               const unsigned char *name, int len);
 
 #endif /* __XFS_DIR2_PRIV_H__ */
index 8b94d33..7b7f6fb 100644 (file)
@@ -37,7 +37,7 @@ static void xfs_dir2_sf_check(xfs_da_args_t *args);
 static void xfs_dir2_sf_toino4(xfs_da_args_t *args);
 static void xfs_dir2_sf_toino8(xfs_da_args_t *args);
 
-static int
+int
 xfs_dir2_sf_entsize(
        struct xfs_mount        *mp,
        struct xfs_dir2_sf_hdr  *hdr,
@@ -84,7 +84,7 @@ xfs_dir2_sf_get_ino(
        return get_unaligned_be64(from) & XFS_MAXINUMBER;
 }
 
-static void
+void
 xfs_dir2_sf_put_ino(
        struct xfs_mount                *mp,
        struct xfs_dir2_sf_hdr          *hdr,
@@ -145,7 +145,7 @@ xfs_dir2_sf_get_ftype(
        return XFS_DIR3_FT_UNKNOWN;
 }
 
-static void
+void
 xfs_dir2_sf_put_ftype(
        struct xfs_mount        *mp,
        struct xfs_dir2_sf_entry *sfep,
index 988cde7..5b759af 100644 (file)
@@ -2909,3 +2909,67 @@ xfs_ialloc_setup_geometry(
        else
                igeo->ialloc_align = 0;
 }
+
+/* Compute the location of the root directory inode that is laid out by mkfs. */
+xfs_ino_t
+xfs_ialloc_calc_rootino(
+       struct xfs_mount        *mp,
+       int                     sunit)
+{
+       struct xfs_ino_geometry *igeo = M_IGEO(mp);
+       xfs_agblock_t           first_bno;
+
+       /*
+        * Pre-calculate the geometry of AG 0.  We know what it looks like
+        * because libxfs knows how to create allocation groups now.
+        *
+        * first_bno is the first block in which mkfs could possibly have
+        * allocated the root directory inode, once we factor in the metadata
+        * that mkfs formats before it.  Namely, the four AG headers...
+        */
+       first_bno = howmany(4 * mp->m_sb.sb_sectsize, mp->m_sb.sb_blocksize);
+
+       /* ...the two free space btree roots... */
+       first_bno += 2;
+
+       /* ...the inode btree root... */
+       first_bno += 1;
+
+       /* ...the initial AGFL... */
+       first_bno += xfs_alloc_min_freelist(mp, NULL);
+
+       /* ...the free inode btree root... */
+       if (xfs_sb_version_hasfinobt(&mp->m_sb))
+               first_bno++;
+
+       /* ...the reverse mapping btree root... */
+       if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+               first_bno++;
+
+       /* ...the reference count btree... */
+       if (xfs_sb_version_hasreflink(&mp->m_sb))
+               first_bno++;
+
+       /*
+        * ...and the log, if it is allocated in the first allocation group.
+        *
+        * This can happen with filesystems that only have a single
+        * allocation group, or very odd geometries created by old mkfs
+        * versions on very small filesystems.
+        */
+       if (mp->m_sb.sb_logstart &&
+           XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == 0)
+                first_bno += mp->m_sb.sb_logblocks;
+
+       /*
+        * Now round first_bno up to whatever allocation alignment is given
+        * by the filesystem or was passed in.
+        */
+       if (xfs_sb_version_hasdalign(&mp->m_sb) && igeo->ialloc_align > 0)
+               first_bno = roundup(first_bno, sunit);
+       else if (xfs_sb_version_hasalign(&mp->m_sb) &&
+                       mp->m_sb.sb_inoalignmt > 1)
+               first_bno = roundup(first_bno, mp->m_sb.sb_inoalignmt);
+
+       return XFS_AGINO_TO_INO(mp, 0, XFS_AGB_TO_AGINO(mp, first_bno));
+}
index 323592d..72b3468 100644 (file)
@@ -152,5 +152,6 @@ int xfs_inobt_insert_rec(struct xfs_btree_cur *cur, uint16_t holemask,
 
 int xfs_ialloc_cluster_alignment(struct xfs_mount *mp);
 void xfs_ialloc_setup_geometry(struct xfs_mount *mp);
+xfs_ino_t xfs_ialloc_calc_rootino(struct xfs_mount *mp, int sunit);
 
 #endif /* __XFS_IALLOC_H__ */
index c55cd9a..7a9c049 100644 (file)
@@ -197,6 +197,24 @@ xfs_calc_inode_chunk_res(
 }
 
 /*
+ * Per-extent log reservation for the btree changes involved in freeing or
+ * allocating a realtime extent.  We have to be able to log as many rtbitmap
+ * blocks as needed to mark inuse MAXEXTLEN blocks' worth of realtime extents,
+ * as well as the realtime summary block.
+ */
+static unsigned int
+xfs_rtalloc_log_count(
+       struct xfs_mount        *mp,
+       unsigned int            num_ops)
+{
+       unsigned int            blksz = XFS_FSB_TO_B(mp, 1);
+       unsigned int            rtbmp_bytes;
+
+       rtbmp_bytes = (MAXEXTLEN / mp->m_sb.sb_rextsize) / NBBY;
+       return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
+}
+
+/*
  * Various log reservation values.
  *
  * These are based on the size of the file system block because that is what
@@ -218,13 +236,21 @@ xfs_calc_inode_chunk_res(
 
 /*
  * In a write transaction we can allocate a maximum of 2
- * extents.  This gives:
+ * extents.  This gives (t1):
  *    the inode getting the new extents: inode size
  *    the inode's bmap btree: max depth * block size
  *    the agfs of the ags from which the extents are allocated: 2 * sector
  *    the superblock free block counter: sector size
  *    the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size
- * And the bmap_finish transaction can free bmap blocks in a join:
+ * Or, if we're writing to a realtime file (t2):
+ *    the inode getting the new extents: inode size
+ *    the inode's bmap btree: max depth * block size
+ *    the agfs of the ags from which the extents are allocated: 2 * sector
+ *    the superblock free block counter: sector size
+ *    the realtime bitmap: ((MAXEXTLEN / rtextsize) / NBBY) bytes
+ *    the realtime summary: 1 block
+ *    the allocation btrees: 2 trees * (2 * max depth - 1) * block size
+ * And the bmap_finish transaction can free bmap blocks in a join (t3):
  *    the agfs of the ags containing the blocks: 2 * sector size
  *    the agfls of the ags containing the blocks: 2 * sector size
  *    the super block free block counter: sector size
@@ -234,40 +260,72 @@ STATIC uint
 xfs_calc_write_reservation(
        struct xfs_mount        *mp)
 {
-       return XFS_DQUOT_LOGRES(mp) +
-               max((xfs_calc_inode_res(mp, 1) +
+       unsigned int            t1, t2, t3;
+       unsigned int            blksz = XFS_FSB_TO_B(mp, 1);
+
+       t1 = xfs_calc_inode_res(mp, 1) +
+            xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK), blksz) +
+            xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
+            xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), blksz);
+
+       if (xfs_sb_version_hasrealtime(&mp->m_sb)) {
+               t2 = xfs_calc_inode_res(mp, 1) +
                     xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK),
-                                     XFS_FSB_TO_B(mp, 1)) +
+                                    blksz) +
                     xfs_calc_buf_res(3, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
-                                     XFS_FSB_TO_B(mp, 1))),
-                   (xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2),
-                                     XFS_FSB_TO_B(mp, 1))));
+                    xfs_calc_buf_res(xfs_rtalloc_log_count(mp, 1), blksz) +
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 1), blksz);
+       } else {
+               t2 = 0;
+       }
+
+       t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
+            xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), blksz);
+
+       return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
 }
 
 /*
- * In truncating a file we free up to two extents at once.  We can modify:
+ * In truncating a file we free up to two extents at once.  We can modify (t1):
  *    the inode being truncated: inode size
  *    the inode's bmap btree: (max depth + 1) * block size
- * And the bmap_finish transaction can free the blocks and bmap blocks:
+ * And the bmap_finish transaction can free the blocks and bmap blocks (t2):
  *    the agf for each of the ags: 4 * sector size
  *    the agfl for each of the ags: 4 * sector size
  *    the super block to reflect the freed blocks: sector size
  *    worst case split in allocation btrees per extent assuming 4 extents:
  *             4 exts * 2 trees * (2 * max depth - 1) * block size
+ * Or, if it's a realtime file (t3):
+ *    the agf for each of the ags: 2 * sector size
+ *    the agfl for each of the ags: 2 * sector size
+ *    the super block to reflect the freed blocks: sector size
+ *    the realtime bitmap: 2 exts * ((MAXEXTLEN / rtextsize) / NBBY) bytes
+ *    the realtime summary: 2 exts * 1 block
+ *    worst case split in allocation btrees per extent assuming 2 extents:
+ *             2 exts * 2 trees * (2 * max depth - 1) * block size
  */
 STATIC uint
 xfs_calc_itruncate_reservation(
        struct xfs_mount        *mp)
 {
-       return XFS_DQUOT_LOGRES(mp) +
-               max((xfs_calc_inode_res(mp, 1) +
-                    xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1,
-                                     XFS_FSB_TO_B(mp, 1))),
-                   (xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
-                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4),
-                                     XFS_FSB_TO_B(mp, 1))));
+       unsigned int            t1, t2, t3;
+       unsigned int            blksz = XFS_FSB_TO_B(mp, 1);
+
+       t1 = xfs_calc_inode_res(mp, 1) +
+            xfs_calc_buf_res(XFS_BM_MAXLEVELS(mp, XFS_DATA_FORK) + 1, blksz);
+
+       t2 = xfs_calc_buf_res(9, mp->m_sb.sb_sectsize) +
+            xfs_calc_buf_res(xfs_allocfree_log_count(mp, 4), blksz);
+
+       if (xfs_sb_version_hasrealtime(&mp->m_sb)) {
+               t3 = xfs_calc_buf_res(5, mp->m_sb.sb_sectsize) +
+                    xfs_calc_buf_res(xfs_rtalloc_log_count(mp, 2), blksz) +
+                    xfs_calc_buf_res(xfs_allocfree_log_count(mp, 2), blksz);
+       } else {
+               t3 = 0;
+       }
+
+       return XFS_DQUOT_LOGRES(mp) + max3(t1, t2, t3);
 }
 
 /*
index 2efd78a..e62fb52 100644 (file)
@@ -992,6 +992,7 @@ xfs_prepare_shift(
        struct xfs_inode        *ip,
        loff_t                  offset)
 {
+       struct xfs_mount        *mp = ip->i_mount;
        int                     error;
 
        /*
@@ -1005,6 +1006,17 @@ xfs_prepare_shift(
        }
 
        /*
+        * Shift operations must stabilize the start block offset boundary along
+        * with the full range of the operation. If we don't, a COW writeback
+        * completion could race with an insert, front merge with the start
+        * extent (after split) during the shift and corrupt the file. Start
+        * with the block just prior to the start to stabilize the boundary.
+        */
+       offset = round_down(offset, 1 << mp->m_sb.sb_blocklog);
+       if (offset)
+               offset -= (1 << mp->m_sb.sb_blocklog);
+
+       /*
         * Writeback and invalidate cache for the remainder of the file as we're
         * about to shift down every extent from offset to EOF.
         */
index 3458a12..3984779 100644 (file)
@@ -956,7 +956,7 @@ xfs_buf_item_relse(
        struct xfs_buf_log_item *bip = bp->b_log_item;
 
        trace_xfs_buf_item_relse(bp, _RET_IP_);
-       ASSERT(!(bip->bli_item.li_flags & XFS_LI_IN_AIL));
+       ASSERT(!test_bit(XFS_LI_IN_AIL, &bip->bli_item.li_flags));
 
        bp->b_log_item = NULL;
        if (list_empty(&bp->b_li_list))
index fca6510..56efe14 100644 (file)
@@ -31,7 +31,7 @@
 #include "xfs_reflink.h"
 #include "xfs_extent_busy.h"
 #include "xfs_health.h"
-
+#include "xfs_trace.h"
 
 static DEFINE_MUTEX(xfs_uuid_table_mutex);
 static int xfs_uuid_table_size;
@@ -360,66 +360,119 @@ release_buf:
 }
 
 /*
- * Update alignment values based on mount options and sb values
+ * If the sunit/swidth change would move the precomputed root inode value, we
+ * must reject the ondisk change because repair will stumble over that.
+ * However, we allow the mount to proceed because we never rejected this
+ * combination before.  Returns true to update the sb, false otherwise.
+ */
+static inline int
+xfs_check_new_dalign(
+       struct xfs_mount        *mp,
+       int                     new_dalign,
+       bool                    *update_sb)
+{
+       struct xfs_sb           *sbp = &mp->m_sb;
+       xfs_ino_t               calc_ino;
+
+       calc_ino = xfs_ialloc_calc_rootino(mp, new_dalign);
+       trace_xfs_check_new_dalign(mp, new_dalign, calc_ino);
+
+       if (sbp->sb_rootino == calc_ino) {
+               *update_sb = true;
+               return 0;
+       }
+
+       xfs_warn(mp,
+"Cannot change stripe alignment; would require moving root inode.");
+
+       /*
+        * XXX: Next time we add a new incompat feature, this should start
+        * returning -EINVAL to fail the mount.  Until then, spit out a warning
+        * that we're ignoring the administrator's instructions.
+        */
+       xfs_warn(mp, "Skipping superblock stripe alignment update.");
+       *update_sb = false;
+       return 0;
+}
+
+/*
+ * If we were provided with new sunit/swidth values as mount options, make sure
+ * that they pass basic alignment and superblock feature checks, and convert
+ * them into the same units (FSB) that everything else expects.  This step
+ * /must/ be done before computing the inode geometry.
  */
 STATIC int
-xfs_update_alignment(xfs_mount_t *mp)
+xfs_validate_new_dalign(
+       struct xfs_mount        *mp)
 {
-       xfs_sb_t        *sbp = &(mp->m_sb);
+       if (mp->m_dalign == 0)
+               return 0;
 
-       if (mp->m_dalign) {
+       /*
+        * If stripe unit and stripe width are not multiples
+        * of the fs blocksize turn off alignment.
+        */
+       if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
+           (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
+               xfs_warn(mp,
+       "alignment check failed: sunit/swidth vs. blocksize(%d)",
+                       mp->m_sb.sb_blocksize);
+               return -EINVAL;
+       } else {
                /*
-                * If stripe unit and stripe width are not multiples
-                * of the fs blocksize turn off alignment.
+                * Convert the stripe unit and width to FSBs.
                 */
-               if ((BBTOB(mp->m_dalign) & mp->m_blockmask) ||
-                   (BBTOB(mp->m_swidth) & mp->m_blockmask)) {
+               mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
+               if (mp->m_dalign && (mp->m_sb.sb_agblocks % mp->m_dalign)) {
                        xfs_warn(mp,
-               "alignment check failed: sunit/swidth vs. blocksize(%d)",
-                               sbp->sb_blocksize);
+               "alignment check failed: sunit/swidth vs. agsize(%d)",
+                                mp->m_sb.sb_agblocks);
                        return -EINVAL;
-               } else {
-                       /*
-                        * Convert the stripe unit and width to FSBs.
-                        */
-                       mp->m_dalign = XFS_BB_TO_FSBT(mp, mp->m_dalign);
-                       if (mp->m_dalign && (sbp->sb_agblocks % mp->m_dalign)) {
-                               xfs_warn(mp,
-                       "alignment check failed: sunit/swidth vs. agsize(%d)",
-                                        sbp->sb_agblocks);
-                               return -EINVAL;
-                       } else if (mp->m_dalign) {
-                               mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
-                       } else {
-                               xfs_warn(mp,
-                       "alignment check failed: sunit(%d) less than bsize(%d)",
-                                        mp->m_dalign, sbp->sb_blocksize);
-                               return -EINVAL;
-                       }
-               }
-
-               /*
-                * Update superblock with new values
-                * and log changes
-                */
-               if (xfs_sb_version_hasdalign(sbp)) {
-                       if (sbp->sb_unit != mp->m_dalign) {
-                               sbp->sb_unit = mp->m_dalign;
-                               mp->m_update_sb = true;
-                       }
-                       if (sbp->sb_width != mp->m_swidth) {
-                               sbp->sb_width = mp->m_swidth;
-                               mp->m_update_sb = true;
-                       }
+               } else if (mp->m_dalign) {
+                       mp->m_swidth = XFS_BB_TO_FSBT(mp, mp->m_swidth);
                } else {
                        xfs_warn(mp,
-       "cannot change alignment: superblock does not support data alignment");
+               "alignment check failed: sunit(%d) less than bsize(%d)",
+                                mp->m_dalign, mp->m_sb.sb_blocksize);
                        return -EINVAL;
                }
+       }
+
+       if (!xfs_sb_version_hasdalign(&mp->m_sb)) {
+               xfs_warn(mp,
+"cannot change alignment: superblock does not support data alignment");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/* Update alignment values based on mount options and sb values. */
+STATIC int
+xfs_update_alignment(
+       struct xfs_mount        *mp)
+{
+       struct xfs_sb           *sbp = &mp->m_sb;
+
+       if (mp->m_dalign) {
+               bool            update_sb;
+               int             error;
+
+               if (sbp->sb_unit == mp->m_dalign &&
+                   sbp->sb_width == mp->m_swidth)
+                       return 0;
+
+               error = xfs_check_new_dalign(mp, mp->m_dalign, &update_sb);
+               if (error || !update_sb)
+                       return error;
+
+               sbp->sb_unit = mp->m_dalign;
+               sbp->sb_width = mp->m_swidth;
+               mp->m_update_sb = true;
        } else if ((mp->m_flags & XFS_MOUNT_NOALIGN) != XFS_MOUNT_NOALIGN &&
                    xfs_sb_version_hasdalign(&mp->m_sb)) {
-                       mp->m_dalign = sbp->sb_unit;
-                       mp->m_swidth = sbp->sb_width;
+               mp->m_dalign = sbp->sb_unit;
+               mp->m_swidth = sbp->sb_width;
        }
 
        return 0;
@@ -648,12 +701,12 @@ xfs_mountfs(
        }
 
        /*
-        * Check if sb_agblocks is aligned at stripe boundary
-        * If sb_agblocks is NOT aligned turn off m_dalign since
-        * allocator alignment is within an ag, therefore ag has
-        * to be aligned at stripe boundary.
+        * If we were given new sunit/swidth options, do some basic validation
+        * checks and convert the incore dalign and swidth values to the
+        * same units (FSB) that everything else uses.  This /must/ happen
+        * before computing the inode geometry.
         */
-       error = xfs_update_alignment(mp);
+       error = xfs_validate_new_dalign(mp);
        if (error)
                goto out;
 
@@ -664,6 +717,17 @@ xfs_mountfs(
        xfs_rmapbt_compute_maxlevels(mp);
        xfs_refcountbt_compute_maxlevels(mp);
 
+       /*
+        * Check if sb_agblocks is aligned at stripe boundary.  If sb_agblocks
+        * is NOT aligned turn off m_dalign since allocator alignment is within
+        * an ag, therefore ag has to be aligned at stripe boundary.  Note that
+        * we must compute the free space and rmap btree geometry before doing
+        * this.
+        */
+       error = xfs_update_alignment(mp);
+       if (error)
+               goto out;
+
        /* enable fail_at_unmount as default */
        mp->m_fail_unmount = true;
 
index c13bb36..a86be7f 100644 (file)
@@ -3573,6 +3573,27 @@ DEFINE_KMEM_EVENT(kmem_alloc_large);
 DEFINE_KMEM_EVENT(kmem_realloc);
 DEFINE_KMEM_EVENT(kmem_zone_alloc);
 
+TRACE_EVENT(xfs_check_new_dalign,
+       TP_PROTO(struct xfs_mount *mp, int new_dalign, xfs_ino_t calc_rootino),
+       TP_ARGS(mp, new_dalign, calc_rootino),
+       TP_STRUCT__entry(
+               __field(dev_t, dev)
+               __field(int, new_dalign)
+               __field(xfs_ino_t, sb_rootino)
+               __field(xfs_ino_t, calc_rootino)
+       ),
+       TP_fast_assign(
+               __entry->dev = mp->m_super->s_dev;
+               __entry->new_dalign = new_dalign;
+               __entry->sb_rootino = mp->m_sb.sb_rootino;
+               __entry->calc_rootino = calc_rootino;
+       ),
+       TP_printk("dev %d:%d new_dalign %d sb_rootino %llu calc_rootino %llu",
+                 MAJOR(__entry->dev), MINOR(__entry->dev),
+                 __entry->new_dalign, __entry->sb_rootino,
+                 __entry->calc_rootino)
+)
+
 #endif /* _TRACE_XFS_H */
 
 #undef TRACE_INCLUDE_PATH
index a950a22..cac7404 100644 (file)
  * The cache doesn't need to be flushed when TLB entries change when
  * the cache is mapped to physical memory, not virtual memory
  */
+#ifndef flush_cache_all
 static inline void flush_cache_all(void)
 {
 }
+#endif
 
+#ifndef flush_cache_mm
 static inline void flush_cache_mm(struct mm_struct *mm)
 {
 }
+#endif
 
+#ifndef flush_cache_dup_mm
 static inline void flush_cache_dup_mm(struct mm_struct *mm)
 {
 }
+#endif
 
+#ifndef flush_cache_range
 static inline void flush_cache_range(struct vm_area_struct *vma,
                                     unsigned long start,
                                     unsigned long end)
 {
 }
+#endif
 
+#ifndef flush_cache_page
 static inline void flush_cache_page(struct vm_area_struct *vma,
                                    unsigned long vmaddr,
                                    unsigned long pfn)
 {
 }
+#endif
 
+#ifndef flush_dcache_page
 static inline void flush_dcache_page(struct page *page)
 {
 }
+#endif
 
+#ifndef flush_dcache_mmap_lock
 static inline void flush_dcache_mmap_lock(struct address_space *mapping)
 {
 }
+#endif
 
+#ifndef flush_dcache_mmap_unlock
 static inline void flush_dcache_mmap_unlock(struct address_space *mapping)
 {
 }
+#endif
 
+#ifndef flush_icache_range
 static inline void flush_icache_range(unsigned long start, unsigned long end)
 {
 }
+#endif
 
+#ifndef flush_icache_page
 static inline void flush_icache_page(struct vm_area_struct *vma,
                                     struct page *page)
 {
 }
+#endif
 
+#ifndef flush_icache_user_range
 static inline void flush_icache_user_range(struct vm_area_struct *vma,
                                           struct page *page,
                                           unsigned long addr, int len)
 {
 }
+#endif
 
+#ifndef flush_cache_vmap
 static inline void flush_cache_vmap(unsigned long start, unsigned long end)
 {
 }
+#endif
 
+#ifndef flush_cache_vunmap
 static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
 {
 }
+#endif
 
-#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
+#ifndef copy_to_user_page
+#define copy_to_user_page(vma, page, vaddr, dst, src, len)     \
        do { \
                memcpy(dst, src, len); \
                flush_icache_user_range(vma, page, vaddr, len); \
        } while (0)
+#endif
+
+#ifndef copy_from_user_page
 #define copy_from_user_page(vma, page, vaddr, dst, src, len) \
        memcpy(dst, src, len)
+#endif
 
 #endif /* __ASM_CACHEFLUSH_H */
index d5fc90b..c1bda70 100644 (file)
@@ -605,6 +605,12 @@ struct drm_dp_mst_topology_mgr {
         * &drm_dp_sideband_msg_tx.state once they are queued
         */
        struct mutex qlock;
+
+       /**
+        * @is_waiting_for_dwn_reply: indicate whether is waiting for down reply
+        */
+       bool is_waiting_for_dwn_reply;
+
        /**
         * @tx_msg_downq: List of pending down replies.
         */
index c614438..fbc524a 100644 (file)
@@ -46,9 +46,9 @@
 #define RESET_VD_RMEM                  64
 #define RESET_AUDIN                    65
 #define RESET_DBLK                     66
-#define RESET_PIC_DC                   66
-#define RESET_PSC                      66
-#define RESET_NAND                     66
+#define RESET_PIC_DC                   67
+#define RESET_PSC                      68
+#define RESET_NAND                     69
 #define RESET_GE2D                     70
 #define RESET_PARSER_REG               71
 #define RESET_PARSER_FETCH             72
index 6782f0d..49e5383 100644 (file)
@@ -19,6 +19,8 @@ struct ahci_host_priv;
 struct platform_device;
 struct scsi_host_template;
 
+int ahci_platform_enable_phys(struct ahci_host_priv *hpriv);
+void ahci_platform_disable_phys(struct ahci_host_priv *hpriv);
 int ahci_platform_enable_clks(struct ahci_host_priv *hpriv);
 void ahci_platform_disable_clks(struct ahci_host_priv *hpriv);
 int ahci_platform_enable_regulators(struct ahci_host_priv *hpriv);
index 3cdb84c..853d92c 100644 (file)
@@ -470,6 +470,7 @@ extern struct bio *bio_copy_user_iov(struct request_queue *,
                                     gfp_t);
 extern int bio_uncopy_user(struct bio *);
 void zero_fill_bio_iter(struct bio *bio, struct bvec_iter iter);
+void bio_truncate(struct bio *bio, unsigned new_size);
 
 static inline void zero_fill_bio(struct bio *bio)
 {
index 19394c7..e4a6949 100644 (file)
@@ -188,7 +188,6 @@ struct blkcg_gq *__blkg_lookup_create(struct blkcg *blkcg,
 struct blkcg_gq *blkg_lookup_create(struct blkcg *blkcg,
                                    struct request_queue *q);
 int blkcg_init_queue(struct request_queue *q);
-void blkcg_drain_queue(struct request_queue *q);
 void blkcg_exit_queue(struct request_queue *q);
 
 /* Blkio controller policy registration */
@@ -720,7 +719,6 @@ static inline struct blkcg_gq *blkg_lookup(struct blkcg *blkcg, void *key) { ret
 static inline struct blkcg_gq *blk_queue_root_blkg(struct request_queue *q)
 { return NULL; }
 static inline int blkcg_init_queue(struct request_queue *q) { return 0; }
-static inline void blkcg_drain_queue(struct request_queue *q) { }
 static inline void blkcg_exit_queue(struct request_queue *q) { }
 static inline int blkcg_policy_register(struct blkcg_policy *pol) { return 0; }
 static inline void blkcg_policy_unregister(struct blkcg_policy *pol) { }
index 47eb22a..4c636c4 100644 (file)
@@ -328,6 +328,7 @@ struct queue_limits {
        unsigned int            max_sectors;
        unsigned int            max_segment_size;
        unsigned int            physical_block_size;
+       unsigned int            logical_block_size;
        unsigned int            alignment_offset;
        unsigned int            io_min;
        unsigned int            io_opt;
@@ -338,7 +339,6 @@ struct queue_limits {
        unsigned int            discard_granularity;
        unsigned int            discard_alignment;
 
-       unsigned short          logical_block_size;
        unsigned short          max_segments;
        unsigned short          max_integrity_segments;
        unsigned short          max_discard_segments;
@@ -1077,7 +1077,7 @@ extern void blk_queue_max_write_same_sectors(struct request_queue *q,
                unsigned int max_write_same_sectors);
 extern void blk_queue_max_write_zeroes_sectors(struct request_queue *q,
                unsigned int max_write_same_sectors);
-extern void blk_queue_logical_block_size(struct request_queue *, unsigned short);
+extern void blk_queue_logical_block_size(struct request_queue *, unsigned int);
 extern void blk_queue_physical_block_size(struct request_queue *, unsigned int);
 extern void blk_queue_alignment_offset(struct request_queue *q,
                                       unsigned int alignment);
@@ -1291,7 +1291,7 @@ static inline unsigned int queue_max_segment_size(const struct request_queue *q)
        return q->limits.max_segment_size;
 }
 
-static inline unsigned short queue_logical_block_size(const struct request_queue *q)
+static inline unsigned queue_logical_block_size(const struct request_queue *q)
 {
        int retval = 512;
 
@@ -1301,7 +1301,7 @@ static inline unsigned short queue_logical_block_size(const struct request_queue
        return retval;
 }
 
-static inline unsigned short bdev_logical_block_size(struct block_device *bdev)
+static inline unsigned int bdev_logical_block_size(struct block_device *bdev)
 {
        return queue_logical_block_size(bdev_get_queue(bdev));
 }
index 169fd25..9be71c1 100644 (file)
@@ -157,8 +157,8 @@ void bpf_cgroup_storage_link(struct bpf_cgroup_storage *storage,
                             struct cgroup *cgroup,
                             enum bpf_attach_type type);
 void bpf_cgroup_storage_unlink(struct bpf_cgroup_storage *storage);
-int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *map);
-void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *map);
+int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *map);
+void bpf_cgroup_storage_release(struct bpf_prog_aux *aux, struct bpf_map *map);
 
 int bpf_percpu_cgroup_storage_copy(struct bpf_map *map, void *key, void *value);
 int bpf_percpu_cgroup_storage_update(struct bpf_map *map, void *key,
@@ -360,9 +360,9 @@ static inline int cgroup_bpf_prog_query(const union bpf_attr *attr,
 
 static inline void bpf_cgroup_storage_set(
        struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE]) {}
-static inline int bpf_cgroup_storage_assign(struct bpf_prog *prog,
+static inline int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux,
                                            struct bpf_map *map) { return 0; }
-static inline void bpf_cgroup_storage_release(struct bpf_prog *prog,
+static inline void bpf_cgroup_storage_release(struct bpf_prog_aux *aux,
                                              struct bpf_map *map) {}
 static inline struct bpf_cgroup_storage *bpf_cgroup_storage_alloc(
        struct bpf_prog *prog, enum bpf_cgroup_storage_type stype) { return NULL; }
index 35903f1..085a59a 100644 (file)
@@ -461,6 +461,7 @@ struct bpf_trampoline {
        struct {
                struct btf_func_model model;
                void *addr;
+               bool ftrace_managed;
        } func;
        /* list of BPF programs using this trampoline */
        struct hlist_head progs_hlist[BPF_TRAMP_MAX];
@@ -817,6 +818,8 @@ struct bpf_prog * __must_check bpf_prog_inc_not_zero(struct bpf_prog *prog);
 void bpf_prog_put(struct bpf_prog *prog);
 int __bpf_prog_charge(struct user_struct *user, u32 pages);
 void __bpf_prog_uncharge(struct user_struct *user, u32 pages);
+void __bpf_free_used_maps(struct bpf_prog_aux *aux,
+                         struct bpf_map **used_maps, u32 len);
 
 void bpf_prog_free_id(struct bpf_prog *prog, bool do_idr_lock);
 void bpf_map_free_id(struct bpf_map *map, bool do_idr_lock);
index 679a422..a81c13a 100644 (file)
@@ -153,26 +153,4 @@ static inline void bvec_advance(const struct bio_vec *bvec,
        }
 }
 
-/*
- * Get the last single-page segment from the multi-page bvec and store it
- * in @seg
- */
-static inline void mp_bvec_last_segment(const struct bio_vec *bvec,
-                                       struct bio_vec *seg)
-{
-       unsigned total = bvec->bv_offset + bvec->bv_len;
-       unsigned last_page = (total - 1) / PAGE_SIZE;
-
-       seg->bv_page = bvec->bv_page + last_page;
-
-       /* the whole segment is inside the last page */
-       if (bvec->bv_offset >= last_page * PAGE_SIZE) {
-               seg->bv_offset = bvec->bv_offset % PAGE_SIZE;
-               seg->bv_len = bvec->bv_len;
-       } else {
-               seg->bv_offset = 0;
-               seg->bv_len = total - last_page * PAGE_SIZE;
-       }
-}
-
 #endif /* __LINUX_BVEC_ITER_H */
index 9b3c720..5e3d455 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/can/error.h>
 #include <linux/can/led.h>
 #include <linux/can/netlink.h>
+#include <linux/can/skb.h>
 #include <linux/netdevice.h>
 
 /*
@@ -91,6 +92,36 @@ struct can_priv {
 #define get_can_dlc(i)         (min_t(__u8, (i), CAN_MAX_DLC))
 #define get_canfd_dlc(i)       (min_t(__u8, (i), CANFD_MAX_DLC))
 
+/* Check for outgoing skbs that have not been created by the CAN subsystem */
+static inline bool can_skb_headroom_valid(struct net_device *dev,
+                                         struct sk_buff *skb)
+{
+       /* af_packet creates a headroom of HH_DATA_MOD bytes which is fine */
+       if (WARN_ON_ONCE(skb_headroom(skb) < sizeof(struct can_skb_priv)))
+               return false;
+
+       /* af_packet does not apply CAN skb specific settings */
+       if (skb->ip_summed == CHECKSUM_NONE) {
+               /* init headroom */
+               can_skb_prv(skb)->ifindex = dev->ifindex;
+               can_skb_prv(skb)->skbcnt = 0;
+
+               skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+               /* preform proper loopback on capable devices */
+               if (dev->flags & IFF_ECHO)
+                       skb->pkt_type = PACKET_LOOPBACK;
+               else
+                       skb->pkt_type = PACKET_HOST;
+
+               skb_reset_mac_header(skb);
+               skb_reset_network_header(skb);
+               skb_reset_transport_header(skb);
+       }
+
+       return true;
+}
+
 /* Drop a given socketbuffer if it does not contain a valid CAN frame. */
 static inline bool can_dropped_invalid_skb(struct net_device *dev,
                                          struct sk_buff *skb)
@@ -108,6 +139,9 @@ static inline bool can_dropped_invalid_skb(struct net_device *dev,
        } else
                goto inval_skb;
 
+       if (!can_skb_headroom_valid(dev, skb))
+               goto inval_skb;
+
        return false;
 
 inval_skb:
index 92d5fdc..31b1b0e 100644 (file)
@@ -595,17 +595,6 @@ struct governor_attr {
                         size_t count);
 };
 
-static inline bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
-{
-       /*
-        * Allow remote callbacks if:
-        * - dvfs_possible_from_any_cpu flag is set
-        * - the local and remote CPUs share cpufreq policy
-        */
-       return policy->dvfs_possible_from_any_cpu ||
-               cpumask_test_cpu(smp_processor_id(), policy->cpus);
-}
-
 /*********************************************************************
  *                     FREQUENCY TABLE HELPERS                       *
  *********************************************************************/
index 2bae9ed..fb376b5 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/device.h>
 #include <linux/notifier.h>
 #include <linux/pm_opp.h>
+#include <linux/pm_qos.h>
 
 #define DEVFREQ_NAME_LEN 16
 
@@ -123,8 +124,8 @@ struct devfreq_dev_profile {
  * @previous_freq:     previously configured frequency value.
  * @data:      Private data of the governor. The devfreq framework does not
  *             touch this.
- * @min_freq:  Limit minimum frequency requested by user (0: none)
- * @max_freq:  Limit maximum frequency requested by user (0: none)
+ * @user_min_freq_req: PM QoS minimum frequency request from user (via sysfs)
+ * @user_max_freq_req: PM QoS maximum frequency request from user (via sysfs)
  * @scaling_min_freq:  Limit minimum frequency requested by OPP interface
  * @scaling_max_freq:  Limit maximum frequency requested by OPP interface
  * @stop_polling:       devfreq polling status of a device.
@@ -136,6 +137,8 @@ struct devfreq_dev_profile {
  * @time_in_state:     Statistics of devfreq states
  * @last_stat_updated: The last time stat updated
  * @transition_notifier_list: list head of DEVFREQ_TRANSITION_NOTIFIER notifier
+ * @nb_min:            Notifier block for DEV_PM_QOS_MIN_FREQUENCY
+ * @nb_max:            Notifier block for DEV_PM_QOS_MAX_FREQUENCY
  *
  * This structure stores the devfreq information for a give device.
  *
@@ -161,8 +164,8 @@ struct devfreq {
 
        void *data; /* private data for governors */
 
-       unsigned long min_freq;
-       unsigned long max_freq;
+       struct dev_pm_qos_request user_min_freq_req;
+       struct dev_pm_qos_request user_max_freq_req;
        unsigned long scaling_min_freq;
        unsigned long scaling_max_freq;
        bool stop_polling;
@@ -178,6 +181,9 @@ struct devfreq {
        unsigned long last_stat_updated;
 
        struct srcu_notifier_head transition_notifier_list;
+
+       struct notifier_block nb_min;
+       struct notifier_block nb_max;
 };
 
 struct devfreq_freqs {
index e226030..96ff767 100644 (file)
@@ -1666,11 +1666,11 @@ extern bool kill_device(struct device *dev);
 #ifdef CONFIG_DEVTMPFS
 extern int devtmpfs_create_node(struct device *dev);
 extern int devtmpfs_delete_node(struct device *dev);
-extern int devtmpfs_mount(const char *mntdir);
+extern int devtmpfs_mount(void);
 #else
 static inline int devtmpfs_create_node(struct device *dev) { return 0; }
 static inline int devtmpfs_delete_node(struct device *dev) { return 0; }
-static inline int devtmpfs_mount(const char *mountpoint) { return 0; }
+static inline int devtmpfs_mount(void) { return 0; }
 #endif
 
 /* drivers/base/power/shutdown.c */
index 8fcdee1..dad4a68 100644 (file)
@@ -1364,8 +1364,11 @@ static inline int dma_get_slave_caps(struct dma_chan *chan,
 static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx)
 {
        struct dma_slave_caps caps;
+       int ret;
 
-       dma_get_slave_caps(tx->chan, &caps);
+       ret = dma_get_slave_caps(tx->chan, &caps);
+       if (ret)
+               return ret;
 
        if (caps.descriptor_reuse) {
                tx->flags |= DMA_CTRL_REUSE;
index 99dfea5..aa54586 100644 (file)
@@ -824,7 +824,7 @@ typedef struct {
        __aligned_u64 image_size;
        unsigned int image_code_type;
        unsigned int image_data_type;
-       unsigned long unload;
+       u32 unload;
 } efi_loaded_image_32_t;
 
 typedef struct {
@@ -840,14 +840,14 @@ typedef struct {
        __aligned_u64 image_size;
        unsigned int image_code_type;
        unsigned int image_data_type;
-       unsigned long unload;
+       u64 unload;
 } efi_loaded_image_64_t;
 
 typedef struct {
        u32 revision;
-       void *parent_handle;
+       efi_handle_t parent_handle;
        efi_system_table_t *system_table;
-       void *device_handle;
+       efi_handle_t device_handle;
        void *file_path;
        void *reserved;
        u32 load_options_size;
@@ -856,7 +856,7 @@ typedef struct {
        __aligned_u64 image_size;
        unsigned int image_code_type;
        unsigned int image_data_type;
-       unsigned long unload;
+       efi_status_t (*unload)(efi_handle_t image_handle);
 } efi_loaded_image_t;
 
 
index a141cb0..345f374 100644 (file)
@@ -420,7 +420,7 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
 
 #define BPF_FIELD_SIZEOF(type, field)                          \
        ({                                                      \
-               const int __size = bytes_to_bpf_size(FIELD_SIZEOF(type, field)); \
+               const int __size = bytes_to_bpf_size(sizeof_field(type, field)); \
                BUILD_BUG_ON(__size < 0);                       \
                __size;                                         \
        })
@@ -497,7 +497,7 @@ static inline bool insn_is_zext(const struct bpf_insn *insn)
 
 #define bpf_target_off(TYPE, MEMBER, SIZE, PTR_SIZE)                           \
        ({                                                                      \
-               BUILD_BUG_ON(FIELD_SIZEOF(TYPE, MEMBER) != (SIZE));             \
+               BUILD_BUG_ON(sizeof_field(TYPE, MEMBER) != (SIZE));             \
                *(PTR_SIZE) = (SIZE);                                           \
                offsetof(TYPE, MEMBER);                                         \
        })
@@ -608,7 +608,7 @@ static inline void bpf_compute_data_pointers(struct sk_buff *skb)
 {
        struct bpf_skb_data_end *cb = (struct bpf_skb_data_end *)skb->cb;
 
-       BUILD_BUG_ON(sizeof(*cb) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(*cb) > sizeof_field(struct sk_buff, cb));
        cb->data_meta = skb->data - skb_metadata_len(skb);
        cb->data_end  = skb->data + skb_headlen(skb);
 }
@@ -646,9 +646,9 @@ static inline u8 *bpf_skb_cb(struct sk_buff *skb)
         * attached to sockets, we need to clear the bpf_skb_cb() area
         * to not leak previous contents to user space.
         */
-       BUILD_BUG_ON(FIELD_SIZEOF(struct __sk_buff, cb) != BPF_SKB_CB_LEN);
-       BUILD_BUG_ON(FIELD_SIZEOF(struct __sk_buff, cb) !=
-                    FIELD_SIZEOF(struct qdisc_skb_cb, data));
+       BUILD_BUG_ON(sizeof_field(struct __sk_buff, cb) != BPF_SKB_CB_LEN);
+       BUILD_BUG_ON(sizeof_field(struct __sk_buff, cb) !=
+                    sizeof_field(struct qdisc_skb_cb, data));
 
        return qdisc_skb_cb(skb)->data;
 }
index 7247d35..db95244 100644 (file)
@@ -264,6 +264,7 @@ int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
                                struct dyn_ftrace *rec,
                                unsigned long old_addr,
                                unsigned long new_addr);
+unsigned long ftrace_find_rec_direct(unsigned long ip);
 #else
 # define ftrace_direct_func_count 0
 static inline int register_ftrace_direct(unsigned long ip, unsigned long addr)
@@ -290,6 +291,10 @@ static inline int ftrace_modify_direct_caller(struct ftrace_func_entry *entry,
 {
        return -ENODEV;
 }
+static inline unsigned long ftrace_find_rec_direct(unsigned long ip)
+{
+       return 0;
+}
 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
 
 #ifndef CONFIG_HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
index d2f7867..582ef05 100644 (file)
@@ -300,6 +300,7 @@ struct i2c_driver {
  *     generic enough to hide second-sourcing and compatible revisions.
  * @adapter: manages the bus segment hosting this I2C device
  * @dev: Driver model device node for the slave.
+ * @init_irq: IRQ that was set at initialization
  * @irq: indicates the IRQ generated by this device (if any)
  * @detected: member of an i2c_driver.clients list or i2c-core's
  *     userspace_devices list
@@ -466,12 +467,6 @@ i2c_new_probed_device(struct i2c_adapter *adap,
 /* Common custom probe functions */
 extern int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr);
 
-/* For devices that use several addresses, use i2c_new_dummy() to make
- * client handles for the extra addresses.
- */
-extern struct i2c_client *
-i2c_new_dummy(struct i2c_adapter *adap, u16 address);
-
 extern struct i2c_client *
 i2c_new_dummy_device(struct i2c_adapter *adapter, u16 address);
 
@@ -856,6 +851,11 @@ extern void i2c_del_driver(struct i2c_driver *driver);
 #define i2c_add_driver(driver) \
        i2c_register_driver(THIS_MODULE, driver)
 
+static inline bool i2c_client_has_driver(struct i2c_client *client)
+{
+       return !IS_ERR_OR_NULL(client) && client->dev.driver;
+}
+
 /* call the i2c_client->command() of all attached clients with
  * the given arguments */
 extern void i2c_clients_command(struct i2c_adapter *adap,
index 76cf11e..8a9792a 100644 (file)
@@ -24,6 +24,14 @@ static inline struct ethhdr *eth_hdr(const struct sk_buff *skb)
        return (struct ethhdr *)skb_mac_header(skb);
 }
 
+/* Prefer this version in TX path, instead of
+ * skb_reset_mac_header() + eth_hdr()
+ */
+static inline struct ethhdr *skb_eth_hdr(const struct sk_buff *skb)
+{
+       return (struct ethhdr *)skb->data;
+}
+
 static inline struct ethhdr *inner_eth_hdr(const struct sk_buff *skb)
 {
        return (struct ethhdr *)skb_inner_mac_header(skb);
index d77fe34..aa59143 100644 (file)
@@ -28,3 +28,5 @@ extern unsigned int real_root_dev;
 
 extern char __initramfs_start[];
 extern unsigned long __initramfs_size;
+
+void console_on_rootfs(void);
index 29dce6f..ce44b68 100644 (file)
@@ -457,7 +457,7 @@ struct jbd2_revoke_table_s;
  * @h_journal: Which journal handle belongs to - used iff h_reserved set.
  * @h_rsv_handle: Handle reserved for finishing the logical operation.
  * @h_total_credits: Number of remaining buffers we are allowed to add to
      journal. These are dirty buffers and revoke descriptor blocks.
*     journal. These are dirty buffers and revoke descriptor blocks.
  * @h_revoke_credits: Number of remaining revoke records available for handle
  * @h_ref: Reference count on this handle.
  * @h_err: Field for caller's use to track errors through large fs operations.
index 4f404c5..e18fe54 100644 (file)
@@ -205,20 +205,23 @@ static inline void *kasan_reset_tag(const void *addr)
 #endif /* CONFIG_KASAN_SW_TAGS */
 
 #ifdef CONFIG_KASAN_VMALLOC
-int kasan_populate_vmalloc(unsigned long requested_size,
-                          struct vm_struct *area);
-void kasan_poison_vmalloc(void *start, unsigned long size);
+int kasan_populate_vmalloc(unsigned long addr, unsigned long size);
+void kasan_poison_vmalloc(const void *start, unsigned long size);
+void kasan_unpoison_vmalloc(const void *start, unsigned long size);
 void kasan_release_vmalloc(unsigned long start, unsigned long end,
                           unsigned long free_region_start,
                           unsigned long free_region_end);
 #else
-static inline int kasan_populate_vmalloc(unsigned long requested_size,
-                                        struct vm_struct *area)
+static inline int kasan_populate_vmalloc(unsigned long start,
+                                       unsigned long size)
 {
        return 0;
 }
 
-static inline void kasan_poison_vmalloc(void *start, unsigned long size) {}
+static inline void kasan_poison_vmalloc(const void *start, unsigned long size)
+{ }
+static inline void kasan_unpoison_vmalloc(const void *start, unsigned long size)
+{ }
 static inline void kasan_release_vmalloc(unsigned long start,
                                         unsigned long end,
                                         unsigned long free_region_start,
index 3adcb39..0d9db2a 100644 (file)
  */
 #define round_down(x, y) ((x) & ~__round_mask(x, y))
 
-/**
- * FIELD_SIZEOF - get the size of a struct's field
- * @t: the target struct
- * @f: the target struct's field
- * Return: the size of @f in the struct definition without having a
- * declared instance of @t.
- */
-#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
-
 #define typeof_member(T, m)    typeof(((T*)0)->m)
 
 #define DIV_ROUND_UP __KERNEL_DIV_ROUND_UP
index 7ed1e2f..538c25e 100644 (file)
@@ -149,7 +149,7 @@ static inline bool is_error_page(struct page *page)
 #define KVM_REQUEST_ARCH_BASE     8
 
 #define KVM_ARCH_REQ_FLAGS(nr, flags) ({ \
-       BUILD_BUG_ON((unsigned)(nr) >= (FIELD_SIZEOF(struct kvm_vcpu, requests) * 8) - KVM_REQUEST_ARCH_BASE); \
+       BUILD_BUG_ON((unsigned)(nr) >= (sizeof_field(struct kvm_vcpu, requests) * 8) - KVM_REQUEST_ARCH_BASE); \
        (unsigned)(((nr) + KVM_REQUEST_ARCH_BASE) | (flags)); \
 })
 #define KVM_ARCH_REQ(nr)           KVM_ARCH_REQ_FLAGS(nr, 0)
index d3bbfdd..2dbde11 100644 (file)
@@ -1175,6 +1175,7 @@ extern unsigned int ata_do_dev_read_id(struct ata_device *dev,
                                        struct ata_taskfile *tf, u16 *id);
 extern void ata_qc_complete(struct ata_queued_cmd *qc);
 extern int ata_qc_complete_multiple(struct ata_port *ap, u64 qc_active);
+extern u64 ata_qc_get_active(struct ata_port *ap);
 extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd);
 extern int ata_std_bios_param(struct scsi_device *sdev,
                              struct block_device *bdev,
index 3a08ecd..ba0dca6 100644 (file)
@@ -122,8 +122,8 @@ static inline bool movable_node_is_enabled(void)
 
 extern void arch_remove_memory(int nid, u64 start, u64 size,
                               struct vmem_altmap *altmap);
-extern void __remove_pages(struct zone *zone, unsigned long start_pfn,
-                          unsigned long nr_pages, struct vmem_altmap *altmap);
+extern void __remove_pages(unsigned long start_pfn, unsigned long nr_pages,
+                          struct vmem_altmap *altmap);
 
 /* reasonably generic interface to expand the physical pages */
 extern int __add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
@@ -342,6 +342,9 @@ extern int add_memory(int nid, u64 start, u64 size);
 extern int add_memory_resource(int nid, struct resource *resource);
 extern void move_pfn_range_to_zone(struct zone *zone, unsigned long start_pfn,
                unsigned long nr_pages, struct vmem_altmap *altmap);
+extern void remove_pfn_range_from_zone(struct zone *zone,
+                                      unsigned long start_pfn,
+                                      unsigned long nr_pages);
 extern bool is_memblock_offlined(struct memory_block *mem);
 extern int sparse_add_section(int nid, unsigned long pfn,
                unsigned long nr_pages, struct vmem_altmap *altmap);
index f84b916..7dfb63b 100644 (file)
 
 #define RTC_AL_SEC             0x0018
 
+#define RTC_AL_SEC_MASK        0x003f
+#define RTC_AL_MIN_MASK        0x003f
+#define RTC_AL_HOU_MASK        0x001f
+#define RTC_AL_DOM_MASK        0x001f
+#define RTC_AL_DOW_MASK        0x0007
+#define RTC_AL_MTH_MASK        0x000f
+#define RTC_AL_YEA_MASK        0x007f
+
 #define RTC_PDN2               0x002e
 #define RTC_PDN2_PWRON_ALARM   BIT(4)
 
index c97ea3b..cfaa8fe 100644 (file)
@@ -2621,6 +2621,9 @@ static inline int vm_fault_to_errno(vm_fault_t vm_fault, int foll_flags)
 typedef int (*pte_fn_t)(pte_t *pte, unsigned long addr, void *data);
 extern int apply_to_page_range(struct mm_struct *mm, unsigned long address,
                               unsigned long size, pte_fn_t fn, void *data);
+extern int apply_to_existing_page_range(struct mm_struct *mm,
+                                  unsigned long address, unsigned long size,
+                                  pte_fn_t fn, void *data);
 
 #ifdef CONFIG_PAGE_POISONING
 extern bool page_poisoning_enabled(void);
@@ -2655,14 +2658,26 @@ static inline bool want_init_on_free(void)
               !page_poisoning_enabled();
 }
 
-#ifdef CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT
-DECLARE_STATIC_KEY_TRUE(_debug_pagealloc_enabled);
+#ifdef CONFIG_DEBUG_PAGEALLOC
+extern void init_debug_pagealloc(void);
 #else
-DECLARE_STATIC_KEY_FALSE(_debug_pagealloc_enabled);
+static inline void init_debug_pagealloc(void) {}
 #endif
+extern bool _debug_pagealloc_enabled_early;
+DECLARE_STATIC_KEY_FALSE(_debug_pagealloc_enabled);
 
 static inline bool debug_pagealloc_enabled(void)
 {
+       return IS_ENABLED(CONFIG_DEBUG_PAGEALLOC) &&
+               _debug_pagealloc_enabled_early;
+}
+
+/*
+ * For use in fast paths after init_debug_pagealloc() has run, or when a
+ * false negative result is not harmful when called too early.
+ */
+static inline bool debug_pagealloc_enabled_static(void)
+{
        if (!IS_ENABLED(CONFIG_DEBUG_PAGEALLOC))
                return false;
 
index 89d8ff0..5334ad8 100644 (file)
@@ -215,9 +215,8 @@ enum node_stat_item {
        NR_INACTIVE_FILE,       /*  "     "     "   "       "         */
        NR_ACTIVE_FILE,         /*  "     "     "   "       "         */
        NR_UNEVICTABLE,         /*  "     "     "   "       "         */
-       NR_SLAB_RECLAIMABLE,    /* Please do not reorder this item */
-       NR_SLAB_UNRECLAIMABLE,  /* and this one without looking at
-                                * memcg_flush_percpu_vmstats() first. */
+       NR_SLAB_RECLAIMABLE,
+       NR_SLAB_UNRECLAIMABLE,
        NR_ISOLATED_ANON,       /* Temporary isolated pages from anon lru */
        NR_ISOLATED_FILE,       /* Temporary isolated pages from file lru */
        WORKINGSET_NODES,
index 5714fd3..e3596db 100644 (file)
@@ -587,9 +587,9 @@ struct platform_device_id {
 #define MDIO_NAME_SIZE         32
 #define MDIO_MODULE_PREFIX     "mdio:"
 
-#define MDIO_ID_FMT "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d"
+#define MDIO_ID_FMT "%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u"
 #define MDIO_ID_ARGS(_id) \
-       (_id)>>31, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1,   \
+       ((_id)>>31) & 1, ((_id)>>30) & 1, ((_id)>>29) & 1, ((_id)>>28) & 1, \
        ((_id)>>27) & 1, ((_id)>>26) & 1, ((_id)>>25) & 1, ((_id)>>24) & 1, \
        ((_id)>>23) & 1, ((_id)>>22) & 1, ((_id)>>21) & 1, ((_id)>>20) & 1, \
        ((_id)>>19) & 1, ((_id)>>18) & 1, ((_id)>>17) & 1, ((_id)>>16) & 1, \
index ecc88a4..c04f690 100644 (file)
@@ -40,7 +40,7 @@ typedef enum {
        FL_READING,
        FL_CACHEDPRG,
        /* These 4 come from onenand_state_t, which has been unified here */
-       FL_RESETING,
+       FL_RESETTING,
        FL_OTPING,
        FL_PREPARING_ERASE,
        FL_VERIFYING_ERASE,
index 7fe7b87..07bfb08 100644 (file)
@@ -34,7 +34,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 
 /* internal use only */
 #define LOOKUP_PARENT          0x0010
-#define LOOKUP_NO_REVAL                0x0080
 #define LOOKUP_JUMPED          0x1000
 #define LOOKUP_ROOT            0x2000
 #define LOOKUP_ROOT_GRABBED    0x0008
index 9ef2038..ae5e260 100644 (file)
@@ -1775,7 +1775,7 @@ enum netdev_priv_flags {
  *                     for hardware timestamping
  *     @sfp_bus:       attached &struct sfp_bus structure.
  *     @qdisc_tx_busylock_key: lockdep class annotating Qdisc->busylock
                              spinlock
*                             spinlock
  *     @qdisc_running_key:     lockdep class annotating Qdisc->running seqcount
  *     @qdisc_xmit_lock_key:   lockdep class annotating
  *                             netdev_queue->_xmit_lock spinlock
index 10f8162..6d0d70f 100644 (file)
@@ -270,6 +270,8 @@ struct nvme_fc_remote_port {
  *
  * Host/Initiator Transport Entrypoints/Parameters:
  *
+ * @module:  The LLDD module using the interface
+ *
  * @localport_delete:  The LLDD initiates deletion of a localport via
  *       nvme_fc_deregister_localport(). However, the teardown is
  *       asynchronous. This routine is called upon the completion of the
@@ -383,6 +385,8 @@ struct nvme_fc_remote_port {
  *       Value is Mandatory. Allowed to be zero.
  */
 struct nvme_fc_port_template {
+       struct module   *module;
+
        /* initiator-based functions */
        void    (*localport_delete)(struct nvme_fc_local_port *);
        void    (*remoteport_delete)(struct nvme_fc_remote_port *);
index 99cefe6..491a2b7 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/of.h>
 
 #if IS_ENABLED(CONFIG_OF_MDIO)
+extern bool of_mdiobus_child_is_phy(struct device_node *child);
 extern int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np);
 extern struct phy_device *of_phy_find_device(struct device_node *phy_np);
 extern struct phy_device *of_phy_connect(struct net_device *dev,
@@ -54,6 +55,11 @@ static inline int of_mdio_parse_addr(struct device *dev,
 }
 
 #else /* CONFIG_OF_MDIO */
+static inline bool of_mdiobus_child_is_phy(struct device_node *child)
+{
+       return false;
+}
+
 static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
 {
        /*
index 5032d45..dd4a91f 100644 (file)
@@ -1000,7 +1000,7 @@ int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum,
 int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,
                     u16 mask, u16 set);
 
-struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id,
+struct phy_device *phy_device_create(struct mii_bus *bus, int addr, u32 phy_id,
                                     bool is_c45,
                                     struct phy_c45_device_ids *c45_ids);
 #if IS_ENABLED(CONFIG_PHYLIB)
index 3d507a8..5c4d7a7 100644 (file)
@@ -14,7 +14,7 @@ struct phy_device;
 #define PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE      11
 
 #define PHY_LINK_LED_TRIGGER_NAME_SIZE (MII_BUS_ID_SIZE + \
-                                      FIELD_SIZEOF(struct mdio_device, addr)+\
+                                      sizeof_field(struct mdio_device, addr)+\
                                       PHY_LED_TRIGGER_SPEED_SUFFIX_SIZE)
 
 struct phy_led_trigger {
index 0b93804..8cfe570 100644 (file)
@@ -49,6 +49,7 @@ struct sysc_regbits {
        s8 emufree_shift;
 };
 
+#define SYSC_QUIRK_FORCE_MSTANDBY      BIT(20)
 #define SYSC_MODULE_QUIRK_AESS         BIT(19)
 #define SYSC_MODULE_QUIRK_SGX          BIT(18)
 #define SYSC_MODULE_QUIRK_HDQ1W                BIT(17)
index fe6cfdc..468328b 100644 (file)
@@ -69,29 +69,32 @@ struct posix_clock_operations {
  *
  * @ops:     Functional interface to the clock
  * @cdev:    Character device instance for this clock
- * @kref:    Reference count.
+ * @dev:     Pointer to the clock's device.
  * @rwsem:   Protects the 'zombie' field from concurrent access.
  * @zombie:  If 'zombie' is true, then the hardware has disappeared.
- * @release: A function to free the structure when the reference count reaches
- *           zero. May be NULL if structure is statically allocated.
  *
  * Drivers should embed their struct posix_clock within a private
  * structure, obtaining a reference to it during callbacks using
  * container_of().
+ *
+ * Drivers should supply an initialized but not exposed struct device
+ * to posix_clock_register(). It is used to manage lifetime of the
+ * driver's private structure. It's 'release' field should be set to
+ * a release function for this private structure.
  */
 struct posix_clock {
        struct posix_clock_operations ops;
        struct cdev cdev;
-       struct kref kref;
+       struct device *dev;
        struct rw_semaphore rwsem;
        bool zombie;
-       void (*release)(struct posix_clock *clk);
 };
 
 /**
  * posix_clock_register() - register a new clock
- * @clk:   Pointer to the clock. Caller must provide 'ops' and 'release'
- * @devid: Allocated device id
+ * @clk:   Pointer to the clock. Caller must provide 'ops' field
+ * @dev:   Pointer to the initialized device. Caller must provide
+ *         'release' field
  *
  * A clock driver calls this function to register itself with the
  * clock device subsystem. If 'clk' points to dynamically allocated
@@ -100,7 +103,7 @@ struct posix_clock {
  *
  * Returns zero on success, non-zero otherwise.
  */
-int posix_clock_register(struct posix_clock *clk, dev_t devid);
+int posix_clock_register(struct posix_clock *clk, struct device *dev);
 
 /**
  * posix_clock_unregister() - unregister a clock
index c09d67e..1e6108b 100644 (file)
@@ -302,9 +302,8 @@ extern int kptr_restrict;
        printk(KERN_CRIT pr_fmt(fmt), ##__VA_ARGS__)
 #define pr_err(fmt, ...) \
        printk(KERN_ERR pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warning(fmt, ...) \
+#define pr_warn(fmt, ...) \
        printk(KERN_WARNING pr_fmt(fmt), ##__VA_ARGS__)
-#define pr_warn pr_warning
 #define pr_notice(fmt, ...) \
        printk(KERN_NOTICE pr_fmt(fmt), ##__VA_ARGS__)
 #define pr_info(fmt, ...) \
index bc8206a..61974c4 100644 (file)
@@ -101,6 +101,43 @@ static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n,
 }
 
 /**
+ * hlist_nulls_add_tail_rcu
+ * @n: the element to add to the hash list.
+ * @h: the list to add to.
+ *
+ * Description:
+ * Adds the specified element to the specified hlist_nulls,
+ * while permitting racing traversals.
+ *
+ * The caller must take whatever precautions are necessary
+ * (such as holding appropriate locks) to avoid racing
+ * with another list-mutation primitive, such as hlist_nulls_add_head_rcu()
+ * or hlist_nulls_del_rcu(), running on this same list.
+ * However, it is perfectly legal to run concurrently with
+ * the _rcu list-traversal primitives, such as
+ * hlist_nulls_for_each_entry_rcu(), used to prevent memory-consistency
+ * problems on Alpha CPUs.  Regardless of the type of CPU, the
+ * list-traversal primitive must be guarded by rcu_read_lock().
+ */
+static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n,
+                                           struct hlist_nulls_head *h)
+{
+       struct hlist_nulls_node *i, *last = NULL;
+
+       /* Note: write side code, so rcu accessors are not needed. */
+       for (i = h->first; !is_a_nulls(i); i = i->next)
+               last = i;
+
+       if (last) {
+               n->next = last->next;
+               n->pprev = &last->next;
+               rcu_assign_pointer(hlist_next_rcu(last), n);
+       } else {
+               hlist_nulls_add_head_rcu(n, h);
+       }
+}
+
+/**
  * hlist_nulls_for_each_entry_rcu - iterate over rcu list of given type
  * @tpos:      the type * to use as a loop cursor.
  * @pos:       the &struct hlist_nulls_node to use as a loop cursor.
index 467d260..716ad1d 100644 (file)
@@ -1929,11 +1929,11 @@ static inline void rseq_migrate(struct task_struct *t)
 
 /*
  * If parent process has a registered restartable sequences area, the
- * child inherits. Only applies when forking a process, not a thread.
+ * child inherits. Unregister rseq for a clone with CLONE_VM set.
  */
 static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
 {
-       if (clone_flags & CLONE_THREAD) {
+       if (clone_flags & CLONE_VM) {
                t->rseq = NULL;
                t->rseq_sig = 0;
                t->rseq_event_mask = 0;
index afa940c..cc6bcc1 100644 (file)
@@ -12,6 +12,8 @@
 #define SCHED_CPUFREQ_MIGRATION        (1U << 1)
 
 #ifdef CONFIG_CPU_FREQ
+struct cpufreq_policy;
+
 struct update_util_data {
        void (*func)(struct update_util_data *data, u64 time, unsigned int flags);
 };
@@ -20,6 +22,7 @@ void cpufreq_add_update_util_hook(int cpu, struct update_util_data *data,
                        void (*func)(struct update_util_data *data, u64 time,
                                    unsigned int flags));
 void cpufreq_remove_update_util_hook(int cpu);
+bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy);
 
 static inline unsigned long map_util_freq(unsigned long util,
                                        unsigned long freq, unsigned long cap)
index ef7031f..14d61bb 100644 (file)
@@ -358,17 +358,22 @@ static inline void sk_psock_update_proto(struct sock *sk,
 static inline void sk_psock_restore_proto(struct sock *sk,
                                          struct sk_psock *psock)
 {
-       sk->sk_write_space = psock->saved_write_space;
+       sk->sk_prot->unhash = psock->saved_unhash;
 
        if (psock->sk_proto) {
                struct inet_connection_sock *icsk = inet_csk(sk);
                bool has_ulp = !!icsk->icsk_ulp_data;
 
-               if (has_ulp)
-                       tcp_update_ulp(sk, psock->sk_proto);
-               else
+               if (has_ulp) {
+                       tcp_update_ulp(sk, psock->sk_proto,
+                                      psock->saved_write_space);
+               } else {
                        sk->sk_prot = psock->sk_proto;
+                       sk->sk_write_space = psock->saved_write_space;
+               }
                psock->sk_proto = NULL;
+       } else {
+               sk->sk_write_space = psock->saved_write_space;
        }
 }
 
index 98fe866..3a67a7e 100644 (file)
@@ -689,10 +689,10 @@ extern void spi_finalize_current_transfer(struct spi_controller *ctlr);
 /* Helper calls for driver to timestamp transfer */
 void spi_take_timestamp_pre(struct spi_controller *ctlr,
                            struct spi_transfer *xfer,
-                           const void *tx, bool irqs_off);
+                           size_t progress, bool irqs_off);
 void spi_take_timestamp_post(struct spi_controller *ctlr,
                             struct spi_transfer *xfer,
-                            const void *tx, bool irqs_off);
+                            size_t progress, bool irqs_off);
 
 /* the spi driver core manages memory for the spi_controller classdev */
 extern struct spi_controller *__spi_alloc_controller(struct device *host,
index 85ec745..966146f 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * 10G controller driver for Samsung EXYNOS SoCs
+ * 10G controller driver for Samsung Exynos SoCs
  *
  * Copyright (C) 2013 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
index d0391cc..5262b7a 100644 (file)
@@ -1231,8 +1231,6 @@ asmlinkage long sys_ni_syscall(void);
  * the ksys_xyzyyz() functions prototyped below.
  */
 
-int ksys_mount(const char __user *dev_name, const char __user *dir_name,
-              const char __user *type, unsigned long flags, void __user *data);
 int ksys_umount(char __user *name, int flags);
 int ksys_dup(unsigned int fildes);
 int ksys_chroot(const char __user *filename);
index c17af77..ea627d1 100644 (file)
@@ -30,7 +30,7 @@ struct tnum tnum_lshift(struct tnum a, u8 shift);
 /* Shift (rsh) a tnum right (by a fixed shift) */
 struct tnum tnum_rshift(struct tnum a, u8 shift);
 /* Shift (arsh) a tnum right (by a fixed min_shift) */
-struct tnum tnum_arshift(struct tnum a, u8 min_shift);
+struct tnum tnum_arshift(struct tnum a, u8 min_shift, u8 insn_bitness);
 /* Add two tnums, return @a + @b */
 struct tnum tnum_add(struct tnum a, struct tnum b);
 /* Subtract two tnums, return @a - @b */
index 0d6e949..03e9b18 100644 (file)
@@ -403,6 +403,7 @@ extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
 extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen);
 extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
 extern struct tpm_chip *tpm_default_chip(void);
+void tpm2_flush_context(struct tpm_chip *chip, u32 handle);
 #else
 static inline int tpm_is_tpm2(struct tpm_chip *chip)
 {
index 059524b..f22bd6c 100644 (file)
@@ -3548,6 +3548,9 @@ struct cfg80211_update_owe_info {
  *
  * @start_radar_detection: Start radar detection in the driver.
  *
+ * @end_cac: End running CAC, probably because a related CAC
+ *     was finished on another phy.
+ *
  * @update_ft_ies: Provide updated Fast BSS Transition information to the
  *     driver. If the SME is in the driver/firmware, this information can be
  *     used in building Authentication and Reassociation Request frames.
@@ -3874,6 +3877,8 @@ struct cfg80211_ops {
                                         struct net_device *dev,
                                         struct cfg80211_chan_def *chandef,
                                         u32 cac_time_ms);
+       void    (*end_cac)(struct wiphy *wiphy,
+                               struct net_device *dev);
        int     (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev,
                                 struct cfg80211_update_ft_ies_params *ftie);
        int     (*crit_proto_start)(struct wiphy *wiphy,
index 47f87b2..38b4acb 100644 (file)
@@ -938,7 +938,7 @@ struct devlink_region *devlink_region_create(struct devlink *devlink,
                                             u32 region_max_snapshots,
                                             u64 region_size);
 void devlink_region_destroy(struct devlink_region *region);
-u32 devlink_region_shapshot_id_get(struct devlink *devlink);
+u32 devlink_region_snapshot_id_get(struct devlink *devlink);
 int devlink_region_snapshot_create(struct devlink_region *region,
                                   u8 *data, u32 snapshot_id,
                                   devlink_snapshot_data_dest_t *data_destructor);
index fe62fe2..3448cf8 100644 (file)
@@ -82,7 +82,7 @@ struct dst_entry {
 struct dst_metrics {
        u32             metrics[RTAX_MAX];
        refcount_t      refcnt;
-};
+} __aligned(4);                /* Low pointer bits contain DST_METRICS_FLAGS */
 extern const struct dst_metrics dst_default_metrics;
 
 u32 *dst_cow_metrics_generic(struct dst_entry *dst, unsigned long old);
@@ -516,7 +516,16 @@ static inline void skb_dst_update_pmtu(struct sk_buff *skb, u32 mtu)
        struct dst_entry *dst = skb_dst(skb);
 
        if (dst && dst->ops->update_pmtu)
-               dst->ops->update_pmtu(dst, NULL, skb, mtu);
+               dst->ops->update_pmtu(dst, NULL, skb, mtu, true);
+}
+
+/* update dst pmtu but not do neighbor confirm */
+static inline void skb_dst_update_pmtu_no_confirm(struct sk_buff *skb, u32 mtu)
+{
+       struct dst_entry *dst = skb_dst(skb);
+
+       if (dst && dst->ops->update_pmtu)
+               dst->ops->update_pmtu(dst, NULL, skb, mtu, false);
 }
 
 static inline void skb_tunnel_check_pmtu(struct sk_buff *skb,
@@ -526,7 +535,7 @@ static inline void skb_tunnel_check_pmtu(struct sk_buff *skb,
        u32 encap_mtu = dst_mtu(encap_dst);
 
        if (skb->len > encap_mtu - headroom)
-               skb_dst_update_pmtu(skb, encap_mtu - headroom);
+               skb_dst_update_pmtu_no_confirm(skb, encap_mtu - headroom);
 }
 
 #endif /* _NET_DST_H */
index 5ec645f..443863c 100644 (file)
@@ -27,7 +27,8 @@ struct dst_ops {
        struct dst_entry *      (*negative_advice)(struct dst_entry *);
        void                    (*link_failure)(struct sk_buff *);
        void                    (*update_pmtu)(struct dst_entry *dst, struct sock *sk,
-                                              struct sk_buff *skb, u32 mtu);
+                                              struct sk_buff *skb, u32 mtu,
+                                              bool confirm_neigh);
        void                    (*redirect)(struct dst_entry *dst, struct sock *sk,
                                            struct sk_buff *skb);
        int                     (*local_out)(struct net *net, struct sock *sk, struct sk_buff *skb);
index c41833b..4d9a0c6 100644 (file)
@@ -37,7 +37,7 @@ struct garp_skb_cb {
 static inline struct garp_skb_cb *garp_cb(struct sk_buff *skb)
 {
        BUILD_BUG_ON(sizeof(struct garp_skb_cb) >
-                    FIELD_SIZEOF(struct sk_buff, cb));
+                    sizeof_field(struct sk_buff, cb));
        return (struct garp_skb_cb *)skb->cb;
 }
 
index af2b4c0..d0019d3 100644 (file)
@@ -103,13 +103,19 @@ struct inet_bind_hashbucket {
        struct hlist_head       chain;
 };
 
-/*
- * Sockets can be hashed in established or listening table
+/* Sockets can be hashed in established or listening table.
+ * We must use different 'nulls' end-of-chain value for all hash buckets :
+ * A socket might transition from ESTABLISH to LISTEN state without
+ * RCU grace period. A lookup in ehash table needs to handle this case.
  */
+#define LISTENING_NULLS_BASE (1U << 29)
 struct inet_listen_hashbucket {
        spinlock_t              lock;
        unsigned int            count;
-       struct hlist_head       head;
+       union {
+               struct hlist_head       head;
+               struct hlist_nulls_head nulls_head;
+       };
 };
 
 /* This is for listening sockets, thus all sockets which possess wildcards. */
index af64560..236503a 100644 (file)
@@ -33,8 +33,8 @@
 /* Used to memset ipv4 address padding. */
 #define IP_TUNNEL_KEY_IPV4_PAD offsetofend(struct ip_tunnel_key, u.ipv4.dst)
 #define IP_TUNNEL_KEY_IPV4_PAD_LEN                             \
-       (FIELD_SIZEOF(struct ip_tunnel_key, u) -                \
-        FIELD_SIZEOF(struct ip_tunnel_key, u.ipv4))
+       (sizeof_field(struct ip_tunnel_key, u) -                \
+        sizeof_field(struct ip_tunnel_key, u.ipv4))
 
 struct ip_tunnel_key {
        __be64                  tun_id;
@@ -63,7 +63,7 @@ struct ip_tunnel_key {
 
 /* Maximum tunnel options length. */
 #define IP_TUNNEL_OPTS_MAX                                     \
-       GENMASK((FIELD_SIZEOF(struct ip_tunnel_info,            \
+       GENMASK((sizeof_field(struct ip_tunnel_info,            \
                              options_len) * BITS_PER_BYTE) - 1, 0)
 
 struct ip_tunnel_info {
index ef58b4a..1c308c0 100644 (file)
@@ -39,7 +39,7 @@ struct mrp_skb_cb {
 static inline struct mrp_skb_cb *mrp_cb(struct sk_buff *skb)
 {
        BUILD_BUG_ON(sizeof(struct mrp_skb_cb) >
-                    FIELD_SIZEOF(struct sk_buff, cb));
+                    sizeof_field(struct sk_buff, cb));
        return (struct mrp_skb_cb *)skb->cb;
 }
 
index 6ad9ad4..8ec77bf 100644 (file)
@@ -72,7 +72,6 @@ struct neigh_parms {
        struct net_device *dev;
        struct list_head list;
        int     (*neigh_setup)(struct neighbour *);
-       void    (*neigh_cleanup)(struct neighbour *);
        struct neigh_table *tbl;
 
        void    *sysctl_table;
index 44b5a00..37f0fbe 100644 (file)
@@ -81,7 +81,7 @@ struct nf_conn_help {
 };
 
 #define NF_CT_HELPER_BUILD_BUG_ON(structsize) \
-       BUILD_BUG_ON((structsize) > FIELD_SIZEOF(struct nf_conn_help, data))
+       BUILD_BUG_ON((structsize) > sizeof_field(struct nf_conn_help, data))
 
 struct nf_conntrack_helper *__nf_conntrack_helper_find(const char *name,
                                                       u16 l3num, u8 protonum);
index f0897b3..415b8f4 100644 (file)
@@ -106,6 +106,12 @@ struct flow_offload {
 };
 
 #define NF_FLOW_TIMEOUT (30 * HZ)
+#define nf_flowtable_time_stamp        (u32)jiffies
+
+static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
+{
+       return (__s32)(timeout - nf_flowtable_time_stamp);
+}
 
 struct nf_flow_route {
        struct {
index 7281895..2656155 100644 (file)
@@ -41,7 +41,7 @@ struct nft_immediate_expr {
  */
 static inline u32 nft_cmp_fast_mask(unsigned int len)
 {
-       return cpu_to_le32(~0U >> (FIELD_SIZEOF(struct nft_cmp_fast_expr,
+       return cpu_to_le32(~0U >> (sizeof_field(struct nft_cmp_fast_expr,
                                                data) * BITS_PER_BYTE - len));
 }
 
index 144f264..fceddf8 100644 (file)
@@ -308,6 +308,7 @@ struct tcf_proto_ops {
        int                     (*delete)(struct tcf_proto *tp, void *arg,
                                          bool *last, bool rtnl_held,
                                          struct netlink_ext_ack *);
+       bool                    (*delete_empty)(struct tcf_proto *tp);
        void                    (*walk)(struct tcf_proto *tp,
                                        struct tcf_walker *arg, bool rtnl_held);
        int                     (*reoffload)(struct tcf_proto *tp, bool add,
@@ -336,6 +337,10 @@ struct tcf_proto_ops {
        int                     flags;
 };
 
+/* Classifiers setting TCF_PROTO_OPS_DOIT_UNLOCKED in tcf_proto_ops->flags
+ * are expected to implement tcf_proto_ops->delete_empty(), otherwise race
+ * conditions can occur when filters are inserted/deleted simultaneously.
+ */
 enum tcf_proto_ops_flags {
        TCF_PROTO_OPS_DOIT_UNLOCKED = 1,
 };
index 87d54ef..8dff68b 100644 (file)
@@ -722,6 +722,11 @@ static inline void __sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_h
        hlist_nulls_add_head_rcu(&sk->sk_nulls_node, list);
 }
 
+static inline void __sk_nulls_add_node_tail_rcu(struct sock *sk, struct hlist_nulls_head *list)
+{
+       hlist_nulls_add_tail_rcu(&sk->sk_nulls_node, list);
+}
+
 static inline void sk_nulls_add_node_rcu(struct sock *sk, struct hlist_nulls_head *list)
 {
        sock_hold(sk);
@@ -2305,7 +2310,7 @@ struct sock_skb_cb {
  * using skb->cb[] would keep using it directly and utilize its
  * alignement guarantee.
  */
-#define SOCK_SKB_CB_OFFSET ((FIELD_SIZEOF(struct sk_buff, cb) - \
+#define SOCK_SKB_CB_OFFSET ((sizeof_field(struct sk_buff, cb) - \
                            sizeof(struct sock_skb_cb)))
 
 #define SOCK_SKB_CB(__skb) ((struct sock_skb_cb *)((__skb)->cb + \
@@ -2583,9 +2588,9 @@ static inline int sk_get_rmem0(const struct sock *sk, const struct proto *proto)
  */
 static inline void sk_pacing_shift_update(struct sock *sk, int val)
 {
-       if (!sk || !sk_fullsock(sk) || sk->sk_pacing_shift == val)
+       if (!sk || !sk_fullsock(sk) || READ_ONCE(sk->sk_pacing_shift) == val)
                return;
-       sk->sk_pacing_shift = val;
+       WRITE_ONCE(sk->sk_pacing_shift, val);
 }
 
 /* if a socket is bound to a device, check that the given device
index 86b9a87..e6f4838 100644 (file)
@@ -1766,9 +1766,18 @@ static inline bool tcp_skb_is_last(const struct sock *sk,
        return skb_queue_is_last(&sk->sk_write_queue, skb);
 }
 
+/**
+ * tcp_write_queue_empty - test if any payload (or FIN) is available in write queue
+ * @sk: socket
+ *
+ * Since the write queue can have a temporary empty skb in it,
+ * we must not use "return skb_queue_empty(&sk->sk_write_queue)"
+ */
 static inline bool tcp_write_queue_empty(const struct sock *sk)
 {
-       return skb_queue_empty(&sk->sk_write_queue);
+       const struct tcp_sock *tp = tcp_sk(sk);
+
+       return tp->write_seq == tp->snd_nxt;
 }
 
 static inline bool tcp_rtx_queue_empty(const struct sock *sk)
@@ -2138,7 +2147,8 @@ struct tcp_ulp_ops {
        /* initialize ulp */
        int (*init)(struct sock *sk);
        /* update ulp */
-       void (*update)(struct sock *sk, struct proto *p);
+       void (*update)(struct sock *sk, struct proto *p,
+                      void (*write_space)(struct sock *sk));
        /* cleanup ulp */
        void (*release)(struct sock *sk);
        /* diagnostic */
@@ -2153,7 +2163,8 @@ void tcp_unregister_ulp(struct tcp_ulp_ops *type);
 int tcp_set_ulp(struct sock *sk, const char *name);
 void tcp_get_available_ulp(char *buf, size_t len);
 void tcp_cleanup_ulp(struct sock *sk);
-void tcp_update_ulp(struct sock *sk, struct proto *p);
+void tcp_update_ulp(struct sock *sk, struct proto *p,
+                   void (*write_space)(struct sock *sk));
 
 #define MODULE_ALIAS_TCP_ULP(name)                             \
        __MODULE_INFO(alias, alias_userspace, name);            \
index ed1acc3..d7d6c2b 100644 (file)
@@ -62,7 +62,8 @@ enum {
        X25_STATE_1,            /* Awaiting Call Accepted */
        X25_STATE_2,            /* Awaiting Clear Confirmation */
        X25_STATE_3,            /* Data Transfer */
-       X25_STATE_4             /* Awaiting Reset Confirmation */
+       X25_STATE_4,            /* Awaiting Reset Confirmation */
+       X25_STATE_5             /* Call Accepted / Call Connected pending */
 };
 
 enum {
index cacb48f..5608e14 100644 (file)
@@ -2832,6 +2832,11 @@ int rdma_user_mmap_io(struct ib_ucontext *ucontext, struct vm_area_struct *vma,
 int rdma_user_mmap_entry_insert(struct ib_ucontext *ucontext,
                                struct rdma_user_mmap_entry *entry,
                                size_t length);
+int rdma_user_mmap_entry_insert_range(struct ib_ucontext *ucontext,
+                                     struct rdma_user_mmap_entry *entry,
+                                     size_t length, u32 min_pgoff,
+                                     u32 max_pgoff);
+
 struct rdma_user_mmap_entry *
 rdma_user_mmap_entry_get_pgoff(struct ib_ucontext *ucontext,
                               unsigned long pgoff);
similarity index 72%
rename from arch/riscv/include/asm/sifive_l2_cache.h
rename to include/soc/sifive/sifive_l2_cache.h
index 04f6748..92ade10 100644 (file)
@@ -4,8 +4,8 @@
  *
  */
 
-#ifndef _ASM_RISCV_SIFIVE_L2_CACHE_H
-#define _ASM_RISCV_SIFIVE_L2_CACHE_H
+#ifndef __SOC_SIFIVE_L2_CACHE_H
+#define __SOC_SIFIVE_L2_CACHE_H
 
 extern int register_sifive_l2_error_notifier(struct notifier_block *nb);
 extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb);
@@ -13,4 +13,4 @@ extern int unregister_sifive_l2_error_notifier(struct notifier_block *nb);
 #define SIFIVE_L2_ERR_TYPE_CE 0
 #define SIFIVE_L2_ERR_TYPE_UE 1
 
-#endif /* _ASM_RISCV_SIFIVE_L2_CACHE_H */
+#endif /* __SOC_SIFIVE_L2_CACHE_H */
index cc38399..49200ec 100644 (file)
@@ -197,7 +197,7 @@ struct snd_ac97_bus_ops {
 
 struct snd_ac97_bus {
        /* -- lowlevel (hardware) driver specific -- */
-       struct snd_ac97_bus_ops *ops;
+       const struct snd_ac97_bus_ops *ops;
        void *private_data;
        void (*private_free) (struct snd_ac97_bus *bus);
        /* --- */
@@ -310,7 +310,8 @@ static inline int ac97_can_spdif(struct snd_ac97 * ac97)
 
 /* functions */
 /* create new AC97 bus */
-int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
+int snd_ac97_bus(struct snd_card *card, int num,
+                const struct snd_ac97_bus_ops *ops,
                 void *private_data, struct snd_ac97_bus **rbus);
 /* create mixer controls */
 int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
index 5d7c994..11feeee 100644 (file)
@@ -22,6 +22,16 @@ typedef int (snd_kcontrol_tlv_rw_t)(struct snd_kcontrol *kcontrol,
                                    unsigned int size,
                                    unsigned int __user *tlv);
 
+/* internal flag for skipping validations */
+#ifdef CONFIG_SND_CTL_VALIDATION
+#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK       (1 << 27)
+#define snd_ctl_skip_validation(info) \
+       ((info)->access & SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK)
+#else
+#define SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK       0
+#define snd_ctl_skip_validation(info)          true
+#endif
+
 enum {
        SNDRV_CTL_TLV_OP_READ = 0,
        SNDRV_CTL_TLV_OP_WRITE = 1,
index af3dce9..ac8b692 100644 (file)
@@ -69,7 +69,7 @@ struct snd_device {
        enum snd_device_state state;    /* state of the device */
        enum snd_device_type type;      /* device type */
        void *device_data;              /* device structure */
-       struct snd_device_ops *ops;     /* operations */
+       const struct snd_device_ops *ops;       /* operations */
 };
 
 #define snd_device(n) list_entry(n, struct snd_device, list)
@@ -120,6 +120,9 @@ struct snd_card {
        int sync_irq;                   /* assigned irq, used for PCM sync */
        wait_queue_head_t remove_sleep;
 
+       size_t total_pcm_alloc_bytes;   /* total amount of allocated buffers */
+       struct mutex memory_mutex;      /* protection for the above */
+
 #ifdef CONFIG_PM
        unsigned int power_state;       /* power state */
        wait_queue_head_t power_sleep;
@@ -256,7 +259,7 @@ static inline void snd_card_unref(struct snd_card *card)
 /* device.c */
 
 int snd_device_new(struct snd_card *card, enum snd_device_type type,
-                  void *device_data, struct snd_device_ops *ops);
+                  void *device_data, const struct snd_device_ops *ops);
 int snd_device_register(struct snd_card *card, void *device_data);
 int snd_device_register_all(struct snd_card *card);
 void snd_device_disconnect(struct snd_card *card, void *device_data);
index ac18f42..3ee8036 100644 (file)
@@ -51,7 +51,6 @@ struct hda_bus {
        DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);
 
        /* misc op flags */
-       unsigned int needs_damn_long_delay :1;
        unsigned int allow_bus_reset:1; /* allow bus reset at fatal error */
        /* status for codec/controller */
        unsigned int shutdown :1;       /* being unloaded */
index 5141f8f..4c1b9be 100644 (file)
@@ -24,6 +24,9 @@ int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
                              unsigned int val);
 int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg,
                               unsigned int mask, unsigned int val);
+int snd_hdac_regmap_update_raw_once(struct hdac_device *codec, unsigned int reg,
+                                   unsigned int mask, unsigned int val);
+void snd_hdac_regmap_sync(struct hdac_device *codec);
 
 /**
  * snd_hdac_regmap_encode_verb - encode the verb to a pseudo register
index e05b95e..d4299e1 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/device.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/timecounter.h>
 #include <sound/core.h>
@@ -86,6 +87,7 @@ struct hdac_device {
 
        /* regmap */
        struct regmap *regmap;
+       struct mutex regmap_lock;
        struct snd_array vendor_verbs;
        bool lazy_cache:1;      /* don't wake up for writes */
        bool caps_overwriting:1; /* caps overwrite being in process */
@@ -317,6 +319,7 @@ struct hdac_bus {
        struct hdac_rb corb;
        struct hdac_rb rirb;
        unsigned int last_cmd[HDA_MAX_CODECS];  /* last sent command */
+       wait_queue_head_t rirb_wq;
 
        /* CORB/RIRB and position buffers */
        struct snd_dma_buffer rb;
@@ -330,6 +333,7 @@ struct hdac_bus {
        bool chip_init:1;               /* h/w initialized */
 
        /* behavior flags */
+       bool aligned_mmio:1;            /* aligned MMIO access */
        bool sync_write:1;              /* sync after verb write */
        bool use_posbuf:1;              /* use position buffer */
        bool snoop:1;                   /* enable snooping */
@@ -337,6 +341,7 @@ struct hdac_bus {
        bool reverse_assign:1;          /* assign devices in reverse order */
        bool corbrp_self_clear:1;       /* CORBRP clears itself after reset */
        bool polling_mode:1;
+       bool needs_damn_long_delay:1;
 
        int poll_count;
 
@@ -405,34 +410,61 @@ void snd_hdac_bus_free_stream_pages(struct hdac_bus *bus);
 unsigned int snd_hdac_aligned_read(void __iomem *addr, unsigned int mask);
 void snd_hdac_aligned_write(unsigned int val, void __iomem *addr,
                            unsigned int mask);
-#define snd_hdac_reg_writeb(v, addr)   snd_hdac_aligned_write(v, addr, 0xff)
-#define snd_hdac_reg_writew(v, addr)   snd_hdac_aligned_write(v, addr, 0xffff)
-#define snd_hdac_reg_readb(addr)       snd_hdac_aligned_read(addr, 0xff)
-#define snd_hdac_reg_readw(addr)       snd_hdac_aligned_read(addr, 0xffff)
-#else /* CONFIG_SND_HDA_ALIGNED_MMIO */
-#define snd_hdac_reg_writeb(val, addr) writeb(val, addr)
-#define snd_hdac_reg_writew(val, addr) writew(val, addr)
-#define snd_hdac_reg_readb(addr)       readb(addr)
-#define snd_hdac_reg_readw(addr)       readw(addr)
-#endif /* CONFIG_SND_HDA_ALIGNED_MMIO */
-#define snd_hdac_reg_writel(val, addr) writel(val, addr)
-#define snd_hdac_reg_readl(addr)       readl(addr)
+#define snd_hdac_aligned_mmio(bus)     (bus)->aligned_mmio
+#else
+#define snd_hdac_aligned_mmio(bus)     false
+#define snd_hdac_aligned_read(addr, mask)      0
+#define snd_hdac_aligned_write(val, addr, mask) do {} while (0)
+#endif
+
+static inline void snd_hdac_reg_writeb(struct hdac_bus *bus, void __iomem *addr,
+                                      u8 val)
+{
+       if (snd_hdac_aligned_mmio(bus))
+               snd_hdac_aligned_write(val, addr, 0xff);
+       else
+               writeb(val, addr);
+}
+
+static inline void snd_hdac_reg_writew(struct hdac_bus *bus, void __iomem *addr,
+                                      u16 val)
+{
+       if (snd_hdac_aligned_mmio(bus))
+               snd_hdac_aligned_write(val, addr, 0xffff);
+       else
+               writew(val, addr);
+}
+
+static inline u8 snd_hdac_reg_readb(struct hdac_bus *bus, void __iomem *addr)
+{
+       return snd_hdac_aligned_mmio(bus) ?
+               snd_hdac_aligned_read(addr, 0xff) : readb(addr);
+}
+
+static inline u16 snd_hdac_reg_readw(struct hdac_bus *bus, void __iomem *addr)
+{
+       return snd_hdac_aligned_mmio(bus) ?
+               snd_hdac_aligned_read(addr, 0xffff) : readw(addr);
+}
+
+#define snd_hdac_reg_writel(bus, addr, val)    writel(val, addr)
+#define snd_hdac_reg_readl(bus, addr)  readl(addr)
 
 /*
  * macros for easy use
  */
 #define _snd_hdac_chip_writeb(chip, reg, value) \
-       snd_hdac_reg_writeb(value, (chip)->remap_addr + (reg))
+       snd_hdac_reg_writeb(chip, (chip)->remap_addr + (reg), value)
 #define _snd_hdac_chip_readb(chip, reg) \
-       snd_hdac_reg_readb((chip)->remap_addr + (reg))
+       snd_hdac_reg_readb(chip, (chip)->remap_addr + (reg))
 #define _snd_hdac_chip_writew(chip, reg, value) \
-       snd_hdac_reg_writew(value, (chip)->remap_addr + (reg))
+       snd_hdac_reg_writew(chip, (chip)->remap_addr + (reg), value)
 #define _snd_hdac_chip_readw(chip, reg) \
-       snd_hdac_reg_readw((chip)->remap_addr + (reg))
+       snd_hdac_reg_readw(chip, (chip)->remap_addr + (reg))
 #define _snd_hdac_chip_writel(chip, reg, value) \
-       snd_hdac_reg_writel(value, (chip)->remap_addr + (reg))
+       snd_hdac_reg_writel(chip, (chip)->remap_addr + (reg), value)
 #define _snd_hdac_chip_readl(chip, reg) \
-       snd_hdac_reg_readl((chip)->remap_addr + (reg))
+       snd_hdac_reg_readl(chip, (chip)->remap_addr + (reg))
 
 /* read/write a register, pass without AZX_REG_ prefix */
 #define snd_hdac_chip_writel(chip, reg, value) \
@@ -540,17 +572,17 @@ int snd_hdac_get_stream_stripe_ctl(struct hdac_bus *bus,
  */
 /* read/write a register, pass without AZX_REG_ prefix */
 #define snd_hdac_stream_writel(dev, reg, value) \
-       snd_hdac_reg_writel(value, (dev)->sd_addr + AZX_REG_ ## reg)
+       snd_hdac_reg_writel((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
 #define snd_hdac_stream_writew(dev, reg, value) \
-       snd_hdac_reg_writew(value, (dev)->sd_addr + AZX_REG_ ## reg)
+       snd_hdac_reg_writew((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
 #define snd_hdac_stream_writeb(dev, reg, value) \
-       snd_hdac_reg_writeb(value, (dev)->sd_addr + AZX_REG_ ## reg)
+       snd_hdac_reg_writeb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg, value)
 #define snd_hdac_stream_readl(dev, reg) \
-       snd_hdac_reg_readl((dev)->sd_addr + AZX_REG_ ## reg)
+       snd_hdac_reg_readl((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
 #define snd_hdac_stream_readw(dev, reg) \
-       snd_hdac_reg_readw((dev)->sd_addr + AZX_REG_ ## reg)
+       snd_hdac_reg_readw((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
 #define snd_hdac_stream_readb(dev, reg) \
-       snd_hdac_reg_readb((dev)->sd_addr + AZX_REG_ ## reg)
+       snd_hdac_reg_readb((dev)->bus, (dev)->sd_addr + AZX_REG_ ## reg)
 
 /* update a register, pass without AZX_REG_ prefix */
 #define snd_hdac_stream_updatel(dev, reg, mask, val) \
index b01a229..7c13bf5 100644 (file)
@@ -64,7 +64,7 @@ struct snd_info_entry {
        unsigned short content;
        union {
                struct snd_info_entry_text text;
-               struct snd_info_entry_ops *ops;
+               const struct snd_info_entry_ops *ops;
        } c;
        struct snd_info_entry *parent;
        struct module *module;
index 3ddae2b..a1ff3b4 100644 (file)
@@ -37,7 +37,7 @@
 #define SNDRV_DEFAULT_PTR      SNDRV_DEFAULT_STR
 
 #ifdef SNDRV_LEGACY_FIND_FREE_IOPORT
-static long snd_legacy_find_free_ioport(long *port_table, long size)
+static long snd_legacy_find_free_ioport(const long *port_table, long size)
 {
        while (*port_table != -1) {
                if (request_region(*port_table, size, "ALSA test")) {
@@ -58,7 +58,7 @@ static irqreturn_t snd_legacy_empty_irq_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static int snd_legacy_find_free_irq(int *irq_table)
+static int snd_legacy_find_free_irq(const int *irq_table)
 {
        while (*irq_table != -1) {
                if (!request_irq(*irq_table, snd_legacy_empty_irq_handler,
@@ -74,7 +74,7 @@ static int snd_legacy_find_free_irq(int *irq_table)
 #endif
 
 #ifdef SNDRV_LEGACY_FIND_FREE_DMA
-static int snd_legacy_find_free_dma(int *dma_table)
+static int snd_legacy_find_free_dma(const int *dma_table)
 {
        while (*dma_table != -1) {
                if (!request_dma(*dma_table, "ALSA Test DMA")) {
index 8a89fa6..f657ff0 100644 (file)
@@ -44,6 +44,7 @@ struct snd_pcm_hardware {
        size_t fifo_size;               /* fifo size in bytes */
 };
 
+struct snd_pcm_status64;
 struct snd_pcm_substream;
 
 struct snd_pcm_audio_tstamp_config; /* definitions further down */
@@ -62,7 +63,7 @@ struct snd_pcm_ops {
        int (*sync_stop)(struct snd_pcm_substream *substream);
        snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *substream);
        int (*get_time_info)(struct snd_pcm_substream *substream,
-                       struct timespec *system_ts, struct timespec *audio_ts,
+                       struct timespec64 *system_ts, struct timespec64 *audio_ts,
                        struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
                        struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
        int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
@@ -343,7 +344,7 @@ static inline void snd_pcm_pack_audio_tstamp_report(__u32 *data, __u32 *accuracy
 struct snd_pcm_runtime {
        /* -- Status -- */
        struct snd_pcm_substream *trigger_master;
-       struct timespec trigger_tstamp; /* trigger timestamp */
+       struct timespec64 trigger_tstamp;       /* trigger timestamp */
        bool trigger_tstamp_latched;     /* trigger timestamp latched in low-level driver/hardware */
        int overrange;
        snd_pcm_uframes_t avail_max;
@@ -421,7 +422,7 @@ struct snd_pcm_runtime {
        /* -- audio timestamp config -- */
        struct snd_pcm_audio_tstamp_config audio_tstamp_config;
        struct snd_pcm_audio_tstamp_report audio_tstamp_report;
-       struct timespec driver_tstamp;
+       struct timespec64 driver_tstamp;
 
 #if IS_ENABLED(CONFIG_SND_PCM_OSS)
        /* -- OSS things -- */
@@ -558,8 +559,8 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree);
 int snd_pcm_info(struct snd_pcm_substream *substream, struct snd_pcm_info *info);
 int snd_pcm_info_user(struct snd_pcm_substream *substream,
                      struct snd_pcm_info __user *info);
-int snd_pcm_status(struct snd_pcm_substream *substream,
-                  struct snd_pcm_status *status);
+int snd_pcm_status64(struct snd_pcm_substream *substream,
+                    struct snd_pcm_status64 *status);
 int snd_pcm_start(struct snd_pcm_substream *substream);
 int snd_pcm_stop(struct snd_pcm_substream *substream, snd_pcm_state_t status);
 int snd_pcm_drain_done(struct snd_pcm_substream *substream);
@@ -1155,22 +1156,22 @@ static inline void snd_pcm_set_runtime_buffer(struct snd_pcm_substream *substrea
 }
 
 /**
- * snd_pcm_gettime - Fill the timespec depending on the timestamp mode
+ * snd_pcm_gettime - Fill the timespec64 depending on the timestamp mode
  * @runtime: PCM runtime instance
- * @tv: timespec to fill
+ * @tv: timespec64 to fill
  */
 static inline void snd_pcm_gettime(struct snd_pcm_runtime *runtime,
-                                  struct timespec *tv)
+                                  struct timespec64 *tv)
 {
        switch (runtime->tstamp_type) {
        case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC:
-               ktime_get_ts(tv);
+               ktime_get_ts64(tv);
                break;
        case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
-               getrawmonotonic(tv);
+               ktime_get_raw_ts64(tv);
                break;
        default:
-               getnstimeofday(tv);
+               ktime_get_real_ts64(tv);
                break;
        }
 }
@@ -1422,4 +1423,55 @@ static inline u64 pcm_format_to_bits(snd_pcm_format_t pcm_format)
 #define pcm_dbg(pcm, fmt, args...) \
        dev_dbg((pcm)->card->dev, fmt, ##args)
 
+struct snd_pcm_status64 {
+       snd_pcm_state_t state;          /* stream state */
+       u8 rsvd[4];
+       s64 trigger_tstamp_sec;         /* time when stream was started/stopped/paused */
+       s64 trigger_tstamp_nsec;
+       s64 tstamp_sec;                 /* reference timestamp */
+       s64 tstamp_nsec;
+       snd_pcm_uframes_t appl_ptr;     /* appl ptr */
+       snd_pcm_uframes_t hw_ptr;       /* hw ptr */
+       snd_pcm_sframes_t delay;        /* current delay in frames */
+       snd_pcm_uframes_t avail;        /* number of frames available */
+       snd_pcm_uframes_t avail_max;    /* max frames available on hw since last status */
+       snd_pcm_uframes_t overrange;    /* count of ADC (capture) overrange detections from last status */
+       snd_pcm_state_t suspended_state; /* suspended stream state */
+       __u32 audio_tstamp_data;         /* needed for 64-bit alignment, used for configs/report to/from userspace */
+       s64 audio_tstamp_sec;           /* sample counter, wall clock, PHC or on-demand sync'ed */
+       s64 audio_tstamp_nsec;
+       s64 driver_tstamp_sec;          /* useful in case reference system tstamp is reported with delay */
+       s64 driver_tstamp_nsec;
+       __u32 audio_tstamp_accuracy;    /* in ns units, only valid if indicated in audio_tstamp_data */
+       unsigned char reserved[52-4*sizeof(s64)]; /* must be filled with zero */
+};
+
+#define SNDRV_PCM_IOCTL_STATUS64       _IOR('A', 0x20, struct snd_pcm_status64)
+#define SNDRV_PCM_IOCTL_STATUS_EXT64   _IOWR('A', 0x24, struct snd_pcm_status64)
+
+struct snd_pcm_status32 {
+       snd_pcm_state_t state;          /* stream state */
+       s32 trigger_tstamp_sec; /* time when stream was started/stopped/paused */
+       s32 trigger_tstamp_nsec;
+       s32 tstamp_sec;         /* reference timestamp */
+       s32 tstamp_nsec;
+       u32 appl_ptr;           /* appl ptr */
+       u32 hw_ptr;             /* hw ptr */
+       s32 delay;              /* current delay in frames */
+       u32 avail;              /* number of frames available */
+       u32 avail_max;          /* max frames available on hw since last status */
+       u32 overrange;          /* count of ADC (capture) overrange detections from last status */
+       snd_pcm_state_t suspended_state;        /* suspended stream state */
+       u32 audio_tstamp_data;  /* needed for 64-bit alignment, used for configs/report to/from userspace */
+       s32 audio_tstamp_sec;   /* sample counter, wall clock, PHC or on-demand sync'ed */
+       s32 audio_tstamp_nsec;
+       s32 driver_tstamp_sec;  /* useful in case reference system tstamp is reported with delay */
+       s32 driver_tstamp_nsec;
+       u32 audio_tstamp_accuracy;      /* in ns units, only valid if indicated in audio_tstamp_data */
+       unsigned char reserved[52-4*sizeof(s32)]; /* must be filled with zero */
+};
+
+#define SNDRV_PCM_IOCTL_STATUS32       _IOR('A', 0x20, struct snd_pcm_status32)
+#define SNDRV_PCM_IOCTL_STATUS_EXT32   _IOWR('A', 0x24, struct snd_pcm_status32)
+
 #endif /* __SOUND_PCM_H */
index d6b7405..88799d1 100644 (file)
@@ -174,7 +174,8 @@ enum {
 };
 
 /* Prototypes for midi_process.c */
-void snd_midi_process_event(struct snd_midi_op *ops, struct snd_seq_event *ev,
+void snd_midi_process_event(const struct snd_midi_op *ops,
+                           struct snd_seq_event *ev,
                            struct snd_midi_channel_set *chanset);
 void snd_midi_channel_set_clear(struct snd_midi_channel_set *chset);
 struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n);
index 506f72a..154d02f 100644 (file)
@@ -93,8 +93,8 @@ struct snd_soc_component_driver {
        snd_pcm_uframes_t (*pointer)(struct snd_soc_component *component,
                                     struct snd_pcm_substream *substream);
        int (*get_time_info)(struct snd_soc_component *component,
-               struct snd_pcm_substream *substream, struct timespec *system_ts,
-               struct timespec *audio_ts,
+               struct snd_pcm_substream *substream, struct timespec64 *system_ts,
+               struct timespec64 *audio_ts,
                struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
                struct snd_pcm_audio_tstamp_report *audio_tstamp_report);
        int (*copy_user)(struct snd_soc_component *component,
index a53e37b..23e885d 100644 (file)
@@ -89,7 +89,7 @@ struct snd_timer_instance {
                          unsigned long ticks, unsigned long resolution);
        void (*ccallback) (struct snd_timer_instance * timeri,
                           int event,
-                          struct timespec * tstamp,
+                          struct timespec64 * tstamp,
                           unsigned long resolution);
        void (*disconnect)(struct snd_timer_instance *timeri);
        void *callback_data;
@@ -113,7 +113,7 @@ struct snd_timer_instance {
  */
 
 int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid, struct snd_timer **rtimer);
-void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp);
+void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp);
 int snd_timer_global_new(char *id, int device, struct snd_timer **rtimer);
 int snd_timer_global_free(struct snd_timer *timer);
 int snd_timer_global_register(struct snd_timer *timer);
index 84569dd..1ddd303 100644 (file)
@@ -147,8 +147,8 @@ struct vx_core {
        /* ports are defined externally */
 
        /* low-level functions */
-       struct snd_vx_hardware *hw;
-       struct snd_vx_ops *ops;
+       const struct snd_vx_hardware *hw;
+       const struct snd_vx_ops *ops;
 
        struct mutex lock;
 
@@ -193,8 +193,9 @@ struct vx_core {
 /*
  * constructor
  */
-struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
-                             struct snd_vx_ops *ops, int extra_size);
+struct vx_core *snd_vx_create(struct snd_card *card,
+                             const struct snd_vx_hardware *hw,
+                             const struct snd_vx_ops *ops, int extra_size);
 int snd_vx_setup_firmware(struct vx_core *chip);
 int snd_vx_load_boot_image(struct vx_core *chip, const struct firmware *dsp);
 int snd_vx_dsp_boot(struct vx_core *chip, const struct firmware *dsp);
index d5ec4fa..564ba1b 100644 (file)
@@ -915,9 +915,9 @@ TRACE_EVENT(afs_call_state,
 
 TRACE_EVENT(afs_lookup,
            TP_PROTO(struct afs_vnode *dvnode, const struct qstr *name,
-                    struct afs_vnode *vnode),
+                    struct afs_fid *fid),
 
-           TP_ARGS(dvnode, name, vnode),
+           TP_ARGS(dvnode, name, fid),
 
            TP_STRUCT__entry(
                    __field_struct(struct afs_fid,      dfid            )
@@ -928,13 +928,7 @@ TRACE_EVENT(afs_lookup,
            TP_fast_assign(
                    int __len = min_t(int, name->len, 23);
                    __entry->dfid = dvnode->fid;
-                   if (vnode) {
-                           __entry->fid = vnode->fid;
-                   } else {
-                           __entry->fid.vid = 0;
-                           __entry->fid.vnode = 0;
-                           __entry->fid.unique = 0;
-                   }
+                   __entry->fid = *fid;
                    memcpy(__entry->name, name->name, __len);
                    __entry->name[__len] = 0;
                           ),
index dd4db33..d82a0f4 100644 (file)
@@ -31,7 +31,8 @@
        EM( SCAN_ALLOC_HUGE_PAGE_FAIL,  "alloc_huge_page_failed")       \
        EM( SCAN_CGROUP_CHARGE_FAIL,    "ccgroup_charge_failed")        \
        EM( SCAN_EXCEED_SWAP_PTE,       "exceed_swap_pte")              \
-       EMe(SCAN_TRUNCATED,             "truncated")                    \
+       EM( SCAN_TRUNCATED,             "truncated")                    \
+       EMe(SCAN_PAGE_HAS_PRIVATE,      "page_has_private")             \
 
 #undef EM
 #undef EMe
index 95fba04..3f249e1 100644 (file)
@@ -18,13 +18,13 @@ DECLARE_EVENT_CLASS(preemptirq_template,
        TP_ARGS(ip, parent_ip),
 
        TP_STRUCT__entry(
-               __field(u32, caller_offs)
-               __field(u32, parent_offs)
+               __field(s32, caller_offs)
+               __field(s32, parent_offs)
        ),
 
        TP_fast_assign(
-               __entry->caller_offs = (u32)(ip - (unsigned long)_stext);
-               __entry->parent_offs = (u32)(parent_ip - (unsigned long)_stext);
+               __entry->caller_offs = (s32)(ip - (unsigned long)_stext);
+               __entry->parent_offs = (s32)(parent_ip - (unsigned long)_stext);
        ),
 
        TP_printk("caller=%pS parent=%pS",
index f056b2a..9a61c28 100644 (file)
@@ -34,6 +34,7 @@ struct input_event {
        __kernel_ulong_t __sec;
 #if defined(__sparc__) && defined(__arch64__)
        unsigned int __usec;
+       unsigned int __pad;
 #else
        __kernel_ulong_t __usec;
 #endif
index eabccb4..a3300e1 100644 (file)
@@ -48,6 +48,7 @@ struct io_uring_sqe {
 #define IOSQE_FIXED_FILE       (1U << 0)       /* use fixed fileset */
 #define IOSQE_IO_DRAIN         (1U << 1)       /* issue after inflight IO */
 #define IOSQE_IO_LINK          (1U << 2)       /* links next sqe */
+#define IOSQE_IO_HARDLINK      (1U << 3)       /* like LINK, but stronger */
 
 /*
  * io_uring_setup() flags
@@ -57,23 +58,28 @@ struct io_uring_sqe {
 #define IORING_SETUP_SQ_AFF    (1U << 2)       /* sq_thread_cpu is valid */
 #define IORING_SETUP_CQSIZE    (1U << 3)       /* app defines CQ size */
 
-#define IORING_OP_NOP          0
-#define IORING_OP_READV                1
-#define IORING_OP_WRITEV       2
-#define IORING_OP_FSYNC                3
-#define IORING_OP_READ_FIXED   4
-#define IORING_OP_WRITE_FIXED  5
-#define IORING_OP_POLL_ADD     6
-#define IORING_OP_POLL_REMOVE  7
-#define IORING_OP_SYNC_FILE_RANGE      8
-#define IORING_OP_SENDMSG      9
-#define IORING_OP_RECVMSG      10
-#define IORING_OP_TIMEOUT      11
-#define IORING_OP_TIMEOUT_REMOVE       12
-#define IORING_OP_ACCEPT       13
-#define IORING_OP_ASYNC_CANCEL 14
-#define IORING_OP_LINK_TIMEOUT 15
-#define IORING_OP_CONNECT      16
+enum {
+       IORING_OP_NOP,
+       IORING_OP_READV,
+       IORING_OP_WRITEV,
+       IORING_OP_FSYNC,
+       IORING_OP_READ_FIXED,
+       IORING_OP_WRITE_FIXED,
+       IORING_OP_POLL_ADD,
+       IORING_OP_POLL_REMOVE,
+       IORING_OP_SYNC_FILE_RANGE,
+       IORING_OP_SENDMSG,
+       IORING_OP_RECVMSG,
+       IORING_OP_TIMEOUT,
+       IORING_OP_TIMEOUT_REMOVE,
+       IORING_OP_ACCEPT,
+       IORING_OP_ASYNC_CANCEL,
+       IORING_OP_LINK_TIMEOUT,
+       IORING_OP_CONNECT,
+
+       /* this goes last, obviously */
+       IORING_OP_LAST,
+};
 
 /*
  * sqe->fsync_flags
index 409d3ad..1d0350e 100644 (file)
@@ -9,11 +9,11 @@
  * and the comment before kcov_remote_start() for usage details.
  */
 struct kcov_remote_arg {
-       unsigned int    trace_mode;     /* KCOV_TRACE_PC or KCOV_TRACE_CMP */
-       unsigned int    area_size;      /* Length of coverage buffer in words */
-       unsigned int    num_handles;    /* Size of handles array */
-       __u64           common_handle;
-       __u64           handles[0];
+       __u32           trace_mode;     /* KCOV_TRACE_PC or KCOV_TRACE_CMP */
+       __u32           area_size;      /* Length of coverage buffer in words */
+       __u32           num_handles;    /* Size of handles array */
+       __aligned_u64   common_handle;
+       __aligned_u64   handles[0];
 };
 
 #define KCOV_REMOTE_MAX_HANDLES                0x100
index 4bc6d1a..b4d804a 100644 (file)
@@ -41,19 +41,19 @@ struct xt_sctp_info {
 #define SCTP_CHUNKMAP_SET(chunkmap, type)              \
        do {                                            \
                (chunkmap)[type / bytes(__u32)] |=      \
-                       1 << (type % bytes(__u32));     \
+                       1u << (type % bytes(__u32));    \
        } while (0)
 
 #define SCTP_CHUNKMAP_CLEAR(chunkmap, type)                    \
        do {                                                    \
                (chunkmap)[type / bytes(__u32)] &=              \
-                       ~(1 << (type % bytes(__u32)));  \
+                       ~(1u << (type % bytes(__u32))); \
        } while (0)
 
 #define SCTP_CHUNKMAP_IS_SET(chunkmap, type)                   \
 ({                                                             \
        ((chunkmap)[type / bytes (__u32)] &             \
-               (1 << (type % bytes (__u32)))) ? 1: 0;  \
+               (1u << (type % bytes (__u32)))) ? 1: 0; \
 })
 
 #define SCTP_CHUNKMAP_RESET(chunkmap) \
index 341e0e8..5eab191 100644 (file)
@@ -5517,6 +5517,10 @@ enum nl80211_feature_flags {
  *     with VLAN tagged frames and separate VLAN-specific netdevs added using
  *     vconfig similarly to the Ethernet case.
  *
+ * @NL80211_EXT_FEATURE_AQL: The driver supports the Airtime Queue Limit (AQL)
+ *     feature, which prevents bufferbloat by using the expected transmission
+ *     time to limit the amount of data buffered in the hardware.
+ *
  * @NUM_NL80211_EXT_FEATURES: number of extended features.
  * @MAX_NL80211_EXT_FEATURES: highest extended feature index.
  */
@@ -5563,6 +5567,7 @@ enum nl80211_ext_feature_index {
        NL80211_EXT_FEATURE_STA_TX_PWR,
        NL80211_EXT_FEATURE_SAE_OFFLOAD,
        NL80211_EXT_FEATURE_VLAN_OFFLOAD,
+       NL80211_EXT_FEATURE_AQL,
 
        /* add new features before the definition below */
        NUM_NL80211_EXT_FEATURES,
index a74ca23..6048553 100644 (file)
@@ -17,7 +17,6 @@
 #define __LINUX_UAPI_SND_ASOC_H
 
 #include <linux/types.h>
-#include <sound/asound.h>
 
 /*
  * Maximum number of channels topology kcontrol can represent.
index df1153c..535a722 100644 (file)
@@ -26,7 +26,9 @@
 
 #if defined(__KERNEL__) || defined(__linux__)
 #include <linux/types.h>
+#include <asm/byteorder.h>
 #else
+#include <endian.h>
 #include <sys/ioctl.h>
 #endif
 
@@ -154,7 +156,7 @@ struct snd_hwdep_dsp_image {
  *                                                                           *
  *****************************************************************************/
 
-#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 14)
+#define SNDRV_PCM_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 15)
 
 typedef unsigned long snd_pcm_uframes_t;
 typedef signed long snd_pcm_sframes_t;
@@ -301,7 +303,9 @@ typedef int __bitwise snd_pcm_subformat_t;
 #define SNDRV_PCM_INFO_DRAIN_TRIGGER   0x40000000              /* internal kernel flag - trigger in drain */
 #define SNDRV_PCM_INFO_FIFO_IN_FRAMES  0x80000000      /* internal kernel flag - FIFO size is in frames */
 
-
+#if (__BITS_PER_LONG == 32 && defined(__USE_TIME_BITS64)) || defined __KERNEL__
+#define __SND_STRUCT_TIME64
+#endif
 
 typedef int __bitwise snd_pcm_state_t;
 #define        SNDRV_PCM_STATE_OPEN            ((__force snd_pcm_state_t) 0) /* stream is open */
@@ -317,8 +321,17 @@ typedef int __bitwise snd_pcm_state_t;
 
 enum {
        SNDRV_PCM_MMAP_OFFSET_DATA = 0x00000000,
-       SNDRV_PCM_MMAP_OFFSET_STATUS = 0x80000000,
-       SNDRV_PCM_MMAP_OFFSET_CONTROL = 0x81000000,
+       SNDRV_PCM_MMAP_OFFSET_STATUS_OLD = 0x80000000,
+       SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD = 0x81000000,
+       SNDRV_PCM_MMAP_OFFSET_STATUS_NEW = 0x82000000,
+       SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW = 0x83000000,
+#ifdef __SND_STRUCT_TIME64
+       SNDRV_PCM_MMAP_OFFSET_STATUS = SNDRV_PCM_MMAP_OFFSET_STATUS_NEW,
+       SNDRV_PCM_MMAP_OFFSET_CONTROL = SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW,
+#else
+       SNDRV_PCM_MMAP_OFFSET_STATUS = SNDRV_PCM_MMAP_OFFSET_STATUS_OLD,
+       SNDRV_PCM_MMAP_OFFSET_CONTROL = SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD,
+#endif
 };
 
 union snd_pcm_sync_id {
@@ -456,8 +469,13 @@ enum {
        SNDRV_PCM_AUDIO_TSTAMP_TYPE_LAST = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED
 };
 
+#ifndef __KERNEL__
+/* explicit padding avoids incompatibility between i386 and x86-64 */
+typedef struct { unsigned char pad[sizeof(time_t) - sizeof(int)]; } __time_pad;
+
 struct snd_pcm_status {
        snd_pcm_state_t state;          /* stream state */
+       __time_pad pad1;                /* align to timespec */
        struct timespec trigger_tstamp; /* time when stream was started/stopped/paused */
        struct timespec tstamp;         /* reference timestamp */
        snd_pcm_uframes_t appl_ptr;     /* appl ptr */
@@ -473,17 +491,48 @@ struct snd_pcm_status {
        __u32 audio_tstamp_accuracy;    /* in ns units, only valid if indicated in audio_tstamp_data */
        unsigned char reserved[52-2*sizeof(struct timespec)]; /* must be filled with zero */
 };
+#endif
+
+/*
+ * For mmap operations, we need the 64-bit layout, both for compat mode,
+ * and for y2038 compatibility. For 64-bit applications, the two definitions
+ * are identical, so we keep the traditional version.
+ */
+#ifdef __SND_STRUCT_TIME64
+#define __snd_pcm_mmap_status64                snd_pcm_mmap_status
+#define __snd_pcm_mmap_control64       snd_pcm_mmap_control
+#define __snd_pcm_sync_ptr64           snd_pcm_sync_ptr
+#ifdef __KERNEL__
+#define __snd_timespec64               __kernel_timespec
+#else
+#define __snd_timespec64               timespec
+#endif
+struct __snd_timespec {
+       __s32 tv_sec;
+       __s32 tv_nsec;
+};
+#else
+#define __snd_pcm_mmap_status          snd_pcm_mmap_status
+#define __snd_pcm_mmap_control         snd_pcm_mmap_control
+#define __snd_pcm_sync_ptr             snd_pcm_sync_ptr
+#define __snd_timespec                 timespec
+struct __snd_timespec64 {
+       __s64 tv_sec;
+       __s64 tv_nsec;
+};
 
-struct snd_pcm_mmap_status {
+#endif
+
+struct __snd_pcm_mmap_status {
        snd_pcm_state_t state;          /* RO: state - SNDRV_PCM_STATE_XXXX */
        int pad1;                       /* Needed for 64 bit alignment */
        snd_pcm_uframes_t hw_ptr;       /* RO: hw ptr (0...boundary-1) */
-       struct timespec tstamp;         /* Timestamp */
+       struct __snd_timespec tstamp;   /* Timestamp */
        snd_pcm_state_t suspended_state; /* RO: suspended stream state */
-       struct timespec audio_tstamp;   /* from sample counter or wall clock */
+       struct __snd_timespec audio_tstamp; /* from sample counter or wall clock */
 };
 
-struct snd_pcm_mmap_control {
+struct __snd_pcm_mmap_control {
        snd_pcm_uframes_t appl_ptr;     /* RW: appl ptr (0...boundary-1) */
        snd_pcm_uframes_t avail_min;    /* RW: min available frames for wakeup */
 };
@@ -492,14 +541,59 @@ struct snd_pcm_mmap_control {
 #define SNDRV_PCM_SYNC_PTR_APPL                (1<<1)  /* get appl_ptr from driver (r/w op) */
 #define SNDRV_PCM_SYNC_PTR_AVAIL_MIN   (1<<2)  /* get avail_min from driver */
 
-struct snd_pcm_sync_ptr {
+struct __snd_pcm_sync_ptr {
        unsigned int flags;
        union {
-               struct snd_pcm_mmap_status status;
+               struct __snd_pcm_mmap_status status;
+               unsigned char reserved[64];
+       } s;
+       union {
+               struct __snd_pcm_mmap_control control;
+               unsigned char reserved[64];
+       } c;
+};
+
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
+typedef char __pad_before_uframe[sizeof(__u64) - sizeof(snd_pcm_uframes_t)];
+typedef char __pad_after_uframe[0];
+#endif
+
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
+typedef char __pad_before_uframe[0];
+typedef char __pad_after_uframe[sizeof(__u64) - sizeof(snd_pcm_uframes_t)];
+#endif
+
+struct __snd_pcm_mmap_status64 {
+       snd_pcm_state_t state;          /* RO: state - SNDRV_PCM_STATE_XXXX */
+       __u32 pad1;                     /* Needed for 64 bit alignment */
+       __pad_before_uframe __pad1;
+       snd_pcm_uframes_t hw_ptr;       /* RO: hw ptr (0...boundary-1) */
+       __pad_after_uframe __pad2;
+       struct __snd_timespec64 tstamp; /* Timestamp */
+       snd_pcm_state_t suspended_state;/* RO: suspended stream state */
+       __u32 pad3;                     /* Needed for 64 bit alignment */
+       struct __snd_timespec64 audio_tstamp; /* sample counter or wall clock */
+};
+
+struct __snd_pcm_mmap_control64 {
+       __pad_before_uframe __pad1;
+       snd_pcm_uframes_t appl_ptr;      /* RW: appl ptr (0...boundary-1) */
+       __pad_before_uframe __pad2;
+
+       __pad_before_uframe __pad3;
+       snd_pcm_uframes_t  avail_min;    /* RW: min available frames for wakeup */
+       __pad_after_uframe __pad4;
+};
+
+struct __snd_pcm_sync_ptr64 {
+       __u32 flags;
+       __u32 pad1;
+       union {
+               struct __snd_pcm_mmap_status64 status;
                unsigned char reserved[64];
        } s;
        union {
-               struct snd_pcm_mmap_control control;
+               struct __snd_pcm_mmap_control64 control;
                unsigned char reserved[64];
        } c;
 };
@@ -584,6 +678,8 @@ enum {
 #define SNDRV_PCM_IOCTL_STATUS         _IOR('A', 0x20, struct snd_pcm_status)
 #define SNDRV_PCM_IOCTL_DELAY          _IOR('A', 0x21, snd_pcm_sframes_t)
 #define SNDRV_PCM_IOCTL_HWSYNC         _IO('A', 0x22)
+#define __SNDRV_PCM_IOCTL_SYNC_PTR     _IOWR('A', 0x23, struct __snd_pcm_sync_ptr)
+#define __SNDRV_PCM_IOCTL_SYNC_PTR64   _IOWR('A', 0x23, struct __snd_pcm_sync_ptr64)
 #define SNDRV_PCM_IOCTL_SYNC_PTR       _IOWR('A', 0x23, struct snd_pcm_sync_ptr)
 #define SNDRV_PCM_IOCTL_STATUS_EXT     _IOWR('A', 0x24, struct snd_pcm_status)
 #define SNDRV_PCM_IOCTL_CHANNEL_INFO   _IOR('A', 0x32, struct snd_pcm_channel_info)
@@ -614,7 +710,7 @@ enum {
  *  Raw MIDI section - /dev/snd/midi??
  */
 
-#define SNDRV_RAWMIDI_VERSION          SNDRV_PROTOCOL_VERSION(2, 0, 0)
+#define SNDRV_RAWMIDI_VERSION          SNDRV_PROTOCOL_VERSION(2, 0, 1)
 
 enum {
        SNDRV_RAWMIDI_STREAM_OUTPUT = 0,
@@ -648,13 +744,16 @@ struct snd_rawmidi_params {
        unsigned char reserved[16];     /* reserved for future use */
 };
 
+#ifndef __KERNEL__
 struct snd_rawmidi_status {
        int stream;
+       __time_pad pad1;
        struct timespec tstamp;         /* Timestamp */
        size_t avail;                   /* available bytes */
        size_t xruns;                   /* count of overruns since last status (in bytes) */
        unsigned char reserved[16];     /* reserved for future use */
 };
+#endif
 
 #define SNDRV_RAWMIDI_IOCTL_PVERSION   _IOR('W', 0x00, int)
 #define SNDRV_RAWMIDI_IOCTL_INFO       _IOR('W', 0x01, struct snd_rawmidi_info)
@@ -667,7 +766,7 @@ struct snd_rawmidi_status {
  *  Timer section - /dev/snd/timer
  */
 
-#define SNDRV_TIMER_VERSION            SNDRV_PROTOCOL_VERSION(2, 0, 6)
+#define SNDRV_TIMER_VERSION            SNDRV_PROTOCOL_VERSION(2, 0, 7)
 
 enum {
        SNDRV_TIMER_CLASS_NONE = -1,
@@ -761,6 +860,7 @@ struct snd_timer_params {
        unsigned char reserved[60];     /* reserved */
 };
 
+#ifndef __KERNEL__
 struct snd_timer_status {
        struct timespec tstamp;         /* Timestamp - last update */
        unsigned int resolution;        /* current period resolution in ns */
@@ -769,10 +869,11 @@ struct snd_timer_status {
        unsigned int queue;             /* used queue size */
        unsigned char reserved[64];     /* reserved */
 };
+#endif
 
 #define SNDRV_TIMER_IOCTL_PVERSION     _IOR('T', 0x00, int)
 #define SNDRV_TIMER_IOCTL_NEXT_DEVICE  _IOWR('T', 0x01, struct snd_timer_id)
-#define SNDRV_TIMER_IOCTL_TREAD                _IOW('T', 0x02, int)
+#define SNDRV_TIMER_IOCTL_TREAD_OLD    _IOW('T', 0x02, int)
 #define SNDRV_TIMER_IOCTL_GINFO                _IOWR('T', 0x03, struct snd_timer_ginfo)
 #define SNDRV_TIMER_IOCTL_GPARAMS      _IOW('T', 0x04, struct snd_timer_gparams)
 #define SNDRV_TIMER_IOCTL_GSTATUS      _IOWR('T', 0x05, struct snd_timer_gstatus)
@@ -785,6 +886,15 @@ struct snd_timer_status {
 #define SNDRV_TIMER_IOCTL_STOP         _IO('T', 0xa1)
 #define SNDRV_TIMER_IOCTL_CONTINUE     _IO('T', 0xa2)
 #define SNDRV_TIMER_IOCTL_PAUSE                _IO('T', 0xa3)
+#define SNDRV_TIMER_IOCTL_TREAD64      _IOW('T', 0xa4, int)
+
+#if __BITS_PER_LONG == 64
+#define SNDRV_TIMER_IOCTL_TREAD SNDRV_TIMER_IOCTL_TREAD_OLD
+#else
+#define SNDRV_TIMER_IOCTL_TREAD ((sizeof(__kernel_long_t) >= sizeof(time_t)) ? \
+                                SNDRV_TIMER_IOCTL_TREAD_OLD : \
+                                SNDRV_TIMER_IOCTL_TREAD64)
+#endif
 
 struct snd_timer_read {
        unsigned int resolution;
@@ -810,11 +920,15 @@ enum {
        SNDRV_TIMER_EVENT_MRESUME = SNDRV_TIMER_EVENT_RESUME + 10,
 };
 
+#ifndef __KERNEL__
 struct snd_timer_tread {
        int event;
+       __time_pad pad1;
        struct timespec tstamp;
        unsigned int val;
+       __time_pad pad2;
 };
+#endif
 
 /****************************************************************************
  *                                                                          *
@@ -822,7 +936,7 @@ struct snd_timer_tread {
  *                                                                          *
  ****************************************************************************/
 
-#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 7)
+#define SNDRV_CTL_VERSION              SNDRV_PROTOCOL_VERSION(2, 0, 8)
 
 struct snd_ctl_card_info {
        int card;                       /* card number */
@@ -860,7 +974,7 @@ typedef int __bitwise snd_ctl_elem_iface_t;
 #define SNDRV_CTL_ELEM_ACCESS_WRITE            (1<<1)
 #define SNDRV_CTL_ELEM_ACCESS_READWRITE                (SNDRV_CTL_ELEM_ACCESS_READ|SNDRV_CTL_ELEM_ACCESS_WRITE)
 #define SNDRV_CTL_ELEM_ACCESS_VOLATILE         (1<<2)  /* control value may be changed without a notification */
-#define SNDRV_CTL_ELEM_ACCESS_TIMESTAMP                (1<<3)  /* when was control changed */
+// (1 << 3) is unused.
 #define SNDRV_CTL_ELEM_ACCESS_TLV_READ         (1<<4)  /* TLV read is possible */
 #define SNDRV_CTL_ELEM_ACCESS_TLV_WRITE                (1<<5)  /* TLV write is possible */
 #define SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE    (SNDRV_CTL_ELEM_ACCESS_TLV_READ|SNDRV_CTL_ELEM_ACCESS_TLV_WRITE)
@@ -926,11 +1040,7 @@ struct snd_ctl_elem_info {
                } enumerated;
                unsigned char reserved[128];
        } value;
-       union {
-               unsigned short d[4];            /* dimensions */
-               unsigned short *d_ptr;          /* indirect - obsoleted */
-       } dimen;
-       unsigned char reserved[64-4*sizeof(unsigned short)];
+       unsigned char reserved[64];
 };
 
 struct snd_ctl_elem_value {
@@ -955,8 +1065,7 @@ struct snd_ctl_elem_value {
                } bytes;
                struct snd_aes_iec958 iec958;
        } value;                /* RO */
-       struct timespec tstamp;
-       unsigned char reserved[128-sizeof(struct timespec)];
+       unsigned char reserved[128];
 };
 
 struct snd_ctl_tlv {
index 042c5a6..88609cc 100644 (file)
@@ -23,8 +23,9 @@
 #ifndef _UAPI__SOUND_EMU10K1_H
 #define _UAPI__SOUND_EMU10K1_H
 
+#ifdef __linux__
 #include <linux/types.h>
-#include <sound/asound.h>
+#endif
 
 /*
  * ---- FX8010 ----
@@ -282,8 +283,22 @@ struct snd_emu10k1_fx8010_info {
 #define EMU10K1_GPR_TRANSLATION_TREBLE         3
 #define EMU10K1_GPR_TRANSLATION_ONOFF          4
 
+enum emu10k1_ctl_elem_iface {
+       EMU10K1_CTL_ELEM_IFACE_MIXER = 2,       /* virtual mixer device */
+       EMU10K1_CTL_ELEM_IFACE_PCM = 3,         /* PCM device */
+};
+
+struct emu10k1_ctl_elem_id {
+       unsigned int pad;               /* don't use */
+       int iface;                      /* interface identifier */
+       unsigned int device;            /* device/client number */
+       unsigned int subdevice;         /* subdevice (substream) number */
+       unsigned char name[44];         /* ASCII name of item */
+       unsigned int index;             /* index of item */
+};
+
 struct snd_emu10k1_fx8010_control_gpr {
-       struct snd_ctl_elem_id id;              /* full control ID definition */
+       struct emu10k1_ctl_elem_id id;  /* full control ID definition */
        unsigned int vcount;            /* visible count */
        unsigned int count;             /* count of GPR (1..16) */
        unsigned short gpr[32];         /* GPR number(s) */
@@ -296,7 +311,7 @@ struct snd_emu10k1_fx8010_control_gpr {
 
 /* old ABI without TLV support */
 struct snd_emu10k1_fx8010_control_old_gpr {
-       struct snd_ctl_elem_id id;
+       struct emu10k1_ctl_elem_id id;
        unsigned int vcount;
        unsigned int count;
        unsigned short gpr[32];
@@ -310,24 +325,24 @@ struct snd_emu10k1_fx8010_code {
        char name[128];
 
        __EMU10K1_DECLARE_BITMAP(gpr_valid, 0x200); /* bitmask of valid initializers */
-       __u32 __user *gpr_map;          /* initializers */
+       __u32 *gpr_map;                 /* initializers */
 
        unsigned int gpr_add_control_count; /* count of GPR controls to add/replace */
-       struct snd_emu10k1_fx8010_control_gpr __user *gpr_add_controls; /* GPR controls to add/replace */
+       struct snd_emu10k1_fx8010_control_gpr *gpr_add_controls; /* GPR controls to add/replace */
 
        unsigned int gpr_del_control_count; /* count of GPR controls to remove */
-       struct snd_ctl_elem_id __user *gpr_del_controls; /* IDs of GPR controls to remove */
+       struct emu10k1_ctl_elem_id *gpr_del_controls; /* IDs of GPR controls to remove */
 
        unsigned int gpr_list_control_count; /* count of GPR controls to list */
        unsigned int gpr_list_control_total; /* total count of GPR controls */
-       struct snd_emu10k1_fx8010_control_gpr __user *gpr_list_controls; /* listed GPR controls */
+       struct snd_emu10k1_fx8010_control_gpr *gpr_list_controls; /* listed GPR controls */
 
        __EMU10K1_DECLARE_BITMAP(tram_valid, 0x100); /* bitmask of valid initializers */
-       __u32 __user *tram_data_map;      /* data initializers */
-       __u32 __user *tram_addr_map;      /* map initializers */
+       __u32 *tram_data_map;             /* data initializers */
+       __u32 *tram_addr_map;             /* map initializers */
 
        __EMU10K1_DECLARE_BITMAP(code_valid, 1024); /* bitmask of valid instructions */
-       __u32 __user *code;               /* one instruction - 64 bits */
+       __u32 *code;                      /* one instruction - 64 bits */
 };
 
 struct snd_emu10k1_fx8010_tram {
@@ -371,11 +386,4 @@ struct snd_emu10k1_fx8010_pcm_rec {
 #define SNDRV_EMU10K1_IOCTL_SINGLE_STEP        _IOW ('H', 0x83, int)
 #define SNDRV_EMU10K1_IOCTL_DBG_READ   _IOR ('H', 0x84, int)
 
-/* typedefs for compatibility to user-space */
-typedef struct snd_emu10k1_fx8010_info emu10k1_fx8010_info_t;
-typedef struct snd_emu10k1_fx8010_control_gpr emu10k1_fx8010_control_gpr_t;
-typedef struct snd_emu10k1_fx8010_code emu10k1_fx8010_code_t;
-typedef struct snd_emu10k1_fx8010_tram emu10k1_fx8010_tram_t;
-typedef struct snd_emu10k1_fx8010_pcm_rec emu10k1_fx8010_pcm_t;
-
 #endif /* _UAPI__SOUND_EMU10K1_H */
index 5dc0c3d..b8df62b 100644 (file)
@@ -20,7 +20,9 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifdef __linux__
 #include <linux/types.h>
+#endif
 
 #define HDSP_MATRIX_MIXER_SIZE 2048
 
@@ -74,7 +76,7 @@ struct hdsp_config_info {
 #define SNDRV_HDSP_IOCTL_GET_CONFIG_INFO _IOR('H', 0x41, struct hdsp_config_info)
 
 struct hdsp_firmware {
-       void __user *firmware_data;     /* 24413 x 4 bytes */
+       void *firmware_data;    /* 24413 x 4 bytes */
 };
 
 #define SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE _IOW('H', 0x42, struct hdsp_firmware)
@@ -99,13 +101,4 @@ struct hdsp_9632_aeb {
 
 #define SNDRV_HDSP_IOCTL_GET_9632_AEB _IOR('H', 0x45, struct hdsp_9632_aeb)
 
-/* typedefs for compatibility to user-space */
-typedef enum HDSP_IO_Type HDSP_IO_Type;
-typedef struct hdsp_peak_rms hdsp_peak_rms_t;
-typedef struct hdsp_config_info hdsp_config_info_t;
-typedef struct hdsp_firmware hdsp_firmware_t;
-typedef struct hdsp_version hdsp_version_t;
-typedef struct hdsp_mixer hdsp_mixer_t;
-typedef struct hdsp_9632_aeb hdsp_9632_aeb_t;
-
 #endif /* __SOUND_HDSP_H */
index a38f3f7..14af3d0 100644 (file)
@@ -21,7 +21,9 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#ifdef __linux__
 #include <linux/types.h>
+#endif
 
 /* Maximum channels is 64 even on 56Mode you have 64playbacks to matrix */
 #define HDSPM_MAX_CHANNELS      64
@@ -221,12 +223,4 @@ struct hdspm_mixer_ioctl {
 /* use indirect access due to the limit of ioctl bit size */
 #define SNDRV_HDSPM_IOCTL_GET_MIXER _IOR('H', 0x44, struct hdspm_mixer_ioctl)
 
-/* typedefs for compatibility to user-space */
-typedef struct hdspm_peak_rms hdspm_peak_rms_t;
-typedef struct hdspm_config_info hdspm_config_info_t;
-typedef struct hdspm_version hdspm_version_t;
-typedef struct hdspm_channelfader snd_hdspm_channelfader_t;
-typedef struct hdspm_mixer hdspm_mixer_t;
-
-
 #endif
index 3f40501..2af7a1c 100644 (file)
@@ -125,35 +125,24 @@ struct __name##_back_ring {                                               \
     memset((_s)->pad, 0, sizeof((_s)->pad));                           \
 } while(0)
 
-#define FRONT_RING_INIT(_r, _s, __size) do {                           \
-    (_r)->req_prod_pvt = 0;                                            \
-    (_r)->rsp_cons = 0;                                                        \
+#define FRONT_RING_ATTACH(_r, _s, _i, __size) do {                     \
+    (_r)->req_prod_pvt = (_i);                                         \
+    (_r)->rsp_cons = (_i);                                             \
     (_r)->nr_ents = __RING_SIZE(_s, __size);                           \
     (_r)->sring = (_s);                                                        \
 } while (0)
 
-#define BACK_RING_INIT(_r, _s, __size) do {                            \
-    (_r)->rsp_prod_pvt = 0;                                            \
-    (_r)->req_cons = 0;                                                        \
-    (_r)->nr_ents = __RING_SIZE(_s, __size);                           \
-    (_r)->sring = (_s);                                                        \
-} while (0)
+#define FRONT_RING_INIT(_r, _s, __size) FRONT_RING_ATTACH(_r, _s, 0, __size)
 
-/* Initialize to existing shared indexes -- for recovery */
-#define FRONT_RING_ATTACH(_r, _s, __size) do {                         \
-    (_r)->sring = (_s);                                                        \
-    (_r)->req_prod_pvt = (_s)->req_prod;                               \
-    (_r)->rsp_cons = (_s)->rsp_prod;                                   \
+#define BACK_RING_ATTACH(_r, _s, _i, __size) do {                      \
+    (_r)->rsp_prod_pvt = (_i);                                         \
+    (_r)->req_cons = (_i);                                             \
     (_r)->nr_ents = __RING_SIZE(_s, __size);                           \
-} while (0)
-
-#define BACK_RING_ATTACH(_r, _s, __size) do {                          \
     (_r)->sring = (_s);                                                        \
-    (_r)->rsp_prod_pvt = (_s)->rsp_prod;                               \
-    (_r)->req_cons = (_s)->req_prod;                                   \
-    (_r)->nr_ents = __RING_SIZE(_s, __size);                           \
 } while (0)
 
+#define BACK_RING_INIT(_r, _s, __size) BACK_RING_ATTACH(_r, _s, 0, __size)
+
 /* How big is this ring? */
 #define RING_SIZE(_r)                                                  \
     ((_r)->nr_ents)
index 869c816..24228a1 100644 (file)
@@ -93,6 +93,7 @@ struct xenbus_device_id
 struct xenbus_driver {
        const char *name;       /* defaults to ids[0].devicetype */
        const struct xenbus_device_id *ids;
+       bool allow_rebind; /* avoid setting xenstore closed during remove */
        int (*probe)(struct xenbus_device *dev,
                     const struct xenbus_device_id *id);
        void (*otherend_changed)(struct xenbus_device *dev,
index af9cda8..0ae9cc2 100644 (file)
@@ -387,12 +387,27 @@ static void __init get_fs_names(char *page)
        *s = '\0';
 }
 
-static int __init do_mount_root(char *name, char *fs, int flags, void *data)
+static int __init do_mount_root(const char *name, const char *fs,
+                                const int flags, const void *data)
 {
        struct super_block *s;
-       int err = ksys_mount(name, "/root", fs, flags, data);
-       if (err)
-               return err;
+       struct page *p = NULL;
+       char *data_page = NULL;
+       int ret;
+
+       if (data) {
+               /* do_mount() requires a full page as fifth argument */
+               p = alloc_page(GFP_KERNEL);
+               if (!p)
+                       return -ENOMEM;
+               data_page = page_address(p);
+               /* zero-pad. do_mount() will make sure it's terminated */
+               strncpy(data_page, data, PAGE_SIZE);
+       }
+
+       ret = do_mount(name, "/root", fs, flags, data_page);
+       if (ret)
+               goto out;
 
        ksys_chdir("/root");
        s = current->fs->pwd.dentry->d_sb;
@@ -402,7 +417,11 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
               s->s_type->name,
               sb_rdonly(s) ? " readonly" : "",
               MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
-       return 0;
+
+out:
+       if (p)
+               put_page(p);
+       return ret;
 }
 
 void __init mount_block_root(char *name, int flags)
@@ -670,8 +689,8 @@ void __init prepare_namespace(void)
 
        mount_root();
 out:
-       devtmpfs_mount("dev");
-       ksys_mount(".", "/", NULL, MS_MOVE, NULL);
+       devtmpfs_mount();
+       do_mount(".", "/", NULL, MS_MOVE, NULL);
        ksys_chroot(".");
 }
 
index a9c6cc5..dab8b11 100644 (file)
@@ -48,13 +48,10 @@ early_param("initrd", early_initrd);
 static int init_linuxrc(struct subprocess_info *info, struct cred *new)
 {
        ksys_unshare(CLONE_FS | CLONE_FILES);
-       /* stdin/stdout/stderr for /linuxrc */
-       ksys_open("/dev/console", O_RDWR, 0);
-       ksys_dup(0);
-       ksys_dup(0);
+       console_on_rootfs();
        /* move initrd over / and chdir/chroot in initrd root */
        ksys_chdir("/root");
-       ksys_mount(".", "/", NULL, MS_MOVE, NULL);
+       do_mount(".", "/", NULL, MS_MOVE, NULL);
        ksys_chroot(".");
        ksys_setsid();
        return 0;
@@ -89,7 +86,7 @@ static void __init handle_initrd(void)
        current->flags &= ~PF_FREEZER_SKIP;
 
        /* move initrd to rootfs' /old */
-       ksys_mount("..", ".", NULL, MS_MOVE, NULL);
+       do_mount("..", ".", NULL, MS_MOVE, NULL);
        /* switch root and cwd back to / of rootfs */
        ksys_chroot("..");
 
@@ -103,7 +100,7 @@ static void __init handle_initrd(void)
        mount_root();
 
        printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
-       error = ksys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
+       error = do_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
        if (!error)
                printk("okay\n");
        else {
index 91f6ebb..da1bc0b 100644 (file)
@@ -553,6 +553,7 @@ static void __init mm_init(void)
         * bigger than MAX_ORDER unless SPARSEMEM.
         */
        page_ext_init_flatmem();
+       init_debug_pagealloc();
        report_meminit();
        mem_init();
        kmem_cache_init();
@@ -1155,6 +1156,17 @@ static int __ref kernel_init(void *unused)
              "See Linux Documentation/admin-guide/init.rst for guidance.");
 }
 
+void console_on_rootfs(void)
+{
+       /* Open the /dev/console as stdin, this should never fail */
+       if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
+               pr_err("Warning: unable to open an initial console.\n");
+
+       /* create stdout/stderr */
+       (void) ksys_dup(0);
+       (void) ksys_dup(0);
+}
+
 static noinline void __init kernel_init_freeable(void)
 {
        /*
@@ -1190,12 +1202,8 @@ static noinline void __init kernel_init_freeable(void)
 
        do_basic_setup();
 
-       /* Open the /dev/console on the rootfs, this should never fail */
-       if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
-               pr_err("Warning: unable to open an initial console.\n");
+       console_on_rootfs();
 
-       (void) ksys_dup(0);
-       (void) ksys_dup(0);
        /*
         * check if there is an early userspace init.  If yes, let it do all
         * the work
index d126d15..915eacb 100644 (file)
@@ -100,7 +100,7 @@ device_initcall(ipc_init);
 static const struct rhashtable_params ipc_kht_params = {
        .head_offset            = offsetof(struct kern_ipc_perm, khtnode),
        .key_offset             = offsetof(struct kern_ipc_perm, key),
-       .key_len                = FIELD_SIZEOF(struct kern_ipc_perm, key),
+       .key_len                = sizeof_field(struct kern_ipc_perm, key),
        .automatic_shrinking    = true,
 };
 
index 7d40da2..ed20758 100644 (file)
@@ -3470,6 +3470,7 @@ static u8 bpf_ctx_convert_map[] = {
        [_id] = __ctx_convert##_id,
 #include <linux/bpf_types.h>
 #undef BPF_PROG_TYPE
+       0, /* avoid empty array */
 };
 #undef BPF_MAP_TYPE
 
index 9f90d3c..9e43b72 100644 (file)
@@ -35,8 +35,8 @@ void cgroup_bpf_offline(struct cgroup *cgrp)
  */
 static void cgroup_bpf_release(struct work_struct *work)
 {
-       struct cgroup *cgrp = container_of(work, struct cgroup,
-                                          bpf.release_work);
+       struct cgroup *p, *cgrp = container_of(work, struct cgroup,
+                                              bpf.release_work);
        enum bpf_cgroup_storage_type stype;
        struct bpf_prog_array *old_array;
        unsigned int type;
@@ -65,6 +65,9 @@ static void cgroup_bpf_release(struct work_struct *work)
 
        mutex_unlock(&cgroup_mutex);
 
+       for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p))
+               cgroup_bpf_put(p);
+
        percpu_ref_exit(&cgrp->bpf.refcnt);
        cgroup_put(cgrp);
 }
@@ -199,6 +202,7 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
  */
 #define        NR ARRAY_SIZE(cgrp->bpf.effective)
        struct bpf_prog_array *arrays[NR] = {};
+       struct cgroup *p;
        int ret, i;
 
        ret = percpu_ref_init(&cgrp->bpf.refcnt, cgroup_bpf_release_fn, 0,
@@ -206,6 +210,9 @@ int cgroup_bpf_inherit(struct cgroup *cgrp)
        if (ret)
                return ret;
 
+       for (p = cgroup_parent(cgrp); p; p = cgroup_parent(p))
+               cgroup_bpf_get(p);
+
        for (i = 0; i < NR; i++)
                INIT_LIST_HEAD(&cgrp->bpf.progs[i]);
 
@@ -1341,7 +1348,7 @@ static u32 sysctl_convert_ctx_access(enum bpf_access_type type,
                *insn++ = BPF_LDX_MEM(
                        BPF_SIZE(si->code), si->dst_reg, si->src_reg,
                        bpf_target_off(struct bpf_sysctl_kern, write,
-                                      FIELD_SIZEOF(struct bpf_sysctl_kern,
+                                      sizeof_field(struct bpf_sysctl_kern,
                                                    write),
                                       target_size));
                break;
index 49e32ac..af6b738 100644 (file)
@@ -2043,23 +2043,28 @@ static void bpf_free_cgroup_storage(struct bpf_prog_aux *aux)
        for_each_cgroup_storage_type(stype) {
                if (!aux->cgroup_storage[stype])
                        continue;
-               bpf_cgroup_storage_release(aux->prog,
-                                          aux->cgroup_storage[stype]);
+               bpf_cgroup_storage_release(aux, aux->cgroup_storage[stype]);
        }
 }
 
-static void bpf_free_used_maps(struct bpf_prog_aux *aux)
+void __bpf_free_used_maps(struct bpf_prog_aux *aux,
+                         struct bpf_map **used_maps, u32 len)
 {
        struct bpf_map *map;
-       int i;
+       u32 i;
 
        bpf_free_cgroup_storage(aux);
-       for (i = 0; i < aux->used_map_cnt; i++) {
-               map = aux->used_maps[i];
+       for (i = 0; i < len; i++) {
+               map = used_maps[i];
                if (map->ops->map_poke_untrack)
                        map->ops->map_poke_untrack(map, aux);
                bpf_map_put(map);
        }
+}
+
+static void bpf_free_used_maps(struct bpf_prog_aux *aux)
+{
+       __bpf_free_used_maps(aux, aux->used_maps, aux->used_map_cnt);
        kfree(aux->used_maps);
 }
 
index 2ba7507..33d0186 100644 (file)
@@ -20,7 +20,7 @@ struct bpf_cgroup_storage_map {
        struct bpf_map map;
 
        spinlock_t lock;
-       struct bpf_prog *prog;
+       struct bpf_prog_aux *aux;
        struct rb_root root;
        struct list_head list;
 };
@@ -357,7 +357,7 @@ static int cgroup_storage_check_btf(const struct bpf_map *map,
         * The first field must be a 64 bit integer at 0 offset.
         */
        m = (struct btf_member *)(key_type + 1);
-       size = FIELD_SIZEOF(struct bpf_cgroup_storage_key, cgroup_inode_id);
+       size = sizeof_field(struct bpf_cgroup_storage_key, cgroup_inode_id);
        if (!btf_member_is_reg_int(btf, key_type, m, 0, size))
                return -EINVAL;
 
@@ -366,7 +366,7 @@ static int cgroup_storage_check_btf(const struct bpf_map *map,
         */
        m++;
        offset = offsetof(struct bpf_cgroup_storage_key, attach_type);
-       size = FIELD_SIZEOF(struct bpf_cgroup_storage_key, attach_type);
+       size = sizeof_field(struct bpf_cgroup_storage_key, attach_type);
        if (!btf_member_is_reg_int(btf, key_type, m, offset, size))
                return -EINVAL;
 
@@ -420,7 +420,7 @@ const struct bpf_map_ops cgroup_storage_map_ops = {
        .map_seq_show_elem = cgroup_storage_seq_show_elem,
 };
 
-int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
+int bpf_cgroup_storage_assign(struct bpf_prog_aux *aux, struct bpf_map *_map)
 {
        enum bpf_cgroup_storage_type stype = cgroup_storage_type(_map);
        struct bpf_cgroup_storage_map *map = map_to_storage(_map);
@@ -428,14 +428,14 @@ int bpf_cgroup_storage_assign(struct bpf_prog *prog, struct bpf_map *_map)
 
        spin_lock_bh(&map->lock);
 
-       if (map->prog && map->prog != prog)
+       if (map->aux && map->aux != aux)
                goto unlock;
-       if (prog->aux->cgroup_storage[stype] &&
-           prog->aux->cgroup_storage[stype] != _map)
+       if (aux->cgroup_storage[stype] &&
+           aux->cgroup_storage[stype] != _map)
                goto unlock;
 
-       map->prog = prog;
-       prog->aux->cgroup_storage[stype] = _map;
+       map->aux = aux;
+       aux->cgroup_storage[stype] = _map;
        ret = 0;
 unlock:
        spin_unlock_bh(&map->lock);
@@ -443,16 +443,16 @@ unlock:
        return ret;
 }
 
-void bpf_cgroup_storage_release(struct bpf_prog *prog, struct bpf_map *_map)
+void bpf_cgroup_storage_release(struct bpf_prog_aux *aux, struct bpf_map *_map)
 {
        enum bpf_cgroup_storage_type stype = cgroup_storage_type(_map);
        struct bpf_cgroup_storage_map *map = map_to_storage(_map);
 
        spin_lock_bh(&map->lock);
-       if (map->prog == prog) {
-               WARN_ON(prog->aux->cgroup_storage[stype] != _map);
-               map->prog = NULL;
-               prog->aux->cgroup_storage[stype] = NULL;
+       if (map->aux == aux) {
+               WARN_ON(aux->cgroup_storage[stype] != _map);
+               map->aux = NULL;
+               aux->cgroup_storage[stype] = NULL;
        }
        spin_unlock_bh(&map->lock);
 }
index ca52b96..d4f335a 100644 (file)
@@ -44,14 +44,19 @@ struct tnum tnum_rshift(struct tnum a, u8 shift)
        return TNUM(a.value >> shift, a.mask >> shift);
 }
 
-struct tnum tnum_arshift(struct tnum a, u8 min_shift)
+struct tnum tnum_arshift(struct tnum a, u8 min_shift, u8 insn_bitness)
 {
        /* if a.value is negative, arithmetic shifting by minimum shift
         * will have larger negative offset compared to more shifting.
         * If a.value is nonnegative, arithmetic shifting by minimum shift
         * will have larger positive offset compare to more shifting.
         */
-       return TNUM((s64)a.value >> min_shift, (s64)a.mask >> min_shift);
+       if (insn_bitness == 32)
+               return TNUM((u32)(((s32)a.value) >> min_shift),
+                           (u32)(((s32)a.mask)  >> min_shift));
+       else
+               return TNUM((s64)a.value >> min_shift,
+                           (s64)a.mask  >> min_shift);
 }
 
 struct tnum tnum_add(struct tnum a, struct tnum b)
index 7e89f1f..23b0d5c 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/hash.h>
 #include <linux/bpf.h>
 #include <linux/filter.h>
+#include <linux/ftrace.h>
 
 /* btf_vmlinux has ~22k attachable functions. 1k htab is enough. */
 #define TRAMPOLINE_HASH_BITS 10
@@ -59,6 +60,60 @@ out:
        return tr;
 }
 
+static int is_ftrace_location(void *ip)
+{
+       long addr;
+
+       addr = ftrace_location((long)ip);
+       if (!addr)
+               return 0;
+       if (WARN_ON_ONCE(addr != (long)ip))
+               return -EFAULT;
+       return 1;
+}
+
+static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr)
+{
+       void *ip = tr->func.addr;
+       int ret;
+
+       if (tr->func.ftrace_managed)
+               ret = unregister_ftrace_direct((long)ip, (long)old_addr);
+       else
+               ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, NULL);
+       return ret;
+}
+
+static int modify_fentry(struct bpf_trampoline *tr, void *old_addr, void *new_addr)
+{
+       void *ip = tr->func.addr;
+       int ret;
+
+       if (tr->func.ftrace_managed)
+               ret = modify_ftrace_direct((long)ip, (long)old_addr, (long)new_addr);
+       else
+               ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, new_addr);
+       return ret;
+}
+
+/* first time registering */
+static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
+{
+       void *ip = tr->func.addr;
+       int ret;
+
+       ret = is_ftrace_location(ip);
+       if (ret < 0)
+               return ret;
+       tr->func.ftrace_managed = ret;
+
+       if (tr->func.ftrace_managed)
+               ret = register_ftrace_direct((long)ip, (long)new_addr);
+       else
+               ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, NULL, new_addr);
+       return ret;
+}
+
 /* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50
  * bytes on x86.  Pick a number to fit into PAGE_SIZE / 2
  */
@@ -77,8 +132,7 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr)
        int err;
 
        if (fentry_cnt + fexit_cnt == 0) {
-               err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_CALL,
-                                        old_image, NULL);
+               err = unregister_fentry(tr, old_image);
                tr->selector = 0;
                goto out;
        }
@@ -105,12 +159,10 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr)
 
        if (tr->selector)
                /* progs already running at this address */
-               err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_CALL,
-                                        old_image, new_image);
+               err = modify_fentry(tr, old_image, new_image);
        else
                /* first time registering */
-               err = bpf_arch_text_poke(tr->func.addr, BPF_MOD_CALL, NULL,
-                                        new_image);
+               err = register_fentry(tr, new_image);
        if (err)
                goto out;
        tr->selector++;
index 034ef81..7d530ce 100644 (file)
@@ -907,7 +907,8 @@ static const int caller_saved[CALLER_SAVED_REGS] = {
        BPF_REG_0, BPF_REG_1, BPF_REG_2, BPF_REG_3, BPF_REG_4, BPF_REG_5
 };
 
-static void __mark_reg_not_init(struct bpf_reg_state *reg);
+static void __mark_reg_not_init(const struct bpf_verifier_env *env,
+                               struct bpf_reg_state *reg);
 
 /* Mark the unknown part of a register (variable offset or scalar value) as
  * known to have the value @imm.
@@ -945,7 +946,7 @@ static void mark_reg_known_zero(struct bpf_verifier_env *env,
                verbose(env, "mark_reg_known_zero(regs, %u)\n", regno);
                /* Something bad happened, let's kill all regs */
                for (regno = 0; regno < MAX_BPF_REG; regno++)
-                       __mark_reg_not_init(regs + regno);
+                       __mark_reg_not_init(env, regs + regno);
                return;
        }
        __mark_reg_known_zero(regs + regno);
@@ -1054,7 +1055,8 @@ static void __mark_reg_unbounded(struct bpf_reg_state *reg)
 }
 
 /* Mark a register as having a completely unknown (scalar) value. */
-static void __mark_reg_unknown(struct bpf_reg_state *reg)
+static void __mark_reg_unknown(const struct bpf_verifier_env *env,
+                              struct bpf_reg_state *reg)
 {
        /*
         * Clear type, id, off, and union(map_ptr, range) and
@@ -1064,6 +1066,8 @@ static void __mark_reg_unknown(struct bpf_reg_state *reg)
        reg->type = SCALAR_VALUE;
        reg->var_off = tnum_unknown;
        reg->frameno = 0;
+       reg->precise = env->subprog_cnt > 1 || !env->allow_ptr_leaks ?
+                      true : false;
        __mark_reg_unbounded(reg);
 }
 
@@ -1074,19 +1078,16 @@ static void mark_reg_unknown(struct bpf_verifier_env *env,
                verbose(env, "mark_reg_unknown(regs, %u)\n", regno);
                /* Something bad happened, let's kill all regs except FP */
                for (regno = 0; regno < BPF_REG_FP; regno++)
-                       __mark_reg_not_init(regs + regno);
+                       __mark_reg_not_init(env, regs + regno);
                return;
        }
-       regs += regno;
-       __mark_reg_unknown(regs);
-       /* constant backtracking is enabled for root without bpf2bpf calls */
-       regs->precise = env->subprog_cnt > 1 || !env->allow_ptr_leaks ?
-                       true : false;
+       __mark_reg_unknown(env, regs + regno);
 }
 
-static void __mark_reg_not_init(struct bpf_reg_state *reg)
+static void __mark_reg_not_init(const struct bpf_verifier_env *env,
+                               struct bpf_reg_state *reg)
 {
-       __mark_reg_unknown(reg);
+       __mark_reg_unknown(env, reg);
        reg->type = NOT_INIT;
 }
 
@@ -1097,10 +1098,10 @@ static void mark_reg_not_init(struct bpf_verifier_env *env,
                verbose(env, "mark_reg_not_init(regs, %u)\n", regno);
                /* Something bad happened, let's kill all regs except FP */
                for (regno = 0; regno < BPF_REG_FP; regno++)
-                       __mark_reg_not_init(regs + regno);
+                       __mark_reg_not_init(env, regs + regno);
                return;
        }
-       __mark_reg_not_init(regs + regno);
+       __mark_reg_not_init(env, regs + regno);
 }
 
 #define DEF_NOT_SUBREG (0)
@@ -3234,7 +3235,7 @@ static int check_stack_boundary(struct bpf_verifier_env *env, int regno,
                }
                if (state->stack[spi].slot_type[0] == STACK_SPILL &&
                    state->stack[spi].spilled_ptr.type == SCALAR_VALUE) {
-                       __mark_reg_unknown(&state->stack[spi].spilled_ptr);
+                       __mark_reg_unknown(env, &state->stack[spi].spilled_ptr);
                        for (j = 0; j < BPF_REG_SIZE; j++)
                                state->stack[spi].slot_type[j] = STACK_MISC;
                        goto mark;
@@ -3892,7 +3893,7 @@ static void __clear_all_pkt_pointers(struct bpf_verifier_env *env,
                if (!reg)
                        continue;
                if (reg_is_pkt_pointer_any(reg))
-                       __mark_reg_unknown(reg);
+                       __mark_reg_unknown(env, reg);
        }
 }
 
@@ -3920,7 +3921,7 @@ static void release_reg_references(struct bpf_verifier_env *env,
                if (!reg)
                        continue;
                if (reg->ref_obj_id == ref_obj_id)
-                       __mark_reg_unknown(reg);
+                       __mark_reg_unknown(env, reg);
        }
 }
 
@@ -4134,6 +4135,7 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
        struct bpf_map *map = meta->map_ptr;
        struct tnum range;
        u64 val;
+       int err;
 
        if (func_id != BPF_FUNC_tail_call)
                return 0;
@@ -4150,6 +4152,10 @@ record_func_key(struct bpf_verifier_env *env, struct bpf_call_arg_meta *meta,
                return 0;
        }
 
+       err = mark_chain_precision(env, BPF_REG_3);
+       if (err)
+               return err;
+
        val = reg->var_off.value;
        if (bpf_map_key_unseen(aux))
                bpf_map_key_store(aux, val);
@@ -4577,7 +4583,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
                /* Taint dst register if offset had invalid bounds derived from
                 * e.g. dead branches.
                 */
-               __mark_reg_unknown(dst_reg);
+               __mark_reg_unknown(env, dst_reg);
                return 0;
        }
 
@@ -4829,13 +4835,13 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
                /* Taint dst register if offset had invalid bounds derived from
                 * e.g. dead branches.
                 */
-               __mark_reg_unknown(dst_reg);
+               __mark_reg_unknown(env, dst_reg);
                return 0;
        }
 
        if (!src_known &&
            opcode != BPF_ADD && opcode != BPF_SUB && opcode != BPF_AND) {
-               __mark_reg_unknown(dst_reg);
+               __mark_reg_unknown(env, dst_reg);
                return 0;
        }
 
@@ -5043,9 +5049,16 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
                /* Upon reaching here, src_known is true and
                 * umax_val is equal to umin_val.
                 */
-               dst_reg->smin_value >>= umin_val;
-               dst_reg->smax_value >>= umin_val;
-               dst_reg->var_off = tnum_arshift(dst_reg->var_off, umin_val);
+               if (insn_bitness == 32) {
+                       dst_reg->smin_value = (u32)(((s32)dst_reg->smin_value) >> umin_val);
+                       dst_reg->smax_value = (u32)(((s32)dst_reg->smax_value) >> umin_val);
+               } else {
+                       dst_reg->smin_value >>= umin_val;
+                       dst_reg->smax_value >>= umin_val;
+               }
+
+               dst_reg->var_off = tnum_arshift(dst_reg->var_off, umin_val,
+                                               insn_bitness);
 
                /* blow away the dst_reg umin_value/umax_value and rely on
                 * dst_reg var_off to refine the result.
@@ -6258,6 +6271,7 @@ static bool may_access_skb(enum bpf_prog_type type)
 static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
 {
        struct bpf_reg_state *regs = cur_regs(env);
+       static const int ctx_reg = BPF_REG_6;
        u8 mode = BPF_MODE(insn->code);
        int i, err;
 
@@ -6291,7 +6305,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
        }
 
        /* check whether implicit source operand (register R6) is readable */
-       err = check_reg_arg(env, BPF_REG_6, SRC_OP);
+       err = check_reg_arg(env, ctx_reg, SRC_OP);
        if (err)
                return err;
 
@@ -6310,7 +6324,7 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
                return -EINVAL;
        }
 
-       if (regs[BPF_REG_6].type != PTR_TO_CTX) {
+       if (regs[ctx_reg].type != PTR_TO_CTX) {
                verbose(env,
                        "at the time of BPF_LD_ABS|IND R6 != pointer to skb\n");
                return -EINVAL;
@@ -6323,6 +6337,10 @@ static int check_ld_abs(struct bpf_verifier_env *env, struct bpf_insn *insn)
                        return err;
        }
 
+       err = check_ctx_reg(env, &regs[ctx_reg], ctx_reg);
+       if (err < 0)
+               return err;
+
        /* reset caller saved regs to unreadable */
        for (i = 0; i < CALLER_SAVED_REGS; i++) {
                mark_reg_not_init(env, regs, caller_saved[i]);
@@ -6977,7 +6995,7 @@ static void clean_func_state(struct bpf_verifier_env *env,
                        /* since the register is unused, clear its state
                         * to make further comparison simpler
                         */
-                       __mark_reg_not_init(&st->regs[i]);
+                       __mark_reg_not_init(env, &st->regs[i]);
        }
 
        for (i = 0; i < st->allocated_stack / BPF_REG_SIZE; i++) {
@@ -6985,7 +7003,7 @@ static void clean_func_state(struct bpf_verifier_env *env,
                /* liveness must not touch this stack slot anymore */
                st->stack[i].spilled_ptr.live |= REG_LIVE_DONE;
                if (!(live & REG_LIVE_READ)) {
-                       __mark_reg_not_init(&st->stack[i].spilled_ptr);
+                       __mark_reg_not_init(env, &st->stack[i].spilled_ptr);
                        for (j = 0; j < BPF_REG_SIZE; j++)
                                st->stack[i].slot_type[j] = STACK_INVALID;
                }
@@ -8268,7 +8286,7 @@ static int replace_map_fd_with_map_ptr(struct bpf_verifier_env *env)
                        env->used_maps[env->used_map_cnt++] = map;
 
                        if (bpf_map_is_cgroup_storage(map) &&
-                           bpf_cgroup_storage_assign(env->prog, map)) {
+                           bpf_cgroup_storage_assign(env->prog->aux, map)) {
                                verbose(env, "only one cgroup storage of each type is allowed\n");
                                fdput(f);
                                return -EBUSY;
@@ -8298,18 +8316,8 @@ next_insn:
 /* drop refcnt of maps used by the rejected program */
 static void release_maps(struct bpf_verifier_env *env)
 {
-       enum bpf_cgroup_storage_type stype;
-       int i;
-
-       for_each_cgroup_storage_type(stype) {
-               if (!env->prog->aux->cgroup_storage[stype])
-                       continue;
-               bpf_cgroup_storage_release(env->prog,
-                       env->prog->aux->cgroup_storage[stype]);
-       }
-
-       for (i = 0; i < env->used_map_cnt; i++)
-               bpf_map_put(env->used_maps[i]);
+       __bpf_free_used_maps(env->prog->aux, env->used_maps,
+                            env->used_map_cnt);
 }
 
 /* convert pseudo BPF_LD_IMM64 into generic BPF_LD_IMM64 */
@@ -9282,7 +9290,8 @@ static int fixup_bpf_calls(struct bpf_verifier_env *env)
                        insn->code = BPF_JMP | BPF_TAIL_CALL;
 
                        aux = &env->insn_aux_data[i + delta];
-                       if (prog->jit_requested && !expect_blinding &&
+                       if (env->allow_ptr_leaks && !expect_blinding &&
+                           prog->jit_requested &&
                            !bpf_map_key_poisoned(aux) &&
                            !bpf_map_ptr_poisoned(aux) &&
                            !bpf_map_ptr_unpriv(aux)) {
index a59cc98..4dc279e 100644 (file)
@@ -1909,6 +1909,78 @@ void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
 }
 EXPORT_SYMBOL(__cpuhp_remove_state);
 
+#ifdef CONFIG_HOTPLUG_SMT
+static void cpuhp_offline_cpu_device(unsigned int cpu)
+{
+       struct device *dev = get_cpu_device(cpu);
+
+       dev->offline = true;
+       /* Tell user space about the state change */
+       kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
+}
+
+static void cpuhp_online_cpu_device(unsigned int cpu)
+{
+       struct device *dev = get_cpu_device(cpu);
+
+       dev->offline = false;
+       /* Tell user space about the state change */
+       kobject_uevent(&dev->kobj, KOBJ_ONLINE);
+}
+
+int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
+{
+       int cpu, ret = 0;
+
+       cpu_maps_update_begin();
+       for_each_online_cpu(cpu) {
+               if (topology_is_primary_thread(cpu))
+                       continue;
+               ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE);
+               if (ret)
+                       break;
+               /*
+                * As this needs to hold the cpu maps lock it's impossible
+                * to call device_offline() because that ends up calling
+                * cpu_down() which takes cpu maps lock. cpu maps lock
+                * needs to be held as this might race against in kernel
+                * abusers of the hotplug machinery (thermal management).
+                *
+                * So nothing would update device:offline state. That would
+                * leave the sysfs entry stale and prevent onlining after
+                * smt control has been changed to 'off' again. This is
+                * called under the sysfs hotplug lock, so it is properly
+                * serialized against the regular offline usage.
+                */
+               cpuhp_offline_cpu_device(cpu);
+       }
+       if (!ret)
+               cpu_smt_control = ctrlval;
+       cpu_maps_update_done();
+       return ret;
+}
+
+int cpuhp_smt_enable(void)
+{
+       int cpu, ret = 0;
+
+       cpu_maps_update_begin();
+       cpu_smt_control = CPU_SMT_ENABLED;
+       for_each_present_cpu(cpu) {
+               /* Skip online CPUs and CPUs on offline nodes */
+               if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
+                       continue;
+               ret = _cpu_up(cpu, 0, CPUHP_ONLINE);
+               if (ret)
+                       break;
+               /* See comment in cpuhp_smt_disable() */
+               cpuhp_online_cpu_device(cpu);
+       }
+       cpu_maps_update_done();
+       return ret;
+}
+#endif
+
 #if defined(CONFIG_SYSFS) && defined(CONFIG_HOTPLUG_CPU)
 static ssize_t show_cpuhp_state(struct device *dev,
                                struct device_attribute *attr, char *buf)
@@ -2063,77 +2135,6 @@ static const struct attribute_group cpuhp_cpu_root_attr_group = {
 
 #ifdef CONFIG_HOTPLUG_SMT
 
-static void cpuhp_offline_cpu_device(unsigned int cpu)
-{
-       struct device *dev = get_cpu_device(cpu);
-
-       dev->offline = true;
-       /* Tell user space about the state change */
-       kobject_uevent(&dev->kobj, KOBJ_OFFLINE);
-}
-
-static void cpuhp_online_cpu_device(unsigned int cpu)
-{
-       struct device *dev = get_cpu_device(cpu);
-
-       dev->offline = false;
-       /* Tell user space about the state change */
-       kobject_uevent(&dev->kobj, KOBJ_ONLINE);
-}
-
-int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
-{
-       int cpu, ret = 0;
-
-       cpu_maps_update_begin();
-       for_each_online_cpu(cpu) {
-               if (topology_is_primary_thread(cpu))
-                       continue;
-               ret = cpu_down_maps_locked(cpu, CPUHP_OFFLINE);
-               if (ret)
-                       break;
-               /*
-                * As this needs to hold the cpu maps lock it's impossible
-                * to call device_offline() because that ends up calling
-                * cpu_down() which takes cpu maps lock. cpu maps lock
-                * needs to be held as this might race against in kernel
-                * abusers of the hotplug machinery (thermal management).
-                *
-                * So nothing would update device:offline state. That would
-                * leave the sysfs entry stale and prevent onlining after
-                * smt control has been changed to 'off' again. This is
-                * called under the sysfs hotplug lock, so it is properly
-                * serialized against the regular offline usage.
-                */
-               cpuhp_offline_cpu_device(cpu);
-       }
-       if (!ret)
-               cpu_smt_control = ctrlval;
-       cpu_maps_update_done();
-       return ret;
-}
-
-int cpuhp_smt_enable(void)
-{
-       int cpu, ret = 0;
-
-       cpu_maps_update_begin();
-       cpu_smt_control = CPU_SMT_ENABLED;
-       for_each_present_cpu(cpu) {
-               /* Skip online CPUs and CPUs on offline nodes */
-               if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
-                       continue;
-               ret = _cpu_up(cpu, 0, CPUHP_ONLINE);
-               if (ret)
-                       break;
-               /* See comment in cpuhp_smt_disable() */
-               cpuhp_online_cpu_device(cpu);
-       }
-       cpu_maps_update_done();
-       return ret;
-}
-
-
 static ssize_t
 __store_smt_control(struct device *dev, struct device_attribute *attr,
                    const char *buf, size_t count)
index c0a4c12..809a985 100644 (file)
@@ -175,8 +175,8 @@ void exit_creds(struct task_struct *tsk)
        put_cred(cred);
 
 #ifdef CONFIG_KEYS_REQUEST_CACHE
-       key_put(current->cached_requested_key);
-       current->cached_requested_key = NULL;
+       key_put(tsk->cached_requested_key);
+       tsk->cached_requested_key = NULL;
 #endif
 }
 
@@ -223,7 +223,7 @@ struct cred *cred_alloc_blank(void)
        new->magic = CRED_MAGIC;
 #endif
 
-       if (security_cred_alloc_blank(new, GFP_KERNEL) < 0)
+       if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0)
                goto error;
 
        return new;
@@ -282,7 +282,7 @@ struct cred *prepare_creds(void)
        new->security = NULL;
 #endif
 
-       if (security_prepare_creds(new, old, GFP_KERNEL) < 0)
+       if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
                goto error;
        validate_creds(new);
        return new;
@@ -715,7 +715,7 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
 #ifdef CONFIG_SECURITY
        new->security = NULL;
 #endif
-       if (security_prepare_creds(new, old, GFP_KERNEL) < 0)
+       if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
                goto error;
 
        put_cred(old);
index 4ff86d5..2173c23 100644 (file)
@@ -10523,7 +10523,7 @@ again:
                goto unlock;
        }
 
-       list_for_each_entry_rcu(pmu, &pmus, entry) {
+       list_for_each_entry_rcu(pmu, &pmus, entry, lockdep_is_held(&pmus_srcu)) {
                ret = perf_try_init_event(pmu, event);
                if (!ret)
                        goto unlock;
@@ -11465,8 +11465,10 @@ SYSCALL_DEFINE5(perf_event_open,
                }
        }
 
-       if (perf_need_aux_event(event) && !perf_get_aux_event(event, group_leader))
+       if (perf_need_aux_event(event) && !perf_get_aux_event(event, group_leader)) {
+               err = -EINVAL;
                goto err_locked;
+       }
 
        /*
         * Must be under the same ctx::mutex as perf_install_in_context(),
index bcbd598..2833ffb 100644 (file)
@@ -517,10 +517,6 @@ static struct task_struct *find_child_reaper(struct task_struct *father,
        }
 
        write_unlock_irq(&tasklist_lock);
-       if (unlikely(pid_ns == &init_pid_ns)) {
-               panic("Attempted to kill init! exitcode=0x%08x\n",
-                       father->signal->group_exit_code ?: father->exit_code);
-       }
 
        list_for_each_entry_safe(p, n, dead, ptrace_entry) {
                list_del_init(&p->ptrace_entry);
@@ -766,6 +762,14 @@ void __noreturn do_exit(long code)
        acct_update_integrals(tsk);
        group_dead = atomic_dec_and_test(&tsk->signal->live);
        if (group_dead) {
+               /*
+                * If the last thread of global init has exited, panic
+                * immediately to get a useable coredump.
+                */
+               if (unlikely(is_global_init(tsk)))
+                       panic("Attempted to kill init! exitcode=0x%08x\n",
+                               tsk->signal->group_exit_code ?: (int)code);
+
 #ifdef CONFIG_POSIX_TIMERS
                hrtimer_cancel(&tsk->signal->real_timer);
                exit_itimers(tsk->signal);
index 2508a4f..0808095 100644 (file)
@@ -2578,6 +2578,16 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
 #endif
 
 #ifdef __ARCH_WANT_SYS_CLONE3
+
+/*
+ * copy_thread implementations handle CLONE_SETTLS by reading the TLS value from
+ * the registers containing the syscall arguments for clone. This doesn't work
+ * with clone3 since the TLS value is passed in clone_args instead.
+ */
+#ifndef CONFIG_HAVE_COPY_THREAD_TLS
+#error clone3 requires copy_thread_tls support in arch
+#endif
+
 noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
                                              struct clone_args __user *uargs,
                                              size_t usize)
index 03c518e..0cf84c8 100644 (file)
@@ -1178,6 +1178,7 @@ out_error:
 
 /**
  * wait_for_owner_exiting - Block until the owner has exited
+ * @ret: owner's current futex lock status
  * @exiting:   Pointer to the exiting task
  *
  * Caller must hold a refcount on @exiting.
index 32282e7..32406ef 100644 (file)
@@ -482,7 +482,7 @@ static struct lock_trace *save_trace(void)
        struct lock_trace *trace, *t2;
        struct hlist_head *hash_head;
        u32 hash;
-       unsigned int max_entries;
+       int max_entries;
 
        BUILD_BUG_ON_NOT_POWER_OF_2(STACK_TRACE_HASH_SIZE);
        BUILD_BUG_ON(LOCK_TRACE_SIZE_IN_LONGS >= MAX_STACK_TRACE_ENTRIES);
@@ -490,10 +490,8 @@ static struct lock_trace *save_trace(void)
        trace = (struct lock_trace *)(stack_trace + nr_stack_trace_entries);
        max_entries = MAX_STACK_TRACE_ENTRIES - nr_stack_trace_entries -
                LOCK_TRACE_SIZE_IN_LONGS;
-       trace->nr_entries = stack_trace_save(trace->entries, max_entries, 3);
 
-       if (nr_stack_trace_entries >= MAX_STACK_TRACE_ENTRIES -
-           LOCK_TRACE_SIZE_IN_LONGS - 1) {
+       if (max_entries <= 0) {
                if (!debug_locks_off_graph_unlock())
                        return NULL;
 
@@ -502,6 +500,7 @@ static struct lock_trace *save_trace(void)
 
                return NULL;
        }
+       trace->nr_entries = stack_trace_save(trace->entries, max_entries, 3);
 
        hash = jhash(trace->entries, trace->nr_entries *
                     sizeof(trace->entries[0]), 0);
index 54cc5f9..5352ce5 100644 (file)
@@ -733,9 +733,6 @@ static noinline void __sched __mutex_unlock_slowpath(struct mutex *lock, unsigne
  */
 void __sched mutex_unlock(struct mutex *lock)
 {
-#ifdef CONFIG_DEBUG_MUTEXES
-       WARN_ON(in_interrupt());
-#endif
 #ifndef CONFIG_DEBUG_LOCK_ALLOC
        if (__mutex_unlock_fast(lock))
                return;
@@ -1416,7 +1413,6 @@ int __sched mutex_trylock(struct mutex *lock)
 
 #ifdef CONFIG_DEBUG_MUTEXES
        DEBUG_LOCKS_WARN_ON(lock->magic != lock);
-       WARN_ON(in_interrupt());
 #endif
 
        locked = __mutex_trylock(lock);
index 44e6876..0d9b6be 100644 (file)
@@ -1226,8 +1226,8 @@ wait:
                 * In this case, we attempt to acquire the lock again
                 * without sleeping.
                 */
-               if ((wstate == WRITER_HANDOFF) &&
-                   (rwsem_spin_on_owner(sem, 0) == OWNER_NULL))
+               if (wstate == WRITER_HANDOFF &&
+                   rwsem_spin_on_owner(sem, RWSEM_NONSPINNABLE) == OWNER_NULL)
                        goto trylock_again;
 
                /* Block until there are no active lockers. */
index 399669f..472dd46 100644 (file)
@@ -51,19 +51,19 @@ EXPORT_SYMBOL(__rwlock_init);
 
 static void spin_dump(raw_spinlock_t *lock, const char *msg)
 {
-       struct task_struct *owner = NULL;
+       struct task_struct *owner = READ_ONCE(lock->owner);
 
-       if (lock->owner && lock->owner != SPINLOCK_OWNER_INIT)
-               owner = lock->owner;
+       if (owner == SPINLOCK_OWNER_INIT)
+               owner = NULL;
        printk(KERN_EMERG "BUG: spinlock %s on CPU#%d, %s/%d\n",
                msg, raw_smp_processor_id(),
                current->comm, task_pid_nr(current));
        printk(KERN_EMERG " lock: %pS, .magic: %08x, .owner: %s/%d, "
                        ".owner_cpu: %d\n",
-               lock, lock->magic,
+               lock, READ_ONCE(lock->magic),
                owner ? owner->comm : "<none>",
                owner ? task_pid_nr(owner) : -1,
-               lock->owner_cpu);
+               READ_ONCE(lock->owner_cpu));
        dump_stack();
 }
 
@@ -80,16 +80,16 @@ static void spin_bug(raw_spinlock_t *lock, const char *msg)
 static inline void
 debug_spin_lock_before(raw_spinlock_t *lock)
 {
-       SPIN_BUG_ON(lock->magic != SPINLOCK_MAGIC, lock, "bad magic");
-       SPIN_BUG_ON(lock->owner == current, lock, "recursion");
-       SPIN_BUG_ON(lock->owner_cpu == raw_smp_processor_id(),
+       SPIN_BUG_ON(READ_ONCE(lock->magic) != SPINLOCK_MAGIC, lock, "bad magic");
+       SPIN_BUG_ON(READ_ONCE(lock->owner) == current, lock, "recursion");
+       SPIN_BUG_ON(READ_ONCE(lock->owner_cpu) == raw_smp_processor_id(),
                                                        lock, "cpu recursion");
 }
 
 static inline void debug_spin_lock_after(raw_spinlock_t *lock)
 {
-       lock->owner_cpu = raw_smp_processor_id();
-       lock->owner = current;
+       WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id());
+       WRITE_ONCE(lock->owner, current);
 }
 
 static inline void debug_spin_unlock(raw_spinlock_t *lock)
@@ -99,8 +99,8 @@ static inline void debug_spin_unlock(raw_spinlock_t *lock)
        SPIN_BUG_ON(lock->owner != current, lock, "wrong owner");
        SPIN_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
                                                        lock, "wrong CPU");
-       lock->owner = SPINLOCK_OWNER_INIT;
-       lock->owner_cpu = -1;
+       WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT);
+       WRITE_ONCE(lock->owner_cpu, -1);
 }
 
 /*
@@ -187,8 +187,8 @@ static inline void debug_write_lock_before(rwlock_t *lock)
 
 static inline void debug_write_lock_after(rwlock_t *lock)
 {
-       lock->owner_cpu = raw_smp_processor_id();
-       lock->owner = current;
+       WRITE_ONCE(lock->owner_cpu, raw_smp_processor_id());
+       WRITE_ONCE(lock->owner, current);
 }
 
 static inline void debug_write_unlock(rwlock_t *lock)
@@ -197,8 +197,8 @@ static inline void debug_write_unlock(rwlock_t *lock)
        RWLOCK_BUG_ON(lock->owner != current, lock, "wrong owner");
        RWLOCK_BUG_ON(lock->owner_cpu != raw_smp_processor_id(),
                                                        lock, "wrong CPU");
-       lock->owner = SPINLOCK_OWNER_INIT;
-       lock->owner_cpu = -1;
+       WRITE_ONCE(lock->owner, SPINLOCK_OWNER_INIT);
+       WRITE_ONCE(lock->owner_cpu, -1);
 }
 
 void do_raw_write_lock(rwlock_t *lock)
index 3a486f8..b56f322 100644 (file)
@@ -3730,6 +3730,7 @@ static int complete_formation(struct module *mod, struct load_info *info)
 
        module_enable_ro(mod, false);
        module_enable_nx(mod);
+       module_enable_x(mod);
 
        /* Mark state as coming so strong_try_module_get() ignores us,
         * but kallsyms etc. can see us. */
@@ -3752,11 +3753,6 @@ static int prepare_coming_module(struct module *mod)
        if (err)
                return err;
 
-       /* Make module executable after ftrace is enabled */
-       mutex_lock(&module_mutex);
-       module_enable_x(mod);
-       mutex_unlock(&module_mutex);
-
        blocking_notifier_call_chain(&module_notify_list,
                                     MODULE_STATE_COMING, mod);
        return 0;
index cb9ddcc..43d6179 100644 (file)
@@ -264,12 +264,17 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
        return ret;
 }
 
-static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
+static bool ptrace_has_cap(const struct cred *cred, struct user_namespace *ns,
+                          unsigned int mode)
 {
+       int ret;
+
        if (mode & PTRACE_MODE_NOAUDIT)
-               return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
+               ret = security_capable(cred, ns, CAP_SYS_PTRACE, CAP_OPT_NOAUDIT);
        else
-               return has_ns_capability(current, ns, CAP_SYS_PTRACE);
+               ret = security_capable(cred, ns, CAP_SYS_PTRACE, CAP_OPT_NONE);
+
+       return ret == 0;
 }
 
 /* Returns 0 on success, -errno on denial. */
@@ -321,7 +326,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)
            gid_eq(caller_gid, tcred->sgid) &&
            gid_eq(caller_gid, tcred->gid))
                goto ok;
-       if (ptrace_has_cap(tcred->user_ns, mode))
+       if (ptrace_has_cap(cred, tcred->user_ns, mode))
                goto ok;
        rcu_read_unlock();
        return -EPERM;
@@ -340,7 +345,7 @@ ok:
        mm = task->mm;
        if (mm &&
            ((get_dumpable(mm) != SUID_DUMP_USER) &&
-            !ptrace_has_cap(mm->user_ns, mode)))
+            !ptrace_has_cap(cred, mm->user_ns, mode)))
            return -EPERM;
 
        return security_ptrace_access_check(task, mode);
index 27c48eb..a4f86a9 100644 (file)
@@ -310,6 +310,8 @@ SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len,
        int ret;
 
        if (flags & RSEQ_FLAG_UNREGISTER) {
+               if (flags & ~RSEQ_FLAG_UNREGISTER)
+                       return -EINVAL;
                /* Unregister rseq for current thread. */
                if (current->rseq != rseq || !current->rseq)
                        return -EINVAL;
index b5dcd1d..7c2fe50 100644 (file)
@@ -5,6 +5,8 @@
  * Copyright (C) 2016, Intel Corporation
  * Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
  */
+#include <linux/cpufreq.h>
+
 #include "sched.h"
 
 DEFINE_PER_CPU(struct update_util_data __rcu *, cpufreq_update_util_data);
@@ -57,3 +59,19 @@ void cpufreq_remove_update_util_hook(int cpu)
        rcu_assign_pointer(per_cpu(cpufreq_update_util_data, cpu), NULL);
 }
 EXPORT_SYMBOL_GPL(cpufreq_remove_update_util_hook);
+
+/**
+ * cpufreq_this_cpu_can_update - Check if cpufreq policy can be updated.
+ * @policy: cpufreq policy to check.
+ *
+ * Return 'true' if:
+ * - the local and remote CPUs share @policy,
+ * - dvfs_possible_from_any_cpu is set in @policy and the local CPU is not going
+ *   offline (in which case it is not expected to run cpufreq updates any more).
+ */
+bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
+{
+       return cpumask_test_cpu(smp_processor_id(), policy->cpus) ||
+               (policy->dvfs_possible_from_any_cpu &&
+                rcu_dereference_sched(*this_cpu_ptr(&cpufreq_update_util_data)));
+}
index 322ca88..9b8916f 100644 (file)
@@ -82,12 +82,10 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
         * by the hardware, as calculating the frequency is pointless if
         * we cannot in fact act on it.
         *
-        * For the slow switching platforms, the kthread is always scheduled on
-        * the right set of CPUs and any CPU can find the next frequency and
-        * schedule the kthread.
+        * This is needed on the slow switching platforms too to prevent CPUs
+        * going offline from leaving stale IRQ work items behind.
         */
-       if (sg_policy->policy->fast_switch_enabled &&
-           !cpufreq_this_cpu_can_update(sg_policy->policy))
+       if (!cpufreq_this_cpu_can_update(sg_policy->policy))
                return false;
 
        if (unlikely(sg_policy->limits_changed)) {
index 08a233e..ba749f5 100644 (file)
@@ -7328,7 +7328,14 @@ static int detach_tasks(struct lb_env *env)
                            load < 16 && !env->sd->nr_balance_failed)
                                goto next;
 
-                       if (load/2 > env->imbalance)
+                       /*
+                        * Make sure that we don't migrate too much load.
+                        * Nevertheless, let relax the constraint if
+                        * scheduler fails to find a good waiting task to
+                        * migrate.
+                        */
+                       if (load/2 > env->imbalance &&
+                           env->sd->nr_balance_failed <= env->sd->cache_nice_tries)
                                goto next;
 
                        env->imbalance -= load;
@@ -8417,6 +8424,10 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p,
        if (!idlest)
                return NULL;
 
+       /* The local group has been skipped because of CPU affinity */
+       if (!local)
+               return idlest;
+
        /*
         * If the local group is idler than the selected idlest group
         * don't try and push the task.
index 517e371..ce8f674 100644 (file)
@@ -185,7 +185,8 @@ static void group_init(struct psi_group *group)
 
        for_each_possible_cpu(cpu)
                seqcount_init(&per_cpu_ptr(group->pcpu, cpu)->seq);
-       group->avg_next_update = sched_clock() + psi_period;
+       group->avg_last_update = sched_clock();
+       group->avg_next_update = group->avg_last_update + psi_period;
        INIT_DELAYED_WORK(&group->avgs_work, psi_avgs_work);
        mutex_init(&group->avgs_lock);
        /* Init trigger-related members */
@@ -481,7 +482,7 @@ static u64 window_update(struct psi_window *win, u64 now, u64 value)
                u32 remaining;
 
                remaining = win->size - elapsed;
-               growth += div_u64(win->prev_growth * remaining, win->size);
+               growth += div64_u64(win->prev_growth * remaining, win->size);
        }
 
        return growth;
index 12d2227..b6ea3dc 100644 (file)
@@ -1026,6 +1026,13 @@ static long seccomp_notify_recv(struct seccomp_filter *filter,
        struct seccomp_notif unotif;
        ssize_t ret;
 
+       /* Verify that we're not given garbage to keep struct extensible. */
+       ret = check_zeroed_user(buf, sizeof(unotif));
+       if (ret < 0)
+               return ret;
+       if (!ret)
+               return -EINVAL;
+
        memset(&unotif, 0, sizeof(unotif));
 
        ret = down_interruptible(&filter->notif->request);
index 13a0f2e..e2ac0e3 100644 (file)
@@ -554,25 +554,33 @@ static int taskstats_user_cmd(struct sk_buff *skb, struct genl_info *info)
 static struct taskstats *taskstats_tgid_alloc(struct task_struct *tsk)
 {
        struct signal_struct *sig = tsk->signal;
-       struct taskstats *stats;
+       struct taskstats *stats_new, *stats;
 
-       if (sig->stats || thread_group_empty(tsk))
-               goto ret;
+       /* Pairs with smp_store_release() below. */
+       stats = smp_load_acquire(&sig->stats);
+       if (stats || thread_group_empty(tsk))
+               return stats;
 
        /* No problem if kmem_cache_zalloc() fails */
-       stats = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
+       stats_new = kmem_cache_zalloc(taskstats_cache, GFP_KERNEL);
 
        spin_lock_irq(&tsk->sighand->siglock);
-       if (!sig->stats) {
-               sig->stats = stats;
-               stats = NULL;
+       stats = sig->stats;
+       if (!stats) {
+               /*
+                * Pairs with smp_store_release() above and order the
+                * kmem_cache_zalloc().
+                */
+               smp_store_release(&sig->stats, stats_new);
+               stats = stats_new;
+               stats_new = NULL;
        }
        spin_unlock_irq(&tsk->sighand->siglock);
 
-       if (stats)
-               kmem_cache_free(taskstats_cache, stats);
-ret:
-       return sig->stats;
+       if (stats_new)
+               kmem_cache_free(taskstats_cache, stats_new);
+
+       return stats;
 }
 
 /* Send pid data out on exit */
index ec960bb..200fb2d 100644 (file)
@@ -14,8 +14,6 @@
 
 #include "posix-timers.h"
 
-static void delete_clock(struct kref *kref);
-
 /*
  * Returns NULL if the posix_clock instance attached to 'fp' is old and stale.
  */
@@ -125,7 +123,7 @@ static int posix_clock_open(struct inode *inode, struct file *fp)
                err = 0;
 
        if (!err) {
-               kref_get(&clk->kref);
+               get_device(clk->dev);
                fp->private_data = clk;
        }
 out:
@@ -141,7 +139,7 @@ static int posix_clock_release(struct inode *inode, struct file *fp)
        if (clk->ops.release)
                err = clk->ops.release(clk);
 
-       kref_put(&clk->kref, delete_clock);
+       put_device(clk->dev);
 
        fp->private_data = NULL;
 
@@ -161,38 +159,35 @@ static const struct file_operations posix_clock_file_operations = {
 #endif
 };
 
-int posix_clock_register(struct posix_clock *clk, dev_t devid)
+int posix_clock_register(struct posix_clock *clk, struct device *dev)
 {
        int err;
 
-       kref_init(&clk->kref);
        init_rwsem(&clk->rwsem);
 
        cdev_init(&clk->cdev, &posix_clock_file_operations);
+       err = cdev_device_add(&clk->cdev, dev);
+       if (err) {
+               pr_err("%s unable to add device %d:%d\n",
+                       dev_name(dev), MAJOR(dev->devt), MINOR(dev->devt));
+               return err;
+       }
        clk->cdev.owner = clk->ops.owner;
-       err = cdev_add(&clk->cdev, devid, 1);
+       clk->dev = dev;
 
-       return err;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(posix_clock_register);
 
-static void delete_clock(struct kref *kref)
-{
-       struct posix_clock *clk = container_of(kref, struct posix_clock, kref);
-
-       if (clk->release)
-               clk->release(clk);
-}
-
 void posix_clock_unregister(struct posix_clock *clk)
 {
-       cdev_del(&clk->cdev);
+       cdev_device_del(&clk->cdev, clk->dev);
 
        down_write(&clk->rwsem);
        clk->zombie = true;
        up_write(&clk->rwsem);
 
-       kref_put(&clk->kref, delete_clock);
+       put_device(clk->dev);
 }
 EXPORT_SYMBOL_GPL(posix_clock_unregister);
 
index 67df65f..20c65a7 100644 (file)
@@ -151,6 +151,9 @@ SYSCALL_DEFINE4(clock_nanosleep, const clockid_t, which_clock, int, flags,
 
 #ifdef CONFIG_COMPAT
 COMPAT_SYS_NI(timer_create);
+#endif
+
+#if defined(CONFIG_COMPAT) || defined(CONFIG_ALPHA)
 COMPAT_SYS_NI(getitimer);
 COMPAT_SYS_NI(setitimer);
 #endif
index 8b192e6..a792d21 100644 (file)
@@ -58,8 +58,9 @@ static void tick_do_update_jiffies64(ktime_t now)
 
        /*
         * Do a quick check without holding jiffies_lock:
+        * The READ_ONCE() pairs with two updates done later in this function.
         */
-       delta = ktime_sub(now, last_jiffies_update);
+       delta = ktime_sub(now, READ_ONCE(last_jiffies_update));
        if (delta < tick_period)
                return;
 
@@ -70,8 +71,9 @@ static void tick_do_update_jiffies64(ktime_t now)
        if (delta >= tick_period) {
 
                delta = ktime_sub(delta, tick_period);
-               last_jiffies_update = ktime_add(last_jiffies_update,
-                                               tick_period);
+               /* Pairs with the lockless read in this function. */
+               WRITE_ONCE(last_jiffies_update,
+                          ktime_add(last_jiffies_update, tick_period));
 
                /* Slow path for long timeouts */
                if (unlikely(delta >= tick_period)) {
@@ -79,8 +81,10 @@ static void tick_do_update_jiffies64(ktime_t now)
 
                        ticks = ktime_divns(delta, incr);
 
-                       last_jiffies_update = ktime_add_ns(last_jiffies_update,
-                                                          incr * ticks);
+                       /* Pairs with the lockless read in this function. */
+                       WRITE_ONCE(last_jiffies_update,
+                                  ktime_add_ns(last_jiffies_update,
+                                               incr * ticks));
                }
                do_timer(++ticks);
 
index 67e0c46..1af321d 100644 (file)
@@ -96,11 +96,34 @@ ftrace_push_return_trace(unsigned long ret, unsigned long func,
        return 0;
 }
 
+/*
+ * Not all archs define MCOUNT_INSN_SIZE which is used to look for direct
+ * functions. But those archs currently don't support direct functions
+ * anyway, and ftrace_find_rec_direct() is just a stub for them.
+ * Define MCOUNT_INSN_SIZE to keep those archs compiling.
+ */
+#ifndef MCOUNT_INSN_SIZE
+/* Make sure this only works without direct calls */
+# ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
+#  error MCOUNT_INSN_SIZE not defined with direct calls enabled
+# endif
+# define MCOUNT_INSN_SIZE 0
+#endif
+
 int function_graph_enter(unsigned long ret, unsigned long func,
                         unsigned long frame_pointer, unsigned long *retp)
 {
        struct ftrace_graph_ent trace;
 
+       /*
+        * Skip graph tracing if the return location is served by direct trampoline,
+        * since call sequence and return addresses is unpredicatable anymore.
+        * Ex: BPF trampoline may call original function and may skip frame
+        * depending on type of BPF programs attached.
+        */
+       if (ftrace_direct_func_count &&
+           ftrace_find_rec_direct(ret - MCOUNT_INSN_SIZE))
+               return -EBUSY;
        trace.func = func;
        trace.depth = ++current->curr_ret_depth;
 
index 74439ab..9bf1f2c 100644 (file)
@@ -526,8 +526,7 @@ static int function_stat_show(struct seq_file *m, void *v)
        }
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
-       avg = rec->time;
-       do_div(avg, rec->counter);
+       avg = div64_ul(rec->time, rec->counter);
        if (tracing_thresh && (avg < tracing_thresh))
                goto out;
 #endif
@@ -553,7 +552,8 @@ static int function_stat_show(struct seq_file *m, void *v)
                 * Divide only 1000 for ns^2 -> us^2 conversion.
                 * trace_print_graph_duration will divide 1000 again.
                 */
-               do_div(stddev, rec->counter * (rec->counter - 1) * 1000);
+               stddev = div64_ul(stddev,
+                                 rec->counter * (rec->counter - 1) * 1000);
        }
 
        trace_seq_init(&s);
@@ -2364,7 +2364,7 @@ int ftrace_direct_func_count;
  * Search the direct_functions hash to see if the given instruction pointer
  * has a direct caller attached to it.
  */
-static unsigned long find_rec_direct(unsigned long ip)
+unsigned long ftrace_find_rec_direct(unsigned long ip)
 {
        struct ftrace_func_entry *entry;
 
@@ -2380,7 +2380,7 @@ static void call_direct_funcs(unsigned long ip, unsigned long pip,
 {
        unsigned long addr;
 
-       addr = find_rec_direct(ip);
+       addr = ftrace_find_rec_direct(ip);
        if (!addr)
                return;
 
@@ -2393,11 +2393,6 @@ struct ftrace_ops direct_ops = {
                          | FTRACE_OPS_FL_DIRECT | FTRACE_OPS_FL_SAVE_REGS
                          | FTRACE_OPS_FL_PERMANENT,
 };
-#else
-static inline unsigned long find_rec_direct(unsigned long ip)
-{
-       return 0;
-}
 #endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */
 
 /**
@@ -2417,7 +2412,7 @@ unsigned long ftrace_get_addr_new(struct dyn_ftrace *rec)
 
        if ((rec->flags & FTRACE_FL_DIRECT) &&
            (ftrace_rec_count(rec) == 1)) {
-               addr = find_rec_direct(rec->ip);
+               addr = ftrace_find_rec_direct(rec->ip);
                if (addr)
                        return addr;
                WARN_ON_ONCE(1);
@@ -2458,7 +2453,7 @@ unsigned long ftrace_get_addr_curr(struct dyn_ftrace *rec)
 
        /* Direct calls take precedence over trampolines */
        if (rec->flags & FTRACE_FL_DIRECT_EN) {
-               addr = find_rec_direct(rec->ip);
+               addr = ftrace_find_rec_direct(rec->ip);
                if (addr)
                        return addr;
                WARN_ON_ONCE(1);
@@ -3604,7 +3599,7 @@ static int t_show(struct seq_file *m, void *v)
                if (rec->flags & FTRACE_FL_DIRECT) {
                        unsigned long direct;
 
-                       direct = find_rec_direct(rec->ip);
+                       direct = ftrace_find_rec_direct(rec->ip);
                        if (direct)
                                seq_printf(m, "\n\tdirect-->%pS", (void *)direct);
                }
@@ -5008,7 +5003,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
        mutex_lock(&direct_mutex);
 
        /* See if there's a direct function at @ip already */
-       if (find_rec_direct(ip))
+       if (ftrace_find_rec_direct(ip))
                goto out_unlock;
 
        ret = -ENODEV;
@@ -5027,7 +5022,7 @@ int register_ftrace_direct(unsigned long ip, unsigned long addr)
        if (ip != rec->ip) {
                ip = rec->ip;
                /* Need to check this ip for a direct. */
-               if (find_rec_direct(ip))
+               if (ftrace_find_rec_direct(ip))
                        goto out_unlock;
        }
 
index 4bf050f..3f65537 100644 (file)
@@ -5070,7 +5070,7 @@ static __init int test_ringbuffer(void)
        int ret = 0;
 
        if (security_locked_down(LOCKDOWN_TRACEFS)) {
-               pr_warning("Lockdown is enabled, skipping ring buffer tests\n");
+               pr_warn("Lockdown is enabled, skipping ring buffer tests\n");
                return 0;
        }
 
index 23459d5..ddb7e7f 100644 (file)
@@ -1889,7 +1889,7 @@ int __init register_tracer(struct tracer *type)
        }
 
        if (security_locked_down(LOCKDOWN_TRACEFS)) {
-               pr_warning("Can not register tracer %s due to lockdown\n",
+               pr_warn("Can not register tracer %s due to lockdown\n",
                           type->name);
                return -EPERM;
        }
@@ -4685,6 +4685,10 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
 
 int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled)
 {
+       if ((mask == TRACE_ITER_RECORD_TGID) ||
+           (mask == TRACE_ITER_RECORD_CMD))
+               lockdep_assert_held(&event_mutex);
+
        /* do nothing if flag is already set */
        if (!!(tr->trace_flags & mask) == !!enabled)
                return 0;
@@ -4752,6 +4756,7 @@ static int trace_set_options(struct trace_array *tr, char *option)
 
        cmp += len;
 
+       mutex_lock(&event_mutex);
        mutex_lock(&trace_types_lock);
 
        ret = match_string(trace_options, -1, cmp);
@@ -4762,6 +4767,7 @@ static int trace_set_options(struct trace_array *tr, char *option)
                ret = set_tracer_flag(tr, 1 << ret, !neg);
 
        mutex_unlock(&trace_types_lock);
+       mutex_unlock(&event_mutex);
 
        /*
         * If the first trailing whitespace is replaced with '\0' by strstrip,
@@ -8076,9 +8082,11 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
        if (val != 0 && val != 1)
                return -EINVAL;
 
+       mutex_lock(&event_mutex);
        mutex_lock(&trace_types_lock);
        ret = set_tracer_flag(tr, 1 << index, val);
        mutex_unlock(&trace_types_lock);
+       mutex_unlock(&event_mutex);
 
        if (ret < 0)
                return ret;
@@ -8796,7 +8804,7 @@ struct dentry *tracing_init_dentry(void)
        struct trace_array *tr = &global_trace;
 
        if (security_locked_down(LOCKDOWN_TRACEFS)) {
-               pr_warning("Tracing disabled due to lockdown\n");
+               pr_warn("Tracing disabled due to lockdown\n");
                return ERR_PTR(-EPERM);
        }
 
@@ -9244,7 +9252,7 @@ __init static int tracer_alloc_buffers(void)
 
 
        if (security_locked_down(LOCKDOWN_TRACEFS)) {
-               pr_warning("Tracing disabled due to lockdown\n");
+               pr_warn("Tracing disabled due to lockdown\n");
                return -EPERM;
        }
 
index c6de3ce..a5b614c 100644 (file)
@@ -320,7 +320,8 @@ void trace_event_enable_cmd_record(bool enable)
        struct trace_event_file *file;
        struct trace_array *tr;
 
-       mutex_lock(&event_mutex);
+       lockdep_assert_held(&event_mutex);
+
        do_for_each_event_file(tr, file) {
 
                if (!(file->flags & EVENT_FILE_FL_ENABLED))
@@ -334,7 +335,6 @@ void trace_event_enable_cmd_record(bool enable)
                        clear_bit(EVENT_FILE_FL_RECORDED_CMD_BIT, &file->flags);
                }
        } while_for_each_event_file();
-       mutex_unlock(&event_mutex);
 }
 
 void trace_event_enable_tgid_record(bool enable)
@@ -342,7 +342,8 @@ void trace_event_enable_tgid_record(bool enable)
        struct trace_event_file *file;
        struct trace_array *tr;
 
-       mutex_lock(&event_mutex);
+       lockdep_assert_held(&event_mutex);
+
        do_for_each_event_file(tr, file) {
                if (!(file->flags & EVENT_FILE_FL_ENABLED))
                        continue;
@@ -356,7 +357,6 @@ void trace_event_enable_tgid_record(bool enable)
                                  &file->flags);
                }
        } while_for_each_event_file();
-       mutex_unlock(&event_mutex);
 }
 
 static int __ftrace_event_enable_disable(struct trace_event_file *file,
index c9a74f8..bf44f6b 100644 (file)
@@ -1662,7 +1662,7 @@ static int process_system_preds(struct trace_subsystem_dir *dir,
        parse_error(pe, FILT_ERR_BAD_SUBSYS_FILTER, 0);
        return -EINVAL;
  fail_mem:
-       kfree(filter);
+       __free_filter(filter);
        /* If any call succeeded, we still need to sync */
        if (!fail)
                tracepoint_synchronize_unregister();
index f49d1a3..f62de5f 100644 (file)
@@ -911,7 +911,26 @@ static notrace void trace_event_raw_event_synth(void *__data,
                        strscpy(str_field, str_val, STR_VAR_LEN_MAX);
                        n_u64 += STR_VAR_LEN_MAX / sizeof(u64);
                } else {
-                       entry->fields[n_u64] = var_ref_vals[var_ref_idx + i];
+                       struct synth_field *field = event->fields[i];
+                       u64 val = var_ref_vals[var_ref_idx + i];
+
+                       switch (field->size) {
+                       case 1:
+                               *(u8 *)&entry->fields[n_u64] = (u8)val;
+                               break;
+
+                       case 2:
+                               *(u16 *)&entry->fields[n_u64] = (u16)val;
+                               break;
+
+                       case 4:
+                               *(u32 *)&entry->fields[n_u64] = (u32)val;
+                               break;
+
+                       default:
+                               entry->fields[n_u64] = val;
+                               break;
+                       }
                        n_u64++;
                }
        }
index d437107..22bcf7c 100644 (file)
@@ -17,12 +17,10 @@ static int
 trace_inject_entry(struct trace_event_file *file, void *rec, int len)
 {
        struct trace_event_buffer fbuffer;
-       struct ring_buffer *buffer;
        int written = 0;
        void *entry;
 
        rcu_read_lock_sched();
-       buffer = file->tr->trace_buffer.buffer;
        entry = trace_event_buffer_reserve(&fbuffer, file, len);
        if (entry) {
                memcpy(entry, rec, len);
@@ -197,7 +195,7 @@ static int parse_entry(char *str, struct trace_event_call *call, void **pentry)
        unsigned long irq_flags;
        void *entry = NULL;
        int entry_size;
-       u64 val;
+       u64 val = 0;
        int len;
 
        entry = trace_alloc_entry(call, &entry_size);
index 5e43b96..617e297 100644 (file)
@@ -630,7 +630,7 @@ static void start_wakeup_tracer(struct trace_array *tr)
        if (ret) {
                pr_info("wakeup trace: Couldn't activate tracepoint"
                        " probe to kernel_sched_migrate_task\n");
-               return;
+               goto fail_deprobe_sched_switch;
        }
 
        wakeup_reset(tr);
@@ -648,6 +648,8 @@ static void start_wakeup_tracer(struct trace_array *tr)
                printk(KERN_ERR "failed to start wakeup tracer\n");
 
        return;
+fail_deprobe_sched_switch:
+       unregister_trace_sched_switch(probe_wakeup_sched_switch, NULL);
 fail_deprobe_wake_new:
        unregister_trace_sched_wakeup_new(probe_wakeup, NULL);
 fail_deprobe:
index 344e4c1..87de6ed 100644 (file)
@@ -381,7 +381,7 @@ int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
                       int prefix_type, int rowsize, int groupsize,
                       const void *buf, size_t len, bool ascii)
 {
-               unsigned int save_len = s->seq.len;
+       unsigned int save_len = s->seq.len;
 
        if (s->full)
                return 0;
index 4df9a20..c557f42 100644 (file)
@@ -283,6 +283,11 @@ static void check_stack(unsigned long ip, unsigned long *stack)
        local_irq_restore(flags);
 }
 
+/* Some archs may not define MCOUNT_INSN_SIZE */
+#ifndef MCOUNT_INSN_SIZE
+# define MCOUNT_INSN_SIZE 0
+#endif
+
 static void
 stack_trace_call(unsigned long ip, unsigned long parent_ip,
                 struct ftrace_ops *op, struct pt_regs *pt_regs)
index 9a1c223..9e31bfc 100644 (file)
@@ -148,8 +148,8 @@ static int tracing_map_cmp_atomic64(void *val_a, void *val_b)
 #define DEFINE_TRACING_MAP_CMP_FN(type)                                        \
 static int tracing_map_cmp_##type(void *val_a, void *val_b)            \
 {                                                                      \
-       type a = *(type *)val_a;                                        \
-       type b = *(type *)val_b;                                        \
+       type a = (type)(*(u64 *)val_a);                                 \
+       type b = (type)(*(u64 *)val_b);                                 \
                                                                        \
        return (a > b) ? 1 : ((a < b) ? -1 : 0);                        \
 }
index bc88fd9..cfc9235 100644 (file)
@@ -4374,8 +4374,8 @@ void destroy_workqueue(struct workqueue_struct *wq)
        for_each_pwq(pwq, wq) {
                spin_lock_irq(&pwq->pool->lock);
                if (WARN_ON(pwq_busy(pwq))) {
-                       pr_warning("%s: %s has the following busy pwq\n",
-                                  __func__, wq->name);
+                       pr_warn("%s: %s has the following busy pwq\n",
+                               __func__, wq->name);
                        show_pwq(pwq);
                        spin_unlock_irq(&pwq->pool->lock);
                        mutex_unlock(&wq->mutex);
index d1842fe..5ffe144 100644 (file)
@@ -1483,6 +1483,55 @@ config PROVIDE_OHCI1394_DMA_INIT
 
          See Documentation/debugging-via-ohci1394.txt for more information.
 
+source "samples/Kconfig"
+
+config ARCH_HAS_DEVMEM_IS_ALLOWED
+       bool
+
+config STRICT_DEVMEM
+       bool "Filter access to /dev/mem"
+       depends on MMU && DEVMEM
+       depends on ARCH_HAS_DEVMEM_IS_ALLOWED
+       default y if PPC || X86 || ARM64
+       help
+         If this option is disabled, you allow userspace (root) access to all
+         of memory, including kernel and userspace memory. Accidental
+         access to this is obviously disastrous, but specific access can
+         be used by people debugging the kernel. Note that with PAT support
+         enabled, even in this case there are restrictions on /dev/mem
+         use due to the cache aliasing requirements.
+
+         If this option is switched on, and IO_STRICT_DEVMEM=n, the /dev/mem
+         file only allows userspace access to PCI space and the BIOS code and
+         data regions.  This is sufficient for dosemu and X and all common
+         users of /dev/mem.
+
+         If in doubt, say Y.
+
+config IO_STRICT_DEVMEM
+       bool "Filter I/O access to /dev/mem"
+       depends on STRICT_DEVMEM
+       help
+         If this option is disabled, you allow userspace (root) access to all
+         io-memory regardless of whether a driver is actively using that
+         range.  Accidental access to this is obviously disastrous, but
+         specific access can be used by people debugging kernel drivers.
+
+         If this option is switched on, the /dev/mem file only allows
+         userspace access to *idle* io-memory ranges (see /proc/iomem) This
+         may break traditional users of /dev/mem (dosemu, legacy X, etc...)
+         if the driver using a given range cannot be disabled.
+
+         If in doubt, say Y.
+
+menu "$(SRCARCH) Debugging"
+
+source "arch/$(SRCARCH)/Kconfig.debug"
+
+endmenu
+
+menu "Kernel Testing and Coverage"
+
 source "lib/kunit/Kconfig"
 
 config NOTIFIER_ERROR_INJECTION
@@ -1643,10 +1692,6 @@ config FAULT_INJECTION_STACKTRACE_FILTER
        help
          Provide stacktrace filter for fault-injection capabilities
 
-endmenu # "Kernel Testing and Coverage"
-
-menu "Kernel Testing and Coverage"
-
 config ARCH_HAS_KCOV
        bool
        help
@@ -2130,52 +2175,7 @@ config MEMTEST
                memtest=17, mean do 17 test patterns.
          If you are unsure how to answer this question, answer N.
 
-source "samples/Kconfig"
-
-config ARCH_HAS_DEVMEM_IS_ALLOWED
-       bool
-
-config STRICT_DEVMEM
-       bool "Filter access to /dev/mem"
-       depends on MMU && DEVMEM
-       depends on ARCH_HAS_DEVMEM_IS_ALLOWED
-       default y if PPC || X86 || ARM64
-       ---help---
-         If this option is disabled, you allow userspace (root) access to all
-         of memory, including kernel and userspace memory. Accidental
-         access to this is obviously disastrous, but specific access can
-         be used by people debugging the kernel. Note that with PAT support
-         enabled, even in this case there are restrictions on /dev/mem
-         use due to the cache aliasing requirements.
-
-         If this option is switched on, and IO_STRICT_DEVMEM=n, the /dev/mem
-         file only allows userspace access to PCI space and the BIOS code and
-         data regions.  This is sufficient for dosemu and X and all common
-         users of /dev/mem.
-
-         If in doubt, say Y.
 
-config IO_STRICT_DEVMEM
-       bool "Filter I/O access to /dev/mem"
-       depends on STRICT_DEVMEM
-       ---help---
-         If this option is disabled, you allow userspace (root) access to all
-         io-memory regardless of whether a driver is actively using that
-         range.  Accidental access to this is obviously disastrous, but
-         specific access can be used by people debugging kernel drivers.
-
-         If this option is switched on, the /dev/mem file only allows
-         userspace access to *idle* io-memory ranges (see /proc/iomem) This
-         may break traditional users of /dev/mem (dosemu, legacy X, etc...)
-         if the driver using a given range cannot be disabled.
-
-         If in doubt, say Y.
-
-menu "$(SRCARCH) Debugging"
-
-source "arch/$(SRCARCH)/Kconfig.debug"
-
-endmenu
 
 config HYPERV_TESTING
        bool "Microsoft Hyper-V driver testing"
@@ -2184,4 +2184,6 @@ config HYPERV_TESTING
        help
          Select this option to enable Hyper-V vmbus testing.
 
+endmenu # "Kernel Testing and Coverage"
+
 endmenu # Kernel hacking
index fb29c02..51595bf 100644 (file)
@@ -1222,11 +1222,12 @@ EXPORT_SYMBOL(iov_iter_discard);
 
 unsigned long iov_iter_alignment(const struct iov_iter *i)
 {
-       unsigned int p_mask = i->pipe->ring_size - 1;
        unsigned long res = 0;
        size_t size = i->count;
 
        if (unlikely(iov_iter_is_pipe(i))) {
+               unsigned int p_mask = i->pipe->ring_size - 1;
+
                if (size && i->iov_offset && allocated(&i->pipe->bufs[i->head & p_mask]))
                        return size | i->iov_offset;
                return size;
index c6aa036..0809805 100644 (file)
@@ -13,7 +13,7 @@ BEGIN {
        for (i = 0; i < rep; ++i) {
                tmp = $0
                gsub(/\$\$/, i, tmp)
-               gsub(/\$\#/, n, tmp)
+               gsub(/\$#/, n, tmp)
                gsub(/\$\*/, "$", tmp)
                print tmp
        }
index 33feec8..af88d13 100644 (file)
@@ -650,8 +650,8 @@ void sbitmap_add_wait_queue(struct sbitmap_queue *sbq,
        if (!sbq_wait->sbq) {
                sbq_wait->sbq = sbq;
                atomic_inc(&sbq->ws_active);
+               add_wait_queue(&ws->wait, &sbq_wait->wait);
        }
-       add_wait_queue(&ws->wait, &sbq_wait->wait);
 }
 EXPORT_SYMBOL_GPL(sbitmap_add_wait_queue);
 
index 9ecfd3b..42bd8ab 100644 (file)
@@ -221,6 +221,7 @@ int __cvdso_clock_getres_common(clockid_t clock, struct __kernel_timespec *res)
        return 0;
 }
 
+static __maybe_unused
 int __cvdso_clock_getres(clockid_t clock, struct __kernel_timespec *res)
 {
        int ret = __cvdso_clock_getres_common(clock, res);
index 7dd602d..ad9d5b1 100644 (file)
@@ -26,6 +26,7 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
        unsigned long i, nr_pages, addr, next;
        int nr;
        struct page **pages;
+       int ret = 0;
 
        if (gup->size > ULONG_MAX)
                return -EINVAL;
@@ -63,7 +64,9 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
                                            NULL);
                        break;
                default:
-                       return -1;
+                       kvfree(pages);
+                       ret = -EINVAL;
+                       goto out;
                }
 
                if (nr <= 0)
@@ -85,7 +88,8 @@ static int __gup_benchmark_ioctl(unsigned int cmd,
        gup->put_delta_usec = ktime_us_delta(end_time, start_time);
 
        kvfree(pages);
-       return 0;
+out:
+       return ret;
 }
 
 static long gup_benchmark_ioctl(struct file *filep, unsigned int cmd,
index 41a0fbd..a880932 100644 (file)
@@ -527,13 +527,13 @@ void prep_transhuge_page(struct page *page)
        set_compound_page_dtor(page, TRANSHUGE_PAGE_DTOR);
 }
 
-static unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,
+static unsigned long __thp_get_unmapped_area(struct file *filp,
+               unsigned long addr, unsigned long len,
                loff_t off, unsigned long flags, unsigned long size)
 {
-       unsigned long addr;
        loff_t off_end = off + len;
        loff_t off_align = round_up(off, size);
-       unsigned long len_pad;
+       unsigned long len_pad, ret;
 
        if (off_end <= off_align || (off_end - off_align) < size)
                return 0;
@@ -542,30 +542,40 @@ static unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long le
        if (len_pad < len || (off + len_pad) < off)
                return 0;
 
-       addr = current->mm->get_unmapped_area(filp, 0, len_pad,
+       ret = current->mm->get_unmapped_area(filp, addr, len_pad,
                                              off >> PAGE_SHIFT, flags);
-       if (IS_ERR_VALUE(addr))
+
+       /*
+        * The failure might be due to length padding. The caller will retry
+        * without the padding.
+        */
+       if (IS_ERR_VALUE(ret))
                return 0;
 
-       addr += (off - addr) & (size - 1);
-       return addr;
+       /*
+        * Do not try to align to THP boundary if allocation at the address
+        * hint succeeds.
+        */
+       if (ret == addr)
+               return addr;
+
+       ret += (off - ret) & (size - 1);
+       return ret;
 }
 
 unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
                unsigned long len, unsigned long pgoff, unsigned long flags)
 {
+       unsigned long ret;
        loff_t off = (loff_t)pgoff << PAGE_SHIFT;
 
-       if (addr)
-               goto out;
        if (!IS_DAX(filp->f_mapping->host) || !IS_ENABLED(CONFIG_FS_DAX_PMD))
                goto out;
 
-       addr = __thp_get_unmapped_area(filp, len, off, flags, PMD_SIZE);
-       if (addr)
-               return addr;
-
- out:
+       ret = __thp_get_unmapped_area(filp, addr, len, off, flags, PMD_SIZE);
+       if (ret)
+               return ret;
+out:
        return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
 }
 EXPORT_SYMBOL_GPL(thp_get_unmapped_area);
index ac65bb5..dd8737a 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/swapops.h>
 #include <linux/jhash.h>
 #include <linux/numa.h>
+#include <linux/llist.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -1136,7 +1137,7 @@ static inline void ClearPageHugeTemporary(struct page *page)
        page[2].mapping = NULL;
 }
 
-void free_huge_page(struct page *page)
+static void __free_huge_page(struct page *page)
 {
        /*
         * Can't pass hstate in here because it is called from the
@@ -1199,6 +1200,54 @@ void free_huge_page(struct page *page)
        spin_unlock(&hugetlb_lock);
 }
 
+/*
+ * As free_huge_page() can be called from a non-task context, we have
+ * to defer the actual freeing in a workqueue to prevent potential
+ * hugetlb_lock deadlock.
+ *
+ * free_hpage_workfn() locklessly retrieves the linked list of pages to
+ * be freed and frees them one-by-one. As the page->mapping pointer is
+ * going to be cleared in __free_huge_page() anyway, it is reused as the
+ * llist_node structure of a lockless linked list of huge pages to be freed.
+ */
+static LLIST_HEAD(hpage_freelist);
+
+static void free_hpage_workfn(struct work_struct *work)
+{
+       struct llist_node *node;
+       struct page *page;
+
+       node = llist_del_all(&hpage_freelist);
+
+       while (node) {
+               page = container_of((struct address_space **)node,
+                                    struct page, mapping);
+               node = node->next;
+               __free_huge_page(page);
+       }
+}
+static DECLARE_WORK(free_hpage_work, free_hpage_workfn);
+
+void free_huge_page(struct page *page)
+{
+       /*
+        * Defer freeing if in non-task context to avoid hugetlb_lock deadlock.
+        */
+       if (!in_task()) {
+               /*
+                * Only call schedule_work() if hpage_freelist is previously
+                * empty. Otherwise, schedule_work() had been called but the
+                * workfn hasn't retrieved the list yet.
+                */
+               if (llist_add((struct llist_node *)&page->mapping,
+                             &hpage_freelist))
+                       schedule_work(&free_hpage_work);
+               return;
+       }
+
+       __free_huge_page(page);
+}
+
 static void prep_new_huge_page(struct hstate *h, struct page *page, int nid)
 {
        INIT_LIST_HEAD(&page->lru);
index 2fa710b..c15d8ae 100644 (file)
@@ -778,15 +778,17 @@ static int kasan_populate_vmalloc_pte(pte_t *ptep, unsigned long addr,
        return 0;
 }
 
-int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)
+int kasan_populate_vmalloc(unsigned long addr, unsigned long size)
 {
        unsigned long shadow_start, shadow_end;
        int ret;
 
-       shadow_start = (unsigned long)kasan_mem_to_shadow(area->addr);
+       if (!is_vmalloc_or_module_addr((void *)addr))
+               return 0;
+
+       shadow_start = (unsigned long)kasan_mem_to_shadow((void *)addr);
        shadow_start = ALIGN_DOWN(shadow_start, PAGE_SIZE);
-       shadow_end = (unsigned long)kasan_mem_to_shadow(area->addr +
-                                                       area->size);
+       shadow_end = (unsigned long)kasan_mem_to_shadow((void *)addr + size);
        shadow_end = ALIGN(shadow_end, PAGE_SIZE);
 
        ret = apply_to_page_range(&init_mm, shadow_start,
@@ -797,10 +799,6 @@ int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)
 
        flush_cache_vmap(shadow_start, shadow_end);
 
-       kasan_unpoison_shadow(area->addr, requested_size);
-
-       area->flags |= VM_KASAN;
-
        /*
         * We need to be careful about inter-cpu effects here. Consider:
         *
@@ -843,12 +841,23 @@ int kasan_populate_vmalloc(unsigned long requested_size, struct vm_struct *area)
  * Poison the shadow for a vmalloc region. Called as part of the
  * freeing process at the time the region is freed.
  */
-void kasan_poison_vmalloc(void *start, unsigned long size)
+void kasan_poison_vmalloc(const void *start, unsigned long size)
 {
+       if (!is_vmalloc_or_module_addr(start))
+               return;
+
        size = round_up(size, KASAN_SHADOW_SCALE_SIZE);
        kasan_poison_shadow(start, size, KASAN_VMALLOC_INVALID);
 }
 
+void kasan_unpoison_vmalloc(const void *start, unsigned long size)
+{
+       if (!is_vmalloc_or_module_addr(start))
+               return;
+
+       kasan_unpoison_shadow(start, size);
+}
+
 static int kasan_depopulate_vmalloc_pte(pte_t *ptep, unsigned long addr,
                                        void *unused)
 {
@@ -948,6 +957,7 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end,
 {
        void *shadow_start, *shadow_end;
        unsigned long region_start, region_end;
+       unsigned long size;
 
        region_start = ALIGN(start, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE);
        region_end = ALIGN_DOWN(end, PAGE_SIZE * KASAN_SHADOW_SCALE_SIZE);
@@ -970,9 +980,11 @@ void kasan_release_vmalloc(unsigned long start, unsigned long end,
        shadow_end = kasan_mem_to_shadow((void *)region_end);
 
        if (shadow_end > shadow_start) {
-               apply_to_page_range(&init_mm, (unsigned long)shadow_start,
-                                   (unsigned long)(shadow_end - shadow_start),
-                                   kasan_depopulate_vmalloc_pte, NULL);
+               size = shadow_end - shadow_start;
+               apply_to_existing_page_range(&init_mm,
+                                            (unsigned long)shadow_start,
+                                            size, kasan_depopulate_vmalloc_pte,
+                                            NULL);
                flush_tlb_kernel_range((unsigned long)shadow_start,
                                       (unsigned long)shadow_end);
        }
index c5b5f74..6c83cf4 100644 (file)
@@ -3287,49 +3287,34 @@ static u64 mem_cgroup_read_u64(struct cgroup_subsys_state *css,
        }
 }
 
-static void memcg_flush_percpu_vmstats(struct mem_cgroup *memcg, bool slab_only)
+static void memcg_flush_percpu_vmstats(struct mem_cgroup *memcg)
 {
-       unsigned long stat[MEMCG_NR_STAT];
+       unsigned long stat[MEMCG_NR_STAT] = {0};
        struct mem_cgroup *mi;
        int node, cpu, i;
-       int min_idx, max_idx;
-
-       if (slab_only) {
-               min_idx = NR_SLAB_RECLAIMABLE;
-               max_idx = NR_SLAB_UNRECLAIMABLE;
-       } else {
-               min_idx = 0;
-               max_idx = MEMCG_NR_STAT;
-       }
-
-       for (i = min_idx; i < max_idx; i++)
-               stat[i] = 0;
 
        for_each_online_cpu(cpu)
-               for (i = min_idx; i < max_idx; i++)
+               for (i = 0; i < MEMCG_NR_STAT; i++)
                        stat[i] += per_cpu(memcg->vmstats_percpu->stat[i], cpu);
 
        for (mi = memcg; mi; mi = parent_mem_cgroup(mi))
-               for (i = min_idx; i < max_idx; i++)
+               for (i = 0; i < MEMCG_NR_STAT; i++)
                        atomic_long_add(stat[i], &mi->vmstats[i]);
 
-       if (!slab_only)
-               max_idx = NR_VM_NODE_STAT_ITEMS;
-
        for_each_node(node) {
                struct mem_cgroup_per_node *pn = memcg->nodeinfo[node];
                struct mem_cgroup_per_node *pi;
 
-               for (i = min_idx; i < max_idx; i++)
+               for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
                        stat[i] = 0;
 
                for_each_online_cpu(cpu)
-                       for (i = min_idx; i < max_idx; i++)
+                       for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
                                stat[i] += per_cpu(
                                        pn->lruvec_stat_cpu->count[i], cpu);
 
                for (pi = pn; pi; pi = parent_nodeinfo(pi, node))
-                       for (i = min_idx; i < max_idx; i++)
+                       for (i = 0; i < NR_VM_NODE_STAT_ITEMS; i++)
                                atomic_long_add(stat[i], &pi->lruvec_stat[i]);
        }
 }
@@ -3403,13 +3388,9 @@ static void memcg_offline_kmem(struct mem_cgroup *memcg)
                parent = root_mem_cgroup;
 
        /*
-        * Deactivate and reparent kmem_caches. Then flush percpu
-        * slab statistics to have precise values at the parent and
-        * all ancestor levels. It's required to keep slab stats
-        * accurate after the reparenting of kmem_caches.
+        * Deactivate and reparent kmem_caches.
         */
        memcg_deactivate_kmem_caches(memcg, parent);
-       memcg_flush_percpu_vmstats(memcg, true);
 
        kmemcg_id = memcg->kmemcg_id;
        BUG_ON(kmemcg_id < 0);
@@ -4913,7 +4894,7 @@ static void mem_cgroup_free(struct mem_cgroup *memcg)
         * Flush percpu vmstats and vmevents to guarantee the value correctness
         * on parent's and all ancestor levels.
         */
-       memcg_flush_percpu_vmstats(memcg, false);
+       memcg_flush_percpu_vmstats(memcg);
        memcg_flush_percpu_vmevents(memcg);
        __mem_cgroup_free(memcg);
 }
index 606da18..45442d9 100644 (file)
@@ -2021,26 +2021,34 @@ EXPORT_SYMBOL(vm_iomap_memory);
 
 static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
                                     unsigned long addr, unsigned long end,
-                                    pte_fn_t fn, void *data)
+                                    pte_fn_t fn, void *data, bool create)
 {
        pte_t *pte;
-       int err;
+       int err = 0;
        spinlock_t *uninitialized_var(ptl);
 
-       pte = (mm == &init_mm) ?
-               pte_alloc_kernel(pmd, addr) :
-               pte_alloc_map_lock(mm, pmd, addr, &ptl);
-       if (!pte)
-               return -ENOMEM;
+       if (create) {
+               pte = (mm == &init_mm) ?
+                       pte_alloc_kernel(pmd, addr) :
+                       pte_alloc_map_lock(mm, pmd, addr, &ptl);
+               if (!pte)
+                       return -ENOMEM;
+       } else {
+               pte = (mm == &init_mm) ?
+                       pte_offset_kernel(pmd, addr) :
+                       pte_offset_map_lock(mm, pmd, addr, &ptl);
+       }
 
        BUG_ON(pmd_huge(*pmd));
 
        arch_enter_lazy_mmu_mode();
 
        do {
-               err = fn(pte++, addr, data);
-               if (err)
-                       break;
+               if (create || !pte_none(*pte)) {
+                       err = fn(pte++, addr, data);
+                       if (err)
+                               break;
+               }
        } while (addr += PAGE_SIZE, addr != end);
 
        arch_leave_lazy_mmu_mode();
@@ -2052,77 +2060,95 @@ static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,
 
 static int apply_to_pmd_range(struct mm_struct *mm, pud_t *pud,
                                     unsigned long addr, unsigned long end,
-                                    pte_fn_t fn, void *data)
+                                    pte_fn_t fn, void *data, bool create)
 {
        pmd_t *pmd;
        unsigned long next;
-       int err;
+       int err = 0;
 
        BUG_ON(pud_huge(*pud));
 
-       pmd = pmd_alloc(mm, pud, addr);
-       if (!pmd)
-               return -ENOMEM;
+       if (create) {
+               pmd = pmd_alloc(mm, pud, addr);
+               if (!pmd)
+                       return -ENOMEM;
+       } else {
+               pmd = pmd_offset(pud, addr);
+       }
        do {
                next = pmd_addr_end(addr, end);
-               err = apply_to_pte_range(mm, pmd, addr, next, fn, data);
-               if (err)
-                       break;
+               if (create || !pmd_none_or_clear_bad(pmd)) {
+                       err = apply_to_pte_range(mm, pmd, addr, next, fn, data,
+                                                create);
+                       if (err)
+                               break;
+               }
        } while (pmd++, addr = next, addr != end);
        return err;
 }
 
 static int apply_to_pud_range(struct mm_struct *mm, p4d_t *p4d,
                                     unsigned long addr, unsigned long end,
-                                    pte_fn_t fn, void *data)
+                                    pte_fn_t fn, void *data, bool create)
 {
        pud_t *pud;
        unsigned long next;
-       int err;
+       int err = 0;
 
-       pud = pud_alloc(mm, p4d, addr);
-       if (!pud)
-               return -ENOMEM;
+       if (create) {
+               pud = pud_alloc(mm, p4d, addr);
+               if (!pud)
+                       return -ENOMEM;
+       } else {
+               pud = pud_offset(p4d, addr);
+       }
        do {
                next = pud_addr_end(addr, end);
-               err = apply_to_pmd_range(mm, pud, addr, next, fn, data);
-               if (err)
-                       break;
+               if (create || !pud_none_or_clear_bad(pud)) {
+                       err = apply_to_pmd_range(mm, pud, addr, next, fn, data,
+                                                create);
+                       if (err)
+                               break;
+               }
        } while (pud++, addr = next, addr != end);
        return err;
 }
 
 static int apply_to_p4d_range(struct mm_struct *mm, pgd_t *pgd,
                                     unsigned long addr, unsigned long end,
-                                    pte_fn_t fn, void *data)
+                                    pte_fn_t fn, void *data, bool create)
 {
        p4d_t *p4d;
        unsigned long next;
-       int err;
+       int err = 0;
 
-       p4d = p4d_alloc(mm, pgd, addr);
-       if (!p4d)
-               return -ENOMEM;
+       if (create) {
+               p4d = p4d_alloc(mm, pgd, addr);
+               if (!p4d)
+                       return -ENOMEM;
+       } else {
+               p4d = p4d_offset(pgd, addr);
+       }
        do {
                next = p4d_addr_end(addr, end);
-               err = apply_to_pud_range(mm, p4d, addr, next, fn, data);
-               if (err)
-                       break;
+               if (create || !p4d_none_or_clear_bad(p4d)) {
+                       err = apply_to_pud_range(mm, p4d, addr, next, fn, data,
+                                                create);
+                       if (err)
+                               break;
+               }
        } while (p4d++, addr = next, addr != end);
        return err;
 }
 
-/*
- * Scan a region of virtual memory, filling in page tables as necessary
- * and calling a provided function on each leaf page table.
- */
-int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
-                       unsigned long size, pte_fn_t fn, void *data)
+static int __apply_to_page_range(struct mm_struct *mm, unsigned long addr,
+                                unsigned long size, pte_fn_t fn,
+                                void *data, bool create)
 {
        pgd_t *pgd;
        unsigned long next;
        unsigned long end = addr + size;
-       int err;
+       int err = 0;
 
        if (WARN_ON(addr >= end))
                return -EINVAL;
@@ -2130,16 +2156,42 @@ int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
        pgd = pgd_offset(mm, addr);
        do {
                next = pgd_addr_end(addr, end);
-               err = apply_to_p4d_range(mm, pgd, addr, next, fn, data);
+               if (!create && pgd_none_or_clear_bad(pgd))
+                       continue;
+               err = apply_to_p4d_range(mm, pgd, addr, next, fn, data, create);
                if (err)
                        break;
        } while (pgd++, addr = next, addr != end);
 
        return err;
 }
+
+/*
+ * Scan a region of virtual memory, filling in page tables as necessary
+ * and calling a provided function on each leaf page table.
+ */
+int apply_to_page_range(struct mm_struct *mm, unsigned long addr,
+                       unsigned long size, pte_fn_t fn, void *data)
+{
+       return __apply_to_page_range(mm, addr, size, fn, data, true);
+}
 EXPORT_SYMBOL_GPL(apply_to_page_range);
 
 /*
+ * Scan a region of virtual memory, calling a provided function on
+ * each leaf page table where it exists.
+ *
+ * Unlike apply_to_page_range, this does _not_ fill in page tables
+ * where they are absent.
+ */
+int apply_to_existing_page_range(struct mm_struct *mm, unsigned long addr,
+                                unsigned long size, pte_fn_t fn, void *data)
+{
+       return __apply_to_page_range(mm, addr, size, fn, data, false);
+}
+EXPORT_SYMBOL_GPL(apply_to_existing_page_range);
+
+/*
  * handle_pte_fault chooses page fault handler according to an entry which was
  * read non-atomically.  Before making any commitment, on those architectures
  * or configurations (e.g. i386 with PAE) which might give a mix of unmatched
index 55ac23e..a91a072 100644 (file)
@@ -483,8 +483,9 @@ static void update_pgdat_span(struct pglist_data *pgdat)
        pgdat->node_spanned_pages = node_end_pfn - node_start_pfn;
 }
 
-static void __remove_zone(struct zone *zone, unsigned long start_pfn,
-               unsigned long nr_pages)
+void __ref remove_pfn_range_from_zone(struct zone *zone,
+                                     unsigned long start_pfn,
+                                     unsigned long nr_pages)
 {
        struct pglist_data *pgdat = zone->zone_pgdat;
        unsigned long flags;
@@ -499,28 +500,30 @@ static void __remove_zone(struct zone *zone, unsigned long start_pfn,
                return;
 #endif
 
+       clear_zone_contiguous(zone);
+
        pgdat_resize_lock(zone->zone_pgdat, &flags);
        shrink_zone_span(zone, start_pfn, start_pfn + nr_pages);
        update_pgdat_span(pgdat);
        pgdat_resize_unlock(zone->zone_pgdat, &flags);
+
+       set_zone_contiguous(zone);
 }
 
-static void __remove_section(struct zone *zone, unsigned long pfn,
-               unsigned long nr_pages, unsigned long map_offset,
-               struct vmem_altmap *altmap)
+static void __remove_section(unsigned long pfn, unsigned long nr_pages,
+                            unsigned long map_offset,
+                            struct vmem_altmap *altmap)
 {
        struct mem_section *ms = __nr_to_section(pfn_to_section_nr(pfn));
 
        if (WARN_ON_ONCE(!valid_section(ms)))
                return;
 
-       __remove_zone(zone, pfn, nr_pages);
        sparse_remove_section(ms, pfn, nr_pages, map_offset, altmap);
 }
 
 /**
- * __remove_pages() - remove sections of pages from a zone
- * @zone: zone from which pages need to be removed
+ * __remove_pages() - remove sections of pages
  * @pfn: starting pageframe (must be aligned to start of a section)
  * @nr_pages: number of pages to remove (must be multiple of section size)
  * @altmap: alternative device page map or %NULL if default memmap is used
@@ -530,16 +533,14 @@ static void __remove_section(struct zone *zone, unsigned long pfn,
  * sure that pages are marked reserved and zones are adjust properly by
  * calling offline_pages().
  */
-void __remove_pages(struct zone *zone, unsigned long pfn,
-                   unsigned long nr_pages, struct vmem_altmap *altmap)
+void __remove_pages(unsigned long pfn, unsigned long nr_pages,
+                   struct vmem_altmap *altmap)
 {
        unsigned long map_offset = 0;
        unsigned long nr, start_sec, end_sec;
 
        map_offset = vmem_altmap_offset(altmap);
 
-       clear_zone_contiguous(zone);
-
        if (check_pfn_span(pfn, nr_pages, "remove"))
                return;
 
@@ -551,13 +552,11 @@ void __remove_pages(struct zone *zone, unsigned long pfn,
                cond_resched();
                pfns = min(nr_pages, PAGES_PER_SECTION
                                - (pfn & ~PAGE_SECTION_MASK));
-               __remove_section(zone, pfn, pfns, map_offset, altmap);
+               __remove_section(pfn, pfns, map_offset, altmap);
                pfn += pfns;
                nr_pages -= pfns;
                map_offset = 0;
        }
-
-       set_zone_contiguous(zone);
 }
 
 int set_online_page_callback(online_page_callback_t callback)
@@ -869,6 +868,7 @@ failed_addition:
                 (unsigned long long) pfn << PAGE_SHIFT,
                 (((unsigned long long) pfn + nr_pages) << PAGE_SHIFT) - 1);
        memory_notify(MEM_CANCEL_ONLINE, &arg);
+       remove_pfn_range_from_zone(zone, pfn, nr_pages);
        mem_hotplug_done();
        return ret;
 }
@@ -1628,6 +1628,7 @@ static int __ref __offline_pages(unsigned long start_pfn,
        writeback_set_ratelimit();
 
        memory_notify(MEM_OFFLINE, &arg);
+       remove_pfn_range_from_zone(zone, start_pfn, nr_pages);
        mem_hotplug_done();
        return 0;
 
index 067cf7d..b2920ae 100644 (file)
@@ -2148,18 +2148,22 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
                nmask = policy_nodemask(gfp, pol);
                if (!nmask || node_isset(hpage_node, *nmask)) {
                        mpol_cond_put(pol);
+                       /*
+                        * First, try to allocate THP only on local node, but
+                        * don't reclaim unnecessarily, just compact.
+                        */
                        page = __alloc_pages_node(hpage_node,
-                                               gfp | __GFP_THISNODE, order);
+                               gfp | __GFP_THISNODE | __GFP_NORETRY, order);
 
                        /*
                         * If hugepage allocations are configured to always
                         * synchronous compact or the vma has been madvised
                         * to prefer hugepage backing, retry allowing remote
-                        * memory as well.
+                        * memory with both reclaim and compact as well.
                         */
                        if (!page && (gfp & __GFP_DIRECT_RECLAIM))
                                page = __alloc_pages_node(hpage_node,
-                                               gfp | __GFP_NORETRY, order);
+                                                               gfp, order);
 
                        goto out;
                }
index 03ccbdf..c51c6bd 100644 (file)
@@ -120,7 +120,7 @@ void memunmap_pages(struct dev_pagemap *pgmap)
 
        mem_hotplug_begin();
        if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
-               __remove_pages(page_zone(first_page), PHYS_PFN(res->start),
+               __remove_pages(PHYS_PFN(res->start),
                               PHYS_PFN(resource_size(res)), NULL);
        } else {
                arch_remove_memory(nid, res->start, resource_size(res),
index eae1565..86873b6 100644 (file)
@@ -1512,9 +1512,11 @@ static int do_move_pages_to_node(struct mm_struct *mm,
 /*
  * Resolves the given address to a struct page, isolates it from the LRU and
  * puts it to the given pagelist.
- * Returns -errno if the page cannot be found/isolated or 0 when it has been
- * queued or the page doesn't need to be migrated because it is already on
- * the target node
+ * Returns:
+ *     errno - if the page cannot be found/isolated
+ *     0 - when it doesn't have to be migrated because it is already on the
+ *         target node
+ *     1 - when it has been queued
  */
 static int add_page_for_migration(struct mm_struct *mm, unsigned long addr,
                int node, struct list_head *pagelist, bool migrate_all)
@@ -1553,7 +1555,7 @@ static int add_page_for_migration(struct mm_struct *mm, unsigned long addr,
        if (PageHuge(page)) {
                if (PageHead(page)) {
                        isolate_huge_page(page, pagelist);
-                       err = 0;
+                       err = 1;
                }
        } else {
                struct page *head;
@@ -1563,7 +1565,7 @@ static int add_page_for_migration(struct mm_struct *mm, unsigned long addr,
                if (err)
                        goto out_putpage;
 
-               err = 0;
+               err = 1;
                list_add_tail(&head->lru, pagelist);
                mod_node_page_state(page_pgdat(head),
                        NR_ISOLATED_ANON + page_is_file_cache(head),
@@ -1640,8 +1642,17 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
                 */
                err = add_page_for_migration(mm, addr, current_node,
                                &pagelist, flags & MPOL_MF_MOVE_ALL);
-               if (!err)
+
+               if (!err) {
+                       /* The page is already on the target node */
+                       err = store_status(status, i, current_node, 1);
+                       if (err)
+                               goto out_flush;
                        continue;
+               } else if (err > 0) {
+                       /* The page is successfully queued for migration */
+                       continue;
+               }
 
                err = store_status(status, i, err, 1);
                if (err)
index 9c64852..71e4ffc 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -90,12 +90,6 @@ static void unmap_region(struct mm_struct *mm,
  * MAP_PRIVATE r: (no) no      r: (yes) yes    r: (no) yes     r: (no) yes
  *             w: (no) no      w: (no) no      w: (copy) copy  w: (no) no
  *             x: (no) no      x: (no) yes     x: (no) yes     x: (yes) yes
- *
- * On arm64, PROT_EXEC has the following behaviour for both MAP_SHARED and
- * MAP_PRIVATE:
- *                                                             r: (no) no
- *                                                             w: (no) no
- *                                                             x: (yes) yes
  */
 pgprot_t protection_map[16] __ro_after_init = {
        __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111,
index 71e3ace..d58c481 100644 (file)
@@ -890,7 +890,7 @@ static void __oom_kill_process(struct task_struct *victim, const char *message)
                K(get_mm_counter(mm, MM_FILEPAGES)),
                K(get_mm_counter(mm, MM_SHMEMPAGES)),
                from_kuid(&init_user_ns, task_uid(victim)),
-               mm_pgtables_bytes(mm), victim->signal->oom_score_adj);
+               mm_pgtables_bytes(mm) >> 10, victim->signal->oom_score_adj);
        task_unlock(victim);
 
        /*
index 50055d2..2caf780 100644 (file)
@@ -201,11 +201,11 @@ static void wb_min_max_ratio(struct bdi_writeback *wb,
        if (this_bw < tot_bw) {
                if (min) {
                        min *= this_bw;
-                       do_div(min, tot_bw);
+                       min = div64_ul(min, tot_bw);
                }
                if (max < 100) {
                        max *= this_bw;
-                       do_div(max, tot_bw);
+                       max = div64_ul(max, tot_bw);
                }
        }
 
@@ -766,7 +766,7 @@ static unsigned long __wb_calc_thresh(struct dirty_throttle_control *dtc)
        struct wb_domain *dom = dtc_dom(dtc);
        unsigned long thresh = dtc->thresh;
        u64 wb_thresh;
-       long numerator, denominator;
+       unsigned long numerator, denominator;
        unsigned long wb_min_ratio, wb_max_ratio;
 
        /*
@@ -777,7 +777,7 @@ static unsigned long __wb_calc_thresh(struct dirty_throttle_control *dtc)
 
        wb_thresh = (thresh * (100 - bdi_min_ratio)) / 100;
        wb_thresh *= numerator;
-       do_div(wb_thresh, denominator);
+       wb_thresh = div64_ul(wb_thresh, denominator);
 
        wb_min_max_ratio(dtc->wb, &wb_min_ratio, &wb_max_ratio);
 
@@ -1102,7 +1102,7 @@ static void wb_update_write_bandwidth(struct bdi_writeback *wb,
        bw = written - min(written, wb->written_stamp);
        bw *= HZ;
        if (unlikely(elapsed > period)) {
-               do_div(bw, elapsed);
+               bw = div64_ul(bw, elapsed);
                avg = bw;
                goto out;
        }
index 4785a8a..d047bf7 100644 (file)
@@ -694,34 +694,27 @@ void prep_compound_page(struct page *page, unsigned int order)
 #ifdef CONFIG_DEBUG_PAGEALLOC
 unsigned int _debug_guardpage_minorder;
 
-#ifdef CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT
-DEFINE_STATIC_KEY_TRUE(_debug_pagealloc_enabled);
-#else
+bool _debug_pagealloc_enabled_early __read_mostly
+                       = IS_ENABLED(CONFIG_DEBUG_PAGEALLOC_ENABLE_DEFAULT);
+EXPORT_SYMBOL(_debug_pagealloc_enabled_early);
 DEFINE_STATIC_KEY_FALSE(_debug_pagealloc_enabled);
-#endif
 EXPORT_SYMBOL(_debug_pagealloc_enabled);
 
 DEFINE_STATIC_KEY_FALSE(_debug_guardpage_enabled);
 
 static int __init early_debug_pagealloc(char *buf)
 {
-       bool enable = false;
-
-       if (kstrtobool(buf, &enable))
-               return -EINVAL;
-
-       if (enable)
-               static_branch_enable(&_debug_pagealloc_enabled);
-
-       return 0;
+       return kstrtobool(buf, &_debug_pagealloc_enabled_early);
 }
 early_param("debug_pagealloc", early_debug_pagealloc);
 
-static void init_debug_guardpage(void)
+void init_debug_pagealloc(void)
 {
        if (!debug_pagealloc_enabled())
                return;
 
+       static_branch_enable(&_debug_pagealloc_enabled);
+
        if (!debug_guardpage_minorder())
                return;
 
@@ -1186,7 +1179,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
         */
        arch_free_page(page, order);
 
-       if (debug_pagealloc_enabled())
+       if (debug_pagealloc_enabled_static())
                kernel_map_pages(page, 1 << order, 0);
 
        kasan_free_nondeferred_pages(page, order);
@@ -1207,7 +1200,7 @@ static bool free_pcp_prepare(struct page *page)
 
 static bool bulkfree_pcp_prepare(struct page *page)
 {
-       if (debug_pagealloc_enabled())
+       if (debug_pagealloc_enabled_static())
                return free_pages_check(page);
        else
                return false;
@@ -1221,7 +1214,7 @@ static bool bulkfree_pcp_prepare(struct page *page)
  */
 static bool free_pcp_prepare(struct page *page)
 {
-       if (debug_pagealloc_enabled())
+       if (debug_pagealloc_enabled_static())
                return free_pages_prepare(page, 0, true);
        else
                return free_pages_prepare(page, 0, false);
@@ -1973,10 +1966,6 @@ void __init page_alloc_init_late(void)
 
        for_each_populated_zone(zone)
                set_zone_contiguous(zone);
-
-#ifdef CONFIG_DEBUG_PAGEALLOC
-       init_debug_guardpage();
-#endif
 }
 
 #ifdef CONFIG_CMA
@@ -2106,7 +2095,7 @@ static inline bool free_pages_prezeroed(void)
  */
 static inline bool check_pcp_refill(struct page *page)
 {
-       if (debug_pagealloc_enabled())
+       if (debug_pagealloc_enabled_static())
                return check_new_page(page);
        else
                return false;
@@ -2128,7 +2117,7 @@ static inline bool check_pcp_refill(struct page *page)
 }
 static inline bool check_new_pcp(struct page *page)
 {
-       if (debug_pagealloc_enabled())
+       if (debug_pagealloc_enabled_static())
                return check_new_page(page);
        else
                return false;
@@ -2155,7 +2144,7 @@ inline void post_alloc_hook(struct page *page, unsigned int order,
        set_page_refcounted(page);
 
        arch_alloc_page(page, order);
-       if (debug_pagealloc_enabled())
+       if (debug_pagealloc_enabled_static())
                kernel_map_pages(page, 1 << order, 1);
        kasan_alloc_pages(page, order);
        kernel_poison_pages(page, 1 << order, 1);
@@ -4476,8 +4465,11 @@ retry_cpuset:
                if (page)
                        goto got_pg;
 
-                if (order >= pageblock_order && (gfp_mask & __GFP_IO) &&
-                    !(gfp_mask & __GFP_RETRY_MAYFAIL)) {
+               /*
+                * Checks for costly allocations with __GFP_NORETRY, which
+                * includes some THP page fault allocations
+                */
+               if (costly_order && (gfp_mask & __GFP_NORETRY)) {
                        /*
                         * If allocating entire pageblock(s) and compaction
                         * failed because all zones are below low watermarks
@@ -4498,23 +4490,6 @@ retry_cpuset:
                        if (compact_result == COMPACT_SKIPPED ||
                            compact_result == COMPACT_DEFERRED)
                                goto nopage;
-               }
-
-               /*
-                * Checks for costly allocations with __GFP_NORETRY, which
-                * includes THP page fault allocations
-                */
-               if (costly_order && (gfp_mask & __GFP_NORETRY)) {
-                       /*
-                        * If compaction is deferred for high-order allocations,
-                        * it is because sync compaction recently failed. If
-                        * this is the case and the caller requested a THP
-                        * allocation, we do not want to heavily disrupt the
-                        * system, so we fail the allocation instead of entering
-                        * direct reclaim.
-                        */
-                       if (compact_result == COMPACT_DEFERRED)
-                               goto nopage;
 
                        /*
                         * Looks like reclaim/compaction is worth trying, but
index 165fa63..8793e8c 100644 (file)
@@ -2107,9 +2107,10 @@ unsigned long shmem_get_unmapped_area(struct file *file,
        /*
         * Our priority is to support MAP_SHARED mapped hugely;
         * and support MAP_PRIVATE mapped hugely too, until it is COWed.
-        * But if caller specified an address hint, respect that as before.
+        * But if caller specified an address hint and we allocated area there
+        * successfully, respect that as before.
         */
-       if (uaddr)
+       if (uaddr == addr)
                return addr;
 
        if (shmem_huge != SHMEM_HUGE_FORCE) {
@@ -2143,7 +2144,7 @@ unsigned long shmem_get_unmapped_area(struct file *file,
        if (inflated_len < len)
                return addr;
 
-       inflated_addr = get_area(NULL, 0, inflated_len, 0, flags);
+       inflated_addr = get_area(NULL, uaddr, inflated_len, 0, flags);
        if (IS_ERR_VALUE(inflated_addr))
                return addr;
        if (inflated_addr & ~PAGE_MASK)
index f1e1840..a896336 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1416,7 +1416,7 @@ static void kmem_rcu_free(struct rcu_head *head)
 #if DEBUG
 static bool is_debug_pagealloc_cache(struct kmem_cache *cachep)
 {
-       if (debug_pagealloc_enabled() && OFF_SLAB(cachep) &&
+       if (debug_pagealloc_enabled_static() && OFF_SLAB(cachep) &&
                (cachep->size % PAGE_SIZE) == 0)
                return true;
 
@@ -2008,7 +2008,7 @@ int __kmem_cache_create(struct kmem_cache *cachep, slab_flags_t flags)
         * to check size >= 256. It guarantees that all necessary small
         * sized slab is initialized in current slab initialization sequence.
         */
-       if (debug_pagealloc_enabled() && (flags & SLAB_POISON) &&
+       if (debug_pagealloc_enabled_static() && (flags & SLAB_POISON) &&
                size >= 256 && cachep->object_size > cache_line_size()) {
                if (size < PAGE_SIZE || size % PAGE_SIZE == 0) {
                        size_t tmp_size = ALIGN(size, PAGE_SIZE);
index f0ab6d4..0d95dde 100644 (file)
@@ -903,7 +903,8 @@ static void flush_memcg_workqueue(struct kmem_cache *s)
         * deactivates the memcg kmem_caches through workqueue. Make sure all
         * previous workitems on workqueue are processed.
         */
-       flush_workqueue(memcg_kmem_cache_wq);
+       if (likely(memcg_kmem_cache_wq))
+               flush_workqueue(memcg_kmem_cache_wq);
 
        /*
         * If we're racing with children kmem_cache deactivation, it might
index d113897..8eafccf 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -288,7 +288,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
        unsigned long freepointer_addr;
        void *p;
 
-       if (!debug_pagealloc_enabled())
+       if (!debug_pagealloc_enabled_static())
                return get_freepointer(s, object);
 
        freepointer_addr = (unsigned long)object + s->offset;
index b20ab7c..3822ecb 100644 (file)
@@ -777,7 +777,14 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages,
        if (bitmap_empty(subsection_map, SUBSECTIONS_PER_SECTION)) {
                unsigned long section_nr = pfn_to_section_nr(pfn);
 
-               if (!section_is_early) {
+               /*
+                * When removing an early section, the usage map is kept (as the
+                * usage maps of other sections fall into the same page). It
+                * will be re-used when re-adding the section - which is then no
+                * longer an early section. If the usage map is PageReserved, it
+                * was allocated during boot.
+                */
+               if (!PageReserved(virt_to_page(ms->usage))) {
                        kfree(ms->usage);
                        ms->usage = NULL;
                }
index 4d3b3d6..b29ad17 100644 (file)
@@ -1062,6 +1062,26 @@ __alloc_vmap_area(unsigned long size, unsigned long align,
 }
 
 /*
+ * Free a region of KVA allocated by alloc_vmap_area
+ */
+static void free_vmap_area(struct vmap_area *va)
+{
+       /*
+        * Remove from the busy tree/list.
+        */
+       spin_lock(&vmap_area_lock);
+       unlink_va(va, &vmap_area_root);
+       spin_unlock(&vmap_area_lock);
+
+       /*
+        * Insert/Merge it back to the free tree/list.
+        */
+       spin_lock(&free_vmap_area_lock);
+       merge_or_add_vmap_area(va, &free_vmap_area_root, &free_vmap_area_list);
+       spin_unlock(&free_vmap_area_lock);
+}
+
+/*
  * Allocate a region of KVA of the specified size and alignment, within the
  * vstart and vend.
  */
@@ -1073,6 +1093,7 @@ static struct vmap_area *alloc_vmap_area(unsigned long size,
        struct vmap_area *va, *pva;
        unsigned long addr;
        int purged = 0;
+       int ret;
 
        BUG_ON(!size);
        BUG_ON(offset_in_page(size));
@@ -1139,6 +1160,7 @@ retry:
        va->va_end = addr + size;
        va->vm = NULL;
 
+
        spin_lock(&vmap_area_lock);
        insert_vmap_area(va, &vmap_area_root, &vmap_area_list);
        spin_unlock(&vmap_area_lock);
@@ -1147,6 +1169,12 @@ retry:
        BUG_ON(va->va_start < vstart);
        BUG_ON(va->va_end > vend);
 
+       ret = kasan_populate_vmalloc(addr, size);
+       if (ret) {
+               free_vmap_area(va);
+               return ERR_PTR(ret);
+       }
+
        return va;
 
 overflow:
@@ -1186,26 +1214,6 @@ int unregister_vmap_purge_notifier(struct notifier_block *nb)
 EXPORT_SYMBOL_GPL(unregister_vmap_purge_notifier);
 
 /*
- * Free a region of KVA allocated by alloc_vmap_area
- */
-static void free_vmap_area(struct vmap_area *va)
-{
-       /*
-        * Remove from the busy tree/list.
-        */
-       spin_lock(&vmap_area_lock);
-       unlink_va(va, &vmap_area_root);
-       spin_unlock(&vmap_area_lock);
-
-       /*
-        * Insert/Merge it back to the free tree/list.
-        */
-       spin_lock(&free_vmap_area_lock);
-       merge_or_add_vmap_area(va, &free_vmap_area_root, &free_vmap_area_list);
-       spin_unlock(&free_vmap_area_lock);
-}
-
-/*
  * Clear the pagetable entries of a given vmap_area
  */
 static void unmap_vmap_area(struct vmap_area *va)
@@ -1375,7 +1383,7 @@ static void free_unmap_vmap_area(struct vmap_area *va)
 {
        flush_cache_vunmap(va->va_start, va->va_end);
        unmap_vmap_area(va);
-       if (debug_pagealloc_enabled())
+       if (debug_pagealloc_enabled_static())
                flush_tlb_kernel_range(va->va_start, va->va_end);
 
        free_vmap_area_noflush(va);
@@ -1673,7 +1681,7 @@ static void vb_free(const void *addr, unsigned long size)
 
        vunmap_page_range((unsigned long)addr, (unsigned long)addr + size);
 
-       if (debug_pagealloc_enabled())
+       if (debug_pagealloc_enabled_static())
                flush_tlb_kernel_range((unsigned long)addr,
                                        (unsigned long)addr + size);
 
@@ -1771,6 +1779,8 @@ void vm_unmap_ram(const void *mem, unsigned int count)
        BUG_ON(addr > VMALLOC_END);
        BUG_ON(!PAGE_ALIGNED(addr));
 
+       kasan_poison_vmalloc(mem, size);
+
        if (likely(count <= VMAP_MAX_ALLOC)) {
                debug_check_no_locks_freed(mem, size);
                vb_free(mem, size);
@@ -1821,6 +1831,9 @@ void *vm_map_ram(struct page **pages, unsigned int count, int node, pgprot_t pro
                addr = va->va_start;
                mem = (void *)addr;
        }
+
+       kasan_unpoison_vmalloc(mem, size);
+
        if (vmap_page_range(addr, addr + size, prot, pages) < 0) {
                vm_unmap_ram(mem, count);
                return NULL;
@@ -2075,6 +2088,7 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
 {
        struct vmap_area *va;
        struct vm_struct *area;
+       unsigned long requested_size = size;
 
        BUG_ON(in_interrupt());
        size = PAGE_ALIGN(size);
@@ -2098,23 +2112,9 @@ static struct vm_struct *__get_vm_area_node(unsigned long size,
                return NULL;
        }
 
-       setup_vmalloc_vm(area, va, flags, caller);
+       kasan_unpoison_vmalloc((void *)va->va_start, requested_size);
 
-       /*
-        * For KASAN, if we are in vmalloc space, we need to cover the shadow
-        * area with real memory. If we come here through VM_ALLOC, this is
-        * done by a higher level function that has access to the true size,
-        * which might not be a full page.
-        *
-        * We assume module space comes via VM_ALLOC path.
-        */
-       if (is_vmalloc_addr(area->addr) && !(area->flags & VM_ALLOC)) {
-               if (kasan_populate_vmalloc(area->size, area)) {
-                       unmap_vmap_area(va);
-                       kfree(area);
-                       return NULL;
-               }
-       }
+       setup_vmalloc_vm(area, va, flags, caller);
 
        return area;
 }
@@ -2293,8 +2293,7 @@ static void __vunmap(const void *addr, int deallocate_pages)
        debug_check_no_locks_freed(area->addr, get_vm_area_size(area));
        debug_check_no_obj_freed(area->addr, get_vm_area_size(area));
 
-       if (area->flags & VM_KASAN)
-               kasan_poison_vmalloc(area->addr, area->size);
+       kasan_poison_vmalloc(area->addr, area->size);
 
        vm_remove_mappings(area, deallocate_pages);
 
@@ -2539,7 +2538,7 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        if (!size || (size >> PAGE_SHIFT) > totalram_pages())
                goto fail;
 
-       area = __get_vm_area_node(size, align, VM_ALLOC | VM_UNINITIALIZED |
+       area = __get_vm_area_node(real_size, align, VM_ALLOC | VM_UNINITIALIZED |
                                vm_flags, start, end, node, gfp_mask, caller);
        if (!area)
                goto fail;
@@ -2548,11 +2547,6 @@ void *__vmalloc_node_range(unsigned long size, unsigned long align,
        if (!addr)
                return NULL;
 
-       if (is_vmalloc_or_module_addr(area->addr)) {
-               if (kasan_populate_vmalloc(real_size, area))
-                       return NULL;
-       }
-
        /*
         * In this function, newly allocated vm_struct has VM_UNINITIALIZED
         * flag. It means that vm_struct is not fully initialized.
@@ -3294,7 +3288,7 @@ struct vm_struct **pcpu_get_vm_areas(const unsigned long *offsets,
        struct vmap_area **vas, *va;
        struct vm_struct **vms;
        int area, area2, last_area, term_area;
-       unsigned long base, start, size, end, last_end;
+       unsigned long base, start, size, end, last_end, orig_start, orig_end;
        bool purged = false;
        enum fit_type type;
 
@@ -3424,6 +3418,15 @@ retry:
 
        spin_unlock(&free_vmap_area_lock);
 
+       /* populate the kasan shadow space */
+       for (area = 0; area < nr_vms; area++) {
+               if (kasan_populate_vmalloc(vas[area]->va_start, sizes[area]))
+                       goto err_free_shadow;
+
+               kasan_unpoison_vmalloc((void *)vas[area]->va_start,
+                                      sizes[area]);
+       }
+
        /* insert all vm's */
        spin_lock(&vmap_area_lock);
        for (area = 0; area < nr_vms; area++) {
@@ -3434,12 +3437,6 @@ retry:
        }
        spin_unlock(&vmap_area_lock);
 
-       /* populate the shadow space outside of the lock */
-       for (area = 0; area < nr_vms; area++) {
-               /* assume success here */
-               kasan_populate_vmalloc(sizes[area], vms[area]);
-       }
-
        kfree(vas);
        return vms;
 
@@ -3451,8 +3448,12 @@ recovery:
         * and when pcpu_get_vm_areas() is success.
         */
        while (area--) {
-               merge_or_add_vmap_area(vas[area], &free_vmap_area_root,
-                                      &free_vmap_area_list);
+               orig_start = vas[area]->va_start;
+               orig_end = vas[area]->va_end;
+               va = merge_or_add_vmap_area(vas[area], &free_vmap_area_root,
+                                           &free_vmap_area_list);
+               kasan_release_vmalloc(orig_start, orig_end,
+                                     va->va_start, va->va_end);
                vas[area] = NULL;
        }
 
@@ -3487,6 +3488,28 @@ err_free2:
        kfree(vas);
        kfree(vms);
        return NULL;
+
+err_free_shadow:
+       spin_lock(&free_vmap_area_lock);
+       /*
+        * We release all the vmalloc shadows, even the ones for regions that
+        * hadn't been successfully added. This relies on kasan_release_vmalloc
+        * being able to tolerate this case.
+        */
+       for (area = 0; area < nr_vms; area++) {
+               orig_start = vas[area]->va_start;
+               orig_end = vas[area]->va_end;
+               va = merge_or_add_vmap_area(vas[area], &free_vmap_area_root,
+                                           &free_vmap_area_list);
+               kasan_release_vmalloc(orig_start, orig_end,
+                                     va->va_start, va->va_end);
+               vas[area] = NULL;
+               kfree(vms[area]);
+       }
+       spin_unlock(&free_vmap_area_lock);
+       kfree(vas);
+       kfree(vms);
+       return NULL;
 }
 
 /**
index 74e8edc..572fb17 100644 (file)
@@ -387,7 +387,7 @@ void register_shrinker_prepared(struct shrinker *shrinker)
 {
        down_write(&shrinker_rwsem);
        list_add_tail(&shrinker->list, &shrinker_list);
-#ifdef CONFIG_MEMCG_KMEM
+#ifdef CONFIG_MEMCG
        if (shrinker->flags & SHRINKER_MEMCG_AWARE)
                idr_replace(&shrinker_idr, shrinker, shrinker->id);
 #endif
index 2b2b9aa..22d17ec 100644 (file)
@@ -2069,6 +2069,11 @@ static int zs_page_migrate(struct address_space *mapping, struct page *newpage,
                zs_pool_dec_isolated(pool);
        }
 
+       if (page_zone(newpage) != page_zone(page)) {
+               dec_zone_page_state(page, NR_ZSPAGES);
+               inc_zone_page_state(newpage, NR_ZSPAGES);
+       }
+
        reset_page(page);
        put_page(page);
        page = newpage;
index 2cfdfbf..bea6e43 100644 (file)
@@ -523,7 +523,7 @@ int mrp_request_join(const struct net_device *dev,
        struct mrp_attr *attr;
 
        if (sizeof(struct mrp_skb_cb) + len >
-           FIELD_SIZEOF(struct sk_buff, cb))
+           sizeof_field(struct sk_buff, cb))
                return -ENOMEM;
 
        spin_lock_bh(&app->lock);
@@ -548,7 +548,7 @@ void mrp_request_leave(const struct net_device *dev,
        struct mrp_attr *attr;
 
        if (sizeof(struct mrp_skb_cb) + len >
-           FIELD_SIZEOF(struct sk_buff, cb))
+           sizeof_field(struct sk_buff, cb))
                return;
 
        spin_lock_bh(&app->lock);
@@ -692,7 +692,7 @@ static int mrp_pdu_parse_vecattr(struct mrp_applicant *app,
         * advance to the next event in its Vector.
         */
        if (sizeof(struct mrp_skb_cb) + mrp_cb(skb)->mh->attrlen >
-           FIELD_SIZEOF(struct sk_buff, cb))
+           sizeof_field(struct sk_buff, cb))
                return -1;
        if (skb_copy_bits(skb, *offset, mrp_cb(skb)->attrvalue,
                          mrp_cb(skb)->mh->attrlen) < 0)
index c46daf0..bb7ec1a 100644 (file)
@@ -126,6 +126,7 @@ int vlan_check_real_dev(struct net_device *real_dev,
 void vlan_setup(struct net_device *dev);
 int register_vlan_dev(struct net_device *dev, struct netlink_ext_ack *extack);
 void unregister_vlan_dev(struct net_device *dev, struct list_head *head);
+void vlan_dev_uninit(struct net_device *dev);
 bool vlan_dev_inherit_address(struct net_device *dev,
                              struct net_device *real_dev);
 
index e5bff5c..2a78da4 100644 (file)
@@ -586,7 +586,8 @@ static int vlan_dev_init(struct net_device *dev)
        return 0;
 }
 
-static void vlan_dev_uninit(struct net_device *dev)
+/* Note: this function might be called multiple times for the same device. */
+void vlan_dev_uninit(struct net_device *dev)
 {
        struct vlan_priority_tci_mapping *pm;
        struct vlan_dev_priv *vlan = vlan_dev_priv(dev);
index c482a6f..0db85ae 100644 (file)
@@ -108,11 +108,13 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
        struct ifla_vlan_flags *flags;
        struct ifla_vlan_qos_mapping *m;
        struct nlattr *attr;
-       int rem;
+       int rem, err;
 
        if (data[IFLA_VLAN_FLAGS]) {
                flags = nla_data(data[IFLA_VLAN_FLAGS]);
-               vlan_dev_change_flags(dev, flags->flags, flags->mask);
+               err = vlan_dev_change_flags(dev, flags->flags, flags->mask);
+               if (err)
+                       return err;
        }
        if (data[IFLA_VLAN_INGRESS_QOS]) {
                nla_for_each_nested(attr, data[IFLA_VLAN_INGRESS_QOS], rem) {
@@ -123,7 +125,9 @@ static int vlan_changelink(struct net_device *dev, struct nlattr *tb[],
        if (data[IFLA_VLAN_EGRESS_QOS]) {
                nla_for_each_nested(attr, data[IFLA_VLAN_EGRESS_QOS], rem) {
                        m = nla_data(attr);
-                       vlan_dev_set_egress_priority(dev, m->from, m->to);
+                       err = vlan_dev_set_egress_priority(dev, m->from, m->to);
+                       if (err)
+                               return err;
                }
        }
        return 0;
@@ -179,10 +183,11 @@ static int vlan_newlink(struct net *src_net, struct net_device *dev,
                return -EINVAL;
 
        err = vlan_changelink(dev, tb, data, extack);
-       if (err < 0)
-               return err;
-
-       return register_vlan_dev(dev, extack);
+       if (!err)
+               err = register_vlan_dev(dev, extack);
+       if (err)
+               vlan_dev_uninit(dev);
+       return err;
 }
 
 static inline size_t vlan_qos_map_size(unsigned int n)
index b0af3a1..ec7bf5a 100644 (file)
@@ -285,6 +285,7 @@ static u32 batadv_hash_dat(const void *data, u32 size)
        u32 hash = 0;
        const struct batadv_dat_entry *dat = data;
        const unsigned char *key;
+       __be16 vid;
        u32 i;
 
        key = (const unsigned char *)&dat->ip;
@@ -294,7 +295,8 @@ static u32 batadv_hash_dat(const void *data, u32 size)
                hash ^= (hash >> 6);
        }
 
-       key = (const unsigned char *)&dat->vid;
+       vid = htons(dat->vid);
+       key = (__force const unsigned char *)&vid;
        for (i = 0; i < sizeof(dat->vid); i++) {
                hash += key[i];
                hash += (hash << 10);
index 4a89177..4811ec6 100644 (file)
@@ -548,7 +548,7 @@ static void batadv_recv_handler_init(void)
        BUILD_BUG_ON(sizeof(struct batadv_tvlv_tt_change) != 12);
        BUILD_BUG_ON(sizeof(struct batadv_tvlv_roam_adv) != 8);
 
-       i = FIELD_SIZEOF(struct sk_buff, cb);
+       i = sizeof_field(struct sk_buff, cb);
        BUILD_BUG_ON(sizeof(struct batadv_skb_cb) > i);
 
        /* broadcast packet */
index 915c2d6..f79205d 100644 (file)
@@ -253,21 +253,21 @@ static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb)
        /* priority is allowed */
 
        if (!range_is_zero(__skb, offsetof(struct __sk_buff, priority) +
-                          FIELD_SIZEOF(struct __sk_buff, priority),
+                          sizeof_field(struct __sk_buff, priority),
                           offsetof(struct __sk_buff, cb)))
                return -EINVAL;
 
        /* cb is allowed */
 
        if (!range_is_zero(__skb, offsetof(struct __sk_buff, cb) +
-                          FIELD_SIZEOF(struct __sk_buff, cb),
+                          sizeof_field(struct __sk_buff, cb),
                           offsetof(struct __sk_buff, tstamp)))
                return -EINVAL;
 
        /* tstamp is allowed */
 
        if (!range_is_zero(__skb, offsetof(struct __sk_buff, tstamp) +
-                          FIELD_SIZEOF(struct __sk_buff, tstamp),
+                          sizeof_field(struct __sk_buff, tstamp),
                           sizeof(struct __sk_buff)))
                return -EINVAL;
 
@@ -438,7 +438,7 @@ static int verify_user_bpf_flow_keys(struct bpf_flow_keys *ctx)
        /* flags is allowed */
 
        if (!range_is_zero(ctx, offsetof(struct bpf_flow_keys, flags) +
-                          FIELD_SIZEOF(struct bpf_flow_keys, flags),
+                          sizeof_field(struct bpf_flow_keys, flags),
                           sizeof(struct bpf_flow_keys)))
                return -EINVAL;
 
index 8a8f9e5..b6fe30e 100644 (file)
@@ -312,7 +312,7 @@ static int __init br_init(void)
 {
        int err;
 
-       BUILD_BUG_ON(sizeof(struct br_input_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct br_input_skb_cb) > sizeof_field(struct sk_buff, cb));
 
        err = stp_proto_register(&br_stp_proto);
        if (err < 0) {
index af78001..59980ec 100644 (file)
@@ -662,6 +662,9 @@ static unsigned int br_nf_forward_arp(void *priv,
                nf_bridge_pull_encap_header(skb);
        }
 
+       if (unlikely(!pskb_may_pull(skb, sizeof(struct arphdr))))
+               return NF_DROP;
+
        if (arp_hdr(skb)->ar_pln != 4) {
                if (is_vlan_arp(skb, state->net))
                        nf_bridge_push_encap_header(skb);
index 2cdfc5d..8c69f0c 100644 (file)
@@ -22,7 +22,8 @@
 #endif
 
 static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                            struct sk_buff *skb, u32 mtu)
+                            struct sk_buff *skb, u32 mtu,
+                            bool confirm_neigh)
 {
 }
 
index 4096d8a..e1256e0 100644 (file)
@@ -1867,7 +1867,7 @@ static int ebt_buf_count(struct ebt_entries_buf_state *state, unsigned int sz)
 }
 
 static int ebt_buf_add(struct ebt_entries_buf_state *state,
-                      void *data, unsigned int sz)
+                      const void *data, unsigned int sz)
 {
        if (state->buf_kern_start == NULL)
                goto count_only;
@@ -1901,7 +1901,7 @@ enum compat_mwt {
        EBT_COMPAT_TARGET,
 };
 
-static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
+static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,
                                enum compat_mwt compat_mwt,
                                struct ebt_entries_buf_state *state,
                                const unsigned char *base)
@@ -1979,22 +1979,23 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt,
 /* return size of all matches, watchers or target, including necessary
  * alignment and padding.
  */
-static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
+static int ebt_size_mwt(const struct compat_ebt_entry_mwt *match32,
                        unsigned int size_left, enum compat_mwt type,
                        struct ebt_entries_buf_state *state, const void *base)
 {
+       const char *buf = (const char *)match32;
        int growth = 0;
-       char *buf;
 
        if (size_left == 0)
                return 0;
 
-       buf = (char *) match32;
-
-       while (size_left >= sizeof(*match32)) {
+       do {
                struct ebt_entry_match *match_kern;
                int ret;
 
+               if (size_left < sizeof(*match32))
+                       return -EINVAL;
+
                match_kern = (struct ebt_entry_match *) state->buf_kern_start;
                if (match_kern) {
                        char *tmp;
@@ -2031,22 +2032,18 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32,
                if (match_kern)
                        match_kern->match_size = ret;
 
-               /* rule should have no remaining data after target */
-               if (type == EBT_COMPAT_TARGET && size_left)
-                       return -EINVAL;
-
                match32 = (struct compat_ebt_entry_mwt *) buf;
-       }
+       } while (size_left);
 
        return growth;
 }
 
 /* called for all ebt_entry structures. */
-static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
+static int size_entry_mwt(const struct ebt_entry *entry, const unsigned char *base,
                          unsigned int *total,
                          struct ebt_entries_buf_state *state)
 {
-       unsigned int i, j, startoff, new_offset = 0;
+       unsigned int i, j, startoff, next_expected_off, new_offset = 0;
        /* stores match/watchers/targets & offset of next struct ebt_entry: */
        unsigned int offsets[4];
        unsigned int *offsets_update = NULL;
@@ -2132,11 +2129,13 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base,
                        return ret;
        }
 
-       startoff = state->buf_user_offset - startoff;
+       next_expected_off = state->buf_user_offset - startoff;
+       if (next_expected_off != entry->next_offset)
+               return -EINVAL;
 
-       if (WARN_ON(*total < startoff))
+       if (*total < entry->next_offset)
                return -EINVAL;
-       *total -= startoff;
+       *total -= entry->next_offset;
        return 0;
 }
 
index de09b0a..f758742 100644 (file)
@@ -423,9 +423,9 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len)
 {
        struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
        struct j1939_sock *jsk = j1939_sk(sock->sk);
-       struct j1939_priv *priv = jsk->priv;
-       struct sock *sk = sock->sk;
-       struct net *net = sock_net(sk);
+       struct j1939_priv *priv;
+       struct sock *sk;
+       struct net *net;
        int ret = 0;
 
        ret = j1939_sk_sanity_check(addr, len);
@@ -434,6 +434,10 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len)
 
        lock_sock(sock->sk);
 
+       priv = jsk->priv;
+       sk = sock->sk;
+       net = sock_net(sk);
+
        /* Already bound to an interface? */
        if (jsk->state & J1939_SOCK_BOUND) {
                /* A re-bind() to a different interface is not
index 2c277b8..7e885d0 100644 (file)
@@ -9177,22 +9177,10 @@ static void netdev_unregister_lockdep_key(struct net_device *dev)
 
 void netdev_update_lockdep_key(struct net_device *dev)
 {
-       struct netdev_queue *queue;
-       int i;
-
-       lockdep_unregister_key(&dev->qdisc_xmit_lock_key);
        lockdep_unregister_key(&dev->addr_list_lock_key);
-
-       lockdep_register_key(&dev->qdisc_xmit_lock_key);
        lockdep_register_key(&dev->addr_list_lock_key);
 
        lockdep_set_class(&dev->addr_list_lock, &dev->addr_list_lock_key);
-       for (i = 0; i < dev->num_tx_queues; i++) {
-               queue = netdev_get_tx_queue(dev, i);
-
-               lockdep_set_class(&queue->_xmit_lock,
-                                 &dev->qdisc_xmit_lock_key);
-       }
 }
 EXPORT_SYMBOL(netdev_update_lockdep_key);
 
@@ -10165,7 +10153,7 @@ static struct hlist_head * __net_init netdev_create_hash(void)
 static int __net_init netdev_init(struct net *net)
 {
        BUILD_BUG_ON(GRO_HASH_BUCKETS >
-                    8 * FIELD_SIZEOF(struct napi_struct, gro_bitmask));
+                    8 * sizeof_field(struct napi_struct, gro_bitmask));
 
        if (net != &init_net)
                INIT_LIST_HEAD(&net->dev_base_head);
index 4c63c9a..f76219b 100644 (file)
@@ -6406,7 +6406,7 @@ static bool devlink_port_type_should_warn(struct devlink_port *devlink_port)
               devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_DSA;
 }
 
-#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 30)
+#define DEVLINK_PORT_TYPE_WARN_TIMEOUT (HZ * 3600)
 
 static void devlink_port_type_warn_schedule(struct devlink_port *devlink_port)
 {
@@ -7563,7 +7563,7 @@ void devlink_region_destroy(struct devlink_region *region)
 EXPORT_SYMBOL_GPL(devlink_region_destroy);
 
 /**
- *     devlink_region_shapshot_id_get - get snapshot ID
+ *     devlink_region_snapshot_id_get - get snapshot ID
  *
  *     This callback should be called when adding a new snapshot,
  *     Driver should use the same id for multiple snapshots taken
@@ -7571,7 +7571,7 @@ EXPORT_SYMBOL_GPL(devlink_region_destroy);
  *
  *     @devlink: devlink
  */
-u32 devlink_region_shapshot_id_get(struct devlink *devlink)
+u32 devlink_region_snapshot_id_get(struct devlink *devlink)
 {
        u32 id;
 
@@ -7581,7 +7581,7 @@ u32 devlink_region_shapshot_id_get(struct devlink *devlink)
 
        return id;
 }
-EXPORT_SYMBOL_GPL(devlink_region_shapshot_id_get);
+EXPORT_SYMBOL_GPL(devlink_region_snapshot_id_get);
 
 /**
  *     devlink_region_snapshot_create - create a new snapshot
index f1e703e..538f6a7 100644 (file)
@@ -274,7 +274,7 @@ static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg,
 
        switch (skb_field) {
        case SKF_AD_MARK:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, mark) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_W, dst_reg, src_reg,
                                      offsetof(struct sk_buff, mark));
@@ -289,14 +289,14 @@ static u32 convert_skb_access(int skb_field, int dst_reg, int src_reg,
                break;
 
        case SKF_AD_QUEUE:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, queue_mapping) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
                                      offsetof(struct sk_buff, queue_mapping));
                break;
 
        case SKF_AD_VLAN_TAG:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, vlan_tci) != 2);
 
                /* dst_reg = *(u16 *) (src_reg + offsetof(vlan_tci)) */
                *insn++ = BPF_LDX_MEM(BPF_H, dst_reg, src_reg,
@@ -322,7 +322,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
 
        switch (fp->k) {
        case SKF_AD_OFF + SKF_AD_PROTOCOL:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, protocol) != 2);
 
                /* A = *(u16 *) (CTX + offsetof(protocol)) */
                *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,
@@ -338,8 +338,8 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
 
        case SKF_AD_OFF + SKF_AD_IFINDEX:
        case SKF_AD_OFF + SKF_AD_HATYPE:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4);
-               BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2);
+               BUILD_BUG_ON(sizeof_field(struct net_device, ifindex) != 4);
+               BUILD_BUG_ON(sizeof_field(struct net_device, type) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, dev),
                                      BPF_REG_TMP, BPF_REG_CTX,
@@ -361,7 +361,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
                break;
 
        case SKF_AD_OFF + SKF_AD_RXHASH:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, hash) != 4);
 
                *insn = BPF_LDX_MEM(BPF_W, BPF_REG_A, BPF_REG_CTX,
                                    offsetof(struct sk_buff, hash));
@@ -385,7 +385,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp,
                break;
 
        case SKF_AD_OFF + SKF_AD_VLAN_TPID:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_proto) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, vlan_proto) != 2);
 
                /* A = *(u16 *) (CTX + offsetof(vlan_proto)) */
                *insn++ = BPF_LDX_MEM(BPF_H, BPF_REG_A, BPF_REG_CTX,
@@ -2055,6 +2055,7 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
        }
 
        skb->dev = dev;
+       skb->tstamp = 0;
 
        dev_xmit_recursion_inc();
        ret = dev_queue_xmit(skb);
@@ -2230,10 +2231,10 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_msg *, msg, u32, start,
        /* First find the starting scatterlist element */
        i = msg->sg.start;
        do {
+               offset += len;
                len = sk_msg_elem(msg, i)->length;
                if (start < offset + len)
                        break;
-               offset += len;
                sk_msg_iter_var_next(i);
        } while (i != msg->sg.end);
 
@@ -2345,7 +2346,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
           u32, len, u64, flags)
 {
        struct scatterlist sge, nsge, nnsge, rsge = {0}, *psge;
-       u32 new, i = 0, l, space, copy = 0, offset = 0;
+       u32 new, i = 0, l = 0, space, copy = 0, offset = 0;
        u8 *raw, *to, *from;
        struct page *page;
 
@@ -2355,11 +2356,11 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
        /* First find the starting scatterlist element */
        i = msg->sg.start;
        do {
+               offset += l;
                l = sk_msg_elem(msg, i)->length;
 
                if (start < offset + l)
                        break;
-               offset += l;
                sk_msg_iter_var_next(i);
        } while (i != msg->sg.end);
 
@@ -2414,6 +2415,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start,
 
                sk_msg_iter_var_next(i);
                sg_unmark_end(psge);
+               sg_unmark_end(&rsge);
                sk_msg_iter_next(msg, end);
        }
 
@@ -2505,7 +2507,7 @@ static void sk_msg_shift_right(struct sk_msg *msg, int i)
 BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
           u32, len, u64, flags)
 {
-       u32 i = 0, l, space, offset = 0;
+       u32 i = 0, l = 0, space, offset = 0;
        u64 last = start + len;
        int pop;
 
@@ -2515,11 +2517,11 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start,
        /* First find the starting scatterlist element */
        i = msg->sg.start;
        do {
+               offset += l;
                l = sk_msg_elem(msg, i)->length;
 
                if (start < offset + l)
                        break;
-               offset += l;
                sk_msg_iter_var_next(i);
        } while (i != msg->sg.end);
 
@@ -5317,8 +5319,7 @@ __bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
        if (sk) {
                sk = sk_to_full_sk(sk);
                if (!sk_fullsock(sk)) {
-                       if (!sock_flag(sk, SOCK_RCU_FREE))
-                               sock_gen_put(sk);
+                       sock_gen_put(sk);
                        return NULL;
                }
        }
@@ -5355,8 +5356,7 @@ bpf_sk_lookup(struct sk_buff *skb, struct bpf_sock_tuple *tuple, u32 len,
        if (sk) {
                sk = sk_to_full_sk(sk);
                if (!sk_fullsock(sk)) {
-                       if (!sock_flag(sk, SOCK_RCU_FREE))
-                               sock_gen_put(sk);
+                       sock_gen_put(sk);
                        return NULL;
                }
        }
@@ -5423,7 +5423,8 @@ static const struct bpf_func_proto bpf_sk_lookup_udp_proto = {
 
 BPF_CALL_1(bpf_sk_release, struct sock *, sk)
 {
-       if (!sock_flag(sk, SOCK_RCU_FREE))
+       /* Only full sockets have sk->sk_flags. */
+       if (!sk_fullsock(sk) || !sock_flag(sk, SOCK_RCU_FREE))
                sock_gen_put(sk);
        return 0;
 }
@@ -5589,8 +5590,8 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
 
 #define BPF_TCP_SOCK_GET_COMMON(FIELD)                                 \
        do {                                                            \
-               BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, FIELD) >     \
-                            FIELD_SIZEOF(struct bpf_tcp_sock, FIELD)); \
+               BUILD_BUG_ON(sizeof_field(struct tcp_sock, FIELD) >     \
+                            sizeof_field(struct bpf_tcp_sock, FIELD)); \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct tcp_sock, FIELD),\
                                      si->dst_reg, si->src_reg,         \
                                      offsetof(struct tcp_sock, FIELD)); \
@@ -5598,9 +5599,9 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
 
 #define BPF_INET_SOCK_GET_COMMON(FIELD)                                        \
        do {                                                            \
-               BUILD_BUG_ON(FIELD_SIZEOF(struct inet_connection_sock,  \
+               BUILD_BUG_ON(sizeof_field(struct inet_connection_sock,  \
                                          FIELD) >                      \
-                            FIELD_SIZEOF(struct bpf_tcp_sock, FIELD)); \
+                            sizeof_field(struct bpf_tcp_sock, FIELD)); \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(                 \
                                        struct inet_connection_sock,    \
                                        FIELD),                         \
@@ -5615,7 +5616,7 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
 
        switch (si->off) {
        case offsetof(struct bpf_tcp_sock, rtt_min):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, rtt_min) !=
+               BUILD_BUG_ON(sizeof_field(struct tcp_sock, rtt_min) !=
                             sizeof(struct minmax));
                BUILD_BUG_ON(sizeof(struct minmax) <
                             sizeof(struct minmax_sample));
@@ -5780,8 +5781,8 @@ u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type,
 
 #define BPF_XDP_SOCK_GET(FIELD)                                                \
        do {                                                            \
-               BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_sock, FIELD) >     \
-                            FIELD_SIZEOF(struct bpf_xdp_sock, FIELD)); \
+               BUILD_BUG_ON(sizeof_field(struct xdp_sock, FIELD) >     \
+                            sizeof_field(struct bpf_xdp_sock, FIELD)); \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct xdp_sock, FIELD),\
                                      si->dst_reg, si->src_reg,         \
                                      offsetof(struct xdp_sock, FIELD)); \
@@ -7344,7 +7345,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
 
        case offsetof(struct __sk_buff, cb[0]) ...
             offsetofend(struct __sk_buff, cb[4]) - 1:
-               BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, data) < 20);
+               BUILD_BUG_ON(sizeof_field(struct qdisc_skb_cb, data) < 20);
                BUILD_BUG_ON((offsetof(struct sk_buff, cb) +
                              offsetof(struct qdisc_skb_cb, data)) %
                             sizeof(__u64));
@@ -7363,7 +7364,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, tc_classid):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, tc_classid) != 2);
+               BUILD_BUG_ON(sizeof_field(struct qdisc_skb_cb, tc_classid) != 2);
 
                off  = si->off;
                off -= offsetof(struct __sk_buff, tc_classid);
@@ -7434,7 +7435,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
 #endif
                break;
        case offsetof(struct __sk_buff, family):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_family) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
                                      si->dst_reg, si->src_reg,
@@ -7445,7 +7446,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                                     2, target_size));
                break;
        case offsetof(struct __sk_buff, remote_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_daddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
                                      si->dst_reg, si->src_reg,
@@ -7456,7 +7457,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                                     4, target_size));
                break;
        case offsetof(struct __sk_buff, local_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_rcv_saddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
@@ -7470,7 +7471,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct __sk_buff, remote_ip6[0]) ...
             offsetof(struct __sk_buff, remote_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_daddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -7490,7 +7491,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct __sk_buff, local_ip6[0]) ...
             offsetof(struct __sk_buff, local_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_rcv_saddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -7509,7 +7510,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, remote_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_dport) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
                                      si->dst_reg, si->src_reg,
@@ -7524,7 +7525,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, local_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_num) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_buff, sk),
                                      si->dst_reg, si->src_reg,
@@ -7535,7 +7536,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct __sk_buff, tstamp):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, tstamp) != 8);
+               BUILD_BUG_ON(sizeof_field(struct sk_buff, tstamp) != 8);
 
                if (type == BPF_WRITE)
                        *insn++ = BPF_STX_MEM(BPF_DW,
@@ -7573,7 +7574,7 @@ static u32 bpf_convert_ctx_access(enum bpf_access_type type,
                                                     target_size));
                break;
        case offsetof(struct __sk_buff, wire_len):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct qdisc_skb_cb, pkt_len) != 4);
+               BUILD_BUG_ON(sizeof_field(struct qdisc_skb_cb, pkt_len) != 4);
 
                off = si->off;
                off -= offsetof(struct __sk_buff, wire_len);
@@ -7603,7 +7604,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
 
        switch (si->off) {
        case offsetof(struct bpf_sock, bound_dev_if):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_bound_dev_if) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock, sk_bound_dev_if) != 4);
 
                if (type == BPF_WRITE)
                        *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
@@ -7614,7 +7615,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock, mark):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_mark) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock, sk_mark) != 4);
 
                if (type == BPF_WRITE)
                        *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
@@ -7625,7 +7626,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock, priority):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock, sk_priority) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock, sk_priority) != 4);
 
                if (type == BPF_WRITE)
                        *insn++ = BPF_STX_MEM(BPF_W, si->dst_reg, si->src_reg,
@@ -7641,7 +7642,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common,
                                       skc_family,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_family),
                                       target_size));
                break;
@@ -7668,7 +7669,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                *insn++ = BPF_LDX_MEM(
                        BPF_SIZE(si->code), si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_rcv_saddr,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_rcv_saddr),
                                       target_size));
                break;
@@ -7677,7 +7678,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                *insn++ = BPF_LDX_MEM(
                        BPF_SIZE(si->code), si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_daddr,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_daddr),
                                       target_size));
                break;
@@ -7691,7 +7692,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        bpf_target_off(
                                struct sock_common,
                                skc_v6_rcv_saddr.s6_addr32[0],
-                               FIELD_SIZEOF(struct sock_common,
+                               sizeof_field(struct sock_common,
                                             skc_v6_rcv_saddr.s6_addr32[0]),
                                target_size) + off);
 #else
@@ -7708,7 +7709,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        BPF_SIZE(si->code), si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common,
                                       skc_v6_daddr.s6_addr32[0],
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_v6_daddr.s6_addr32[0]),
                                       target_size) + off);
 #else
@@ -7722,7 +7723,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        BPF_FIELD_SIZEOF(struct sock_common, skc_num),
                        si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_num,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_num),
                                       target_size));
                break;
@@ -7732,7 +7733,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        BPF_FIELD_SIZEOF(struct sock_common, skc_dport),
                        si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_dport,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_dport),
                                       target_size));
                break;
@@ -7742,7 +7743,7 @@ u32 bpf_sock_convert_ctx_access(enum bpf_access_type type,
                        BPF_FIELD_SIZEOF(struct sock_common, skc_state),
                        si->dst_reg, si->src_reg,
                        bpf_target_off(struct sock_common, skc_state,
-                                      FIELD_SIZEOF(struct sock_common,
+                                      sizeof_field(struct sock_common,
                                                    skc_state),
                                       target_size));
                break;
@@ -7837,7 +7838,7 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
                                      si->src_reg, offsetof(S, F));            \
                *insn++ = BPF_LDX_MEM(                                         \
                        SIZE, si->dst_reg, si->dst_reg,                        \
-                       bpf_target_off(NS, NF, FIELD_SIZEOF(NS, NF),           \
+                       bpf_target_off(NS, NF, sizeof_field(NS, NF),           \
                                       target_size)                            \
                                + OFF);                                        \
        } while (0)
@@ -7868,7 +7869,7 @@ static u32 xdp_convert_ctx_access(enum bpf_access_type type,
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(S, F), tmp_reg,         \
                                      si->dst_reg, offsetof(S, F));            \
                *insn++ = BPF_STX_MEM(SIZE, tmp_reg, si->src_reg,              \
-                       bpf_target_off(NS, NF, FIELD_SIZEOF(NS, NF),           \
+                       bpf_target_off(NS, NF, sizeof_field(NS, NF),           \
                                       target_size)                            \
                                + OFF);                                        \
                *insn++ = BPF_LDX_MEM(BPF_DW, tmp_reg, si->dst_reg,            \
@@ -7930,8 +7931,8 @@ static u32 sock_addr_convert_ctx_access(enum bpf_access_type type,
                 */
                BUILD_BUG_ON(offsetof(struct sockaddr_in, sin_port) !=
                             offsetof(struct sockaddr_in6, sin6_port));
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sockaddr_in, sin_port) !=
-                            FIELD_SIZEOF(struct sockaddr_in6, sin6_port));
+               BUILD_BUG_ON(sizeof_field(struct sockaddr_in, sin_port) !=
+                            sizeof_field(struct sockaddr_in6, sin6_port));
                SOCK_ADDR_LOAD_OR_STORE_NESTED_FIELD(struct bpf_sock_addr_kern,
                                                     struct sockaddr_in6, uaddr,
                                                     sin6_port, tmp_reg);
@@ -7997,8 +7998,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
 /* Helper macro for adding read access to tcp_sock or sock fields. */
 #define SOCK_OPS_GET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ)                        \
        do {                                                                  \
-               BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) >                   \
-                            FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD));   \
+               BUILD_BUG_ON(sizeof_field(OBJ, OBJ_FIELD) >                   \
+                            sizeof_field(struct bpf_sock_ops, BPF_FIELD));   \
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(                       \
                                                struct bpf_sock_ops_kern,     \
                                                is_fullsock),                 \
@@ -8031,8 +8032,8 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
 #define SOCK_OPS_SET_FIELD(BPF_FIELD, OBJ_FIELD, OBJ)                        \
        do {                                                                  \
                int reg = BPF_REG_9;                                          \
-               BUILD_BUG_ON(FIELD_SIZEOF(OBJ, OBJ_FIELD) >                   \
-                            FIELD_SIZEOF(struct bpf_sock_ops, BPF_FIELD));   \
+               BUILD_BUG_ON(sizeof_field(OBJ, OBJ_FIELD) >                   \
+                            sizeof_field(struct bpf_sock_ops, BPF_FIELD));   \
                if (si->dst_reg == reg || si->src_reg == reg)                 \
                        reg--;                                                \
                if (si->dst_reg == reg || si->src_reg == reg)                 \
@@ -8073,12 +8074,12 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
        switch (si->off) {
        case offsetof(struct bpf_sock_ops, op) ...
             offsetof(struct bpf_sock_ops, replylong[3]):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, op) !=
-                            FIELD_SIZEOF(struct bpf_sock_ops_kern, op));
-               BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, reply) !=
-                            FIELD_SIZEOF(struct bpf_sock_ops_kern, reply));
-               BUILD_BUG_ON(FIELD_SIZEOF(struct bpf_sock_ops, replylong) !=
-                            FIELD_SIZEOF(struct bpf_sock_ops_kern, replylong));
+               BUILD_BUG_ON(sizeof_field(struct bpf_sock_ops, op) !=
+                            sizeof_field(struct bpf_sock_ops_kern, op));
+               BUILD_BUG_ON(sizeof_field(struct bpf_sock_ops, reply) !=
+                            sizeof_field(struct bpf_sock_ops_kern, reply));
+               BUILD_BUG_ON(sizeof_field(struct bpf_sock_ops, replylong) !=
+                            sizeof_field(struct bpf_sock_ops_kern, replylong));
                off = si->off;
                off -= offsetof(struct bpf_sock_ops, op);
                off += offsetof(struct bpf_sock_ops_kern, op);
@@ -8091,7 +8092,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, family):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_family) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                              struct bpf_sock_ops_kern, sk),
@@ -8102,7 +8103,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, remote_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_daddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct bpf_sock_ops_kern, sk),
@@ -8113,7 +8114,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, local_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_rcv_saddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
@@ -8128,7 +8129,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct bpf_sock_ops, remote_ip6[0]) ...
             offsetof(struct bpf_sock_ops, remote_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_daddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -8149,7 +8150,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct bpf_sock_ops, local_ip6[0]) ...
             offsetof(struct bpf_sock_ops, local_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_rcv_saddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -8168,7 +8169,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, remote_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_dport) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct bpf_sock_ops_kern, sk),
@@ -8182,7 +8183,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, local_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_num) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct bpf_sock_ops_kern, sk),
@@ -8202,7 +8203,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, state):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_state) != 1);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_state) != 1);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct bpf_sock_ops_kern, sk),
@@ -8213,7 +8214,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct bpf_sock_ops, rtt_min):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct tcp_sock, rtt_min) !=
+               BUILD_BUG_ON(sizeof_field(struct tcp_sock, rtt_min) !=
                             sizeof(struct minmax));
                BUILD_BUG_ON(sizeof(struct minmax) <
                             sizeof(struct minmax_sample));
@@ -8224,7 +8225,7 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
                                      offsetof(struct bpf_sock_ops_kern, sk));
                *insn++ = BPF_LDX_MEM(BPF_W, si->dst_reg, si->dst_reg,
                                      offsetof(struct tcp_sock, rtt_min) +
-                                     FIELD_SIZEOF(struct minmax_sample, t));
+                                     sizeof_field(struct minmax_sample, t));
                break;
 
        case offsetof(struct bpf_sock_ops, bpf_sock_ops_cb_flags):
@@ -8366,7 +8367,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                                      offsetof(struct sk_msg, data_end));
                break;
        case offsetof(struct sk_msg_md, family):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_family) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_family) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                              struct sk_msg, sk),
@@ -8377,7 +8378,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct sk_msg_md, remote_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_daddr) != 4);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_daddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct sk_msg, sk),
@@ -8388,7 +8389,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct sk_msg_md, local_ip4):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_rcv_saddr) != 4);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
@@ -8403,7 +8404,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct sk_msg_md, remote_ip6[0]) ...
             offsetof(struct sk_msg_md, remote_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_daddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -8424,7 +8425,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
        case offsetof(struct sk_msg_md, local_ip6[0]) ...
             offsetof(struct sk_msg_md, local_ip6[3]):
 #if IS_ENABLED(CONFIG_IPV6)
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common,
+               BUILD_BUG_ON(sizeof_field(struct sock_common,
                                          skc_v6_rcv_saddr.s6_addr32[0]) != 4);
 
                off = si->off;
@@ -8443,7 +8444,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct sk_msg_md, remote_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_dport) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_dport) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct sk_msg, sk),
@@ -8457,7 +8458,7 @@ static u32 sk_msg_convert_ctx_access(enum bpf_access_type type,
                break;
 
        case offsetof(struct sk_msg_md, local_port):
-               BUILD_BUG_ON(FIELD_SIZEOF(struct sock_common, skc_num) != 2);
+               BUILD_BUG_ON(sizeof_field(struct sock_common, skc_num) != 2);
 
                *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(
                                                struct sk_msg, sk),
@@ -8847,7 +8848,7 @@ sk_reuseport_is_valid_access(int off, int size,
 
        /* Fields that allow narrowing */
        case bpf_ctx_range(struct sk_reuseport_md, eth_protocol):
-               if (size < FIELD_SIZEOF(struct sk_buff, protocol))
+               if (size < sizeof_field(struct sk_buff, protocol))
                        return false;
                /* fall through */
        case bpf_ctx_range(struct sk_reuseport_md, ip_protocol):
@@ -8865,7 +8866,7 @@ sk_reuseport_is_valid_access(int off, int size,
        *insn++ = BPF_LDX_MEM(BPF_FIELD_SIZEOF(struct sk_reuseport_kern, F), \
                              si->dst_reg, si->src_reg,                 \
                              bpf_target_off(struct sk_reuseport_kern, F, \
-                                            FIELD_SIZEOF(struct sk_reuseport_kern, F), \
+                                            sizeof_field(struct sk_reuseport_kern, F), \
                                             target_size));             \
        })
 
index d524a69..2dbbb03 100644 (file)
@@ -599,8 +599,8 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
        offset += sizeof(struct gre_base_hdr);
 
        if (hdr->flags & GRE_CSUM)
-               offset += FIELD_SIZEOF(struct gre_full_hdr, csum) +
-                         FIELD_SIZEOF(struct gre_full_hdr, reserved1);
+               offset += sizeof_field(struct gre_full_hdr, csum) +
+                         sizeof_field(struct gre_full_hdr, reserved1);
 
        if (hdr->flags & GRE_KEY) {
                const __be32 *keyid;
@@ -622,11 +622,11 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
                        else
                                key_keyid->keyid = *keyid & GRE_PPTP_KEY_MASK;
                }
-               offset += FIELD_SIZEOF(struct gre_full_hdr, key);
+               offset += sizeof_field(struct gre_full_hdr, key);
        }
 
        if (hdr->flags & GRE_SEQ)
-               offset += FIELD_SIZEOF(struct pptp_gre_header, seq);
+               offset += sizeof_field(struct pptp_gre_header, seq);
 
        if (gre_ver == 0) {
                if (*p_proto == htons(ETH_P_TEB)) {
@@ -653,7 +653,7 @@ __skb_flow_dissect_gre(const struct sk_buff *skb,
                u8 *ppp_hdr;
 
                if (hdr->flags & GRE_ACK)
-                       offset += FIELD_SIZEOF(struct pptp_gre_header, ack);
+                       offset += sizeof_field(struct pptp_gre_header, ack);
 
                ppp_hdr = __skb_header_pointer(skb, *p_nhoff + offset,
                                               sizeof(_ppp_hdr),
index 652da63..920784a 100644 (file)
@@ -98,9 +98,6 @@ static int neigh_blackhole(struct neighbour *neigh, struct sk_buff *skb)
 
 static void neigh_cleanup_and_release(struct neighbour *neigh)
 {
-       if (neigh->parms->neigh_cleanup)
-               neigh->parms->neigh_cleanup(neigh);
-
        trace_neigh_cleanup_and_release(neigh, 0);
        __neigh_notify(neigh, RTM_DELNEIGH, 0, 0);
        call_netevent_notifiers(NETEVENT_NEIGH_UPDATE, neigh);
index 5c46242..4c826b8 100644 (file)
@@ -919,14 +919,17 @@ static int rx_queue_add_kobject(struct net_device *dev, int index)
        struct kobject *kobj = &queue->kobj;
        int error = 0;
 
+       /* Kobject_put later will trigger rx_queue_release call which
+        * decreases dev refcount: Take that reference here
+        */
+       dev_hold(queue->dev);
+
        kobj->kset = dev->queues_kset;
        error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL,
                                     "rx-%u", index);
        if (error)
                goto err;
 
-       dev_hold(queue->dev);
-
        if (dev->sysfs_rx_queue_group) {
                error = sysfs_create_group(kobj, dev->sysfs_rx_queue_group);
                if (error)
index ded2d52..3866d7e 100644 (file)
@@ -594,6 +594,8 @@ EXPORT_SYMBOL_GPL(sk_psock_destroy);
 
 void sk_psock_drop(struct sock *sk, struct sk_psock *psock)
 {
+       sock_owned_by_me(sk);
+
        sk_psock_cork_free(psock);
        sk_psock_zap_ingress(psock);
 
index 043db3c..8459ad5 100644 (file)
@@ -2916,7 +2916,7 @@ void sock_init_data(struct socket *sock, struct sock *sk)
 
        sk->sk_max_pacing_rate = ~0UL;
        sk->sk_pacing_rate = ~0UL;
-       sk->sk_pacing_shift = 10;
+       WRITE_ONCE(sk->sk_pacing_shift, 10);
        sk->sk_incoming_cpu = -1;
 
        sk_rx_queue_clear(sk);
index eb114ee..8998e35 100644 (file)
@@ -241,8 +241,11 @@ static void sock_map_free(struct bpf_map *map)
                struct sock *sk;
 
                sk = xchg(psk, NULL);
-               if (sk)
+               if (sk) {
+                       lock_sock(sk);
                        sock_map_unref(sk, psk);
+                       release_sock(sk);
+               }
        }
        raw_spin_unlock_bh(&stab->lock);
        rcu_read_unlock();
@@ -862,7 +865,9 @@ static void sock_hash_free(struct bpf_map *map)
                raw_spin_lock_bh(&bucket->lock);
                hlist_for_each_entry_safe(elem, node, &bucket->head, node) {
                        hlist_del_rcu(&elem->node);
+                       lock_sock(elem->sk);
                        sock_map_unref(elem->sk, elem);
+                       release_sock(elem->sk);
                }
                raw_spin_unlock_bh(&bucket->lock);
        }
index eb29e5a..9f9e00b 100644 (file)
@@ -288,6 +288,7 @@ static int proc_dointvec_minmax_bpf_enable(struct ctl_table *table, int write,
        return ret;
 }
 
+# ifdef CONFIG_HAVE_EBPF_JIT
 static int
 proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write,
                                    void __user *buffer, size_t *lenp,
@@ -298,6 +299,7 @@ proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write,
 
        return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
 }
+# endif /* CONFIG_HAVE_EBPF_JIT */
 
 static int
 proc_dolongvec_minmax_bpf_restricted(struct ctl_table *table, int write,
index 7c8390a..8310714 100644 (file)
@@ -36,7 +36,7 @@ static u32 xdp_mem_id_hashfn(const void *data, u32 len, u32 seed)
        const u32 *k = data;
        const u32 key = *k;
 
-       BUILD_BUG_ON(FIELD_SIZEOF(struct xdp_mem_allocator, mem.id)
+       BUILD_BUG_ON(sizeof_field(struct xdp_mem_allocator, mem.id)
                     != sizeof(u32));
 
        /* Use cyclic increasing ID as direct hash key */
@@ -56,7 +56,7 @@ static const struct rhashtable_params mem_id_rht_params = {
        .nelem_hint = 64,
        .head_offset = offsetof(struct xdp_mem_allocator, node),
        .key_offset  = offsetof(struct xdp_mem_allocator, mem.id),
-       .key_len = FIELD_SIZEOF(struct xdp_mem_allocator, mem.id),
+       .key_len = sizeof_field(struct xdp_mem_allocator, mem.id),
        .max_size = MEM_ID_MAX,
        .min_size = 8,
        .automatic_shrinking = true,
index a52e8ba..4af8a98 100644 (file)
@@ -1132,7 +1132,7 @@ static int __init dccp_init(void)
        int rc;
 
        BUILD_BUG_ON(sizeof(struct dccp_skb_cb) >
-                    FIELD_SIZEOF(struct sk_buff, cb));
+                    sizeof_field(struct sk_buff, cb));
        rc = percpu_counter_init(&dccp_orphan_count, 0, GFP_KERNEL);
        if (rc)
                goto out_fail;
index aea9181..08c3dc4 100644 (file)
@@ -110,7 +110,8 @@ static void dn_dst_ifdown(struct dst_entry *, struct net_device *dev, int how);
 static struct dst_entry *dn_dst_negative_advice(struct dst_entry *);
 static void dn_dst_link_failure(struct sk_buff *);
 static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                              struct sk_buff *skb , u32 mtu);
+                              struct sk_buff *skb , u32 mtu,
+                              bool confirm_neigh);
 static void dn_dst_redirect(struct dst_entry *dst, struct sock *sk,
                            struct sk_buff *skb);
 static struct neighbour *dn_dst_neigh_lookup(const struct dst_entry *dst,
@@ -251,7 +252,8 @@ static int dn_dst_gc(struct dst_ops *ops)
  * advertise to the other end).
  */
 static void dn_dst_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                              struct sk_buff *skb, u32 mtu)
+                              struct sk_buff *skb, u32 mtu,
+                              bool confirm_neigh)
 {
        struct dn_route *rt = (struct dn_route *) dst;
        struct neighbour *n = rt->n;
index 9ef2caa..c66abbe 100644 (file)
@@ -124,7 +124,8 @@ static struct dsa_port *dsa_tree_find_port_by_node(struct dsa_switch_tree *dst,
        return NULL;
 }
 
-struct dsa_link *dsa_link_touch(struct dsa_port *dp, struct dsa_port *link_dp)
+static struct dsa_link *dsa_link_touch(struct dsa_port *dp,
+                                      struct dsa_port *link_dp)
 {
        struct dsa_switch *ds = dp->ds;
        struct dsa_switch_tree *dst;
index b678160..408d4af 100644 (file)
@@ -104,7 +104,7 @@ static struct sk_buff *gswip_tag_rcv(struct sk_buff *skb,
 }
 
 static const struct dsa_device_ops gswip_netdev_ops = {
-       .name = "gwsip",
+       .name = "gswip",
        .proto  = DSA_TAG_PROTO_GSWIP,
        .xmit = gswip_tag_xmit,
        .rcv = gswip_tag_rcv,
index 73605bc..90d055c 100644 (file)
@@ -84,8 +84,6 @@ static struct sk_buff *ksz_common_rcv(struct sk_buff *skb,
  *       (eg, 0x00=port1, 0x02=port3, 0x06=port7)
  */
 
-#define KSZ8795_INGRESS_TAG_LEN                1
-
 #define KSZ8795_TAIL_TAG_OVERRIDE      BIT(6)
 #define KSZ8795_TAIL_TAG_LOOKUP                BIT(7)
 
@@ -96,12 +94,12 @@ static struct sk_buff *ksz8795_xmit(struct sk_buff *skb, struct net_device *dev)
        u8 *tag;
        u8 *addr;
 
-       nskb = ksz_common_xmit(skb, dev, KSZ8795_INGRESS_TAG_LEN);
+       nskb = ksz_common_xmit(skb, dev, KSZ_INGRESS_TAG_LEN);
        if (!nskb)
                return NULL;
 
        /* Tag encoding */
-       tag = skb_put(nskb, KSZ8795_INGRESS_TAG_LEN);
+       tag = skb_put(nskb, KSZ_INGRESS_TAG_LEN);
        addr = skb_mac_header(nskb);
 
        *tag = 1 << dp->index;
@@ -124,7 +122,7 @@ static const struct dsa_device_ops ksz8795_netdev_ops = {
        .proto  = DSA_TAG_PROTO_KSZ8795,
        .xmit   = ksz8795_xmit,
        .rcv    = ksz8795_rcv,
-       .overhead = KSZ8795_INGRESS_TAG_LEN,
+       .overhead = KSZ_INGRESS_TAG_LEN,
 };
 
 DSA_TAG_DRIVER(ksz8795_netdev_ops);
index c958852..c8a128c 100644 (file)
@@ -33,9 +33,6 @@ static struct sk_buff *qca_tag_xmit(struct sk_buff *skb, struct net_device *dev)
        struct dsa_port *dp = dsa_slave_to_port(dev);
        u16 *phdr, hdr;
 
-       dev->stats.tx_packets++;
-       dev->stats.tx_bytes += skb->len;
-
        if (skb_cow_head(skb, 0) < 0)
                return NULL;
 
index 9444797..d5f709b 100644 (file)
@@ -20,6 +20,8 @@
 #include "hsr_main.h"
 #include "hsr_framereg.h"
 
+static struct dentry *hsr_debugfs_root_dir;
+
 static void print_mac_address(struct seq_file *sfp, unsigned char *mac)
 {
        seq_printf(sfp, "%02x:%02x:%02x:%02x:%02x:%02x:",
@@ -63,8 +65,20 @@ hsr_node_table_open(struct inode *inode, struct file *filp)
        return single_open(filp, hsr_node_table_show, inode->i_private);
 }
 
+void hsr_debugfs_rename(struct net_device *dev)
+{
+       struct hsr_priv *priv = netdev_priv(dev);
+       struct dentry *d;
+
+       d = debugfs_rename(hsr_debugfs_root_dir, priv->node_tbl_root,
+                          hsr_debugfs_root_dir, dev->name);
+       if (IS_ERR(d))
+               netdev_warn(dev, "failed to rename\n");
+       else
+               priv->node_tbl_root = d;
+}
+
 static const struct file_operations hsr_fops = {
-       .owner  = THIS_MODULE,
        .open   = hsr_node_table_open,
        .read   = seq_read,
        .llseek = seq_lseek,
@@ -78,15 +92,14 @@ static const struct file_operations hsr_fops = {
  * When debugfs is configured this routine sets up the node_table file per
  * hsr device for dumping the node_table entries
  */
-int hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev)
+void hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev)
 {
-       int rc = -1;
        struct dentry *de = NULL;
 
-       de = debugfs_create_dir(hsr_dev->name, NULL);
-       if (!de) {
-               pr_err("Cannot create hsr debugfs root\n");
-               return rc;
+       de = debugfs_create_dir(hsr_dev->name, hsr_debugfs_root_dir);
+       if (IS_ERR(de)) {
+               pr_err("Cannot create hsr debugfs directory\n");
+               return;
        }
 
        priv->node_tbl_root = de;
@@ -94,13 +107,13 @@ int hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev)
        de = debugfs_create_file("node_table", S_IFREG | 0444,
                                 priv->node_tbl_root, priv,
                                 &hsr_fops);
-       if (!de) {
-               pr_err("Cannot create hsr node_table directory\n");
-               return rc;
+       if (IS_ERR(de)) {
+               pr_err("Cannot create hsr node_table file\n");
+               debugfs_remove(priv->node_tbl_root);
+               priv->node_tbl_root = NULL;
+               return;
        }
        priv->node_tbl_file = de;
-
-       return 0;
 }
 
 /* hsr_debugfs_term - Tear down debugfs intrastructure
@@ -117,3 +130,18 @@ hsr_debugfs_term(struct hsr_priv *priv)
        debugfs_remove(priv->node_tbl_root);
        priv->node_tbl_root = NULL;
 }
+
+void hsr_debugfs_create_root(void)
+{
+       hsr_debugfs_root_dir = debugfs_create_dir("hsr", NULL);
+       if (IS_ERR(hsr_debugfs_root_dir)) {
+               pr_err("Cannot create hsr debugfs root directory\n");
+               hsr_debugfs_root_dir = NULL;
+       }
+}
+
+void hsr_debugfs_remove_root(void)
+{
+       /* debugfs_remove() internally checks NULL and ERROR */
+       debugfs_remove(hsr_debugfs_root_dir);
+}
index b01e1ba..c7bd6c4 100644 (file)
@@ -272,6 +272,8 @@ static void send_hsr_supervision_frame(struct hsr_port *master,
                            skb->dev->dev_addr, skb->len) <= 0)
                goto out;
        skb_reset_mac_header(skb);
+       skb_reset_network_header(skb);
+       skb_reset_transport_header(skb);
 
        if (hsr_ver > 0) {
                hsr_tag = skb_put(skb, sizeof(struct hsr_tag));
@@ -368,7 +370,7 @@ static void hsr_dev_destroy(struct net_device *hsr_dev)
        del_timer_sync(&hsr->prune_timer);
        del_timer_sync(&hsr->announce_timer);
 
-       hsr_del_self_node(&hsr->self_node_db);
+       hsr_del_self_node(hsr);
        hsr_del_nodes(&hsr->node_db);
 }
 
@@ -440,11 +442,12 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
        INIT_LIST_HEAD(&hsr->ports);
        INIT_LIST_HEAD(&hsr->node_db);
        INIT_LIST_HEAD(&hsr->self_node_db);
+       spin_lock_init(&hsr->list_lock);
 
        ether_addr_copy(hsr_dev->dev_addr, slave[0]->dev_addr);
 
        /* Make sure we recognize frames from ourselves in hsr_rcv() */
-       res = hsr_create_self_node(&hsr->self_node_db, hsr_dev->dev_addr,
+       res = hsr_create_self_node(hsr, hsr_dev->dev_addr,
                                   slave[1]->dev_addr);
        if (res < 0)
                return res;
@@ -477,31 +480,32 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2],
 
        res = hsr_add_port(hsr, hsr_dev, HSR_PT_MASTER);
        if (res)
-               goto err_add_port;
+               goto err_add_master;
 
        res = register_netdevice(hsr_dev);
        if (res)
-               goto fail;
+               goto err_unregister;
 
        res = hsr_add_port(hsr, slave[0], HSR_PT_SLAVE_A);
        if (res)
-               goto fail;
+               goto err_add_slaves;
+
        res = hsr_add_port(hsr, slave[1], HSR_PT_SLAVE_B);
        if (res)
-               goto fail;
+               goto err_add_slaves;
 
+       hsr_debugfs_init(hsr, hsr_dev);
        mod_timer(&hsr->prune_timer, jiffies + msecs_to_jiffies(PRUNE_PERIOD));
-       res = hsr_debugfs_init(hsr, hsr_dev);
-       if (res)
-               goto fail;
 
        return 0;
 
-fail:
+err_add_slaves:
+       unregister_netdevice(hsr_dev);
+err_unregister:
        list_for_each_entry_safe(port, tmp, &hsr->ports, port_list)
                hsr_del_port(port);
-err_add_port:
-       hsr_del_self_node(&hsr->self_node_db);
+err_add_master:
+       hsr_del_self_node(hsr);
 
        return res;
 }
index 292be44..27dc65d 100644 (file)
@@ -75,10 +75,11 @@ static struct hsr_node *find_node_by_addr_A(struct list_head *node_db,
 /* Helper for device init; the self_node_db is used in hsr_rcv() to recognize
  * frames from self that's been looped over the HSR ring.
  */
-int hsr_create_self_node(struct list_head *self_node_db,
+int hsr_create_self_node(struct hsr_priv *hsr,
                         unsigned char addr_a[ETH_ALEN],
                         unsigned char addr_b[ETH_ALEN])
 {
+       struct list_head *self_node_db = &hsr->self_node_db;
        struct hsr_node *node, *oldnode;
 
        node = kmalloc(sizeof(*node), GFP_KERNEL);
@@ -88,33 +89,33 @@ int hsr_create_self_node(struct list_head *self_node_db,
        ether_addr_copy(node->macaddress_A, addr_a);
        ether_addr_copy(node->macaddress_B, addr_b);
 
-       rcu_read_lock();
+       spin_lock_bh(&hsr->list_lock);
        oldnode = list_first_or_null_rcu(self_node_db,
                                         struct hsr_node, mac_list);
        if (oldnode) {
                list_replace_rcu(&oldnode->mac_list, &node->mac_list);
-               rcu_read_unlock();
-               synchronize_rcu();
-               kfree(oldnode);
+               spin_unlock_bh(&hsr->list_lock);
+               kfree_rcu(oldnode, rcu_head);
        } else {
-               rcu_read_unlock();
                list_add_tail_rcu(&node->mac_list, self_node_db);
+               spin_unlock_bh(&hsr->list_lock);
        }
 
        return 0;
 }
 
-void hsr_del_self_node(struct list_head *self_node_db)
+void hsr_del_self_node(struct hsr_priv *hsr)
 {
+       struct list_head *self_node_db = &hsr->self_node_db;
        struct hsr_node *node;
 
-       rcu_read_lock();
+       spin_lock_bh(&hsr->list_lock);
        node = list_first_or_null_rcu(self_node_db, struct hsr_node, mac_list);
-       rcu_read_unlock();
        if (node) {
                list_del_rcu(&node->mac_list);
-               kfree(node);
+               kfree_rcu(node, rcu_head);
        }
+       spin_unlock_bh(&hsr->list_lock);
 }
 
 void hsr_del_nodes(struct list_head *node_db)
@@ -130,30 +131,43 @@ void hsr_del_nodes(struct list_head *node_db)
  * seq_out is used to initialize filtering of outgoing duplicate frames
  * originating from the newly added node.
  */
-struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[],
-                             u16 seq_out)
+static struct hsr_node *hsr_add_node(struct hsr_priv *hsr,
+                                    struct list_head *node_db,
+                                    unsigned char addr[],
+                                    u16 seq_out)
 {
-       struct hsr_node *node;
+       struct hsr_node *new_node, *node;
        unsigned long now;
        int i;
 
-       node = kzalloc(sizeof(*node), GFP_ATOMIC);
-       if (!node)
+       new_node = kzalloc(sizeof(*new_node), GFP_ATOMIC);
+       if (!new_node)
                return NULL;
 
-       ether_addr_copy(node->macaddress_A, addr);
+       ether_addr_copy(new_node->macaddress_A, addr);
 
        /* We are only interested in time diffs here, so use current jiffies
         * as initialization. (0 could trigger an spurious ring error warning).
         */
        now = jiffies;
        for (i = 0; i < HSR_PT_PORTS; i++)
-               node->time_in[i] = now;
+               new_node->time_in[i] = now;
        for (i = 0; i < HSR_PT_PORTS; i++)
-               node->seq_out[i] = seq_out;
-
-       list_add_tail_rcu(&node->mac_list, node_db);
+               new_node->seq_out[i] = seq_out;
 
+       spin_lock_bh(&hsr->list_lock);
+       list_for_each_entry_rcu(node, node_db, mac_list) {
+               if (ether_addr_equal(node->macaddress_A, addr))
+                       goto out;
+               if (ether_addr_equal(node->macaddress_B, addr))
+                       goto out;
+       }
+       list_add_tail_rcu(&new_node->mac_list, node_db);
+       spin_unlock_bh(&hsr->list_lock);
+       return new_node;
+out:
+       spin_unlock_bh(&hsr->list_lock);
+       kfree(new_node);
        return node;
 }
 
@@ -163,6 +177,7 @@ struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
                              bool is_sup)
 {
        struct list_head *node_db = &port->hsr->node_db;
+       struct hsr_priv *hsr = port->hsr;
        struct hsr_node *node;
        struct ethhdr *ethhdr;
        u16 seq_out;
@@ -196,7 +211,7 @@ struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
                seq_out = HSR_SEQNR_START;
        }
 
-       return hsr_add_node(node_db, ethhdr->h_source, seq_out);
+       return hsr_add_node(hsr, node_db, ethhdr->h_source, seq_out);
 }
 
 /* Use the Supervision frame's info about an eventual macaddress_B for merging
@@ -206,10 +221,11 @@ struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
 void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
                          struct hsr_port *port_rcv)
 {
-       struct ethhdr *ethhdr;
-       struct hsr_node *node_real;
+       struct hsr_priv *hsr = port_rcv->hsr;
        struct hsr_sup_payload *hsr_sp;
+       struct hsr_node *node_real;
        struct list_head *node_db;
+       struct ethhdr *ethhdr;
        int i;
 
        ethhdr = (struct ethhdr *)skb_mac_header(skb);
@@ -231,7 +247,7 @@ void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
        node_real = find_node_by_addr_A(node_db, hsr_sp->macaddress_A);
        if (!node_real)
                /* No frame received from AddrA of this node yet */
-               node_real = hsr_add_node(node_db, hsr_sp->macaddress_A,
+               node_real = hsr_add_node(hsr, node_db, hsr_sp->macaddress_A,
                                         HSR_SEQNR_START - 1);
        if (!node_real)
                goto done; /* No mem */
@@ -252,7 +268,9 @@ void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
        }
        node_real->addr_B_port = port_rcv->type;
 
+       spin_lock_bh(&hsr->list_lock);
        list_del_rcu(&node_curr->mac_list);
+       spin_unlock_bh(&hsr->list_lock);
        kfree_rcu(node_curr, rcu_head);
 
 done:
@@ -368,12 +386,13 @@ void hsr_prune_nodes(struct timer_list *t)
 {
        struct hsr_priv *hsr = from_timer(hsr, t, prune_timer);
        struct hsr_node *node;
+       struct hsr_node *tmp;
        struct hsr_port *port;
        unsigned long timestamp;
        unsigned long time_a, time_b;
 
-       rcu_read_lock();
-       list_for_each_entry_rcu(node, &hsr->node_db, mac_list) {
+       spin_lock_bh(&hsr->list_lock);
+       list_for_each_entry_safe(node, tmp, &hsr->node_db, mac_list) {
                /* Don't prune own node. Neither time_in[HSR_PT_SLAVE_A]
                 * nor time_in[HSR_PT_SLAVE_B], will ever be updated for
                 * the master port. Thus the master node will be repeatedly
@@ -421,7 +440,7 @@ void hsr_prune_nodes(struct timer_list *t)
                        kfree_rcu(node, rcu_head);
                }
        }
-       rcu_read_unlock();
+       spin_unlock_bh(&hsr->list_lock);
 
        /* Restart timer */
        mod_timer(&hsr->prune_timer,
index 89a3ce3..0f0fa12 100644 (file)
 
 struct hsr_node;
 
-void hsr_del_self_node(struct list_head *self_node_db);
+void hsr_del_self_node(struct hsr_priv *hsr);
 void hsr_del_nodes(struct list_head *node_db);
-struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[],
-                             u16 seq_out);
 struct hsr_node *hsr_get_node(struct hsr_port *port, struct sk_buff *skb,
                              bool is_sup);
 void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr,
@@ -33,7 +31,7 @@ int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node,
 
 void hsr_prune_nodes(struct timer_list *t);
 
-int hsr_create_self_node(struct list_head *self_node_db,
+int hsr_create_self_node(struct hsr_priv *hsr,
                         unsigned char addr_a[ETH_ALEN],
                         unsigned char addr_b[ETH_ALEN]);
 
index b9988a6..9e389ac 100644 (file)
@@ -45,6 +45,10 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
        case NETDEV_CHANGE:     /* Link (carrier) state changes */
                hsr_check_carrier_and_operstate(hsr);
                break;
+       case NETDEV_CHANGENAME:
+               if (is_hsr_master(dev))
+                       hsr_debugfs_rename(dev);
+               break;
        case NETDEV_CHANGEADDR:
                if (port->type == HSR_PT_MASTER) {
                        /* This should not happen since there's no
@@ -64,7 +68,7 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event,
 
                /* Make sure we recognize frames from ourselves in hsr_rcv() */
                port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B);
-               res = hsr_create_self_node(&hsr->self_node_db,
+               res = hsr_create_self_node(hsr,
                                           master->dev->dev_addr,
                                           port ?
                                                port->dev->dev_addr :
@@ -123,6 +127,7 @@ static void __exit hsr_exit(void)
 {
        unregister_netdevice_notifier(&hsr_nb);
        hsr_netlink_exit();
+       hsr_debugfs_remove_root();
 }
 
 module_init(hsr_init);
index 96fac69..d40de84 100644 (file)
@@ -160,8 +160,9 @@ struct hsr_priv {
        int announce_count;
        u16 sequence_nr;
        u16 sup_sequence_nr;    /* For HSRv1 separate seq_nr for supervision */
-       u8 prot_version;                /* Indicate if HSRv0 or HSRv1. */
-       spinlock_t seqnr_lock;                  /* locking for sequence_nr */
+       u8 prot_version;        /* Indicate if HSRv0 or HSRv1. */
+       spinlock_t seqnr_lock;  /* locking for sequence_nr */
+       spinlock_t list_lock;   /* locking for node list */
        unsigned char           sup_multicast_addr[ETH_ALEN];
 #ifdef CONFIG_DEBUG_FS
        struct dentry *node_tbl_root;
@@ -184,17 +185,24 @@ static inline u16 hsr_get_skb_sequence_nr(struct sk_buff *skb)
 }
 
 #if IS_ENABLED(CONFIG_DEBUG_FS)
-int hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev);
+void hsr_debugfs_rename(struct net_device *dev);
+void hsr_debugfs_init(struct hsr_priv *priv, struct net_device *hsr_dev);
 void hsr_debugfs_term(struct hsr_priv *priv);
+void hsr_debugfs_create_root(void);
+void hsr_debugfs_remove_root(void);
 #else
-static inline int hsr_debugfs_init(struct hsr_priv *priv,
-                                  struct net_device *hsr_dev)
+static inline void void hsr_debugfs_rename(struct net_device *dev)
 {
-       return 0;
 }
-
+static inline void hsr_debugfs_init(struct hsr_priv *priv,
+                                   struct net_device *hsr_dev)
+{}
 static inline void hsr_debugfs_term(struct hsr_priv *priv)
 {}
+static inline void hsr_debugfs_create_root(void)
+{}
+static inline void hsr_debugfs_remove_root(void)
+{}
 #endif
 
 #endif /*  __HSR_PRIVATE_H */
index 8f8337f..8dc0547 100644 (file)
@@ -476,6 +476,7 @@ int __init hsr_netlink_init(void)
        if (rc)
                goto fail_genl_register_family;
 
+       hsr_debugfs_create_root();
        return 0;
 
 fail_genl_register_family:
index b9df9c0..195469a 100644 (file)
@@ -2193,6 +2193,12 @@ int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
        int count = cb->args[2];
        t_key key = cb->args[3];
 
+       /* First time here, count and key are both always 0. Count > 0
+        * and key == 0 means the dump has wrapped around and we are done.
+        */
+       if (count && !key)
+               return skb->len;
+
        while ((l = leaf_walk_rcu(&tp, key)) != NULL) {
                int err;
 
index e4c6e8b..18c0d5b 100644 (file)
@@ -1086,7 +1086,7 @@ struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu)
                if (!dst)
                        goto out;
        }
-       dst->ops->update_pmtu(dst, sk, NULL, mtu);
+       dst->ops->update_pmtu(dst, sk, NULL, mtu, true);
 
        dst = __sk_dst_check(sk, 0);
        if (!dst)
index af15497..f11e997 100644 (file)
@@ -911,11 +911,12 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 
                for (i = s_i; i < INET_LHTABLE_SIZE; i++) {
                        struct inet_listen_hashbucket *ilb;
+                       struct hlist_nulls_node *node;
 
                        num = 0;
                        ilb = &hashinfo->listening_hash[i];
                        spin_lock(&ilb->lock);
-                       sk_for_each(sk, &ilb->head) {
+                       sk_nulls_for_each(sk, node, &ilb->nulls_head) {
                                struct inet_sock *inet = inet_sk(sk);
 
                                if (!net_eq(sock_net(sk), net))
index 83fb001..2bbaaf0 100644 (file)
@@ -516,10 +516,11 @@ static int inet_reuseport_add_sock(struct sock *sk,
                                   struct inet_listen_hashbucket *ilb)
 {
        struct inet_bind_bucket *tb = inet_csk(sk)->icsk_bind_hash;
+       const struct hlist_nulls_node *node;
        struct sock *sk2;
        kuid_t uid = sock_i_uid(sk);
 
-       sk_for_each_rcu(sk2, &ilb->head) {
+       sk_nulls_for_each_rcu(sk2, node, &ilb->nulls_head) {
                if (sk2 != sk &&
                    sk2->sk_family == sk->sk_family &&
                    ipv6_only_sock(sk2) == ipv6_only_sock(sk) &&
@@ -555,9 +556,9 @@ int __inet_hash(struct sock *sk, struct sock *osk)
        }
        if (IS_ENABLED(CONFIG_IPV6) && sk->sk_reuseport &&
                sk->sk_family == AF_INET6)
-               hlist_add_tail_rcu(&sk->sk_node, &ilb->head);
+               __sk_nulls_add_node_tail_rcu(sk, &ilb->nulls_head);
        else
-               hlist_add_head_rcu(&sk->sk_node, &ilb->head);
+               __sk_nulls_add_node_rcu(sk, &ilb->nulls_head);
        inet_hash2(hashinfo, sk);
        ilb->count++;
        sock_set_flag(sk, SOCK_RCU_FREE);
@@ -606,11 +607,9 @@ void inet_unhash(struct sock *sk)
                reuseport_detach_sock(sk);
        if (ilb) {
                inet_unhash2(hashinfo, sk);
-                __sk_del_node_init(sk);
-                ilb->count--;
-       } else {
-               __sk_nulls_del_node_init_rcu(sk);
+               ilb->count--;
        }
+       __sk_nulls_del_node_init_rcu(sk);
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
 unlock:
        spin_unlock_bh(lock);
@@ -750,7 +749,8 @@ void inet_hashinfo_init(struct inet_hashinfo *h)
 
        for (i = 0; i < INET_LHTABLE_SIZE; i++) {
                spin_lock_init(&h->listening_hash[i].lock);
-               INIT_HLIST_HEAD(&h->listening_hash[i].head);
+               INIT_HLIST_NULLS_HEAD(&h->listening_hash[i].nulls_head,
+                                     i + LISTENING_NULLS_BASE);
                h->listening_hash[i].count = 0;
        }
 
index 572b630..8274f98 100644 (file)
@@ -1464,8 +1464,8 @@ static const struct nla_policy ipgre_policy[IFLA_GRE_MAX + 1] = {
        [IFLA_GRE_OFLAGS]       = { .type = NLA_U16 },
        [IFLA_GRE_IKEY]         = { .type = NLA_U32 },
        [IFLA_GRE_OKEY]         = { .type = NLA_U32 },
-       [IFLA_GRE_LOCAL]        = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
-       [IFLA_GRE_REMOTE]       = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+       [IFLA_GRE_LOCAL]        = { .len = sizeof_field(struct iphdr, saddr) },
+       [IFLA_GRE_REMOTE]       = { .len = sizeof_field(struct iphdr, daddr) },
        [IFLA_GRE_TTL]          = { .type = NLA_U8 },
        [IFLA_GRE_TOS]          = { .type = NLA_U8 },
        [IFLA_GRE_PMTUDISC]     = { .type = NLA_U8 },
index 38c02bb..0fe2a5d 100644 (file)
@@ -505,7 +505,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb,
                mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu;
 
        if (skb_valid_dst(skb))
-               skb_dst_update_pmtu(skb, mtu);
+               skb_dst_update_pmtu_no_confirm(skb, mtu);
 
        if (skb->protocol == htons(ETH_P_IP)) {
                if (!skb_is_gso(skb) &&
index cfb0256..e90b600 100644 (file)
@@ -214,7 +214,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev,
 
        mtu = dst_mtu(dst);
        if (skb->len > mtu) {
-               skb_dst_update_pmtu(skb, mtu);
+               skb_dst_update_pmtu_no_confirm(skb, mtu);
                if (skb->protocol == htons(ETH_P_IP)) {
                        icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
                                  htonl(mtu));
@@ -580,8 +580,8 @@ static const struct nla_policy vti_policy[IFLA_VTI_MAX + 1] = {
        [IFLA_VTI_LINK]         = { .type = NLA_U32 },
        [IFLA_VTI_IKEY]         = { .type = NLA_U32 },
        [IFLA_VTI_OKEY]         = { .type = NLA_U32 },
-       [IFLA_VTI_LOCAL]        = { .len = FIELD_SIZEOF(struct iphdr, saddr) },
-       [IFLA_VTI_REMOTE]       = { .len = FIELD_SIZEOF(struct iphdr, daddr) },
+       [IFLA_VTI_LOCAL]        = { .len = sizeof_field(struct iphdr, saddr) },
+       [IFLA_VTI_REMOTE]       = { .len = sizeof_field(struct iphdr, daddr) },
        [IFLA_VTI_FWMARK]       = { .type = NLA_U32 },
 };
 
index 214154b..f1f78a7 100644 (file)
@@ -384,10 +384,11 @@ next:             ;
        return 1;
 }
 
-static inline int check_target(struct arpt_entry *e, const char *name)
+static int check_target(struct arpt_entry *e, struct net *net, const char *name)
 {
        struct xt_entry_target *t = arpt_get_target(e);
        struct xt_tgchk_param par = {
+               .net       = net,
                .table     = name,
                .entryinfo = e,
                .target    = t->u.kernel.target,
@@ -399,8 +400,9 @@ static inline int check_target(struct arpt_entry *e, const char *name)
        return xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
 }
 
-static inline int
-find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
+static int
+find_check_entry(struct arpt_entry *e, struct net *net, const char *name,
+                unsigned int size,
                 struct xt_percpu_counter_alloc_state *alloc_state)
 {
        struct xt_entry_target *t;
@@ -419,7 +421,7 @@ find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,
        }
        t->u.kernel.target = target;
 
-       ret = check_target(e, name);
+       ret = check_target(e, net, name);
        if (ret)
                goto err;
        return 0;
@@ -494,12 +496,13 @@ static inline int check_entry_size_and_hooks(struct arpt_entry *e,
        return 0;
 }
 
-static inline void cleanup_entry(struct arpt_entry *e)
+static void cleanup_entry(struct arpt_entry *e, struct net *net)
 {
        struct xt_tgdtor_param par;
        struct xt_entry_target *t;
 
        t = arpt_get_target(e);
+       par.net      = net;
        par.target   = t->u.kernel.target;
        par.targinfo = t->data;
        par.family   = NFPROTO_ARP;
@@ -512,7 +515,9 @@ static inline void cleanup_entry(struct arpt_entry *e)
 /* Checks and translates the user-supplied table segment (held in
  * newinfo).
  */
-static int translate_table(struct xt_table_info *newinfo, void *entry0,
+static int translate_table(struct net *net,
+                          struct xt_table_info *newinfo,
+                          void *entry0,
                           const struct arpt_replace *repl)
 {
        struct xt_percpu_counter_alloc_state alloc_state = { 0 };
@@ -569,7 +574,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
        /* Finally, each sanity check must pass */
        i = 0;
        xt_entry_foreach(iter, entry0, newinfo->size) {
-               ret = find_check_entry(iter, repl->name, repl->size,
+               ret = find_check_entry(iter, net, repl->name, repl->size,
                                       &alloc_state);
                if (ret != 0)
                        break;
@@ -580,7 +585,7 @@ static int translate_table(struct xt_table_info *newinfo, void *entry0,
                xt_entry_foreach(iter, entry0, newinfo->size) {
                        if (i-- == 0)
                                break;
-                       cleanup_entry(iter);
+                       cleanup_entry(iter, net);
                }
                return ret;
        }
@@ -923,7 +928,7 @@ static int __do_replace(struct net *net, const char *name,
        /* Decrease module usage counts and free resource */
        loc_cpu_old_entry = oldinfo->entries;
        xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)
-               cleanup_entry(iter);
+               cleanup_entry(iter, net);
 
        xt_free_table_info(oldinfo);
        if (copy_to_user(counters_ptr, counters,
@@ -974,7 +979,7 @@ static int do_replace(struct net *net, const void __user *user,
                goto free_newinfo;
        }
 
-       ret = translate_table(newinfo, loc_cpu_entry, &tmp);
+       ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);
        if (ret != 0)
                goto free_newinfo;
 
@@ -986,7 +991,7 @@ static int do_replace(struct net *net, const void __user *user,
 
  free_newinfo_untrans:
        xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
-               cleanup_entry(iter);
+               cleanup_entry(iter, net);
  free_newinfo:
        xt_free_table_info(newinfo);
        return ret;
@@ -1149,7 +1154,8 @@ compat_copy_entry_from_user(struct compat_arpt_entry *e, void **dstptr,
        }
 }
 
-static int translate_compat_table(struct xt_table_info **pinfo,
+static int translate_compat_table(struct net *net,
+                                 struct xt_table_info **pinfo,
                                  void **pentry0,
                                  const struct compat_arpt_replace *compatr)
 {
@@ -1217,7 +1223,7 @@ static int translate_compat_table(struct xt_table_info **pinfo,
        repl.num_counters = 0;
        repl.counters = NULL;
        repl.size = newinfo->size;
-       ret = translate_table(newinfo, entry1, &repl);
+       ret = translate_table(net, newinfo, entry1, &repl);
        if (ret)
                goto free_newinfo;
 
@@ -1270,7 +1276,7 @@ static int compat_do_replace(struct net *net, void __user *user,
                goto free_newinfo;
        }
 
-       ret = translate_compat_table(&newinfo, &loc_cpu_entry, &tmp);
+       ret = translate_compat_table(net, &newinfo, &loc_cpu_entry, &tmp);
        if (ret != 0)
                goto free_newinfo;
 
@@ -1282,7 +1288,7 @@ static int compat_do_replace(struct net *net, void __user *user,
 
  free_newinfo_untrans:
        xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)
-               cleanup_entry(iter);
+               cleanup_entry(iter, net);
  free_newinfo:
        xt_free_table_info(newinfo);
        return ret;
@@ -1509,7 +1515,7 @@ static int do_arpt_get_ctl(struct sock *sk, int cmd, void __user *user, int *len
        return ret;
 }
 
-static void __arpt_unregister_table(struct xt_table *table)
+static void __arpt_unregister_table(struct net *net, struct xt_table *table)
 {
        struct xt_table_info *private;
        void *loc_cpu_entry;
@@ -1521,7 +1527,7 @@ static void __arpt_unregister_table(struct xt_table *table)
        /* Decrease module usage counts and free resources */
        loc_cpu_entry = private->entries;
        xt_entry_foreach(iter, loc_cpu_entry, private->size)
-               cleanup_entry(iter);
+               cleanup_entry(iter, net);
        if (private->number > private->initial_entries)
                module_put(table_owner);
        xt_free_table_info(private);
@@ -1546,7 +1552,7 @@ int arpt_register_table(struct net *net,
        loc_cpu_entry = newinfo->entries;
        memcpy(loc_cpu_entry, repl->entries, repl->size);
 
-       ret = translate_table(newinfo, loc_cpu_entry, repl);
+       ret = translate_table(net, newinfo, loc_cpu_entry, repl);
        if (ret != 0)
                goto out_free;
 
@@ -1561,7 +1567,7 @@ int arpt_register_table(struct net *net,
 
        ret = nf_register_net_hooks(net, ops, hweight32(table->valid_hooks));
        if (ret != 0) {
-               __arpt_unregister_table(new_table);
+               __arpt_unregister_table(net, new_table);
                *res = NULL;
        }
 
@@ -1576,7 +1582,7 @@ void arpt_unregister_table(struct net *net, struct xt_table *table,
                           const struct nf_hook_ops *ops)
 {
        nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks));
-       __arpt_unregister_table(table);
+       __arpt_unregister_table(net, table);
 }
 
 /* The built-in targets: standard (NULL) and error. */
index f88c93c..87e979f 100644 (file)
@@ -139,7 +139,8 @@ static unsigned int  ipv4_mtu(const struct dst_entry *dst);
 static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
 static void             ipv4_link_failure(struct sk_buff *skb);
 static void             ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                                          struct sk_buff *skb, u32 mtu);
+                                          struct sk_buff *skb, u32 mtu,
+                                          bool confirm_neigh);
 static void             ip_do_redirect(struct dst_entry *dst, struct sock *sk,
                                        struct sk_buff *skb);
 static void            ipv4_dst_destroy(struct dst_entry *dst);
@@ -1043,7 +1044,8 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
 }
 
 static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                             struct sk_buff *skb, u32 mtu)
+                             struct sk_buff *skb, u32 mtu,
+                             bool confirm_neigh)
 {
        struct rtable *rt = (struct rtable *) dst;
        struct flowi4 fl4;
@@ -2687,7 +2689,8 @@ static unsigned int ipv4_blackhole_mtu(const struct dst_entry *dst)
 }
 
 static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                                         struct sk_buff *skb, u32 mtu)
+                                         struct sk_buff *skb, u32 mtu,
+                                         bool confirm_neigh)
 {
 }
 
index 8a39ee7..d885ba8 100644 (file)
@@ -1087,8 +1087,7 @@ do_error:
                goto out;
 out_err:
        /* make sure we wake any epoll edge trigger waiter */
-       if (unlikely(skb_queue_len(&sk->sk_write_queue) == 0 &&
-                    err == -EAGAIN)) {
+       if (unlikely(tcp_rtx_and_write_queues_empty(sk) && err == -EAGAIN)) {
                sk->sk_write_space(sk);
                tcp_chrono_stop(sk, TCP_CHRONO_SNDBUF_LIMITED);
        }
@@ -1419,8 +1418,7 @@ out_err:
        sock_zerocopy_put_abort(uarg, true);
        err = sk_stream_error(sk, flags, err);
        /* make sure we wake any epoll edge trigger waiter */
-       if (unlikely(skb_queue_len(&sk->sk_write_queue) == 0 &&
-                    err == -EAGAIN)) {
+       if (unlikely(tcp_rtx_and_write_queues_empty(sk) && err == -EAGAIN)) {
                sk->sk_write_space(sk);
                tcp_chrono_stop(sk, TCP_CHRONO_SNDBUF_LIMITED);
        }
@@ -3949,7 +3947,7 @@ void __init tcp_init(void)
 
        BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE);
        BUILD_BUG_ON(sizeof(struct tcp_skb_cb) >
-                    FIELD_SIZEOF(struct sk_buff, cb));
+                    sizeof_field(struct sk_buff, cb));
 
        percpu_counter_init(&tcp_sockets_allocated, 0, GFP_KERNEL);
        percpu_counter_init(&tcp_orphan_count, 0, GFP_KERNEL);
index 32772d6..a6545ef 100644 (file)
@@ -306,7 +306,8 @@ static u32 bbr_tso_segs_goal(struct sock *sk)
        /* Sort of tcp_tso_autosize() but ignoring
         * driver provided sk_gso_max_size.
         */
-       bytes = min_t(unsigned long, sk->sk_pacing_rate >> sk->sk_pacing_shift,
+       bytes = min_t(unsigned long,
+                     sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift),
                      GSO_MAX_SIZE - 1 - MAX_TCP_HEADER);
        segs = max_t(u32, bytes / tp->mss_cache, bbr_min_tso_segs(sk));
 
index e387051..8a01428 100644 (file)
@@ -121,14 +121,14 @@ int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
        struct sk_psock *psock;
        int copied, ret;
 
-       if (unlikely(flags & MSG_ERRQUEUE))
-               return inet_recv_error(sk, msg, len, addr_len);
-       if (!skb_queue_empty(&sk->sk_receive_queue))
-               return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
-
        psock = sk_psock_get(sk);
        if (unlikely(!psock))
                return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
+       if (unlikely(flags & MSG_ERRQUEUE))
+               return inet_recv_error(sk, msg, len, addr_len);
+       if (!skb_queue_empty(&sk->sk_receive_queue) &&
+           sk_psock_queue_empty(psock))
+               return tcp_recvmsg(sk, msg, len, nonblock, flags, addr_len);
        lock_sock(sk);
 msg_bytes_ready:
        copied = __tcp_bpf_recvmsg(sk, psock, msg, len, flags);
@@ -139,7 +139,7 @@ msg_bytes_ready:
                timeo = sock_rcvtimeo(sk, nonblock);
                data = tcp_bpf_wait_data(sk, psock, flags, timeo, &err);
                if (data) {
-                       if (skb_queue_empty(&sk->sk_receive_queue))
+                       if (!sk_psock_queue_empty(psock))
                                goto msg_bytes_ready;
                        release_sock(sk);
                        sk_psock_put(sk, psock);
@@ -315,10 +315,7 @@ more_data:
                 */
                delta = msg->sg.size;
                psock->eval = sk_psock_msg_verdict(sk, psock, msg);
-               if (msg->sg.size < delta)
-                       delta -= msg->sg.size;
-               else
-                       delta = 0;
+               delta -= msg->sg.size;
        }
 
        if (msg->cork_bytes &&
index 88b987c..5347ab2 100644 (file)
@@ -915,9 +915,10 @@ static void tcp_check_sack_reordering(struct sock *sk, const u32 low_seq,
 /* This must be called before lost_out is incremented */
 static void tcp_verify_retransmit_hint(struct tcp_sock *tp, struct sk_buff *skb)
 {
-       if (!tp->retransmit_skb_hint ||
-           before(TCP_SKB_CB(skb)->seq,
-                  TCP_SKB_CB(tp->retransmit_skb_hint)->seq))
+       if ((!tp->retransmit_skb_hint && tp->retrans_out >= tp->lost_out) ||
+           (tp->retransmit_skb_hint &&
+            before(TCP_SKB_CB(skb)->seq,
+                   TCP_SKB_CB(tp->retransmit_skb_hint)->seq)))
                tp->retransmit_skb_hint = skb;
 }
 
@@ -1727,8 +1728,11 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb,
                }
 
                /* Ignore very old stuff early */
-               if (!after(sp[used_sacks].end_seq, prior_snd_una))
+               if (!after(sp[used_sacks].end_seq, prior_snd_una)) {
+                       if (i == 0)
+                               first_sack_index = -1;
                        continue;
+               }
 
                used_sacks++;
        }
index 92282f9..1c7326e 100644 (file)
@@ -2147,13 +2147,14 @@ static void *listening_get_next(struct seq_file *seq, void *cur)
        struct tcp_iter_state *st = seq->private;
        struct net *net = seq_file_net(seq);
        struct inet_listen_hashbucket *ilb;
+       struct hlist_nulls_node *node;
        struct sock *sk = cur;
 
        if (!sk) {
 get_head:
                ilb = &tcp_hashinfo.listening_hash[st->bucket];
                spin_lock(&ilb->lock);
-               sk = sk_head(&ilb->head);
+               sk = sk_nulls_head(&ilb->nulls_head);
                st->offset = 0;
                goto get_sk;
        }
@@ -2161,9 +2162,9 @@ get_head:
        ++st->num;
        ++st->offset;
 
-       sk = sk_next(sk);
+       sk = sk_nulls_next(sk);
 get_sk:
-       sk_for_each_from(sk) {
+       sk_nulls_for_each_from(sk, node) {
                if (!net_eq(sock_net(sk), net))
                        continue;
                if (sk->sk_family == afinfo->family)
index b184f03..58c92a7 100644 (file)
@@ -72,6 +72,9 @@ static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb)
        __skb_unlink(skb, &sk->sk_write_queue);
        tcp_rbtree_insert(&sk->tcp_rtx_queue, skb);
 
+       if (tp->highest_sack == NULL)
+               tp->highest_sack = skb;
+
        tp->packets_out += tcp_skb_pcount(skb);
        if (!prior_packets || icsk->icsk_pending == ICSK_TIME_LOSS_PROBE)
                tcp_rearm_rto(sk);
@@ -1725,7 +1728,7 @@ static u32 tcp_tso_autosize(const struct sock *sk, unsigned int mss_now,
        u32 bytes, segs;
 
        bytes = min_t(unsigned long,
-                     sk->sk_pacing_rate >> sk->sk_pacing_shift,
+                     sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift),
                      sk->sk_gso_max_size - 1 - MAX_TCP_HEADER);
 
        /* Goal is to send at least one packet per ms,
@@ -2260,7 +2263,7 @@ static bool tcp_small_queue_check(struct sock *sk, const struct sk_buff *skb,
 
        limit = max_t(unsigned long,
                      2 * skb->truesize,
-                     sk->sk_pacing_rate >> sk->sk_pacing_shift);
+                     sk->sk_pacing_rate >> READ_ONCE(sk->sk_pacing_shift));
        if (sk->sk_pacing_status == SK_PACING_NONE)
                limit = min_t(unsigned long, limit,
                              sock_net(sk)->ipv4.sysctl_tcp_limit_output_bytes);
@@ -2438,6 +2441,14 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                if (tcp_small_queue_check(sk, skb, 0))
                        break;
 
+               /* Argh, we hit an empty skb(), presumably a thread
+                * is sleeping in sendmsg()/sk_stream_wait_memory().
+                * We do not want to send a pure-ack packet and have
+                * a strange looking rtx queue with empty packet(s).
+                */
+               if (TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq)
+                       break;
+
                if (unlikely(tcp_transmit_skb(sk, skb, 1, gfp)))
                        break;
 
@@ -3121,7 +3132,7 @@ void sk_forced_mem_schedule(struct sock *sk, int size)
  */
 void tcp_send_fin(struct sock *sk)
 {
-       struct sk_buff *skb, *tskb = tcp_write_queue_tail(sk);
+       struct sk_buff *skb, *tskb, *tail = tcp_write_queue_tail(sk);
        struct tcp_sock *tp = tcp_sk(sk);
 
        /* Optimization, tack on the FIN if we have one skb in write queue and
@@ -3129,6 +3140,7 @@ void tcp_send_fin(struct sock *sk)
         * Note: in the latter case, FIN packet will be sent after a timeout,
         * as TCP stack thinks it has already been transmitted.
         */
+       tskb = tail;
        if (!tskb && tcp_under_memory_pressure(sk))
                tskb = skb_rb_last(&sk->tcp_rtx_queue);
 
@@ -3136,7 +3148,7 @@ void tcp_send_fin(struct sock *sk)
                TCP_SKB_CB(tskb)->tcp_flags |= TCPHDR_FIN;
                TCP_SKB_CB(tskb)->end_seq++;
                tp->write_seq++;
-               if (tcp_write_queue_empty(sk)) {
+               if (!tail) {
                        /* This means tskb was already sent.
                         * Pretend we included the FIN on previous transmit.
                         * We need to set tp->snd_nxt to the value it would have
index 12ab5db..38d3ad1 100644 (file)
@@ -99,17 +99,19 @@ void tcp_get_available_ulp(char *buf, size_t maxlen)
        rcu_read_unlock();
 }
 
-void tcp_update_ulp(struct sock *sk, struct proto *proto)
+void tcp_update_ulp(struct sock *sk, struct proto *proto,
+                   void (*write_space)(struct sock *sk))
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
 
        if (!icsk->icsk_ulp_ops) {
+               sk->sk_write_space = write_space;
                sk->sk_prot = proto;
                return;
        }
 
        if (icsk->icsk_ulp_ops->update)
-               icsk->icsk_ulp_ops->update(sk, proto);
+               icsk->icsk_ulp_ops->update(sk, proto, write_space);
 }
 
 void tcp_cleanup_ulp(struct sock *sk)
index 4da5758..93a355b 100644 (file)
@@ -1475,7 +1475,7 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
         * queue contains some other skb
         */
        rmem = atomic_add_return(size, &sk->sk_rmem_alloc);
-       if (rmem > (size + sk->sk_rcvbuf))
+       if (rmem > (size + (unsigned int)sk->sk_rcvbuf))
                goto uncharge_drop;
 
        spin_lock(&list->lock);
index 35b84b5..9ebd547 100644 (file)
@@ -100,12 +100,13 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
 }
 
 static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                             struct sk_buff *skb, u32 mtu)
+                             struct sk_buff *skb, u32 mtu,
+                             bool confirm_neigh)
 {
        struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
        struct dst_entry *path = xdst->route;
 
-       path->ops->update_pmtu(path, sk, skb, mtu);
+       path->ops->update_pmtu(path, sk, skb, mtu, confirm_neigh);
 }
 
 static void xfrm4_redirect(struct dst_entry *dst, struct sock *sk,
index 98d8230..39d861d 100644 (file)
@@ -5231,16 +5231,16 @@ static int inet6_rtm_valid_getaddr_req(struct sk_buff *skb,
                return -EINVAL;
        }
 
+       if (!netlink_strict_get_check(skb))
+               return nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
+                                             ifa_ipv6_policy, extack);
+
        ifm = nlmsg_data(nlh);
        if (ifm->ifa_prefixlen || ifm->ifa_flags || ifm->ifa_scope) {
                NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for get address request");
                return -EINVAL;
        }
 
-       if (!netlink_strict_get_check(skb))
-               return nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
-                                             ifa_ipv6_policy, extack);
-
        err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifm), tb, IFA_MAX,
                                            ifa_ipv6_policy, extack);
        if (err)
index fe9cb8d..e315526 100644 (file)
@@ -146,7 +146,7 @@ struct dst_entry *inet6_csk_update_pmtu(struct sock *sk, u32 mtu)
 
        if (IS_ERR(dst))
                return NULL;
-       dst->ops->update_pmtu(dst, sk, NULL, mtu);
+       dst->ops->update_pmtu(dst, sk, NULL, mtu, true);
 
        dst = inet6_csk_route_socket(sk, &fl6);
        return IS_ERR(dst) ? NULL : dst;
index 923034c..ee968d9 100644 (file)
@@ -1040,7 +1040,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
 
        /* TooBig packet may have updated dst->dev's mtu */
        if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu)
-               dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu);
+               dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu, false);
 
        err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
                           NEXTHDR_GRE);
@@ -2170,8 +2170,8 @@ static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = {
        [IFLA_GRE_OFLAGS]      = { .type = NLA_U16 },
        [IFLA_GRE_IKEY]        = { .type = NLA_U32 },
        [IFLA_GRE_OKEY]        = { .type = NLA_U32 },
-       [IFLA_GRE_LOCAL]       = { .len = FIELD_SIZEOF(struct ipv6hdr, saddr) },
-       [IFLA_GRE_REMOTE]      = { .len = FIELD_SIZEOF(struct ipv6hdr, daddr) },
+       [IFLA_GRE_LOCAL]       = { .len = sizeof_field(struct ipv6hdr, saddr) },
+       [IFLA_GRE_REMOTE]      = { .len = sizeof_field(struct ipv6hdr, daddr) },
        [IFLA_GRE_TTL]         = { .type = NLA_U8 },
        [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 },
        [IFLA_GRE_FLOWINFO]    = { .type = NLA_U32 },
index 754a484..2f376db 100644 (file)
@@ -640,7 +640,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                if (rel_info > dst_mtu(skb_dst(skb2)))
                        goto out;
 
-               skb_dst_update_pmtu(skb2, rel_info);
+               skb_dst_update_pmtu_no_confirm(skb2, rel_info);
        }
 
        icmp_send(skb2, rel_type, rel_code, htonl(rel_info));
@@ -1132,7 +1132,7 @@ route_lookup:
        mtu = max(mtu, skb->protocol == htons(ETH_P_IPV6) ?
                       IPV6_MIN_MTU : IPV4_MIN_MTU);
 
-       skb_dst_update_pmtu(skb, mtu);
+       skb_dst_update_pmtu_no_confirm(skb, mtu);
        if (skb->len - t->tun_hlen - eth_hlen > mtu && !skb_is_gso(skb)) {
                *pmtu = mtu;
                err = -EMSGSIZE;
index 024db17..6f08b76 100644 (file)
@@ -479,7 +479,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl)
 
        mtu = dst_mtu(dst);
        if (skb->len > mtu) {
-               skb_dst_update_pmtu(skb, mtu);
+               skb_dst_update_pmtu_no_confirm(skb, mtu);
 
                if (skb->protocol == htons(ETH_P_IPV6)) {
                        if (mtu < IPV6_MIN_MTU)
index b599404..affb51c 100644 (file)
@@ -95,7 +95,8 @@ static int            ip6_pkt_prohibit(struct sk_buff *skb);
 static int             ip6_pkt_prohibit_out(struct net *net, struct sock *sk, struct sk_buff *skb);
 static void            ip6_link_failure(struct sk_buff *skb);
 static void            ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                                          struct sk_buff *skb, u32 mtu);
+                                          struct sk_buff *skb, u32 mtu,
+                                          bool confirm_neigh);
 static void            rt6_do_redirect(struct dst_entry *dst, struct sock *sk,
                                        struct sk_buff *skb);
 static int rt6_score_route(const struct fib6_nh *nh, u32 fib6_flags, int oif,
@@ -264,7 +265,8 @@ static unsigned int ip6_blackhole_mtu(const struct dst_entry *dst)
 }
 
 static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                                        struct sk_buff *skb, u32 mtu)
+                                        struct sk_buff *skb, u32 mtu,
+                                        bool confirm_neigh)
 {
 }
 
@@ -2692,7 +2694,8 @@ static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
 }
 
 static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
-                                const struct ipv6hdr *iph, u32 mtu)
+                                const struct ipv6hdr *iph, u32 mtu,
+                                bool confirm_neigh)
 {
        const struct in6_addr *daddr, *saddr;
        struct rt6_info *rt6 = (struct rt6_info *)dst;
@@ -2710,7 +2713,10 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
                daddr = NULL;
                saddr = NULL;
        }
-       dst_confirm_neigh(dst, daddr);
+
+       if (confirm_neigh)
+               dst_confirm_neigh(dst, daddr);
+
        mtu = max_t(u32, mtu, IPV6_MIN_MTU);
        if (mtu >= dst_mtu(dst))
                return;
@@ -2764,9 +2770,11 @@ out_unlock:
 }
 
 static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                              struct sk_buff *skb, u32 mtu)
+                              struct sk_buff *skb, u32 mtu,
+                              bool confirm_neigh)
 {
-       __ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu);
+       __ip6_rt_update_pmtu(dst, sk, skb ? ipv6_hdr(skb) : NULL, mtu,
+                            confirm_neigh);
 }
 
 void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
@@ -2785,7 +2793,7 @@ void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
 
        dst = ip6_route_output(net, NULL, &fl6);
        if (!dst->error)
-               __ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu));
+               __ip6_rt_update_pmtu(dst, NULL, iph, ntohl(mtu), true);
        dst_release(dst);
 }
 EXPORT_SYMBOL_GPL(ip6_update_pmtu);
index b2ccbc4..9895483 100644 (file)
@@ -944,7 +944,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb,
                }
 
                if (tunnel->parms.iph.daddr)
-                       skb_dst_update_pmtu(skb, mtu);
+                       skb_dst_update_pmtu_no_confirm(skb, mtu);
 
                if (skb->len > mtu && !skb_is_gso(skb)) {
                        icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
index 699e073..af7a4b8 100644 (file)
@@ -98,12 +98,13 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
 }
 
 static void xfrm6_update_pmtu(struct dst_entry *dst, struct sock *sk,
-                             struct sk_buff *skb, u32 mtu)
+                             struct sk_buff *skb, u32 mtu,
+                             bool confirm_neigh)
 {
        struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
        struct dst_entry *path = xdst->route;
 
-       path->ops->update_pmtu(path, sk, skb, mtu);
+       path->ops->update_pmtu(path, sk, skb, mtu, confirm_neigh);
 }
 
 static void xfrm6_redirect(struct dst_entry *dst, struct sock *sk,
index ebb62a4..c4bdcbc 100644 (file)
@@ -50,7 +50,7 @@ static struct iucv_interface *pr_iucv;
 static const u8 iprm_shutdown[8] =
        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
 
-#define TRGCLS_SIZE    FIELD_SIZEOF(struct iucv_message, class)
+#define TRGCLS_SIZE    sizeof_field(struct iucv_message, class)
 
 #define __iucv_sock_wait(sk, condition, timeo, ret)                    \
 do {                                                                   \
index 204a835..c29170e 100644 (file)
@@ -32,7 +32,7 @@ static int llc_stat_ev_rx_null_dsap_xid_c(struct sk_buff *skb)
        return LLC_PDU_IS_CMD(pdu) &&                   /* command PDU */
               LLC_PDU_TYPE_IS_U(pdu) &&                /* U type PDU */
               LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_XID &&
-              !pdu->dsap ? 0 : 1;                      /* NULL DSAP value */
+              !pdu->dsap;                              /* NULL DSAP value */
 }
 
 static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb)
@@ -42,7 +42,7 @@ static int llc_stat_ev_rx_null_dsap_test_c(struct sk_buff *skb)
        return LLC_PDU_IS_CMD(pdu) &&                   /* command PDU */
               LLC_PDU_TYPE_IS_U(pdu) &&                /* U type PDU */
               LLC_U_PDU_CMD(pdu) == LLC_1_PDU_CMD_TEST &&
-              !pdu->dsap ? 0 : 1;                      /* NULL DSAP */
+              !pdu->dsap;                              /* NULL DSAP */
 }
 
 static int llc_station_ac_send_xid_r(struct sk_buff *skb)
index 63cb002..9fc2968 100644 (file)
@@ -442,7 +442,7 @@ u32 ieee80211_calc_rx_airtime(struct ieee80211_hw *hw,
                        return 0;
 
                sband = hw->wiphy->bands[status->band];
-               if (!sband || status->rate_idx > sband->n_bitrates)
+               if (!sband || status->rate_idx >= sband->n_bitrates)
                        return 0;
 
                rate = &sband->bitrates[status->rate_idx];
index 4fb7f1f..000c742 100644 (file)
@@ -2954,6 +2954,28 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
        return err;
 }
 
+static void ieee80211_end_cac(struct wiphy *wiphy,
+                             struct net_device *dev)
+{
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
+
+       mutex_lock(&local->mtx);
+       list_for_each_entry(sdata, &local->interfaces, list) {
+               /* it might be waiting for the local->mtx, but then
+                * by the time it gets it, sdata->wdev.cac_started
+                * will no longer be true
+                */
+               cancel_delayed_work(&sdata->dfs_cac_timer_work);
+
+               if (sdata->wdev.cac_started) {
+                       ieee80211_vif_release_channel(sdata);
+                       sdata->wdev.cac_started = false;
+               }
+       }
+       mutex_unlock(&local->mtx);
+}
+
 static struct cfg80211_beacon_data *
 cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
 {
@@ -4023,6 +4045,7 @@ const struct cfg80211_ops mac80211_config_ops = {
 #endif
        .get_channel = ieee80211_cfg_get_channel,
        .start_radar_detection = ieee80211_start_radar_detection,
+       .end_cac = ieee80211_end_cac,
        .channel_switch = ieee80211_channel_switch,
        .set_qos_map = ieee80211_set_qos_map,
        .set_ap_chanwidth = ieee80211_set_ap_chanwidth,
index b3c9001..c80b1e1 100644 (file)
@@ -201,8 +201,6 @@ static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
        char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
        u64 rx_airtime = 0, tx_airtime = 0;
        s64 deficit[IEEE80211_NUM_ACS];
-       u32 q_depth[IEEE80211_NUM_ACS];
-       u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
        ssize_t rv;
        int ac;
 
@@ -214,6 +212,56 @@ static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
                rx_airtime += sta->airtime[ac].rx_airtime;
                tx_airtime += sta->airtime[ac].tx_airtime;
                deficit[ac] = sta->airtime[ac].deficit;
+               spin_unlock_bh(&local->active_txq_lock[ac]);
+       }
+
+       p += scnprintf(p, bufsz + buf - p,
+               "RX: %llu us\nTX: %llu us\nWeight: %u\n"
+               "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n",
+               rx_airtime, tx_airtime, sta->airtime_weight,
+               deficit[0], deficit[1], deficit[2], deficit[3]);
+
+       rv = simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
+       kfree(buf);
+       return rv;
+}
+
+static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
+                                size_t count, loff_t *ppos)
+{
+       struct sta_info *sta = file->private_data;
+       struct ieee80211_local *local = sta->sdata->local;
+       int ac;
+
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               spin_lock_bh(&local->active_txq_lock[ac]);
+               sta->airtime[ac].rx_airtime = 0;
+               sta->airtime[ac].tx_airtime = 0;
+               sta->airtime[ac].deficit = sta->airtime_weight;
+               spin_unlock_bh(&local->active_txq_lock[ac]);
+       }
+
+       return count;
+}
+STA_OPS_RW(airtime);
+
+static ssize_t sta_aql_read(struct file *file, char __user *userbuf,
+                               size_t count, loff_t *ppos)
+{
+       struct sta_info *sta = file->private_data;
+       struct ieee80211_local *local = sta->sdata->local;
+       size_t bufsz = 400;
+       char *buf = kzalloc(bufsz, GFP_KERNEL), *p = buf;
+       u32 q_depth[IEEE80211_NUM_ACS];
+       u32 q_limit_l[IEEE80211_NUM_ACS], q_limit_h[IEEE80211_NUM_ACS];
+       ssize_t rv;
+       int ac;
+
+       if (!buf)
+               return -ENOMEM;
+
+       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
+               spin_lock_bh(&local->active_txq_lock[ac]);
                q_limit_l[ac] = sta->airtime[ac].aql_limit_low;
                q_limit_h[ac] = sta->airtime[ac].aql_limit_high;
                spin_unlock_bh(&local->active_txq_lock[ac]);
@@ -221,12 +269,8 @@ static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
        }
 
        p += scnprintf(p, bufsz + buf - p,
-               "RX: %llu us\nTX: %llu us\nWeight: %u\n"
-               "Deficit: VO: %lld us VI: %lld us BE: %lld us BK: %lld us\n"
                "Q depth: VO: %u us VI: %u us BE: %u us BK: %u us\n"
                "Q limit[low/high]: VO: %u/%u VI: %u/%u BE: %u/%u BK: %u/%u\n",
-               rx_airtime, tx_airtime, sta->airtime_weight,
-               deficit[0], deficit[1], deficit[2], deficit[3],
                q_depth[0], q_depth[1], q_depth[2], q_depth[3],
                q_limit_l[0], q_limit_h[0], q_limit_l[1], q_limit_h[1],
                q_limit_l[2], q_limit_h[2], q_limit_l[3], q_limit_h[3]),
@@ -236,11 +280,10 @@ static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,
        return rv;
 }
 
-static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
+static ssize_t sta_aql_write(struct file *file, const char __user *userbuf,
                                 size_t count, loff_t *ppos)
 {
        struct sta_info *sta = file->private_data;
-       struct ieee80211_local *local = sta->sdata->local;
        u32 ac, q_limit_l, q_limit_h;
        char _buf[100] = {}, *buf = _buf;
 
@@ -251,7 +294,7 @@ static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
                return -EFAULT;
 
        buf[sizeof(_buf) - 1] = '\0';
-       if (sscanf(buf, "queue limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
+       if (sscanf(buf, "limit %u %u %u", &ac, &q_limit_l, &q_limit_h)
            != 3)
                return -EINVAL;
 
@@ -261,17 +304,10 @@ static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,
        sta->airtime[ac].aql_limit_low = q_limit_l;
        sta->airtime[ac].aql_limit_high = q_limit_h;
 
-       for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-               spin_lock_bh(&local->active_txq_lock[ac]);
-               sta->airtime[ac].rx_airtime = 0;
-               sta->airtime[ac].tx_airtime = 0;
-               sta->airtime[ac].deficit = sta->airtime_weight;
-               spin_unlock_bh(&local->active_txq_lock[ac]);
-       }
-
        return count;
 }
-STA_OPS_RW(airtime);
+STA_OPS_RW(aql);
+
 
 static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
                                        size_t count, loff_t *ppos)
@@ -996,6 +1032,10 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta)
                                    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))
                DEBUGFS_ADD(airtime);
 
+       if (wiphy_ext_feature_isset(local->hw.wiphy,
+                                   NL80211_EXT_FEATURE_AQL))
+               DEBUGFS_ADD(aql);
+
        debugfs_create_xul("driver_buffered_tids", 0400, sta->debugfs_dir,
                           &sta->driver_buffered_tids);
 
index 6cca085..4c2b5ba 100644 (file)
@@ -672,9 +672,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
                        IEEE80211_DEFAULT_AQL_TXQ_LIMIT_H;
        }
 
-       local->airtime_flags = AIRTIME_USE_TX |
-                              AIRTIME_USE_RX |
-                              AIRTIME_USE_AQL;
+       local->airtime_flags = AIRTIME_USE_TX | AIRTIME_USE_RX;
        local->aql_threshold = IEEE80211_AQL_THRESHOLD;
        atomic_set(&local->aql_total_pending_airtime, 0);
 
index 68af623..d699833 100644 (file)
@@ -328,6 +328,9 @@ u32 airtime_link_metric_get(struct ieee80211_local *local,
        unsigned long fail_avg =
                ewma_mesh_fail_avg_read(&sta->mesh->fail_avg);
 
+       if (sta->mesh->plink_state != NL80211_PLINK_ESTAB)
+               return MAX_METRIC;
+
        /* Try to get rate based on HW/SW RC algorithm.
         * Rate is returned in units of Kbps, correct this
         * to comply with airtime calculation units
index 8eafd81..0f5f406 100644 (file)
@@ -1916,6 +1916,9 @@ void ieee80211_sta_update_pending_airtime(struct ieee80211_local *local,
 {
        int tx_pending;
 
+       if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
+               return;
+
        if (!tx_completed) {
                if (sta)
                        atomic_add(tx_airtime,
index ad5d8a4..c00e285 100644 (file)
@@ -127,7 +127,6 @@ enum ieee80211_agg_stop_reason {
 /* Debugfs flags to enable/disable use of RX/TX airtime in scheduler */
 #define AIRTIME_USE_TX         BIT(0)
 #define AIRTIME_USE_RX         BIT(1)
-#define AIRTIME_USE_AQL                BIT(2)
 
 struct airtime_info {
        u64 rx_airtime;
index 727dc9f..e7f57bb 100644 (file)
@@ -263,9 +263,21 @@ int ieee80211_tkip_decrypt_data(struct arc4_ctx *ctx,
        if ((keyid >> 6) != key->conf.keyidx)
                return TKIP_DECRYPT_INVALID_KEYIDX;
 
-       if (rx_ctx->ctx.state != TKIP_STATE_NOT_INIT &&
-           (iv32 < rx_ctx->iv32 ||
-            (iv32 == rx_ctx->iv32 && iv16 <= rx_ctx->iv16)))
+       /* Reject replays if the received TSC is smaller than or equal to the
+        * last received value in a valid message, but with an exception for
+        * the case where a new key has been set and no valid frame using that
+        * key has yet received and the local RSC was initialized to 0. This
+        * exception allows the very first frame sent by the transmitter to be
+        * accepted even if that transmitter were to use TSC 0 (IEEE 802.11
+        * described TSC to be initialized to 1 whenever a new key is taken into
+        * use).
+        */
+       if (iv32 < rx_ctx->iv32 ||
+           (iv32 == rx_ctx->iv32 &&
+            (iv16 < rx_ctx->iv16 ||
+             (iv16 == rx_ctx->iv16 &&
+              (rx_ctx->iv32 || rx_ctx->iv16 ||
+               rx_ctx->ctx.state != TKIP_STATE_NOT_INIT)))))
                return TKIP_DECRYPT_REPLAY;
 
        if (only_iv) {
index b696b91..a8a7306 100644 (file)
@@ -2256,6 +2256,15 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb,
                                                    payload[7]);
        }
 
+       /*
+        * Initialize skb->priority for QoS frames. This is put in the TID field
+        * of the frame before passing it to the driver.
+        */
+       if (ieee80211_is_data_qos(hdr->frame_control)) {
+               u8 *p = ieee80211_get_qos_ctl(hdr);
+               skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
+       }
+
        memset(info, 0, sizeof(*info));
 
        info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS |
@@ -3668,7 +3677,7 @@ begin:
 
        IEEE80211_SKB_CB(skb)->control.vif = vif;
 
-       if (local->airtime_flags & AIRTIME_USE_AQL) {
+       if (wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL)) {
                u32 airtime;
 
                airtime = ieee80211_calc_expected_tx_airtime(hw, vif, txq->sta,
@@ -3790,7 +3799,7 @@ bool ieee80211_txq_airtime_check(struct ieee80211_hw *hw,
        struct sta_info *sta;
        struct ieee80211_local *local = hw_to_local(hw);
 
-       if (!(local->airtime_flags & AIRTIME_USE_AQL))
+       if (!wiphy_ext_feature_isset(local->hw.wiphy, NL80211_EXT_FEATURE_AQL))
                return true;
 
        if (!txq->sta)
index 1abd6f0..077a2cb 100644 (file)
@@ -60,9 +60,9 @@ mtype_destroy(struct ip_set *set)
        if (SET_WITH_TIMEOUT(set))
                del_timer_sync(&map->gc);
 
-       ip_set_free(map->members);
        if (set->dsize && set->extensions & IPSET_EXT_DESTROY)
                mtype_ext_cleanup(set);
+       ip_set_free(map->members);
        ip_set_free(map);
 
        set->data = NULL;
index 169e0a0..cf895bc 100644 (file)
@@ -1848,6 +1848,7 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
        struct ip_set *set;
        struct nlattr *tb[IPSET_ATTR_ADT_MAX + 1] = {};
        int ret = 0;
+       u32 lineno;
 
        if (unlikely(protocol_min_failed(attr) ||
                     !attr[IPSET_ATTR_SETNAME] ||
@@ -1864,7 +1865,7 @@ static int ip_set_utest(struct net *net, struct sock *ctnl, struct sk_buff *skb,
                return -IPSET_ERR_PROTOCOL;
 
        rcu_read_lock_bh();
-       ret = set->variant->uadt(set, tb, IPSET_TEST, NULL, 0, 0);
+       ret = set->variant->uadt(set, tb, IPSET_TEST, &lineno, 0, 0);
        rcu_read_unlock_bh();
        /* Userspace can't trigger element to be re-added */
        if (ret == -EAGAIN)
index b1e300f..b00866d 100644 (file)
@@ -208,7 +208,7 @@ static inline void maybe_update_pmtu(int skb_af, struct sk_buff *skb, int mtu)
        struct rtable *ort = skb_rtable(skb);
 
        if (!skb->dev && sk && sk_fullsock(sk))
-               ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu);
+               ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu, true);
 }
 
 static inline bool ensure_mtu_is_adequate(struct netns_ipvs *ipvs, int skb_af,
index 0af1898..f475fec 100644 (file)
@@ -895,9 +895,10 @@ static void nf_ct_acct_merge(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
 }
 
 /* Resolve race on insertion if this protocol allows this. */
-static int nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
-                              enum ip_conntrack_info ctinfo,
-                              struct nf_conntrack_tuple_hash *h)
+static __cold noinline int
+nf_ct_resolve_clash(struct net *net, struct sk_buff *skb,
+                   enum ip_conntrack_info ctinfo,
+                   struct nf_conntrack_tuple_hash *h)
 {
        /* This is the conntrack entry already in hashes that won race. */
        struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
index d8d33ef..6a1c8f1 100644 (file)
@@ -3626,6 +3626,9 @@ static void __net_exit ctnetlink_net_exit_batch(struct list_head *net_exit_list)
 
        list_for_each_entry(net, net_exit_list, exit_list)
                ctnetlink_net_exit(net);
+
+       /* wait for other cpus until they are done with ctnl_notifiers */
+       synchronize_rcu();
 }
 
 static struct pernet_operations ctnetlink_net_ops = {
index b6b14db..b3f4a33 100644 (file)
@@ -677,6 +677,9 @@ static int dccp_timeout_nlattr_to_obj(struct nlattr *tb[],
        unsigned int *timeouts = data;
        int i;
 
+       if (!timeouts)
+                timeouts = dn->dccp_timeout;
+
        /* set default DCCP timeouts. */
        for (i=0; i<CT_DCCP_MAX; i++)
                timeouts[i] = dn->dccp_timeout[i];
index fce3d93..0399ae8 100644 (file)
@@ -594,6 +594,9 @@ static int sctp_timeout_nlattr_to_obj(struct nlattr *tb[],
        struct nf_sctp_net *sn = nf_sctp_pernet(net);
        int i;
 
+       if (!timeouts)
+               timeouts = sn->timeouts;
+
        /* set default SCTP timeouts. */
        for (i=0; i<SCTP_CONNTRACK_MAX; i++)
                timeouts[i] = sn->timeouts[i];
index 9889d52..e33a73c 100644 (file)
@@ -134,11 +134,6 @@ static void flow_offload_fixup_tcp(struct ip_ct_tcp *tcp)
 #define NF_FLOWTABLE_TCP_PICKUP_TIMEOUT        (120 * HZ)
 #define NF_FLOWTABLE_UDP_PICKUP_TIMEOUT        (30 * HZ)
 
-static inline __s32 nf_flow_timeout_delta(unsigned int timeout)
-{
-       return (__s32)(timeout - (u32)jiffies);
-}
-
 static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
 {
        const struct nf_conntrack_l4proto *l4proto;
@@ -232,7 +227,7 @@ int flow_offload_add(struct nf_flowtable *flow_table, struct flow_offload *flow)
 {
        int err;
 
-       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
+       flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
 
        err = rhashtable_insert_fast(&flow_table->rhashtable,
                                     &flow->tuplehash[0].node,
index b9e7dd6..7ea2ddc 100644 (file)
@@ -280,7 +280,7 @@ nf_flow_offload_ip_hook(void *priv, struct sk_buff *skb,
        if (nf_flow_nat_ip(flow, skb, thoff, dir) < 0)
                return NF_DROP;
 
-       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
+       flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
        iph = ip_hdr(skb);
        ip_decrease_ttl(iph);
        skb->tstamp = 0;
@@ -509,7 +509,7 @@ nf_flow_offload_ipv6_hook(void *priv, struct sk_buff *skb,
        if (nf_flow_nat_ipv6(flow, skb, dir) < 0)
                return NF_DROP;
 
-       flow->timeout = (u32)jiffies + NF_FLOW_TIMEOUT;
+       flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
        ip6h = ipv6_hdr(skb);
        ip6h->hop_limit--;
        skb->tstamp = 0;
index c54c9a6..d06969a 100644 (file)
@@ -28,6 +28,7 @@ struct nf_flow_key {
        struct flow_dissector_key_basic                 basic;
        union {
                struct flow_dissector_key_ipv4_addrs    ipv4;
+               struct flow_dissector_key_ipv6_addrs    ipv6;
        };
        struct flow_dissector_key_tcp                   tcp;
        struct flow_dissector_key_ports                 tp;
@@ -57,6 +58,7 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
        NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_CONTROL, control);
        NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_BASIC, basic);
        NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV4_ADDRS, ipv4);
+       NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_IPV6_ADDRS, ipv6);
        NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_TCP, tcp);
        NF_FLOW_DISSECTOR(match, FLOW_DISSECTOR_KEY_PORTS, tp);
 
@@ -69,15 +71,24 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
                key->ipv4.dst = tuple->dst_v4.s_addr;
                mask->ipv4.dst = 0xffffffff;
                break;
+       case AF_INET6:
+               key->control.addr_type = FLOW_DISSECTOR_KEY_IPV6_ADDRS;
+               key->basic.n_proto = htons(ETH_P_IPV6);
+               key->ipv6.src = tuple->src_v6;
+               memset(&mask->ipv6.src, 0xff, sizeof(mask->ipv6.src));
+               key->ipv6.dst = tuple->dst_v6;
+               memset(&mask->ipv6.dst, 0xff, sizeof(mask->ipv6.dst));
+               break;
        default:
                return -EOPNOTSUPP;
        }
+       match->dissector.used_keys |= BIT(key->control.addr_type);
        mask->basic.n_proto = 0xffff;
 
        switch (tuple->l4proto) {
        case IPPROTO_TCP:
                key->tcp.flags = 0;
-               mask->tcp.flags = TCP_FLAG_RST | TCP_FLAG_FIN;
+               mask->tcp.flags = cpu_to_be16(be32_to_cpu(TCP_FLAG_RST | TCP_FLAG_FIN) >> 16);
                match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_TCP);
                break;
        case IPPROTO_UDP:
@@ -96,14 +107,13 @@ static int nf_flow_rule_match(struct nf_flow_match *match,
 
        match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CONTROL) |
                                      BIT(FLOW_DISSECTOR_KEY_BASIC) |
-                                     BIT(FLOW_DISSECTOR_KEY_IPV4_ADDRS) |
                                      BIT(FLOW_DISSECTOR_KEY_PORTS);
        return 0;
 }
 
 static void flow_offload_mangle(struct flow_action_entry *entry,
-                               enum flow_action_mangle_base htype,
-                               u32 offset, u8 *value, u8 *mask)
+                               enum flow_action_mangle_base htype, u32 offset,
+                               const __be32 *value, const __be32 *mask)
 {
        entry->id = FLOW_ACTION_MANGLE;
        entry->mangle.htype = htype;
@@ -140,12 +150,12 @@ static int flow_offload_eth_src(struct net *net,
        memcpy(&val16, dev->dev_addr, 2);
        val = val16 << 16;
        flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
-                           (u8 *)&val, (u8 *)&mask);
+                           &val, &mask);
 
        mask = ~0xffffffff;
        memcpy(&val, dev->dev_addr + 2, 4);
        flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 8,
-                           (u8 *)&val, (u8 *)&mask);
+                           &val, &mask);
        dev_put(dev);
 
        return 0;
@@ -156,27 +166,41 @@ static int flow_offload_eth_dst(struct net *net,
                                enum flow_offload_tuple_dir dir,
                                struct nf_flow_rule *flow_rule)
 {
-       const struct flow_offload_tuple *tuple = &flow->tuplehash[dir].tuple;
        struct flow_action_entry *entry0 = flow_action_entry_next(flow_rule);
        struct flow_action_entry *entry1 = flow_action_entry_next(flow_rule);
+       const void *daddr = &flow->tuplehash[!dir].tuple.src_v4;
+       const struct dst_entry *dst_cache;
+       unsigned char ha[ETH_ALEN];
        struct neighbour *n;
        u32 mask, val;
+       u8 nud_state;
        u16 val16;
 
-       n = dst_neigh_lookup(tuple->dst_cache, &tuple->dst_v4);
+       dst_cache = flow->tuplehash[dir].tuple.dst_cache;
+       n = dst_neigh_lookup(dst_cache, daddr);
        if (!n)
                return -ENOENT;
 
+       read_lock_bh(&n->lock);
+       nud_state = n->nud_state;
+       ether_addr_copy(ha, n->ha);
+       read_unlock_bh(&n->lock);
+
+       if (!(nud_state & NUD_VALID)) {
+               neigh_release(n);
+               return -ENOENT;
+       }
+
        mask = ~0xffffffff;
-       memcpy(&val, n->ha, 4);
+       memcpy(&val, ha, 4);
        flow_offload_mangle(entry0, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 0,
-                           (u8 *)&val, (u8 *)&mask);
+                           &val, &mask);
 
        mask = ~0x0000ffff;
-       memcpy(&val16, n->ha + 4, 2);
+       memcpy(&val16, ha + 4, 2);
        val = val16;
        flow_offload_mangle(entry1, FLOW_ACT_MANGLE_HDR_TYPE_ETH, 4,
-                           (u8 *)&val, (u8 *)&mask);
+                           &val, &mask);
        neigh_release(n);
 
        return 0;
@@ -206,7 +230,7 @@ static void flow_offload_ipv4_snat(struct net *net,
        }
 
        flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,
-                           (u8 *)&addr, (u8 *)&mask);
+                           &addr, &mask);
 }
 
 static void flow_offload_ipv4_dnat(struct net *net,
@@ -233,12 +257,12 @@ static void flow_offload_ipv4_dnat(struct net *net,
        }
 
        flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP4, offset,
-                           (u8 *)&addr, (u8 *)&mask);
+                           &addr, &mask);
 }
 
 static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,
                                     unsigned int offset,
-                                    u8 *addr, u8 *mask)
+                                    const __be32 *addr, const __be32 *mask)
 {
        struct flow_action_entry *entry;
        int i;
@@ -246,8 +270,7 @@ static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule,
        for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i += sizeof(u32)) {
                entry = flow_action_entry_next(flow_rule);
                flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6,
-                                   offset + i,
-                                   &addr[i], mask);
+                                   offset + i, &addr[i], mask);
        }
 }
 
@@ -257,23 +280,23 @@ static void flow_offload_ipv6_snat(struct net *net,
                                   struct nf_flow_rule *flow_rule)
 {
        u32 mask = ~htonl(0xffffffff);
-       const u8 *addr;
+       const __be32 *addr;
        u32 offset;
 
        switch (dir) {
        case FLOW_OFFLOAD_DIR_ORIGINAL:
-               addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6.s6_addr;
+               addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_v6.s6_addr32;
                offset = offsetof(struct ipv6hdr, saddr);
                break;
        case FLOW_OFFLOAD_DIR_REPLY:
-               addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6.s6_addr;
+               addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_v6.s6_addr32;
                offset = offsetof(struct ipv6hdr, daddr);
                break;
        default:
                return;
        }
 
-       flow_offload_ipv6_mangle(flow_rule, offset, (u8 *)addr, (u8 *)&mask);
+       flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
 }
 
 static void flow_offload_ipv6_dnat(struct net *net,
@@ -282,23 +305,23 @@ static void flow_offload_ipv6_dnat(struct net *net,
                                   struct nf_flow_rule *flow_rule)
 {
        u32 mask = ~htonl(0xffffffff);
-       const u8 *addr;
+       const __be32 *addr;
        u32 offset;
 
        switch (dir) {
        case FLOW_OFFLOAD_DIR_ORIGINAL:
-               addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6.s6_addr;
+               addr = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_v6.s6_addr32;
                offset = offsetof(struct ipv6hdr, daddr);
                break;
        case FLOW_OFFLOAD_DIR_REPLY:
-               addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6.s6_addr;
+               addr = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_v6.s6_addr32;
                offset = offsetof(struct ipv6hdr, saddr);
                break;
        default:
                return;
        }
 
-       flow_offload_ipv6_mangle(flow_rule, offset, (u8 *)addr, (u8 *)&mask);
+       flow_offload_ipv6_mangle(flow_rule, offset, addr, &mask);
 }
 
 static int flow_offload_l4proto(const struct flow_offload *flow)
@@ -326,25 +349,28 @@ static void flow_offload_port_snat(struct net *net,
                                   struct nf_flow_rule *flow_rule)
 {
        struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
-       u32 mask = ~htonl(0xffff0000);
-       __be16 port;
+       u32 mask, port;
        u32 offset;
 
        switch (dir) {
        case FLOW_OFFLOAD_DIR_ORIGINAL:
-               port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port;
+               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port);
                offset = 0; /* offsetof(struct tcphdr, source); */
+               port = htonl(port << 16);
+               mask = ~htonl(0xffff0000);
                break;
        case FLOW_OFFLOAD_DIR_REPLY:
-               port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port;
+               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port);
                offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = htonl(port);
+               mask = ~htonl(0xffff);
                break;
        default:
-               break;
+               return;
        }
 
        flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
-                           (u8 *)&port, (u8 *)&mask);
+                           &port, &mask);
 }
 
 static void flow_offload_port_dnat(struct net *net,
@@ -353,25 +379,28 @@ static void flow_offload_port_dnat(struct net *net,
                                   struct nf_flow_rule *flow_rule)
 {
        struct flow_action_entry *entry = flow_action_entry_next(flow_rule);
-       u32 mask = ~htonl(0xffff);
-       __be16 port;
+       u32 mask, port;
        u32 offset;
 
        switch (dir) {
        case FLOW_OFFLOAD_DIR_ORIGINAL:
-               port = flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.dst_port;
-               offset = 0; /* offsetof(struct tcphdr, source); */
+               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_REPLY].tuple.src_port);
+               offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = htonl(port);
+               mask = ~htonl(0xffff);
                break;
        case FLOW_OFFLOAD_DIR_REPLY:
-               port = flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.src_port;
-               offset = 0; /* offsetof(struct tcphdr, dest); */
+               port = ntohs(flow->tuplehash[FLOW_OFFLOAD_DIR_ORIGINAL].tuple.dst_port);
+               offset = 0; /* offsetof(struct tcphdr, source); */
+               port = htonl(port << 16);
+               mask = ~htonl(0xffff0000);
                break;
        default:
-               break;
+               return;
        }
 
        flow_offload_mangle(entry, flow_offload_l4proto(flow), offset,
-                           (u8 *)&port, (u8 *)&mask);
+                           &port, &mask);
 }
 
 static void flow_offload_ipv4_checksum(struct net *net,
@@ -574,7 +603,7 @@ static int flow_offload_tuple_add(struct flow_offload_work *offload,
        cls_flow.rule = flow_rule->rule;
 
        list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list) {
-               err = block_cb->cb(TC_SETUP_FT, &cls_flow,
+               err = block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow,
                                   block_cb->cb_priv);
                if (err < 0)
                        continue;
@@ -599,7 +628,7 @@ static void flow_offload_tuple_del(struct flow_offload_work *offload,
                             &offload->flow->tuplehash[dir].tuple, &extack);
 
        list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list)
-               block_cb->cb(TC_SETUP_FT, &cls_flow, block_cb->cb_priv);
+               block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow, block_cb->cb_priv);
 
        offload->flow->flags |= FLOW_OFFLOAD_HW_DEAD;
 }
@@ -656,7 +685,7 @@ static void flow_offload_tuple_stats(struct flow_offload_work *offload,
                             &offload->flow->tuplehash[dir].tuple, &extack);
 
        list_for_each_entry(block_cb, &flowtable->flow_block.cb_list, list)
-               block_cb->cb(TC_SETUP_FT, &cls_flow, block_cb->cb_priv);
+               block_cb->cb(TC_SETUP_CLSFLOWER, &cls_flow, block_cb->cb_priv);
        memcpy(stats, &cls_flow.stats, sizeof(*stats));
 }
 
@@ -752,9 +781,9 @@ void nf_flow_offload_stats(struct nf_flowtable *flowtable,
                           struct flow_offload *flow)
 {
        struct flow_offload_work *offload;
-       s64 delta;
+       __s32 delta;
 
-       delta = flow->timeout - jiffies;
+       delta = nf_flow_timeout_delta(flow->timeout);
        if ((delta >= (9 * NF_FLOW_TIMEOUT) / 10) ||
            flow->flags & FLOW_OFFLOAD_HW_DYING)
                return;
@@ -822,7 +851,7 @@ int nf_flow_table_offload_setup(struct nf_flowtable *flowtable,
        bo.extack       = &extack;
        INIT_LIST_HEAD(&bo.cb_list);
 
-       err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_BLOCK, &bo);
+       err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_FT, &bo);
        if (err < 0)
                return err;
 
index 0a59c14..64eedc1 100644 (file)
@@ -233,6 +233,19 @@ icmp_manip_pkt(struct sk_buff *skb,
                return false;
 
        hdr = (struct icmphdr *)(skb->data + hdroff);
+       switch (hdr->type) {
+       case ICMP_ECHO:
+       case ICMP_ECHOREPLY:
+       case ICMP_TIMESTAMP:
+       case ICMP_TIMESTAMPREPLY:
+       case ICMP_INFO_REQUEST:
+       case ICMP_INFO_REPLY:
+       case ICMP_ADDRESS:
+       case ICMP_ADDRESSREPLY:
+               break;
+       default:
+               return true;
+       }
        inet_proto_csum_replace2(&hdr->checksum, skb,
                                 hdr->un.echo.id, tuple->src.u.icmp.id, false);
        hdr->un.echo.id = tuple->src.u.icmp.id;
index a2b58de..f8f52ff 100644 (file)
@@ -189,7 +189,7 @@ static int __nf_queue(struct sk_buff *skb, const struct nf_hook_state *state,
                goto err;
        }
 
-       if (!skb_dst_force(skb) && state->hook != NF_INET_PRE_ROUTING) {
+       if (skb_dst(skb) && !skb_dst_force(skb)) {
                status = -ENETDOWN;
                goto err;
        }
index 062b73a..65f51a2 100644 (file)
@@ -22,6 +22,8 @@
 #include <net/net_namespace.h>
 #include <net/sock.h>
 
+#define NFT_MODULE_AUTOLOAD_LIMIT (MODULE_NAME_LEN - sizeof("nft-expr-255-"))
+
 static LIST_HEAD(nf_tables_expressions);
 static LIST_HEAD(nf_tables_objects);
 static LIST_HEAD(nf_tables_flowtables);
@@ -564,33 +566,34 @@ __nf_tables_chain_type_lookup(const struct nlattr *nla, u8 family)
 }
 
 /*
- * Loading a module requires dropping mutex that guards the
- * transaction.
- * We first need to abort any pending transactions as once
- * mutex is unlocked a different client could start a new
- * transaction.  It must not see any 'future generation'
- * changes * as these changes will never happen.
+ * Loading a module requires dropping mutex that guards the transaction.
+ * A different client might race to start a new transaction meanwhile. Zap the
+ * list of pending transaction and then restore it once the mutex is grabbed
+ * again. Users of this function return EAGAIN which implicitly triggers the
+ * transaction abort path to clean up the list of pending transactions.
  */
 #ifdef CONFIG_MODULES
-static int __nf_tables_abort(struct net *net);
-
 static void nft_request_module(struct net *net, const char *fmt, ...)
 {
        char module_name[MODULE_NAME_LEN];
+       LIST_HEAD(commit_list);
        va_list args;
        int ret;
 
-       __nf_tables_abort(net);
+       list_splice_init(&net->nft.commit_list, &commit_list);
 
        va_start(args, fmt);
        ret = vsnprintf(module_name, MODULE_NAME_LEN, fmt, args);
        va_end(args);
-       if (WARN(ret >= MODULE_NAME_LEN, "truncated: '%s' (len %d)", module_name, ret))
+       if (ret >= MODULE_NAME_LEN)
                return;
 
        mutex_unlock(&net->nft.commit_mutex);
        request_module("%s", module_name);
        mutex_lock(&net->nft.commit_mutex);
+
+       WARN_ON_ONCE(!list_empty(&net->nft.commit_list));
+       list_splice(&commit_list, &net->nft.commit_list);
 }
 #endif
 
@@ -1045,12 +1048,18 @@ static int nft_flush_table(struct nft_ctx *ctx)
        }
 
        list_for_each_entry_safe(flowtable, nft, &ctx->table->flowtables, list) {
+               if (!nft_is_active_next(ctx->net, flowtable))
+                       continue;
+
                err = nft_delflowtable(ctx, flowtable);
                if (err < 0)
                        goto out;
        }
 
        list_for_each_entry_safe(obj, ne, &ctx->table->objects, list) {
+               if (!nft_is_active_next(ctx->net, obj))
+                       continue;
+
                err = nft_delobj(ctx, obj);
                if (err < 0)
                        goto out;
@@ -1241,7 +1250,8 @@ static const struct nla_policy nft_chain_policy[NFTA_CHAIN_MAX + 1] = {
                                    .len = NFT_CHAIN_MAXNAMELEN - 1 },
        [NFTA_CHAIN_HOOK]       = { .type = NLA_NESTED },
        [NFTA_CHAIN_POLICY]     = { .type = NLA_U32 },
-       [NFTA_CHAIN_TYPE]       = { .type = NLA_STRING },
+       [NFTA_CHAIN_TYPE]       = { .type = NLA_STRING,
+                                   .len = NFT_MODULE_AUTOLOAD_LIMIT },
        [NFTA_CHAIN_COUNTERS]   = { .type = NLA_NESTED },
        [NFTA_CHAIN_FLAGS]      = { .type = NLA_U32 },
 };
@@ -1676,6 +1686,7 @@ static int nf_tables_parse_netdev_hooks(struct net *net,
                        goto err_hook;
                }
                if (nft_hook_list_find(hook_list, hook)) {
+                       kfree(hook);
                        err = -EEXIST;
                        goto err_hook;
                }
@@ -2355,7 +2366,8 @@ static const struct nft_expr_type *nft_expr_type_get(struct net *net,
 }
 
 static const struct nla_policy nft_expr_policy[NFTA_EXPR_MAX + 1] = {
-       [NFTA_EXPR_NAME]        = { .type = NLA_STRING },
+       [NFTA_EXPR_NAME]        = { .type = NLA_STRING,
+                                   .len = NFT_MODULE_AUTOLOAD_LIMIT },
        [NFTA_EXPR_DATA]        = { .type = NLA_NESTED },
 };
 
@@ -4198,7 +4210,8 @@ static const struct nla_policy nft_set_elem_policy[NFTA_SET_ELEM_MAX + 1] = {
        [NFTA_SET_ELEM_USERDATA]        = { .type = NLA_BINARY,
                                            .len = NFT_USERDATA_MAXLEN },
        [NFTA_SET_ELEM_EXPR]            = { .type = NLA_NESTED },
-       [NFTA_SET_ELEM_OBJREF]          = { .type = NLA_STRING },
+       [NFTA_SET_ELEM_OBJREF]          = { .type = NLA_STRING,
+                                           .len = NFT_OBJ_MAXNAMELEN - 1 },
 };
 
 static const struct nla_policy nft_set_elem_list_policy[NFTA_SET_ELEM_LIST_MAX + 1] = {
@@ -4519,8 +4532,10 @@ static int nft_get_set_elem(struct nft_ctx *ctx, struct nft_set *set,
                return err;
 
        err = -EINVAL;
-       if (desc.type != NFT_DATA_VALUE || desc.len != set->klen)
+       if (desc.type != NFT_DATA_VALUE || desc.len != set->klen) {
+               nft_data_release(&elem.key.val, desc.type);
                return err;
+       }
 
        priv = set->ops->get(ctx->net, set, &elem, flags);
        if (IS_ERR(priv))
@@ -4756,14 +4771,20 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
                if (nla[NFTA_SET_ELEM_DATA] == NULL &&
                    !(flags & NFT_SET_ELEM_INTERVAL_END))
                        return -EINVAL;
-               if (nla[NFTA_SET_ELEM_DATA] != NULL &&
-                   flags & NFT_SET_ELEM_INTERVAL_END)
-                       return -EINVAL;
        } else {
                if (nla[NFTA_SET_ELEM_DATA] != NULL)
                        return -EINVAL;
        }
 
+       if ((flags & NFT_SET_ELEM_INTERVAL_END) &&
+            (nla[NFTA_SET_ELEM_DATA] ||
+             nla[NFTA_SET_ELEM_OBJREF] ||
+             nla[NFTA_SET_ELEM_TIMEOUT] ||
+             nla[NFTA_SET_ELEM_EXPIRATION] ||
+             nla[NFTA_SET_ELEM_USERDATA] ||
+             nla[NFTA_SET_ELEM_EXPR]))
+               return -EINVAL;
+
        timeout = 0;
        if (nla[NFTA_SET_ELEM_TIMEOUT] != NULL) {
                if (!(set->flags & NFT_SET_TIMEOUT))
@@ -5476,7 +5497,7 @@ static int nf_tables_newobj(struct net *net, struct sock *nlsk,
                if (nlh->nlmsg_flags & NLM_F_REPLACE)
                        return -EOPNOTSUPP;
 
-               type = nft_obj_type_get(net, objtype);
+               type = __nft_obj_type_get(objtype);
                nft_ctx_init(&ctx, net, skb, nlh, family, table, NULL, nla);
 
                return nf_tables_updobj(&ctx, type, nla[NFTA_OBJ_DATA], obj);
@@ -5976,6 +5997,7 @@ nft_flowtable_type_get(struct net *net, u8 family)
        return ERR_PTR(-ENOENT);
 }
 
+/* Only called from error and netdev event paths. */
 static void nft_unregister_flowtable_hook(struct net *net,
                                          struct nft_flowtable *flowtable,
                                          struct nft_hook *hook)
@@ -5991,7 +6013,7 @@ static void nft_unregister_flowtable_net_hooks(struct net *net,
        struct nft_hook *hook;
 
        list_for_each_entry(hook, &flowtable->hook_list, list)
-               nft_unregister_flowtable_hook(net, flowtable, hook);
+               nf_unregister_net_hook(net, &hook->ops);
 }
 
 static int nft_register_flowtable_net_hooks(struct net *net,
@@ -6440,12 +6462,14 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
 {
        struct nft_hook *hook, *next;
 
+       flowtable->data.type->free(&flowtable->data);
        list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
+               flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
+                                           FLOW_BLOCK_UNBIND);
                list_del_rcu(&hook->list);
                kfree(hook);
        }
        kfree(flowtable->name);
-       flowtable->data.type->free(&flowtable->data);
        module_put(flowtable->data.type->owner);
        kfree(flowtable);
 }
@@ -6489,6 +6513,7 @@ static void nft_flowtable_event(unsigned long event, struct net_device *dev,
                if (hook->ops.dev != dev)
                        continue;
 
+               /* flow_offload_netdev_event() cleans up entries for us. */
                nft_unregister_flowtable_hook(dev_net(dev), flowtable, hook);
                list_del_rcu(&hook->list);
                kfree_rcu(hook, rcu);
@@ -7595,7 +7620,7 @@ int nft_validate_register_load(enum nft_registers reg, unsigned int len)
                return -EINVAL;
        if (len == 0)
                return -EINVAL;
-       if (reg * NFT_REG32_SIZE + len > FIELD_SIZEOF(struct nft_regs, data))
+       if (reg * NFT_REG32_SIZE + len > sizeof_field(struct nft_regs, data))
                return -ERANGE;
 
        return 0;
@@ -7643,7 +7668,7 @@ int nft_validate_register_store(const struct nft_ctx *ctx,
                if (len == 0)
                        return -EINVAL;
                if (reg * NFT_REG32_SIZE + len >
-                   FIELD_SIZEOF(struct nft_regs, data))
+                   sizeof_field(struct nft_regs, data))
                        return -ERANGE;
 
                if (data != NULL && type != NFT_DATA_VALUE)
index 431f3b8..a9ea29a 100644 (file)
@@ -44,6 +44,9 @@ struct nft_flow_rule *nft_flow_rule_create(struct net *net,
                expr = nft_expr_next(expr);
        }
 
+       if (num_actions == 0)
+               return ERR_PTR(-EOPNOTSUPP);
+
        flow = nft_flow_rule_alloc(num_actions);
        if (!flow)
                return ERR_PTR(-ENOMEM);
@@ -577,6 +580,9 @@ static int nft_offload_netdev_event(struct notifier_block *this,
        struct net *net = dev_net(dev);
        struct nft_chain *chain;
 
+       if (event != NETDEV_UNREGISTER)
+               return NOTIFY_DONE;
+
        mutex_lock(&net->nft.commit_mutex);
        chain = __nft_offload_get_chain(dev);
        if (chain)
index 7525063..de3a959 100644 (file)
@@ -236,7 +236,7 @@ nfnl_cthelper_create(const struct nlattr * const tb[],
        nla_strlcpy(helper->name,
                    tb[NFCTH_NAME], NF_CT_HELPER_NAME_LEN);
        size = ntohl(nla_get_be32(tb[NFCTH_PRIV_DATA_LEN]));
-       if (size > FIELD_SIZEOF(struct nf_conn_help, data)) {
+       if (size > sizeof_field(struct nf_conn_help, data)) {
                ret = -ENOMEM;
                goto err2;
        }
index 02afa75..10e9d50 100644 (file)
@@ -80,7 +80,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
                            tb[NFTA_BITWISE_MASK]);
        if (err < 0)
                return err;
-       if (d1.len != priv->len) {
+       if (d1.type != NFT_DATA_VALUE || d1.len != priv->len) {
                err = -EINVAL;
                goto err1;
        }
@@ -89,7 +89,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
                            tb[NFTA_BITWISE_XOR]);
        if (err < 0)
                goto err1;
-       if (d2.len != priv->len) {
+       if (d2.type != NFT_DATA_VALUE || d2.len != priv->len) {
                err = -EINVAL;
                goto err2;
        }
index b809206..8a28c12 100644 (file)
@@ -81,6 +81,12 @@ static int nft_cmp_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
        if (err < 0)
                return err;
 
+       if (desc.type != NFT_DATA_VALUE) {
+               err = -EINVAL;
+               nft_data_release(&priv->data, desc.type);
+               return err;
+       }
+
        priv->sreg = nft_parse_register(tb[NFTA_CMP_SREG]);
        err = nft_validate_register_load(priv->sreg, desc.len);
        if (err < 0)
index 46ca8bc..faea72c 100644 (file)
@@ -440,12 +440,12 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
 
                switch (ctx->family) {
                case NFPROTO_IPV4:
-                       len = FIELD_SIZEOF(struct nf_conntrack_tuple,
+                       len = sizeof_field(struct nf_conntrack_tuple,
                                           src.u3.ip);
                        break;
                case NFPROTO_IPV6:
                case NFPROTO_INET:
-                       len = FIELD_SIZEOF(struct nf_conntrack_tuple,
+                       len = sizeof_field(struct nf_conntrack_tuple,
                                           src.u3.ip6);
                        break;
                default:
@@ -457,20 +457,20 @@ static int nft_ct_get_init(const struct nft_ctx *ctx,
                if (tb[NFTA_CT_DIRECTION] == NULL)
                        return -EINVAL;
 
-               len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u3.ip);
+               len = sizeof_field(struct nf_conntrack_tuple, src.u3.ip);
                break;
        case NFT_CT_SRC_IP6:
        case NFT_CT_DST_IP6:
                if (tb[NFTA_CT_DIRECTION] == NULL)
                        return -EINVAL;
 
-               len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u3.ip6);
+               len = sizeof_field(struct nf_conntrack_tuple, src.u3.ip6);
                break;
        case NFT_CT_PROTO_SRC:
        case NFT_CT_PROTO_DST:
                if (tb[NFTA_CT_DIRECTION] == NULL)
                        return -EINVAL;
-               len = FIELD_SIZEOF(struct nf_conntrack_tuple, src.u.all);
+               len = sizeof_field(struct nf_conntrack_tuple, src.u.all);
                break;
        case NFT_CT_BYTES:
        case NFT_CT_PKTS:
@@ -551,7 +551,7 @@ static int nft_ct_set_init(const struct nft_ctx *ctx,
        case NFT_CT_MARK:
                if (tb[NFTA_CT_DIRECTION])
                        return -EINVAL;
-               len = FIELD_SIZEOF(struct nf_conn, mark);
+               len = sizeof_field(struct nf_conn, mark);
                break;
 #endif
 #ifdef CONFIG_NF_CONNTRACK_LABELS
index dd82ff2..b70b489 100644 (file)
@@ -200,9 +200,6 @@ static void nft_flow_offload_activate(const struct nft_ctx *ctx,
 static void nft_flow_offload_destroy(const struct nft_ctx *ctx,
                                     const struct nft_expr *expr)
 {
-       struct nft_flow_offload *priv = nft_expr_priv(expr);
-
-       priv->flowtable->use--;
        nf_ct_netns_put(ctx->net, ctx->family);
 }
 
index 39dc94f..bc9fd98 100644 (file)
@@ -43,7 +43,7 @@ static int nft_masq_init(const struct nft_ctx *ctx,
                         const struct nft_expr *expr,
                         const struct nlattr * const tb[])
 {
-       u32 plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
+       u32 plen = sizeof_field(struct nf_nat_range, min_addr.all);
        struct nft_masq *priv = nft_expr_priv(expr);
        int err;
 
index c3c93e9..8b44a4d 100644 (file)
@@ -141,10 +141,10 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
 
        switch (family) {
        case NFPROTO_IPV4:
-               alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip);
+               alen = sizeof_field(struct nf_nat_range, min_addr.ip);
                break;
        case NFPROTO_IPV6:
-               alen = FIELD_SIZEOF(struct nf_nat_range, min_addr.ip6);
+               alen = sizeof_field(struct nf_nat_range, min_addr.ip6);
                break;
        default:
                return -EAFNOSUPPORT;
@@ -171,7 +171,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                }
        }
 
-       plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
+       plen = sizeof_field(struct nf_nat_range, min_addr.all);
        if (tb[NFTA_NAT_REG_PROTO_MIN]) {
                priv->sreg_proto_min =
                        nft_parse_register(tb[NFTA_NAT_REG_PROTO_MIN]);
index 4701fa8..89efcc5 100644 (file)
@@ -66,11 +66,21 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
        if (err < 0)
                return err;
 
+       if (desc_from.type != NFT_DATA_VALUE) {
+               err = -EINVAL;
+               goto err1;
+       }
+
        err = nft_data_init(NULL, &priv->data_to, sizeof(priv->data_to),
                            &desc_to, tb[NFTA_RANGE_TO_DATA]);
        if (err < 0)
                goto err1;
 
+       if (desc_to.type != NFT_DATA_VALUE) {
+               err = -EINVAL;
+               goto err2;
+       }
+
        if (desc_from.len != desc_to.len) {
                err = -EINVAL;
                goto err2;
index 43eeb1f..5b77917 100644 (file)
@@ -48,7 +48,7 @@ static int nft_redir_init(const struct nft_ctx *ctx,
        unsigned int plen;
        int err;
 
-       plen = FIELD_SIZEOF(struct nf_nat_range, min_addr.all);
+       plen = sizeof_field(struct nf_nat_range, min_addr.all);
        if (tb[NFTA_REDIR_REG_PROTO_MIN]) {
                priv->sreg_proto_min =
                        nft_parse_register(tb[NFTA_REDIR_REG_PROTO_MIN]);
index 5712325..a9f804f 100644 (file)
@@ -74,8 +74,13 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
                                parent = rcu_dereference_raw(parent->rb_left);
                                continue;
                        }
-                       if (nft_rbtree_interval_end(rbe))
-                               goto out;
+                       if (nft_rbtree_interval_end(rbe)) {
+                               if (nft_set_is_anonymous(set))
+                                       return false;
+                               parent = rcu_dereference_raw(parent->rb_left);
+                               interval = NULL;
+                               continue;
+                       }
 
                        *ext = &rbe->ext;
                        return true;
@@ -88,7 +93,7 @@ static bool __nft_rbtree_lookup(const struct net *net, const struct nft_set *set
                *ext = &interval->ext;
                return true;
        }
-out:
+
        return false;
 }
 
@@ -139,8 +144,10 @@ static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set,
                        if (flags & NFT_SET_ELEM_INTERVAL_END)
                                interval = rbe;
                } else {
-                       if (!nft_set_elem_active(&rbe->ext, genmask))
+                       if (!nft_set_elem_active(&rbe->ext, genmask)) {
                                parent = rcu_dereference_raw(parent->rb_left);
+                               continue;
+                       }
 
                        if (!nft_set_ext_exists(&rbe->ext, NFT_SET_EXT_FLAGS) ||
                            (*nft_set_ext_flags(&rbe->ext) & NFT_SET_ELEM_INTERVAL_END) ==
@@ -148,7 +155,11 @@ static bool __nft_rbtree_get(const struct net *net, const struct nft_set *set,
                                *elem = rbe;
                                return true;
                        }
-                       return false;
+
+                       if (nft_rbtree_interval_end(rbe))
+                               interval = NULL;
+
+                       parent = rcu_dereference_raw(parent->rb_left);
                }
        }
 
index f92a82c..d67f83a 100644 (file)
@@ -50,7 +50,7 @@ static void nft_tproxy_eval_v4(const struct nft_expr *expr,
        taddr = nf_tproxy_laddr4(skb, taddr, iph->daddr);
 
        if (priv->sreg_port)
-               tport = regs->data[priv->sreg_port];
+               tport = nft_reg_load16(&regs->data[priv->sreg_port]);
        if (!tport)
                tport = hp->dest;
 
@@ -117,7 +117,7 @@ static void nft_tproxy_eval_v6(const struct nft_expr *expr,
        taddr = *nf_tproxy_laddr6(skb, &taddr, &iph->daddr);
 
        if (priv->sreg_port)
-               tport = regs->data[priv->sreg_port];
+               tport = nft_reg_load16(&regs->data[priv->sreg_port]);
        if (!tport)
                tport = hp->dest;
 
@@ -218,14 +218,14 @@ static int nft_tproxy_init(const struct nft_ctx *ctx,
 
        switch (priv->family) {
        case NFPROTO_IPV4:
-               alen = FIELD_SIZEOF(union nf_inet_addr, in);
+               alen = sizeof_field(union nf_inet_addr, in);
                err = nf_defrag_ipv4_enable(ctx->net);
                if (err)
                        return err;
                break;
 #if IS_ENABLED(CONFIG_NF_TABLES_IPV6)
        case NFPROTO_IPV6:
-               alen = FIELD_SIZEOF(union nf_inet_addr, in6);
+               alen = sizeof_field(union nf_inet_addr, in6);
                err = nf_defrag_ipv6_enable(ctx->net);
                if (err)
                        return err;
index 3d4c2ae..5284fcf 100644 (file)
@@ -76,7 +76,7 @@ static int nft_tunnel_get_init(const struct nft_ctx *ctx,
        struct nft_tunnel *priv = nft_expr_priv(expr);
        u32 len;
 
-       if (!tb[NFTA_TUNNEL_KEY] &&
+       if (!tb[NFTA_TUNNEL_KEY] ||
            !tb[NFTA_TUNNEL_DREG])
                return -EINVAL;
 
@@ -266,6 +266,9 @@ static int nft_tunnel_obj_erspan_init(const struct nlattr *attr,
        if (err < 0)
                return err;
 
+       if (!tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION])
+                return -EINVAL;
+
        version = ntohl(nla_get_be32(tb[NFTA_TUNNEL_KEY_ERSPAN_VERSION]));
        switch (version) {
        case ERSPAN_VERSION:
index 2236455..37253d3 100644 (file)
@@ -30,7 +30,7 @@ static unsigned int jhash_rnd __read_mostly;
 
 static unsigned int xt_rateest_hash(const char *name)
 {
-       return jhash(name, FIELD_SIZEOF(struct xt_rateest, name), jhash_rnd) &
+       return jhash(name, sizeof_field(struct xt_rateest, name), jhash_rnd) &
               (RATEEST_HSIZE - 1);
 }
 
index 90b2ab9..4e31721 100644 (file)
@@ -2755,7 +2755,7 @@ static int __init netlink_proto_init(void)
        if (err != 0)
                goto out;
 
-       BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct netlink_skb_parms) > sizeof_field(struct sk_buff, cb));
 
        nl_table = kcalloc(MAX_LINKS, sizeof(*nl_table), GFP_KERNEL);
        if (!nl_table)
index 78fe622..11b554c 100644 (file)
@@ -346,7 +346,7 @@ static int nci_uart_default_recv_buf(struct nci_uart *nu, const u8 *data,
                        nu->rx_packet_len = -1;
                        nu->rx_skb = nci_skb_alloc(nu->ndev,
                                                   NCI_MAX_PACKET_SIZE,
-                                                  GFP_KERNEL);
+                                                  GFP_ATOMIC);
                        if (!nu->rx_skb)
                                return -ENOMEM;
                }
index 1047e80..e3a37d2 100644 (file)
@@ -2497,7 +2497,7 @@ static int __init dp_init(void)
 {
        int err;
 
-       BUILD_BUG_ON(sizeof(struct ovs_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct ovs_skb_cb) > sizeof_field(struct sk_buff, cb));
 
        pr_info("Open vSwitch switching datapath\n");
 
index fd8ed76..758a8c7 100644 (file)
@@ -37,7 +37,7 @@ enum sw_flow_mac_proto {
  * matching for small options.
  */
 #define TUN_METADATA_OFFSET(opt_len) \
-       (FIELD_SIZEOF(struct sw_flow_key, tun_opts) - opt_len)
+       (sizeof_field(struct sw_flow_key, tun_opts) - opt_len)
 #define TUN_METADATA_OPTS(flow_key, opt_len) \
        ((void *)((flow_key)->tun_opts + TUN_METADATA_OFFSET(opt_len)))
 
@@ -52,7 +52,7 @@ struct vlan_head {
 
 #define OVS_SW_FLOW_KEY_METADATA_SIZE                  \
        (offsetof(struct sw_flow_key, recirc_id) +      \
-       FIELD_SIZEOF(struct sw_flow_key, recirc_id))
+       sizeof_field(struct sw_flow_key, recirc_id))
 
 struct ovs_key_nsh {
        struct ovs_nsh_key_base base;
index 53c1d41..118cd66 100644 (file)
@@ -544,7 +544,8 @@ static int prb_calc_retire_blk_tmo(struct packet_sock *po,
                        msec = 1;
                        div = ecmd.base.speed / 1000;
                }
-       }
+       } else
+               return DEFAULT_PRB_RETIRE_TOV;
 
        mbits = (blk_size_in_bytes * 8) / (1024 * 1024);
 
index 88f98f2..3d24d45 100644 (file)
@@ -196,7 +196,7 @@ static int qrtr_node_enqueue(struct qrtr_node *node, struct sk_buff *skb,
        hdr->size = cpu_to_le32(len);
        hdr->confirm_rx = 0;
 
-       skb_put_padto(skb, ALIGN(len, 4));
+       skb_put_padto(skb, ALIGN(len, 4) + sizeof(*hdr));
 
        mutex_lock(&node->ep_lock);
        if (node->ep)
index 461d752..971c73c 100644 (file)
@@ -1002,10 +1002,13 @@ static void rfkill_sync_work(struct work_struct *work)
 int __must_check rfkill_register(struct rfkill *rfkill)
 {
        static unsigned long rfkill_no;
-       struct device *dev = &rfkill->dev;
+       struct device *dev;
        int error;
 
-       BUG_ON(!rfkill);
+       if (!rfkill)
+               return -EINVAL;
+
+       dev = &rfkill->dev;
 
        mutex_lock(&rfkill_global_mutex);
 
index d72ddb6..9d3c4d2 100644 (file)
@@ -972,7 +972,7 @@ static int __init af_rxrpc_init(void)
        int ret = -1;
        unsigned int tmp;
 
-       BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct rxrpc_skb_priv) > sizeof_field(struct sk_buff, cb));
 
        get_random_bytes(&tmp, sizeof(tmp));
        tmp &= 0x3fffffff;
index 7c7d10f..5e99df8 100644 (file)
@@ -209,6 +209,7 @@ struct rxrpc_skb_priv {
 struct rxrpc_security {
        const char              *name;          /* name of this service */
        u8                      security_index; /* security type provided */
+       u32                     no_key_abort;   /* Abort code indicating no key */
 
        /* Initialise a security service */
        int (*init)(void);
@@ -977,8 +978,9 @@ static inline void rxrpc_reduce_conn_timer(struct rxrpc_connection *conn,
 struct rxrpc_connection *rxrpc_find_service_conn_rcu(struct rxrpc_peer *,
                                                     struct sk_buff *);
 struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *, gfp_t);
-void rxrpc_new_incoming_connection(struct rxrpc_sock *,
-                                  struct rxrpc_connection *, struct sk_buff *);
+void rxrpc_new_incoming_connection(struct rxrpc_sock *, struct rxrpc_connection *,
+                                  const struct rxrpc_security *, struct key *,
+                                  struct sk_buff *);
 void rxrpc_unpublish_service_conn(struct rxrpc_connection *);
 
 /*
@@ -1103,7 +1105,9 @@ extern const struct rxrpc_security rxkad;
 int __init rxrpc_init_security(void);
 void rxrpc_exit_security(void);
 int rxrpc_init_client_conn_security(struct rxrpc_connection *);
-int rxrpc_init_server_conn_security(struct rxrpc_connection *);
+bool rxrpc_look_up_server_security(struct rxrpc_local *, struct rxrpc_sock *,
+                                  const struct rxrpc_security **, struct key **,
+                                  struct sk_buff *);
 
 /*
  * sendmsg.c
index 135bf5c..70e44ab 100644 (file)
@@ -240,6 +240,22 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
 }
 
 /*
+ * Ping the other end to fill our RTT cache and to retrieve the rwind
+ * and MTU parameters.
+ */
+static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb)
+{
+       struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+       ktime_t now = skb->tstamp;
+
+       if (call->peer->rtt_usage < 3 ||
+           ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now))
+               rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
+                                 true, true,
+                                 rxrpc_propose_ack_ping_for_params);
+}
+
+/*
  * Allocate a new incoming call from the prealloc pool, along with a connection
  * and a peer as necessary.
  */
@@ -247,6 +263,8 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
                                                    struct rxrpc_local *local,
                                                    struct rxrpc_peer *peer,
                                                    struct rxrpc_connection *conn,
+                                                   const struct rxrpc_security *sec,
+                                                   struct key *key,
                                                    struct sk_buff *skb)
 {
        struct rxrpc_backlog *b = rx->backlog;
@@ -294,7 +312,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
                conn->params.local = rxrpc_get_local(local);
                conn->params.peer = peer;
                rxrpc_see_connection(conn);
-               rxrpc_new_incoming_connection(rx, conn, skb);
+               rxrpc_new_incoming_connection(rx, conn, sec, key, skb);
        } else {
                rxrpc_get_connection(conn);
        }
@@ -333,9 +351,11 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
                                           struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+       const struct rxrpc_security *sec = NULL;
        struct rxrpc_connection *conn;
        struct rxrpc_peer *peer = NULL;
-       struct rxrpc_call *call;
+       struct rxrpc_call *call = NULL;
+       struct key *key = NULL;
 
        _enter("");
 
@@ -346,9 +366,7 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
                                  sp->hdr.seq, RX_INVALID_OPERATION, ESHUTDOWN);
                skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
                skb->priority = RX_INVALID_OPERATION;
-               _leave(" = NULL [close]");
-               call = NULL;
-               goto out;
+               goto no_call;
        }
 
        /* The peer, connection and call may all have sprung into existence due
@@ -358,29 +376,19 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
         */
        conn = rxrpc_find_connection_rcu(local, skb, &peer);
 
-       call = rxrpc_alloc_incoming_call(rx, local, peer, conn, skb);
+       if (!conn && !rxrpc_look_up_server_security(local, rx, &sec, &key, skb))
+               goto no_call;
+
+       call = rxrpc_alloc_incoming_call(rx, local, peer, conn, sec, key, skb);
+       key_put(key);
        if (!call) {
                skb->mark = RXRPC_SKB_MARK_REJECT_BUSY;
-               _leave(" = NULL [busy]");
-               call = NULL;
-               goto out;
+               goto no_call;
        }
 
        trace_rxrpc_receive(call, rxrpc_receive_incoming,
                            sp->hdr.serial, sp->hdr.seq);
 
-       /* Lock the call to prevent rxrpc_kernel_send/recv_data() and
-        * sendmsg()/recvmsg() inconveniently stealing the mutex once the
-        * notification is generated.
-        *
-        * The BUG should never happen because the kernel should be well
-        * behaved enough not to access the call before the first notification
-        * event and userspace is prevented from doing so until the state is
-        * appropriate.
-        */
-       if (!mutex_trylock(&call->user_mutex))
-               BUG();
-
        /* Make the call live. */
        rxrpc_incoming_call(rx, call, skb);
        conn = call->conn;
@@ -421,6 +429,9 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
                BUG();
        }
        spin_unlock(&conn->state_lock);
+       spin_unlock(&rx->incoming_lock);
+
+       rxrpc_send_ping(call, skb);
 
        if (call->state == RXRPC_CALL_SERVER_ACCEPTING)
                rxrpc_notify_socket(call);
@@ -433,9 +444,12 @@ struct rxrpc_call *rxrpc_new_incoming_call(struct rxrpc_local *local,
        rxrpc_put_call(call, rxrpc_call_put);
 
        _leave(" = %p{%d}", call, call->debug_id);
-out:
-       spin_unlock(&rx->incoming_lock);
        return call;
+
+no_call:
+       spin_unlock(&rx->incoming_lock);
+       _leave(" = NULL [%u]", skb->mark);
+       return NULL;
 }
 
 /*
index a1ceef4..808a472 100644 (file)
@@ -376,21 +376,7 @@ static void rxrpc_secure_connection(struct rxrpc_connection *conn)
        _enter("{%d}", conn->debug_id);
 
        ASSERT(conn->security_ix != 0);
-
-       if (!conn->params.key) {
-               _debug("set up security");
-               ret = rxrpc_init_server_conn_security(conn);
-               switch (ret) {
-               case 0:
-                       break;
-               case -ENOENT:
-                       abort_code = RX_CALL_DEAD;
-                       goto abort;
-               default:
-                       abort_code = RXKADNOAUTH;
-                       goto abort;
-               }
-       }
+       ASSERT(conn->server_key);
 
        if (conn->security->issue_challenge(conn) < 0) {
                abort_code = RX_CALL_DEAD;
index 123d6ce..21da48e 100644 (file)
@@ -148,6 +148,8 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn
  */
 void rxrpc_new_incoming_connection(struct rxrpc_sock *rx,
                                   struct rxrpc_connection *conn,
+                                  const struct rxrpc_security *sec,
+                                  struct key *key,
                                   struct sk_buff *skb)
 {
        struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
@@ -160,6 +162,8 @@ void rxrpc_new_incoming_connection(struct rxrpc_sock *rx,
        conn->service_id        = sp->hdr.serviceId;
        conn->security_ix       = sp->hdr.securityIndex;
        conn->out_clientflag    = 0;
+       conn->security          = sec;
+       conn->server_key        = key_get(key);
        if (conn->security_ix)
                conn->state     = RXRPC_CONN_SERVICE_UNSECURED;
        else
index 157be1f..86bd133 100644 (file)
@@ -193,22 +193,6 @@ send_extra_data:
 }
 
 /*
- * Ping the other end to fill our RTT cache and to retrieve the rwind
- * and MTU parameters.
- */
-static void rxrpc_send_ping(struct rxrpc_call *call, struct sk_buff *skb)
-{
-       struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
-       ktime_t now = skb->tstamp;
-
-       if (call->peer->rtt_usage < 3 ||
-           ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), now))
-               rxrpc_propose_ACK(call, RXRPC_ACK_PING, sp->hdr.serial,
-                                 true, true,
-                                 rxrpc_propose_ack_ping_for_params);
-}
-
-/*
  * Apply a hard ACK by advancing the Tx window.
  */
 static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
@@ -1396,8 +1380,6 @@ int rxrpc_input_packet(struct sock *udp_sk, struct sk_buff *skb)
                call = rxrpc_new_incoming_call(local, rx, skb);
                if (!call)
                        goto reject_packet;
-               rxrpc_send_ping(call, skb);
-               mutex_unlock(&call->user_mutex);
        }
 
        /* Process a call packet; this either discards or passes on the ref
index 8d8aa3c..098f1f9 100644 (file)
@@ -648,9 +648,9 @@ static int rxkad_issue_challenge(struct rxrpc_connection *conn)
        u32 serial;
        int ret;
 
-       _enter("{%d,%x}", conn->debug_id, key_serial(conn->params.key));
+       _enter("{%d,%x}", conn->debug_id, key_serial(conn->server_key));
 
-       ret = key_validate(conn->params.key);
+       ret = key_validate(conn->server_key);
        if (ret < 0)
                return ret;
 
@@ -1293,6 +1293,7 @@ static void rxkad_exit(void)
 const struct rxrpc_security rxkad = {
        .name                           = "rxkad",
        .security_index                 = RXRPC_SECURITY_RXKAD,
+       .no_key_abort                   = RXKADUNKNOWNKEY,
        .init                           = rxkad_init,
        .exit                           = rxkad_exit,
        .init_connection_security       = rxkad_init_connection_security,
index a4c47d2..9b1fb9e 100644 (file)
@@ -101,62 +101,58 @@ int rxrpc_init_client_conn_security(struct rxrpc_connection *conn)
 }
 
 /*
- * initialise the security on a server connection
+ * Find the security key for a server connection.
  */
-int rxrpc_init_server_conn_security(struct rxrpc_connection *conn)
+bool rxrpc_look_up_server_security(struct rxrpc_local *local, struct rxrpc_sock *rx,
+                                  const struct rxrpc_security **_sec,
+                                  struct key **_key,
+                                  struct sk_buff *skb)
 {
        const struct rxrpc_security *sec;
-       struct rxrpc_local *local = conn->params.local;
-       struct rxrpc_sock *rx;
-       struct key *key;
-       key_ref_t kref;
+       struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+       key_ref_t kref = NULL;
        char kdesc[5 + 1 + 3 + 1];
 
        _enter("");
 
-       sprintf(kdesc, "%u:%u", conn->service_id, conn->security_ix);
+       sprintf(kdesc, "%u:%u", sp->hdr.serviceId, sp->hdr.securityIndex);
 
-       sec = rxrpc_security_lookup(conn->security_ix);
+       sec = rxrpc_security_lookup(sp->hdr.securityIndex);
        if (!sec) {
-               _leave(" = -ENOKEY [lookup]");
-               return -ENOKEY;
+               trace_rxrpc_abort(0, "SVS",
+                                 sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
+                                 RX_INVALID_OPERATION, EKEYREJECTED);
+               skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
+               skb->priority = RX_INVALID_OPERATION;
+               return false;
        }
 
-       /* find the service */
-       read_lock(&local->services_lock);
-       rx = rcu_dereference_protected(local->service,
-                                      lockdep_is_held(&local->services_lock));
-       if (rx && (rx->srx.srx_service == conn->service_id ||
-                  rx->second_service == conn->service_id))
-               goto found_service;
+       if (sp->hdr.securityIndex == RXRPC_SECURITY_NONE)
+               goto out;
 
-       /* the service appears to have died */
-       read_unlock(&local->services_lock);
-       _leave(" = -ENOENT");
-       return -ENOENT;
-
-found_service:
        if (!rx->securities) {
-               read_unlock(&local->services_lock);
-               _leave(" = -ENOKEY");
-               return -ENOKEY;
+               trace_rxrpc_abort(0, "SVR",
+                                 sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
+                                 RX_INVALID_OPERATION, EKEYREJECTED);
+               skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
+               skb->priority = RX_INVALID_OPERATION;
+               return false;
        }
 
        /* look through the service's keyring */
        kref = keyring_search(make_key_ref(rx->securities, 1UL),
                              &key_type_rxrpc_s, kdesc, true);
        if (IS_ERR(kref)) {
-               read_unlock(&local->services_lock);
-               _leave(" = %ld [search]", PTR_ERR(kref));
-               return PTR_ERR(kref);
+               trace_rxrpc_abort(0, "SVK",
+                                 sp->hdr.cid, sp->hdr.callNumber, sp->hdr.seq,
+                                 sec->no_key_abort, EKEYREJECTED);
+               skb->mark = RXRPC_SKB_MARK_REJECT_ABORT;
+               skb->priority = sec->no_key_abort;
+               return false;
        }
 
-       key = key_ref_to_ptr(kref);
-       read_unlock(&local->services_lock);
-
-       conn->server_key = key;
-       conn->security = sec;
-
-       _leave(" = 0");
-       return 0;
+out:
+       *_sec = sec;
+       *_key = key_ref_to_ptr(kref);
+       return true;
 }
index bf2d693..f685c0d 100644 (file)
@@ -312,7 +312,7 @@ static void tcf_ct_act_set_labels(struct nf_conn *ct,
                                  u32 *labels_m)
 {
 #if IS_ENABLED(CONFIG_NF_CONNTRACK_LABELS)
-       size_t labels_sz = FIELD_SIZEOF(struct tcf_ct_params, labels);
+       size_t labels_sz = sizeof_field(struct tcf_ct_params, labels);
 
        if (!memchr_inv(labels_m, 0, labels_sz))
                return;
@@ -936,7 +936,7 @@ static struct tc_action_ops act_ct_ops = {
 
 static __net_init int ct_init_net(struct net *net)
 {
-       unsigned int n_bits = FIELD_SIZEOF(struct tcf_ct_params, labels) * 8;
+       unsigned int n_bits = sizeof_field(struct tcf_ct_params, labels) * 8;
        struct tc_ct_action_net *tn = net_generic(net, ct_net_id);
 
        if (nf_connlabels_get(net, n_bits - 1)) {
index 40038c3..1964962 100644 (file)
@@ -360,6 +360,16 @@ static int tcf_ctinfo_search(struct net *net, struct tc_action **a, u32 index)
        return tcf_idr_search(tn, a, index);
 }
 
+static void tcf_ctinfo_cleanup(struct tc_action *a)
+{
+       struct tcf_ctinfo *ci = to_ctinfo(a);
+       struct tcf_ctinfo_params *cp;
+
+       cp = rcu_dereference_protected(ci->params, 1);
+       if (cp)
+               kfree_rcu(cp, rcu);
+}
+
 static struct tc_action_ops act_ctinfo_ops = {
        .kind   = "ctinfo",
        .id     = TCA_ID_CTINFO,
@@ -367,6 +377,7 @@ static struct tc_action_ops act_ctinfo_ops = {
        .act    = tcf_ctinfo_act,
        .dump   = tcf_ctinfo_dump,
        .init   = tcf_ctinfo_init,
+       .cleanup= tcf_ctinfo_cleanup,
        .walk   = tcf_ctinfo_walker,
        .lookup = tcf_ctinfo_search,
        .size   = sizeof(struct tcf_ctinfo),
index 5e63790..c1fcd85 100644 (file)
@@ -537,6 +537,9 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
        }
 
        ife = to_ife(*a);
+       if (ret == ACT_P_CREATED)
+               INIT_LIST_HEAD(&ife->metalist);
+
        err = tcf_action_check_ctrlact(parm->action, tp, &goto_ch, extack);
        if (err < 0)
                goto release_idr;
@@ -566,10 +569,6 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
                p->eth_type = ife_type;
        }
 
-
-       if (ret == ACT_P_CREATED)
-               INIT_LIST_HEAD(&ife->metalist);
-
        if (tb[TCA_IFE_METALST]) {
                err = nla_parse_nested_deprecated(tb2, IFE_META_MAX,
                                                  tb[TCA_IFE_METALST], NULL,
index 1e3eb3a..1ad300e 100644 (file)
@@ -219,8 +219,10 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
        bool use_reinsert;
        bool want_ingress;
        bool is_redirect;
+       bool expects_nh;
        int m_eaction;
        int mac_len;
+       bool at_nh;
 
        rec_level = __this_cpu_inc_return(mirred_rec_level);
        if (unlikely(rec_level > MIRRED_RECURSION_LIMIT)) {
@@ -261,19 +263,19 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
                        goto out;
        }
 
-       /* If action's target direction differs than filter's direction,
-        * and devices expect a mac header on xmit, then mac push/pull is
-        * needed.
-        */
        want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
-       if (skb_at_tc_ingress(skb) != want_ingress && m_mac_header_xmit) {
-               if (!skb_at_tc_ingress(skb)) {
-                       /* caught at egress, act ingress: pull mac */
-                       mac_len = skb_network_header(skb) - skb_mac_header(skb);
+
+       expects_nh = want_ingress || !m_mac_header_xmit;
+       at_nh = skb->data == skb_network_header(skb);
+       if (at_nh != expects_nh) {
+               mac_len = skb_at_tc_ingress(skb) ? skb->mac_len :
+                         skb_network_header(skb) - skb_mac_header(skb);
+               if (expects_nh) {
+                       /* target device/action expect data at nh */
                        skb_pull_rcsum(skb2, mac_len);
                } else {
-                       /* caught at ingress, act egress: push mac */
-                       skb_push_rcsum(skb2, skb->mac_len);
+                       /* target device/action expect data at mac */
+                       skb_push_rcsum(skb2, mac_len);
                }
        }
 
index 6a0eaca..76e0d12 100644 (file)
@@ -308,33 +308,12 @@ static void tcf_proto_put(struct tcf_proto *tp, bool rtnl_held,
                tcf_proto_destroy(tp, rtnl_held, true, extack);
 }
 
-static int walker_check_empty(struct tcf_proto *tp, void *fh,
-                             struct tcf_walker *arg)
+static bool tcf_proto_check_delete(struct tcf_proto *tp)
 {
-       if (fh) {
-               arg->nonempty = true;
-               return -1;
-       }
-       return 0;
-}
-
-static bool tcf_proto_is_empty(struct tcf_proto *tp, bool rtnl_held)
-{
-       struct tcf_walker walker = { .fn = walker_check_empty, };
-
-       if (tp->ops->walk) {
-               tp->ops->walk(tp, &walker, rtnl_held);
-               return !walker.nonempty;
-       }
-       return true;
-}
+       if (tp->ops->delete_empty)
+               return tp->ops->delete_empty(tp);
 
-static bool tcf_proto_check_delete(struct tcf_proto *tp, bool rtnl_held)
-{
-       spin_lock(&tp->lock);
-       if (tcf_proto_is_empty(tp, rtnl_held))
-               tp->deleting = true;
-       spin_unlock(&tp->lock);
+       tp->deleting = true;
        return tp->deleting;
 }
 
@@ -1751,7 +1730,7 @@ static void tcf_chain_tp_delete_empty(struct tcf_chain *chain,
         * concurrently.
         * Mark tp for deletion if it is empty.
         */
-       if (!tp_iter || !tcf_proto_check_delete(tp, rtnl_held)) {
+       if (!tp_iter || !tcf_proto_check_delete(tp)) {
                mutex_unlock(&chain->filter_chain_lock);
                return;
        }
index 6c68971..b0f42e6 100644 (file)
@@ -1481,7 +1481,7 @@ static int fl_init_mask_hashtable(struct fl_flow_mask *mask)
 }
 
 #define FL_KEY_MEMBER_OFFSET(member) offsetof(struct fl_flow_key, member)
-#define FL_KEY_MEMBER_SIZE(member) FIELD_SIZEOF(struct fl_flow_key, member)
+#define FL_KEY_MEMBER_SIZE(member) sizeof_field(struct fl_flow_key, member)
 
 #define FL_KEY_IS_MASKED(mask, member)                                         \
        memchr_inv(((char *)mask) + FL_KEY_MEMBER_OFFSET(member),               \
@@ -2773,6 +2773,17 @@ static void fl_bind_class(void *fh, u32 classid, unsigned long cl)
                f->res.class = cl;
 }
 
+static bool fl_delete_empty(struct tcf_proto *tp)
+{
+       struct cls_fl_head *head = fl_head_dereference(tp);
+
+       spin_lock(&tp->lock);
+       tp->deleting = idr_is_empty(&head->handle_idr);
+       spin_unlock(&tp->lock);
+
+       return tp->deleting;
+}
+
 static struct tcf_proto_ops cls_fl_ops __read_mostly = {
        .kind           = "flower",
        .classify       = fl_classify,
@@ -2782,6 +2793,7 @@ static struct tcf_proto_ops cls_fl_ops __read_mostly = {
        .put            = fl_put,
        .change         = fl_change,
        .delete         = fl_delete,
+       .delete_empty   = fl_delete_empty,
        .walk           = fl_walk,
        .reoffload      = fl_reoffload,
        .hw_add         = fl_hw_add,
index e0f4040..2277369 100644 (file)
@@ -1769,7 +1769,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                                                      q->avg_window_begin));
                        u64 b = q->avg_window_bytes * (u64)NSEC_PER_SEC;
 
-                       do_div(b, window_interval);
+                       b = div64_u64(b, window_interval);
                        q->avg_peak_bandwidth =
                                cake_ewma(q->avg_peak_bandwidth, b,
                                          b > q->avg_peak_bandwidth ? 2 : 8);
index b1c7e72..a5a2954 100644 (file)
@@ -301,6 +301,9 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
                                     f->socket_hash != sk->sk_hash)) {
                                f->credit = q->initial_quantum;
                                f->socket_hash = sk->sk_hash;
+                               if (q->rate_enable)
+                                       smp_store_release(&sk->sk_pacing_status,
+                                                         SK_PACING_FQ);
                                if (fq_flow_is_throttled(f))
                                        fq_flow_unset_throttled(q, f);
                                f->time_next_packet = 0ULL;
@@ -322,8 +325,12 @@ static struct fq_flow *fq_classify(struct sk_buff *skb, struct fq_sched_data *q)
 
        fq_flow_set_detached(f);
        f->sk = sk;
-       if (skb->sk == sk)
+       if (skb->sk == sk) {
                f->socket_hash = sk->sk_hash;
+               if (q->rate_enable)
+                       smp_store_release(&sk->sk_pacing_status,
+                                         SK_PACING_FQ);
+       }
        f->credit = q->initial_quantum;
 
        rb_link_node(&f->fq_node, parent, p);
@@ -428,17 +435,9 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        f->qlen++;
        qdisc_qstats_backlog_inc(sch, skb);
        if (fq_flow_is_detached(f)) {
-               struct sock *sk = skb->sk;
-
                fq_flow_add_tail(&q->new_flows, f);
                if (time_after(jiffies, f->age + q->flow_refill_delay))
                        f->credit = max_t(u32, f->credit, q->quantum);
-               if (sk && q->rate_enable) {
-                       if (unlikely(smp_load_acquire(&sk->sk_pacing_status) !=
-                                    SK_PACING_FQ))
-                               smp_store_release(&sk->sk_pacing_status,
-                                                 SK_PACING_FQ);
-               }
                q->inactive_flows--;
        }
 
@@ -787,10 +786,12 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt,
        if (tb[TCA_FQ_QUANTUM]) {
                u32 quantum = nla_get_u32(tb[TCA_FQ_QUANTUM]);
 
-               if (quantum > 0)
+               if (quantum > 0 && quantum <= (1 << 20)) {
                        q->quantum = quantum;
-               else
+               } else {
+                       NL_SET_ERR_MSG_MOD(extack, "invalid quantum");
                        err = -EINVAL;
+               }
        }
 
        if (tb[TCA_FQ_INITIAL_QUANTUM])
index 18b884c..6479417 100644 (file)
@@ -292,8 +292,14 @@ static int prio_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
        struct tc_prio_qopt_offload graft_offload;
        unsigned long band = arg - 1;
 
-       if (new == NULL)
-               new = &noop_qdisc;
+       if (!new) {
+               new = qdisc_create_dflt(sch->dev_queue, &pfifo_qdisc_ops,
+                                       TC_H_MAKE(sch->handle, arg), extack);
+               if (!new)
+                       new = &noop_qdisc;
+               else
+                       qdisc_hash_add(new, true);
+       }
 
        *old = qdisc_replace(sch, new, &q->queues[band]);
 
index fbbf191..78af2fc 100644 (file)
@@ -227,6 +227,7 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
                sa->sin_port = sh->dest;
                sa->sin_addr.s_addr = ip_hdr(skb)->daddr;
        }
+       memset(sa->sin_zero, 0, sizeof(sa->sin_zero));
 }
 
 /* Initialize an sctp_addr from a socket. */
@@ -235,6 +236,7 @@ static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
        addr->v4.sin_family = AF_INET;
        addr->v4.sin_port = 0;
        addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr;
+       memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
 }
 
 /* Initialize sk->sk_rcv_saddr from sctp_addr. */
@@ -257,6 +259,7 @@ static void sctp_v4_from_addr_param(union sctp_addr *addr,
        addr->v4.sin_family = AF_INET;
        addr->v4.sin_port = port;
        addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
+       memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
 }
 
 /* Initialize an address parameter from a sctp_addr and return the length
@@ -281,6 +284,7 @@ static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4,
        saddr->v4.sin_family = AF_INET;
        saddr->v4.sin_port = port;
        saddr->v4.sin_addr.s_addr = fl4->saddr;
+       memset(saddr->v4.sin_zero, 0, sizeof(saddr->v4.sin_zero));
 }
 
 /* Compare two addresses exactly. */
@@ -303,6 +307,7 @@ static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port)
        addr->v4.sin_family = AF_INET;
        addr->v4.sin_addr.s_addr = htonl(INADDR_ANY);
        addr->v4.sin_port = port;
+       memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero));
 }
 
 /* Is this a wildcard address? */
index acd737d..834e9f8 100644 (file)
@@ -1363,8 +1363,10 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
                        /* Generate an INIT ACK chunk.  */
                        new_obj = sctp_make_init_ack(asoc, chunk, GFP_ATOMIC,
                                                     0);
-                       if (!new_obj)
-                               goto nomem;
+                       if (!new_obj) {
+                               error = -ENOMEM;
+                               break;
+                       }
 
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
                                        SCTP_CHUNK(new_obj));
@@ -1386,7 +1388,8 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
                        if (!new_obj) {
                                if (cmd->obj.chunk)
                                        sctp_chunk_free(cmd->obj.chunk);
-                               goto nomem;
+                               error = -ENOMEM;
+                               break;
                        }
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
                                        SCTP_CHUNK(new_obj));
@@ -1433,8 +1436,10 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
 
                        /* Generate a SHUTDOWN chunk.  */
                        new_obj = sctp_make_shutdown(asoc, chunk);
-                       if (!new_obj)
-                               goto nomem;
+                       if (!new_obj) {
+                               error = -ENOMEM;
+                               break;
+                       }
                        sctp_add_cmd_sf(commands, SCTP_CMD_REPLY,
                                        SCTP_CHUNK(new_obj));
                        break;
@@ -1770,11 +1775,17 @@ static int sctp_cmd_interpreter(enum sctp_event_type event_type,
                        break;
                }
 
-               if (error)
+               if (error) {
+                       cmd = sctp_next_cmd(commands);
+                       while (cmd) {
+                               if (cmd->verb == SCTP_CMD_REPLY)
+                                       sctp_chunk_free(cmd->obj.chunk);
+                               cmd = sctp_next_cmd(commands);
+                       }
                        break;
+               }
        }
 
-out:
        /* If this is in response to a received chunk, wait until
         * we are done with the packet to open the queue so that we don't
         * send multiple packets in response to a single request.
@@ -1789,7 +1800,4 @@ out:
                sp->data_ready_signalled = 0;
 
        return error;
-nomem:
-       error = -ENOMEM;
-       goto out;
 }
index e83cdaa..c1a100d 100644 (file)
@@ -119,7 +119,7 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
         * a new one with new outcnt to save memory if needed.
         */
        if (outcnt == stream->outcnt)
-               goto in;
+               goto handle_in;
 
        /* Filter out chunks queued on streams that won't exist anymore */
        sched->unsched_all(stream);
@@ -128,24 +128,28 @@ int sctp_stream_init(struct sctp_stream *stream, __u16 outcnt, __u16 incnt,
 
        ret = sctp_stream_alloc_out(stream, outcnt, gfp);
        if (ret)
-               goto out;
+               goto out_err;
 
        for (i = 0; i < stream->outcnt; i++)
                SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
 
-in:
+handle_in:
        sctp_stream_interleave_init(stream);
        if (!incnt)
                goto out;
 
        ret = sctp_stream_alloc_in(stream, incnt, gfp);
-       if (ret) {
-               sched->free(stream);
-               genradix_free(&stream->out);
-               stream->outcnt = 0;
-               goto out;
-       }
+       if (ret)
+               goto in_err;
 
+       goto out;
+
+in_err:
+       sched->free(stream);
+       genradix_free(&stream->in);
+out_err:
+       genradix_free(&stream->out);
+       stream->outcnt = 0;
 out:
        return ret;
 }
index 7235a60..3bbe1a5 100644 (file)
@@ -263,7 +263,7 @@ bool sctp_transport_update_pmtu(struct sctp_transport *t, u32 pmtu)
 
                pf->af->from_sk(&addr, sk);
                pf->to_sk_daddr(&t->ipaddr, sk);
-               dst->ops->update_pmtu(dst, sk, NULL, pmtu);
+               dst->ops->update_pmtu(dst, sk, NULL, pmtu, true);
                pf->to_sk_daddr(&addr, sk);
 
                dst = sctp_transport_dst_check(t);
index b997072..cee5bf4 100644 (file)
@@ -857,6 +857,8 @@ static int smc_connect(struct socket *sock, struct sockaddr *addr,
                goto out;
 
        sock_hold(&smc->sk); /* sock put in passive closing */
+       if (smc->use_fallback)
+               goto out;
        if (flags & O_NONBLOCK) {
                if (schedule_work(&smc->connect_work))
                        smc->connect_nonblock = 1;
@@ -1721,8 +1723,6 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
                sk->sk_err = smc->clcsock->sk->sk_err;
                sk->sk_error_report(sk);
        }
-       if (rc)
-               return rc;
 
        if (optlen < sizeof(int))
                return -EINVAL;
@@ -1730,6 +1730,8 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
                return -EFAULT;
 
        lock_sock(sk);
+       if (rc || smc->use_fallback)
+               goto out;
        switch (optname) {
        case TCP_ULP:
        case TCP_FASTOPEN:
@@ -1741,15 +1743,14 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
                        smc_switch_to_fallback(smc);
                        smc->fallback_rsn = SMC_CLC_DECL_OPTUNSUPP;
                } else {
-                       if (!smc->use_fallback)
-                               rc = -EINVAL;
+                       rc = -EINVAL;
                }
                break;
        case TCP_NODELAY:
                if (sk->sk_state != SMC_INIT &&
                    sk->sk_state != SMC_LISTEN &&
                    sk->sk_state != SMC_CLOSED) {
-                       if (val && !smc->use_fallback)
+                       if (val)
                                mod_delayed_work(system_wq, &smc->conn.tx_work,
                                                 0);
                }
@@ -1758,7 +1759,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
                if (sk->sk_state != SMC_INIT &&
                    sk->sk_state != SMC_LISTEN &&
                    sk->sk_state != SMC_CLOSED) {
-                       if (!val && !smc->use_fallback)
+                       if (!val)
                                mod_delayed_work(system_wq, &smc->conn.tx_work,
                                                 0);
                }
@@ -1769,6 +1770,7 @@ static int smc_setsockopt(struct socket *sock, int level, int optname,
        default:
                break;
        }
+out:
        release_sock(sk);
 
        return rc;
index bb92c7c..e419ff2 100644 (file)
@@ -1287,7 +1287,7 @@ static int smc_core_reboot_event(struct notifier_block *this,
                                 unsigned long event, void *ptr)
 {
        smc_lgrs_shutdown();
-
+       smc_ib_unregister_client();
        return 0;
 }
 
index 4d38d49..5062321 100644 (file)
@@ -957,7 +957,7 @@ static ssize_t sock_read_iter(struct kiocb *iocb, struct iov_iter *to)
                             .msg_iocb = iocb};
        ssize_t res;
 
-       if (file->f_flags & O_NONBLOCK)
+       if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
                msg.msg_flags = MSG_DONTWAIT;
 
        if (iocb->ki_pos != 0)
@@ -982,7 +982,7 @@ static ssize_t sock_write_iter(struct kiocb *iocb, struct iov_iter *from)
        if (iocb->ki_pos != 0)
                return -ESPIPE;
 
-       if (file->f_flags & O_NONBLOCK)
+       if (file->f_flags & O_NONBLOCK || (iocb->ki_flags & IOCB_NOWAIT))
                msg.msg_flags = MSG_DONTWAIT;
 
        if (sock->type == SOCK_SEQPACKET)
index 77c7dd7..fda3889 100644 (file)
@@ -77,7 +77,7 @@
 static void rpcrdma_sendctx_put_locked(struct rpcrdma_xprt *r_xprt,
                                       struct rpcrdma_sendctx *sc);
 static void rpcrdma_reqs_reset(struct rpcrdma_xprt *r_xprt);
-static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf);
+static void rpcrdma_reps_unmap(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_mrs_create(struct rpcrdma_xprt *r_xprt);
 static void rpcrdma_mrs_destroy(struct rpcrdma_xprt *r_xprt);
 static struct rpcrdma_regbuf *
@@ -244,6 +244,7 @@ rpcrdma_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event)
                        ia->ri_id->device->name,
                        rpcrdma_addrstr(r_xprt), rpcrdma_portstr(r_xprt));
 #endif
+               init_completion(&ia->ri_remove_done);
                set_bit(RPCRDMA_IAF_REMOVING, &ia->ri_flags);
                ep->rep_connected = -ENODEV;
                xprt_force_disconnect(xprt);
@@ -297,7 +298,6 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt, struct rpcrdma_ia *ia)
        int rc;
 
        init_completion(&ia->ri_done);
-       init_completion(&ia->ri_remove_done);
 
        id = rdma_create_id(xprt->rx_xprt.xprt_net, rpcrdma_cm_event_handler,
                            xprt, RDMA_PS_TCP, IB_QPT_RC);
@@ -421,7 +421,7 @@ rpcrdma_ia_remove(struct rpcrdma_ia *ia)
        /* The ULP is responsible for ensuring all DMA
         * mappings and MRs are gone.
         */
-       rpcrdma_reps_destroy(buf);
+       rpcrdma_reps_unmap(r_xprt);
        list_for_each_entry(req, &buf->rb_allreqs, rl_all) {
                rpcrdma_regbuf_dma_unmap(req->rl_rdmabuf);
                rpcrdma_regbuf_dma_unmap(req->rl_sendbuf);
@@ -599,6 +599,7 @@ static int rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt,
                                    struct ib_qp_init_attr *qp_init_attr)
 {
        struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+       struct rpcrdma_ep *ep = &r_xprt->rx_ep;
        int rc, err;
 
        trace_xprtrdma_reinsert(r_xprt);
@@ -613,6 +614,7 @@ static int rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt,
                pr_err("rpcrdma: rpcrdma_ep_create returned %d\n", err);
                goto out2;
        }
+       memcpy(qp_init_attr, &ep->rep_attr, sizeof(*qp_init_attr));
 
        rc = -ENETUNREACH;
        err = rdma_create_qp(ia->ri_id, ia->ri_pd, qp_init_attr);
@@ -1090,6 +1092,7 @@ static struct rpcrdma_rep *rpcrdma_rep_create(struct rpcrdma_xprt *r_xprt,
        rep->rr_recv_wr.sg_list = &rep->rr_rdmabuf->rg_iov;
        rep->rr_recv_wr.num_sge = 1;
        rep->rr_temp = temp;
+       list_add(&rep->rr_all, &r_xprt->rx_buf.rb_all_reps);
        return rep;
 
 out_free:
@@ -1100,6 +1103,7 @@ out:
 
 static void rpcrdma_rep_destroy(struct rpcrdma_rep *rep)
 {
+       list_del(&rep->rr_all);
        rpcrdma_regbuf_free(rep->rr_rdmabuf);
        kfree(rep);
 }
@@ -1118,10 +1122,16 @@ static struct rpcrdma_rep *rpcrdma_rep_get_locked(struct rpcrdma_buffer *buf)
 static void rpcrdma_rep_put(struct rpcrdma_buffer *buf,
                            struct rpcrdma_rep *rep)
 {
-       if (!rep->rr_temp)
-               llist_add(&rep->rr_node, &buf->rb_free_reps);
-       else
-               rpcrdma_rep_destroy(rep);
+       llist_add(&rep->rr_node, &buf->rb_free_reps);
+}
+
+static void rpcrdma_reps_unmap(struct rpcrdma_xprt *r_xprt)
+{
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+       struct rpcrdma_rep *rep;
+
+       list_for_each_entry(rep, &buf->rb_all_reps, rr_all)
+               rpcrdma_regbuf_dma_unmap(rep->rr_rdmabuf);
 }
 
 static void rpcrdma_reps_destroy(struct rpcrdma_buffer *buf)
@@ -1152,6 +1162,7 @@ int rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
 
        INIT_LIST_HEAD(&buf->rb_send_bufs);
        INIT_LIST_HEAD(&buf->rb_allreqs);
+       INIT_LIST_HEAD(&buf->rb_all_reps);
 
        rc = -ENOMEM;
        for (i = 0; i < buf->rb_max_requests; i++) {
@@ -1504,6 +1515,10 @@ void rpcrdma_post_recvs(struct rpcrdma_xprt *r_xprt, bool temp)
        wr = NULL;
        while (needed) {
                rep = rpcrdma_rep_get_locked(buf);
+               if (rep && rep->rr_temp) {
+                       rpcrdma_rep_destroy(rep);
+                       continue;
+               }
                if (!rep)
                        rep = rpcrdma_rep_create(r_xprt, temp);
                if (!rep)
index 5d15140..d796d68 100644 (file)
@@ -203,6 +203,7 @@ struct rpcrdma_rep {
        struct xdr_stream       rr_stream;
        struct llist_node       rr_node;
        struct ib_recv_wr       rr_recv_wr;
+       struct list_head        rr_all;
 };
 
 /* To reduce the rate at which a transport invokes ib_post_recv
@@ -368,6 +369,7 @@ struct rpcrdma_buffer {
 
        struct list_head        rb_allreqs;
        struct list_head        rb_all_mrs;
+       struct list_head        rb_all_reps;
 
        struct llist_head       rb_free_reps;
 
index 11255e9..ee49a9f 100644 (file)
@@ -9,7 +9,7 @@ tipc-y  += addr.o bcast.o bearer.o \
           core.o link.o discover.o msg.o  \
           name_distr.o  subscr.o monitor.o name_table.o net.o  \
           netlink.o netlink_compat.o node.o socket.o eth_media.o \
-          topsrv.o socket.o group.o trace.o
+          topsrv.o group.o trace.o
 
 CFLAGS_trace.o += -I$(src)
 
@@ -20,5 +20,3 @@ tipc-$(CONFIG_TIPC_CRYPTO)    += crypto.o
 
 
 obj-$(CONFIG_TIPC_DIAG)        += diag.o
-
-tipc_diag-y    := diag.o
index 55aeba6..656ebc7 100644 (file)
@@ -305,17 +305,17 @@ static int tipc_rcast_xmit(struct net *net, struct sk_buff_head *pkts,
  * @skb: socket buffer to copy
  * @method: send method to be used
  * @dests: destination nodes for message.
- * @cong_link_cnt: returns number of encountered congested destination links
  * Returns 0 if success, otherwise errno
  */
 static int tipc_mcast_send_sync(struct net *net, struct sk_buff *skb,
                                struct tipc_mc_method *method,
-                               struct tipc_nlist *dests,
-                               u16 *cong_link_cnt)
+                               struct tipc_nlist *dests)
 {
        struct tipc_msg *hdr, *_hdr;
        struct sk_buff_head tmpq;
        struct sk_buff *_skb;
+       u16 cong_link_cnt;
+       int rc = 0;
 
        /* Is a cluster supporting with new capabilities ? */
        if (!(tipc_net(net)->capabilities & TIPC_MCAST_RBCTL))
@@ -343,18 +343,19 @@ static int tipc_mcast_send_sync(struct net *net, struct sk_buff *skb,
        _hdr = buf_msg(_skb);
        msg_set_size(_hdr, MCAST_H_SIZE);
        msg_set_is_rcast(_hdr, !msg_is_rcast(hdr));
+       msg_set_errcode(_hdr, TIPC_ERR_NO_PORT);
 
        __skb_queue_head_init(&tmpq);
        __skb_queue_tail(&tmpq, _skb);
        if (method->rcast)
-               tipc_bcast_xmit(net, &tmpq, cong_link_cnt);
+               rc = tipc_bcast_xmit(net, &tmpq, &cong_link_cnt);
        else
-               tipc_rcast_xmit(net, &tmpq, dests, cong_link_cnt);
+               rc = tipc_rcast_xmit(net, &tmpq, dests, &cong_link_cnt);
 
        /* This queue should normally be empty by now */
        __skb_queue_purge(&tmpq);
 
-       return 0;
+       return rc;
 }
 
 /* tipc_mcast_xmit - deliver message to indicated destination nodes
@@ -396,9 +397,14 @@ int tipc_mcast_xmit(struct net *net, struct sk_buff_head *pkts,
                msg_set_is_rcast(hdr, method->rcast);
 
                /* Switch method ? */
-               if (rcast != method->rcast)
-                       tipc_mcast_send_sync(net, skb, method,
-                                            dests, cong_link_cnt);
+               if (rcast != method->rcast) {
+                       rc = tipc_mcast_send_sync(net, skb, method, dests);
+                       if (unlikely(rc)) {
+                               pr_err("Unable to send SYN: method %d, rc %d\n",
+                                      rcast, rc);
+                               goto exit;
+                       }
+               }
 
                if (method->rcast)
                        rc = tipc_rcast_xmit(net, pkts, dests, cong_link_cnt);
index b043e8c..bfe43da 100644 (file)
@@ -194,6 +194,7 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb,
 {
        struct tipc_net *tn = tipc_net(net);
        struct tipc_msg *hdr = buf_msg(skb);
+       u32 pnet_hash = msg_peer_net_hash(hdr);
        u16 caps = msg_node_capabilities(hdr);
        bool legacy = tn->legacy_addr_format;
        u32 sugg = msg_sugg_node_addr(hdr);
@@ -242,9 +243,8 @@ void tipc_disc_rcv(struct net *net, struct sk_buff *skb,
                return;
        if (!tipc_in_scope(legacy, b->domain, src))
                return;
-       tipc_node_check_dest(net, src, peer_id, b, caps, signature,
-                            msg_peer_net_hash(hdr), &maddr, &respond,
-                            &dupl_addr);
+       tipc_node_check_dest(net, src, peer_id, b, caps, signature, pnet_hash,
+                            &maddr, &respond, &dupl_addr);
        if (dupl_addr)
                disc_dupl_alert(b, src, &maddr);
        if (!respond)
index 92d04dc..359b2bc 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <net/sock.h>
 #include <linux/list_sort.h>
+#include <linux/rbtree_augmented.h>
 #include "core.h"
 #include "netlink.h"
 #include "name_table.h"
@@ -51,6 +52,7 @@
  * @lower: service range lower bound
  * @upper: service range upper bound
  * @tree_node: member of service range RB tree
+ * @max: largest 'upper' in this node subtree
  * @local_publ: list of identical publications made from this node
  *   Used by closest_first lookup and multicast lookup algorithm
  * @all_publ: all publications identical to this one, whatever node and scope
@@ -60,6 +62,7 @@ struct service_range {
        u32 lower;
        u32 upper;
        struct rb_node tree_node;
+       u32 max;
        struct list_head local_publ;
        struct list_head all_publ;
 };
@@ -84,6 +87,130 @@ struct tipc_service {
        struct rcu_head rcu;
 };
 
+#define service_range_upper(sr) ((sr)->upper)
+RB_DECLARE_CALLBACKS_MAX(static, sr_callbacks,
+                        struct service_range, tree_node, u32, max,
+                        service_range_upper)
+
+#define service_range_entry(rbtree_node)                               \
+       (container_of(rbtree_node, struct service_range, tree_node))
+
+#define service_range_overlap(sr, start, end)                          \
+       ((sr)->lower <= (end) && (sr)->upper >= (start))
+
+/**
+ * service_range_foreach_match - iterate over tipc service rbtree for each
+ *                               range match
+ * @sr: the service range pointer as a loop cursor
+ * @sc: the pointer to tipc service which holds the service range rbtree
+ * @start, end: the range (end >= start) for matching
+ */
+#define service_range_foreach_match(sr, sc, start, end)                        \
+       for (sr = service_range_match_first((sc)->ranges.rb_node,       \
+                                           start,                      \
+                                           end);                       \
+            sr;                                                        \
+            sr = service_range_match_next(&(sr)->tree_node,            \
+                                          start,                       \
+                                          end))
+
+/**
+ * service_range_match_first - find first service range matching a range
+ * @n: the root node of service range rbtree for searching
+ * @start, end: the range (end >= start) for matching
+ *
+ * Return: the leftmost service range node in the rbtree that overlaps the
+ * specific range if any. Otherwise, returns NULL.
+ */
+static struct service_range *service_range_match_first(struct rb_node *n,
+                                                      u32 start, u32 end)
+{
+       struct service_range *sr;
+       struct rb_node *l, *r;
+
+       /* Non overlaps in tree at all? */
+       if (!n || service_range_entry(n)->max < start)
+               return NULL;
+
+       while (n) {
+               l = n->rb_left;
+               if (l && service_range_entry(l)->max >= start) {
+                       /* A leftmost overlap range node must be one in the left
+                        * subtree. If not, it has lower > end, then nodes on
+                        * the right side cannot satisfy the condition either.
+                        */
+                       n = l;
+                       continue;
+               }
+
+               /* No one in the left subtree can match, return if this node is
+                * an overlap i.e. leftmost.
+                */
+               sr = service_range_entry(n);
+               if (service_range_overlap(sr, start, end))
+                       return sr;
+
+               /* Ok, try to lookup on the right side */
+               r = n->rb_right;
+               if (sr->lower <= end &&
+                   r && service_range_entry(r)->max >= start) {
+                       n = r;
+                       continue;
+               }
+               break;
+       }
+
+       return NULL;
+}
+
+/**
+ * service_range_match_next - find next service range matching a range
+ * @n: a node in service range rbtree from which the searching starts
+ * @start, end: the range (end >= start) for matching
+ *
+ * Return: the next service range node to the given node in the rbtree that
+ * overlaps the specific range if any. Otherwise, returns NULL.
+ */
+static struct service_range *service_range_match_next(struct rb_node *n,
+                                                     u32 start, u32 end)
+{
+       struct service_range *sr;
+       struct rb_node *p, *r;
+
+       while (n) {
+               r = n->rb_right;
+               if (r && service_range_entry(r)->max >= start)
+                       /* A next overlap range node must be one in the right
+                        * subtree. If not, it has lower > end, then any next
+                        * successor (- an ancestor) of this node cannot
+                        * satisfy the condition either.
+                        */
+                       return service_range_match_first(r, start, end);
+
+               /* No one in the right subtree can match, go up to find an
+                * ancestor of this node which is parent of a left-hand child.
+                */
+               while ((p = rb_parent(n)) && n == p->rb_right)
+                       n = p;
+               if (!p)
+                       break;
+
+               /* Return if this ancestor is an overlap */
+               sr = service_range_entry(p);
+               if (service_range_overlap(sr, start, end))
+                       return sr;
+
+               /* Ok, try to lookup more from this ancestor */
+               if (sr->lower <= end) {
+                       n = p;
+                       continue;
+               }
+               break;
+       }
+
+       return NULL;
+}
+
 static int hash(int x)
 {
        return x & (TIPC_NAMETBL_SIZE - 1);
@@ -139,84 +266,51 @@ static struct tipc_service *tipc_service_create(u32 type, struct hlist_head *hd)
        return service;
 }
 
-/**
- * tipc_service_first_range - find first service range in tree matching instance
- *
- * Very time-critical, so binary search through range rb tree
- */
-static struct service_range *tipc_service_first_range(struct tipc_service *sc,
-                                                     u32 instance)
-{
-       struct rb_node *n = sc->ranges.rb_node;
-       struct service_range *sr;
-
-       while (n) {
-               sr = container_of(n, struct service_range, tree_node);
-               if (sr->lower > instance)
-                       n = n->rb_left;
-               else if (sr->upper < instance)
-                       n = n->rb_right;
-               else
-                       return sr;
-       }
-       return NULL;
-}
-
 /*  tipc_service_find_range - find service range matching publication parameters
  */
 static struct service_range *tipc_service_find_range(struct tipc_service *sc,
                                                     u32 lower, u32 upper)
 {
-       struct rb_node *n = sc->ranges.rb_node;
        struct service_range *sr;
 
-       sr = tipc_service_first_range(sc, lower);
-       if (!sr)
-               return NULL;
-
-       /* Look for exact match */
-       for (n = &sr->tree_node; n; n = rb_next(n)) {
-               sr = container_of(n, struct service_range, tree_node);
-               if (sr->upper == upper)
-                       break;
+       service_range_foreach_match(sr, sc, lower, upper) {
+               /* Look for exact match */
+               if (sr->lower == lower && sr->upper == upper)
+                       return sr;
        }
-       if (!n || sr->lower != lower || sr->upper != upper)
-               return NULL;
 
-       return sr;
+       return NULL;
 }
 
 static struct service_range *tipc_service_create_range(struct tipc_service *sc,
                                                       u32 lower, u32 upper)
 {
        struct rb_node **n, *parent = NULL;
-       struct service_range *sr, *tmp;
+       struct service_range *sr;
 
        n = &sc->ranges.rb_node;
        while (*n) {
-               tmp = container_of(*n, struct service_range, tree_node);
                parent = *n;
-               tmp = container_of(parent, struct service_range, tree_node);
-               if (lower < tmp->lower)
-                       n = &(*n)->rb_left;
-               else if (lower > tmp->lower)
-                       n = &(*n)->rb_right;
-               else if (upper < tmp->upper)
-                       n = &(*n)->rb_left;
-               else if (upper > tmp->upper)
-                       n = &(*n)->rb_right;
+               sr = service_range_entry(parent);
+               if (lower == sr->lower && upper == sr->upper)
+                       return sr;
+               if (sr->max < upper)
+                       sr->max = upper;
+               if (lower <= sr->lower)
+                       n = &parent->rb_left;
                else
-                       return tmp;
+                       n = &parent->rb_right;
        }
        sr = kzalloc(sizeof(*sr), GFP_ATOMIC);
        if (!sr)
                return NULL;
        sr->lower = lower;
        sr->upper = upper;
+       sr->max = upper;
        INIT_LIST_HEAD(&sr->local_publ);
        INIT_LIST_HEAD(&sr->all_publ);
        rb_link_node(&sr->tree_node, parent, n);
-       rb_insert_color(&sr->tree_node, &sc->ranges);
+       rb_insert_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
        return sr;
 }
 
@@ -310,7 +404,6 @@ static void tipc_service_subscribe(struct tipc_service *service,
        struct list_head publ_list;
        struct service_range *sr;
        struct tipc_name_seq ns;
-       struct rb_node *n;
        u32 filter;
 
        ns.type = tipc_sub_read(sb, seq.type);
@@ -325,13 +418,7 @@ static void tipc_service_subscribe(struct tipc_service *service,
                return;
 
        INIT_LIST_HEAD(&publ_list);
-       for (n = rb_first(&service->ranges); n; n = rb_next(n)) {
-               sr = container_of(n, struct service_range, tree_node);
-               if (sr->lower > ns.upper)
-                       break;
-               if (!tipc_sub_check_overlap(&ns, sr->lower, sr->upper))
-                       continue;
-
+       service_range_foreach_match(sr, service, ns.lower, ns.upper) {
                first = NULL;
                list_for_each_entry(p, &sr->all_publ, all_publ) {
                        if (filter & TIPC_SUB_PORTS)
@@ -425,7 +512,7 @@ struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,
 
        /* Remove service range item if this was its last publication */
        if (list_empty(&sr->all_publ)) {
-               rb_erase(&sr->tree_node, &sc->ranges);
+               rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
                kfree(sr);
        }
 
@@ -473,34 +560,39 @@ u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *dnode)
        rcu_read_lock();
        sc = tipc_service_find(net, type);
        if (unlikely(!sc))
-               goto not_found;
+               goto exit;
 
        spin_lock_bh(&sc->lock);
-       sr = tipc_service_first_range(sc, instance);
-       if (unlikely(!sr))
-               goto no_match;
-
-       /* Select lookup algorithm: local, closest-first or round-robin */
-       if (*dnode == self) {
-               list = &sr->local_publ;
-               if (list_empty(list))
-                       goto no_match;
-               p = list_first_entry(list, struct publication, local_publ);
-               list_move_tail(&p->local_publ, &sr->local_publ);
-       } else if (legacy && !*dnode && !list_empty(&sr->local_publ)) {
-               list = &sr->local_publ;
-               p = list_first_entry(list, struct publication, local_publ);
-               list_move_tail(&p->local_publ, &sr->local_publ);
-       } else {
-               list = &sr->all_publ;
-               p = list_first_entry(list, struct publication, all_publ);
-               list_move_tail(&p->all_publ, &sr->all_publ);
+       service_range_foreach_match(sr, sc, instance, instance) {
+               /* Select lookup algo: local, closest-first or round-robin */
+               if (*dnode == self) {
+                       list = &sr->local_publ;
+                       if (list_empty(list))
+                               continue;
+                       p = list_first_entry(list, struct publication,
+                                            local_publ);
+                       list_move_tail(&p->local_publ, &sr->local_publ);
+               } else if (legacy && !*dnode && !list_empty(&sr->local_publ)) {
+                       list = &sr->local_publ;
+                       p = list_first_entry(list, struct publication,
+                                            local_publ);
+                       list_move_tail(&p->local_publ, &sr->local_publ);
+               } else {
+                       list = &sr->all_publ;
+                       p = list_first_entry(list, struct publication,
+                                            all_publ);
+                       list_move_tail(&p->all_publ, &sr->all_publ);
+               }
+               port = p->port;
+               node = p->node;
+               /* Todo: as for legacy, pick the first matching range only, a
+                * "true" round-robin will be performed as needed.
+                */
+               break;
        }
-       port = p->port;
-       node = p->node;
-no_match:
        spin_unlock_bh(&sc->lock);
-not_found:
+
+exit:
        rcu_read_unlock();
        *dnode = node;
        return port;
@@ -523,7 +615,8 @@ bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 scope,
 
        spin_lock_bh(&sc->lock);
 
-       sr = tipc_service_first_range(sc, instance);
+       /* Todo: a full search i.e. service_range_foreach_match() instead? */
+       sr = service_range_match_first(sc->ranges.rb_node, instance, instance);
        if (!sr)
                goto no_match;
 
@@ -552,7 +645,6 @@ void tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper,
        struct service_range *sr;
        struct tipc_service *sc;
        struct publication *p;
-       struct rb_node *n;
 
        rcu_read_lock();
        sc = tipc_service_find(net, type);
@@ -560,13 +652,7 @@ void tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper,
                goto exit;
 
        spin_lock_bh(&sc->lock);
-
-       for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
-               sr = container_of(n, struct service_range, tree_node);
-               if (sr->upper < lower)
-                       continue;
-               if (sr->lower > upper)
-                       break;
+       service_range_foreach_match(sr, sc, lower, upper) {
                list_for_each_entry(p, &sr->local_publ, local_publ) {
                        if (p->scope == scope || (!exact && p->scope < scope))
                                tipc_dest_push(dports, 0, p->port);
@@ -587,7 +673,6 @@ void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
        struct service_range *sr;
        struct tipc_service *sc;
        struct publication *p;
-       struct rb_node *n;
 
        rcu_read_lock();
        sc = tipc_service_find(net, type);
@@ -595,13 +680,7 @@ void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
                goto exit;
 
        spin_lock_bh(&sc->lock);
-
-       for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
-               sr = container_of(n, struct service_range, tree_node);
-               if (sr->upper < lower)
-                       continue;
-               if (sr->lower > upper)
-                       break;
+       service_range_foreach_match(sr, sc, lower, upper) {
                list_for_each_entry(p, &sr->all_publ, all_publ) {
                        tipc_nlist_add(nodes, p->node);
                }
@@ -799,7 +878,7 @@ static void tipc_service_delete(struct net *net, struct tipc_service *sc)
                        tipc_service_remove_publ(sr, p->node, p->key);
                        kfree_rcu(p, rcu);
                }
-               rb_erase(&sr->tree_node, &sc->ranges);
+               rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
                kfree(sr);
        }
        hlist_del_init_rcu(&sc->service_list);
index 0254bb7..2175163 100644 (file)
@@ -204,8 +204,8 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
                return -ENOMEM;
        }
 
-       attrbuf = kmalloc_array(tipc_genl_family.maxattr + 1,
-                               sizeof(struct nlattr *), GFP_KERNEL);
+       attrbuf = kcalloc(tipc_genl_family.maxattr + 1,
+                         sizeof(struct nlattr *), GFP_KERNEL);
        if (!attrbuf) {
                err = -ENOMEM;
                goto err_out;
index 41688da..f9b4fb9 100644 (file)
@@ -287,12 +287,12 @@ static void tipc_sk_respond(struct sock *sk, struct sk_buff *skb, int err)
  *
  * Caller must hold socket lock
  */
-static void tsk_rej_rx_queue(struct sock *sk)
+static void tsk_rej_rx_queue(struct sock *sk, int error)
 {
        struct sk_buff *skb;
 
        while ((skb = __skb_dequeue(&sk->sk_receive_queue)))
-               tipc_sk_respond(sk, skb, TIPC_ERR_NO_PORT);
+               tipc_sk_respond(sk, skb, error);
 }
 
 static bool tipc_sk_connected(struct sock *sk)
@@ -545,34 +545,45 @@ static void __tipc_shutdown(struct socket *sock, int error)
        /* Remove pending SYN */
        __skb_queue_purge(&sk->sk_write_queue);
 
-       /* Reject all unreceived messages, except on an active connection
-        * (which disconnects locally & sends a 'FIN+' to peer).
-        */
-       while ((skb = __skb_dequeue(&sk->sk_receive_queue)) != NULL) {
-               if (TIPC_SKB_CB(skb)->bytes_read) {
-                       kfree_skb(skb);
-                       continue;
-               }
-               if (!tipc_sk_type_connectionless(sk) &&
-                   sk->sk_state != TIPC_DISCONNECTING) {
-                       tipc_set_sk_state(sk, TIPC_DISCONNECTING);
-                       tipc_node_remove_conn(net, dnode, tsk->portid);
-               }
-               tipc_sk_respond(sk, skb, error);
+       /* Remove partially received buffer if any */
+       skb = skb_peek(&sk->sk_receive_queue);
+       if (skb && TIPC_SKB_CB(skb)->bytes_read) {
+               __skb_unlink(skb, &sk->sk_receive_queue);
+               kfree_skb(skb);
        }
 
-       if (tipc_sk_type_connectionless(sk))
+       /* Reject all unreceived messages if connectionless */
+       if (tipc_sk_type_connectionless(sk)) {
+               tsk_rej_rx_queue(sk, error);
                return;
+       }
 
-       if (sk->sk_state != TIPC_DISCONNECTING) {
+       switch (sk->sk_state) {
+       case TIPC_CONNECTING:
+       case TIPC_ESTABLISHED:
+               tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+               tipc_node_remove_conn(net, dnode, tsk->portid);
+               /* Send a FIN+/- to its peer */
+               skb = __skb_dequeue(&sk->sk_receive_queue);
+               if (skb) {
+                       __skb_queue_purge(&sk->sk_receive_queue);
+                       tipc_sk_respond(sk, skb, error);
+                       break;
+               }
                skb = tipc_msg_create(TIPC_CRITICAL_IMPORTANCE,
                                      TIPC_CONN_MSG, SHORT_H_SIZE, 0, dnode,
                                      tsk_own_node(tsk), tsk_peer_port(tsk),
                                      tsk->portid, error);
                if (skb)
                        tipc_node_xmit_skb(net, skb, dnode, tsk->portid);
-               tipc_node_remove_conn(net, dnode, tsk->portid);
-               tipc_set_sk_state(sk, TIPC_DISCONNECTING);
+               break;
+       case TIPC_LISTEN:
+               /* Reject all SYN messages */
+               tsk_rej_rx_queue(sk, error);
+               break;
+       default:
+               __skb_queue_purge(&sk->sk_receive_queue);
+               break;
        }
 }
 
@@ -1364,8 +1375,8 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
        struct tipc_msg *hdr = &tsk->phdr;
        struct tipc_name_seq *seq;
        struct sk_buff_head pkts;
-       u32 dport, dnode = 0;
-       u32 type, inst;
+       u32 dport = 0, dnode = 0;
+       u32 type = 0, inst = 0;
        int mtu, rc;
 
        if (unlikely(dlen > TIPC_MAX_USER_MSG_SIZE))
@@ -1418,23 +1429,11 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
                type = dest->addr.name.name.type;
                inst = dest->addr.name.name.instance;
                dnode = dest->addr.name.domain;
-               msg_set_type(hdr, TIPC_NAMED_MSG);
-               msg_set_hdr_sz(hdr, NAMED_H_SIZE);
-               msg_set_nametype(hdr, type);
-               msg_set_nameinst(hdr, inst);
-               msg_set_lookup_scope(hdr, tipc_node2scope(dnode));
                dport = tipc_nametbl_translate(net, type, inst, &dnode);
-               msg_set_destnode(hdr, dnode);
-               msg_set_destport(hdr, dport);
                if (unlikely(!dport && !dnode))
                        return -EHOSTUNREACH;
        } else if (dest->addrtype == TIPC_ADDR_ID) {
                dnode = dest->addr.id.node;
-               msg_set_type(hdr, TIPC_DIRECT_MSG);
-               msg_set_lookup_scope(hdr, 0);
-               msg_set_destnode(hdr, dnode);
-               msg_set_destport(hdr, dest->addr.id.ref);
-               msg_set_hdr_sz(hdr, BASIC_H_SIZE);
        } else {
                return -EINVAL;
        }
@@ -1445,6 +1444,22 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
        if (unlikely(rc))
                return rc;
 
+       if (dest->addrtype == TIPC_ADDR_NAME) {
+               msg_set_type(hdr, TIPC_NAMED_MSG);
+               msg_set_hdr_sz(hdr, NAMED_H_SIZE);
+               msg_set_nametype(hdr, type);
+               msg_set_nameinst(hdr, inst);
+               msg_set_lookup_scope(hdr, tipc_node2scope(dnode));
+               msg_set_destnode(hdr, dnode);
+               msg_set_destport(hdr, dport);
+       } else { /* TIPC_ADDR_ID */
+               msg_set_type(hdr, TIPC_DIRECT_MSG);
+               msg_set_lookup_scope(hdr, 0);
+               msg_set_destnode(hdr, dnode);
+               msg_set_destport(hdr, dest->addr.id.ref);
+               msg_set_hdr_sz(hdr, BASIC_H_SIZE);
+       }
+
        __skb_queue_head_init(&pkts);
        mtu = tipc_node_get_mtu(net, dnode, tsk->portid, false);
        rc = tipc_msg_build(hdr, m, 0, dlen, mtu, &pkts);
@@ -2428,8 +2443,8 @@ static int tipc_wait_for_connect(struct socket *sock, long *timeo_p)
                        return sock_intr_errno(*timeo_p);
 
                add_wait_queue(sk_sleep(sk), &wait);
-               done = sk_wait_event(sk, timeo_p,
-                                    sk->sk_state != TIPC_CONNECTING, &wait);
+               done = sk_wait_event(sk, timeo_p, tipc_sk_connected(sk),
+                                    &wait);
                remove_wait_queue(sk_sleep(sk), &wait);
        } while (!done);
        return 0;
@@ -2639,7 +2654,7 @@ static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags,
         * Reject any stray messages received by new socket
         * before the socket lock was taken (very, very unlikely)
         */
-       tsk_rej_rx_queue(new_sk);
+       tsk_rej_rx_queue(new_sk, TIPC_ERR_NO_PORT);
 
        /* Connect new socket to it's peer */
        tipc_sk_finish_conn(new_tsock, msg_origport(msg), msg_orignode(msg));
index dac24c7..94774c0 100644 (file)
@@ -732,15 +732,19 @@ out:
        return rc;
 }
 
-static void tls_update(struct sock *sk, struct proto *p)
+static void tls_update(struct sock *sk, struct proto *p,
+                      void (*write_space)(struct sock *sk))
 {
        struct tls_context *ctx;
 
        ctx = tls_get_ctx(sk);
-       if (likely(ctx))
+       if (likely(ctx)) {
+               ctx->sk_write_space = write_space;
                ctx->sk_proto = p;
-       else
+       } else {
                sk->sk_prot = p;
+               sk->sk_write_space = write_space;
+       }
 }
 
 static int tls_get_info(const struct sock *sk, struct sk_buff *skb)
index c6803a8..c98e602 100644 (file)
@@ -256,8 +256,6 @@ static int tls_do_decryption(struct sock *sk,
                        return ret;
 
                ret = crypto_wait_req(ret, &ctx->async_wait);
-       } else if (ret == -EBADMSG) {
-               TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSDECRYPTERROR);
        }
 
        if (async)
@@ -682,12 +680,32 @@ static int tls_push_record(struct sock *sk, int flags,
 
        split_point = msg_pl->apply_bytes;
        split = split_point && split_point < msg_pl->sg.size;
+       if (unlikely((!split &&
+                     msg_pl->sg.size +
+                     prot->overhead_size > msg_en->sg.size) ||
+                    (split &&
+                     split_point +
+                     prot->overhead_size > msg_en->sg.size))) {
+               split = true;
+               split_point = msg_en->sg.size;
+       }
        if (split) {
                rc = tls_split_open_record(sk, rec, &tmp, msg_pl, msg_en,
                                           split_point, prot->overhead_size,
                                           &orig_end);
                if (rc < 0)
                        return rc;
+               /* This can happen if above tls_split_open_record allocates
+                * a single large encryption buffer instead of two smaller
+                * ones. In this case adjust pointers and continue without
+                * split.
+                */
+               if (!msg_pl->sg.size) {
+                       tls_merge_open_record(sk, rec, tmp, orig_end);
+                       msg_pl = &rec->msg_plaintext;
+                       msg_en = &rec->msg_encrypted;
+                       split = false;
+               }
                sk_msg_trim(sk, msg_en, msg_pl->sg.size +
                            prot->overhead_size);
        }
@@ -709,6 +727,12 @@ static int tls_push_record(struct sock *sk, int flags,
                sg_mark_end(sk_msg_elem(msg_pl, i));
        }
 
+       if (msg_pl->sg.end < msg_pl->sg.start) {
+               sg_chain(&msg_pl->sg.data[msg_pl->sg.start],
+                        MAX_SKB_FRAGS - msg_pl->sg.start + 1,
+                        msg_pl->sg.data);
+       }
+
        i = msg_pl->sg.start;
        sg_chain(rec->sg_aead_in, 2, &msg_pl->sg.data[i]);
 
@@ -772,7 +796,7 @@ static int bpf_exec_tx_verdict(struct sk_msg *msg, struct sock *sk,
        psock = sk_psock_get(sk);
        if (!psock || !policy) {
                err = tls_push_record(sk, flags, record_type);
-               if (err) {
+               if (err && err != -EINPROGRESS) {
                        *copied -= sk_msg_free(sk, msg);
                        tls_free_open_rec(sk);
                }
@@ -783,10 +807,7 @@ more_data:
        if (psock->eval == __SK_NONE) {
                delta = msg->sg.size;
                psock->eval = sk_psock_msg_verdict(sk, psock, msg);
-               if (delta < msg->sg.size)
-                       delta -= msg->sg.size;
-               else
-                       delta = 0;
+               delta -= msg->sg.size;
        }
        if (msg->cork_bytes && msg->cork_bytes > msg->sg.size &&
            !enospc && !full_record) {
@@ -801,7 +822,7 @@ more_data:
        switch (psock->eval) {
        case __SK_PASS:
                err = tls_push_record(sk, flags, record_type);
-               if (err < 0) {
+               if (err && err != -EINPROGRESS) {
                        *copied -= sk_msg_free(sk, msg);
                        tls_free_open_rec(sk);
                        goto out_err;
@@ -1515,7 +1536,9 @@ static int decrypt_skb_update(struct sock *sk, struct sk_buff *skb,
                                if (err == -EINPROGRESS)
                                        tls_advance_record_sn(sk, prot,
                                                              &tls_ctx->rx);
-
+                               else if (err == -EBADMSG)
+                                       TLS_INC_STATS(sock_net(sk),
+                                                     LINUX_MIB_TLSDECRYPTERROR);
                                return err;
                        }
                } else {
index 7cfdce1..774babb 100644 (file)
@@ -2865,7 +2865,7 @@ static int __init af_unix_init(void)
 {
        int rc = -1;
 
-       BUILD_BUG_ON(sizeof(struct unix_skb_parms) > FIELD_SIZEOF(struct sk_buff, cb));
+       BUILD_BUG_ON(sizeof(struct unix_skb_parms) > sizeof_field(struct sk_buff, cb));
 
        rc = proto_register(&unix_proto, 1);
        if (rc != 0) {
index b3bdae7..3492c02 100644 (file)
@@ -138,28 +138,15 @@ struct hvsock {
  ****************************************************************************
  * The only valid Service GUIDs, from the perspectives of both the host and *
  * Linux VM, that can be connected by the other end, must conform to this   *
- * format: <port>-facb-11e6-bd58-64006a7986d3, and the "port" must be in    *
- * this range [0, 0x7FFFFFFF].                                              *
+ * format: <port>-facb-11e6-bd58-64006a7986d3.                              *
  ****************************************************************************
  *
  * When we write apps on the host to connect(), the GUID ServiceID is used.
  * When we write apps in Linux VM to connect(), we only need to specify the
  * port and the driver will form the GUID and use that to request the host.
  *
- * From the perspective of Linux VM:
- * 1. the local ephemeral port (i.e. the local auto-bound port when we call
- * connect() without explicit bind()) is generated by __vsock_bind_stream(),
- * and the range is [1024, 0xFFFFFFFF).
- * 2. the remote ephemeral port (i.e. the auto-generated remote port for
- * a connect request initiated by the host's connect()) is generated by
- * hvs_remote_addr_init() and the range is [0x80000000, 0xFFFFFFFF).
  */
 
-#define MAX_LISTEN_PORT                        ((u32)0x7FFFFFFF)
-#define MAX_VM_LISTEN_PORT             MAX_LISTEN_PORT
-#define MAX_HOST_LISTEN_PORT           MAX_LISTEN_PORT
-#define MIN_HOST_EPHEMERAL_PORT                (MAX_HOST_LISTEN_PORT + 1)
-
 /* 00000000-facb-11e6-bd58-64006a7986d3 */
 static const guid_t srv_id_template =
        GUID_INIT(0x00000000, 0xfacb, 0x11e6, 0xbd, 0x58,
@@ -184,34 +171,6 @@ static void hvs_addr_init(struct sockaddr_vm *addr, const guid_t *svr_id)
        vsock_addr_init(addr, VMADDR_CID_ANY, port);
 }
 
-static void hvs_remote_addr_init(struct sockaddr_vm *remote,
-                                struct sockaddr_vm *local)
-{
-       static u32 host_ephemeral_port = MIN_HOST_EPHEMERAL_PORT;
-       struct sock *sk;
-
-       /* Remote peer is always the host */
-       vsock_addr_init(remote, VMADDR_CID_HOST, VMADDR_PORT_ANY);
-
-       while (1) {
-               /* Wrap around ? */
-               if (host_ephemeral_port < MIN_HOST_EPHEMERAL_PORT ||
-                   host_ephemeral_port == VMADDR_PORT_ANY)
-                       host_ephemeral_port = MIN_HOST_EPHEMERAL_PORT;
-
-               remote->svm_port = host_ephemeral_port++;
-
-               sk = vsock_find_connected_socket(remote, local);
-               if (!sk) {
-                       /* Found an available ephemeral port */
-                       return;
-               }
-
-               /* Release refcnt got in vsock_find_connected_socket */
-               sock_put(sk);
-       }
-}
-
 static void hvs_set_channel_pending_send_size(struct vmbus_channel *chan)
 {
        set_channel_pending_send_size(chan,
@@ -341,12 +300,7 @@ static void hvs_open_connection(struct vmbus_channel *chan)
        if_type = &chan->offermsg.offer.if_type;
        if_instance = &chan->offermsg.offer.if_instance;
        conn_from_host = chan->offermsg.offer.u.pipe.user_def[0];
-
-       /* The host or the VM should only listen on a port in
-        * [0, MAX_LISTEN_PORT]
-        */
-       if (!is_valid_srv_id(if_type) ||
-           get_port_by_srv_id(if_type) > MAX_LISTEN_PORT)
+       if (!is_valid_srv_id(if_type))
                return;
 
        hvs_addr_init(&addr, conn_from_host ? if_type : if_instance);
@@ -371,8 +325,11 @@ static void hvs_open_connection(struct vmbus_channel *chan)
                vnew = vsock_sk(new);
 
                hvs_addr_init(&vnew->local_addr, if_type);
-               hvs_remote_addr_init(&vnew->remote_addr, &vnew->local_addr);
 
+               /* Remote peer is always the host */
+               vsock_addr_init(&vnew->remote_addr,
+                               VMADDR_CID_HOST, VMADDR_PORT_ANY);
+               vnew->remote_addr.svm_port = get_port_by_srv_id(if_instance);
                ret = vsock_assign_transport(vnew, vsock_sk(sk));
                /* Transport assigned (looking at remote_addr) must be the
                 * same where we received the request.
@@ -766,16 +723,6 @@ static bool hvs_stream_is_active(struct vsock_sock *vsk)
 
 static bool hvs_stream_allow(u32 cid, u32 port)
 {
-       /* The host's port range [MIN_HOST_EPHEMERAL_PORT, 0xFFFFFFFF) is
-        * reserved as ephemeral ports, which are used as the host's ports
-        * when the host initiates connections.
-        *
-        * Perform this check in the guest so an immediate error is produced
-        * instead of a timeout.
-        */
-       if (port > MAX_HOST_LISTEN_PORT)
-               return false;
-
        if (cid == VMADDR_CID_HOST)
                return true;
 
index e5ea29c..6abec3f 100644 (file)
@@ -34,6 +34,9 @@ virtio_transport_get_ops(struct vsock_sock *vsk)
 {
        const struct vsock_transport *t = vsock_core_get_transport(vsk);
 
+       if (WARN_ON(!t))
+               return NULL;
+
        return container_of(t, struct virtio_transport, transport);
 }
 
@@ -161,15 +164,25 @@ void virtio_transport_deliver_tap_pkt(struct virtio_vsock_pkt *pkt)
 }
 EXPORT_SYMBOL_GPL(virtio_transport_deliver_tap_pkt);
 
+/* This function can only be used on connecting/connected sockets,
+ * since a socket assigned to a transport is required.
+ *
+ * Do not use on listener sockets!
+ */
 static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
                                          struct virtio_vsock_pkt_info *info)
 {
        u32 src_cid, src_port, dst_cid, dst_port;
+       const struct virtio_transport *t_ops;
        struct virtio_vsock_sock *vvs;
        struct virtio_vsock_pkt *pkt;
        u32 pkt_len = info->pkt_len;
 
-       src_cid = virtio_transport_get_ops(vsk)->transport.get_local_cid();
+       t_ops = virtio_transport_get_ops(vsk);
+       if (unlikely(!t_ops))
+               return -EFAULT;
+
+       src_cid = t_ops->transport.get_local_cid();
        src_port = vsk->local_addr.svm_port;
        if (!info->remote_cid) {
                dst_cid = vsk->remote_addr.svm_cid;
@@ -202,7 +215,7 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk,
 
        virtio_transport_inc_tx_pkt(vvs, pkt);
 
-       return virtio_transport_get_ops(vsk)->send_pkt(pkt);
+       return t_ops->send_pkt(pkt);
 }
 
 static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,
@@ -1021,18 +1034,18 @@ virtio_transport_recv_listen(struct sock *sk, struct virtio_vsock_pkt *pkt,
        int ret;
 
        if (le16_to_cpu(pkt->hdr.op) != VIRTIO_VSOCK_OP_REQUEST) {
-               virtio_transport_reset(vsk, pkt);
+               virtio_transport_reset_no_sock(t, pkt);
                return -EINVAL;
        }
 
        if (sk_acceptq_is_full(sk)) {
-               virtio_transport_reset(vsk, pkt);
+               virtio_transport_reset_no_sock(t, pkt);
                return -ENOMEM;
        }
 
        child = vsock_create_connected(sk);
        if (!child) {
-               virtio_transport_reset(vsk, pkt);
+               virtio_transport_reset_no_sock(t, pkt);
                return -ENOMEM;
        }
 
@@ -1054,7 +1067,7 @@ virtio_transport_recv_listen(struct sock *sk, struct virtio_vsock_pkt *pkt,
         */
        if (ret || vchild->transport != &t->transport) {
                release_sock(child);
-               virtio_transport_reset(vsk, pkt);
+               virtio_transport_reset_no_sock(t, pkt);
                sock_put(child);
                return ret;
        }
index 3505137..3e25229 100644 (file)
@@ -1102,6 +1102,7 @@ static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
 
 #ifdef CONFIG_CFG80211_WEXT
        kzfree(wdev->wext.keys);
+       wdev->wext.keys = NULL;
 #endif
        /* only initialized if we have a netdev */
        if (wdev->netdev)
index da5262b..1e97ac5 100644 (file)
@@ -10843,6 +10843,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev,
                if (err)
                        return err;
 
+               cfg80211_sinfo_release_content(&sinfo);
                if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG))
                        wdev->cqm_config->last_rssi_event_value =
                                (s8) sinfo.rx_beacon_signal_avg;
@@ -13796,6 +13797,8 @@ static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
        if (err)
                return err;
 
+       cfg80211_sinfo_release_content(&sinfo);
+
        return rdev_probe_mesh_link(rdev, dev, dest, buf, len);
 }
 
index e853a4f..e0d34f7 100644 (file)
@@ -538,6 +538,10 @@ static inline int
 rdev_set_wiphy_params(struct cfg80211_registered_device *rdev, u32 changed)
 {
        int ret;
+
+       if (!rdev->ops->set_wiphy_params)
+               return -EOPNOTSUPP;
+
        trace_rdev_set_wiphy_params(&rdev->wiphy, changed);
        ret = rdev->ops->set_wiphy_params(&rdev->wiphy, changed);
        trace_rdev_return_int(&rdev->wiphy, ret);
@@ -1167,6 +1171,16 @@ rdev_start_radar_detection(struct cfg80211_registered_device *rdev,
        return ret;
 }
 
+static inline void
+rdev_end_cac(struct cfg80211_registered_device *rdev,
+            struct net_device *dev)
+{
+       trace_rdev_end_cac(&rdev->wiphy, dev);
+       if (rdev->ops->end_cac)
+               rdev->ops->end_cac(&rdev->wiphy, dev);
+       trace_rdev_return_void(&rdev->wiphy);
+}
+
 static inline int
 rdev_set_mcast_rate(struct cfg80211_registered_device *rdev,
                    struct net_device *dev,
index 446c76d..fff9a74 100644 (file)
@@ -2261,14 +2261,15 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
 
 static void handle_channel_custom(struct wiphy *wiphy,
                                  struct ieee80211_channel *chan,
-                                 const struct ieee80211_regdomain *regd)
+                                 const struct ieee80211_regdomain *regd,
+                                 u32 min_bw)
 {
        u32 bw_flags = 0;
        const struct ieee80211_reg_rule *reg_rule = NULL;
        const struct ieee80211_power_rule *power_rule = NULL;
        u32 bw;
 
-       for (bw = MHZ_TO_KHZ(20); bw >= MHZ_TO_KHZ(5); bw = bw / 2) {
+       for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) {
                reg_rule = freq_reg_info_regd(MHZ_TO_KHZ(chan->center_freq),
                                              regd, bw);
                if (!IS_ERR(reg_rule))
@@ -2324,8 +2325,14 @@ static void handle_band_custom(struct wiphy *wiphy,
        if (!sband)
                return;
 
+       /*
+        * We currently assume that you always want at least 20 MHz,
+        * otherwise channel 12 might get enabled if this rule is
+        * compatible to US, which permits 2402 - 2472 MHz.
+        */
        for (i = 0; i < sband->n_channels; i++)
-               handle_channel_custom(wiphy, &sband->channels[i], regd);
+               handle_channel_custom(wiphy, &sband->channels[i], regd,
+                                     MHZ_TO_KHZ(20));
 }
 
 /* Used by drivers prior to wiphy registration */
@@ -3885,6 +3892,25 @@ bool regulatory_pre_cac_allowed(struct wiphy *wiphy)
 }
 EXPORT_SYMBOL(regulatory_pre_cac_allowed);
 
+static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
+{
+       struct wireless_dev *wdev;
+       /* If we finished CAC or received radar, we should end any
+        * CAC running on the same channels.
+        * the check !cfg80211_chandef_dfs_usable contain 2 options:
+        * either all channels are available - those the CAC_FINISHED
+        * event has effected another wdev state, or there is a channel
+        * in unavailable state in wdev chandef - those the RADAR_DETECTED
+        * event has effected another wdev state.
+        * In both cases we should end the CAC on the wdev.
+        */
+       list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+               if (wdev->cac_started &&
+                   !cfg80211_chandef_dfs_usable(&rdev->wiphy, &wdev->chandef))
+                       rdev_end_cac(rdev, wdev->netdev);
+       }
+}
+
 void regulatory_propagate_dfs_state(struct wiphy *wiphy,
                                    struct cfg80211_chan_def *chandef,
                                    enum nl80211_dfs_state dfs_state,
@@ -3911,8 +3937,10 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
                cfg80211_set_dfs_state(&rdev->wiphy, chandef, dfs_state);
 
                if (event == NL80211_RADAR_DETECTED ||
-                   event == NL80211_RADAR_CAC_FINISHED)
+                   event == NL80211_RADAR_CAC_FINISHED) {
                        cfg80211_sched_dfs_chan_update(rdev);
+                       cfg80211_check_and_end_cac(rdev);
+               }
 
                nl80211_radar_notify(rdev, chandef, event, NULL, GFP_KERNEL);
        }
index 7a6c38d..d32a2ec 100644 (file)
@@ -1307,14 +1307,14 @@ void cfg80211_autodisconnect_wk(struct work_struct *work)
        if (wdev->conn_owner_nlportid) {
                switch (wdev->iftype) {
                case NL80211_IFTYPE_ADHOC:
-                       cfg80211_leave_ibss(rdev, wdev->netdev, false);
+                       __cfg80211_leave_ibss(rdev, wdev->netdev, false);
                        break;
                case NL80211_IFTYPE_AP:
                case NL80211_IFTYPE_P2P_GO:
-                       cfg80211_stop_ap(rdev, wdev->netdev, false);
+                       __cfg80211_stop_ap(rdev, wdev->netdev, false);
                        break;
                case NL80211_IFTYPE_MESH_POINT:
-                       cfg80211_leave_mesh(rdev, wdev->netdev);
+                       __cfg80211_leave_mesh(rdev, wdev->netdev);
                        break;
                case NL80211_IFTYPE_STATION:
                case NL80211_IFTYPE_P2P_CLIENT:
index d98ad2b..8677d7a 100644 (file)
@@ -646,6 +646,11 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
        TP_ARGS(wiphy, netdev)
 );
 
+DEFINE_EVENT(wiphy_netdev_evt, rdev_end_cac,
+            TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
+            TP_ARGS(wiphy, netdev)
+);
+
 DECLARE_EVENT_CLASS(station_add_change,
        TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u8 *mac,
                 struct station_parameters *params),
index 5b4ed5b..8481e9a 100644 (file)
@@ -564,7 +564,7 @@ __frame_add_frag(struct sk_buff *skb, struct page *page,
        struct skb_shared_info *sh = skb_shinfo(skb);
        int page_offset;
 
-       page_ref_inc(page);
+       get_page(page);
        page_offset = ptr - page_address(page);
        skb_add_rx_frag(skb, sh->nr_frags, page, page_offset, len, size);
 }
index 5e677da..69102fd 100644 (file)
@@ -657,7 +657,8 @@ struct iw_statistics *get_wireless_stats(struct net_device *dev)
        return NULL;
 }
 
-static int iw_handler_get_iwstats(struct net_device *          dev,
+/* noinline to avoid a bogus warning with -O3 */
+static noinline int iw_handler_get_iwstats(struct net_device * dev,
                                  struct iw_request_info *      info,
                                  union iwreq_data *            wrqu,
                                  char *                        extra)
index c34f7d0..d5b09bb 100644 (file)
@@ -659,6 +659,12 @@ static int x25_release(struct socket *sock)
                        sock_set_flag(sk, SOCK_DEAD);
                        sock_set_flag(sk, SOCK_DESTROY);
                        break;
+
+               case X25_STATE_5:
+                       x25_write_internal(sk, X25_CLEAR_REQUEST);
+                       x25_disconnect(sk, 0, 0, 0);
+                       __x25_destroy_socket(sk);
+                       goto out;
        }
 
        sock_orphan(sk);
@@ -760,6 +766,10 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
        if (sk->sk_state == TCP_ESTABLISHED)
                goto out;
 
+       rc = -EALREADY; /* Do nothing if call is already in progress */
+       if (sk->sk_state == TCP_SYN_SENT)
+               goto out;
+
        sk->sk_state   = TCP_CLOSE;
        sock->state = SS_UNCONNECTED;
 
@@ -806,7 +816,7 @@ static int x25_connect(struct socket *sock, struct sockaddr *uaddr,
        /* Now the loop */
        rc = -EINPROGRESS;
        if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK))
-               goto out_put_neigh;
+               goto out;
 
        rc = x25_wait_for_connection_establishment(sk);
        if (rc)
@@ -1054,6 +1064,8 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb,
        if (test_bit(X25_ACCPT_APPRV_FLAG, &makex25->flags)) {
                x25_write_internal(make, X25_CALL_ACCEPTED);
                makex25->state = X25_STATE_3;
+       } else {
+               makex25->state = X25_STATE_5;
        }
 
        /*
index f97c433..4d3bb46 100644 (file)
@@ -382,6 +382,35 @@ out_clear:
        return 0;
 }
 
+/*
+ * State machine for state 5, Call Accepted / Call Connected pending (X25_ACCPT_APPRV_FLAG).
+ * The handling of the timer(s) is in file x25_timer.c
+ * Handling of state 0 and connection release is in af_x25.c.
+ */
+static int x25_state5_machine(struct sock *sk, struct sk_buff *skb, int frametype)
+{
+       struct x25_sock *x25 = x25_sk(sk);
+
+       switch (frametype) {
+               case X25_CLEAR_REQUEST:
+                       if (!pskb_may_pull(skb, X25_STD_MIN_LEN + 2)) {
+                               x25_write_internal(sk, X25_CLEAR_REQUEST);
+                               x25->state = X25_STATE_2;
+                               x25_start_t23timer(sk);
+                               return 0;
+                       }
+
+                       x25_write_internal(sk, X25_CLEAR_CONFIRMATION);
+                       x25_disconnect(sk, 0, skb->data[3], skb->data[4]);
+                       break;
+
+               default:
+                       break;
+       }
+
+       return 0;
+}
+
 /* Higher level upcall for a LAPB frame */
 int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
 {
@@ -406,6 +435,9 @@ int x25_process_rx_frame(struct sock *sk, struct sk_buff *skb)
        case X25_STATE_4:
                queued = x25_state4_machine(sk, skb, frametype);
                break;
+       case X25_STATE_5:
+               queued = x25_state5_machine(sk, skb, frametype);
+               break;
        }
 
        x25_kick(sk);
index 9567938..328f661 100644 (file)
@@ -334,12 +334,21 @@ out:
 }
 EXPORT_SYMBOL(xsk_umem_consume_tx);
 
-static int xsk_zc_xmit(struct xdp_sock *xs)
+static int xsk_wakeup(struct xdp_sock *xs, u8 flags)
 {
        struct net_device *dev = xs->dev;
+       int err;
+
+       rcu_read_lock();
+       err = dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id, flags);
+       rcu_read_unlock();
+
+       return err;
+}
 
-       return dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id,
-                                              XDP_WAKEUP_TX);
+static int xsk_zc_xmit(struct xdp_sock *xs)
+{
+       return xsk_wakeup(xs, XDP_WAKEUP_TX);
 }
 
 static void xsk_destruct_skb(struct sk_buff *skb)
@@ -453,19 +462,16 @@ static __poll_t xsk_poll(struct file *file, struct socket *sock,
        __poll_t mask = datagram_poll(file, sock, wait);
        struct sock *sk = sock->sk;
        struct xdp_sock *xs = xdp_sk(sk);
-       struct net_device *dev;
        struct xdp_umem *umem;
 
        if (unlikely(!xsk_is_bound(xs)))
                return mask;
 
-       dev = xs->dev;
        umem = xs->umem;
 
        if (umem->need_wakeup) {
-               if (dev->netdev_ops->ndo_xsk_wakeup)
-                       dev->netdev_ops->ndo_xsk_wakeup(dev, xs->queue_id,
-                                                       umem->need_wakeup);
+               if (xs->zc)
+                       xsk_wakeup(xs, umem->need_wakeup);
                else
                        /* Poll needs to drive Tx also in copy mode */
                        __xsk_sendmsg(sk);
index 1d78819..630ce8c 100644 (file)
@@ -47,13 +47,27 @@ static __always_inline void count(void *map)
 SEC("tracepoint/syscalls/sys_enter_open")
 int trace_enter_open(struct syscalls_enter_open_args *ctx)
 {
-       count((void *)&enter_open_map);
+       count(&enter_open_map);
+       return 0;
+}
+
+SEC("tracepoint/syscalls/sys_enter_openat")
+int trace_enter_open_at(struct syscalls_enter_open_args *ctx)
+{
+       count(&enter_open_map);
        return 0;
 }
 
 SEC("tracepoint/syscalls/sys_exit_open")
 int trace_enter_exit(struct syscalls_exit_open_args *ctx)
 {
-       count((void *)&exit_open_map);
+       count(&exit_open_map);
+       return 0;
+}
+
+SEC("tracepoint/syscalls/sys_exit_openat")
+int trace_enter_exit_at(struct syscalls_exit_open_args *ctx)
+{
+       count(&exit_open_map);
        return 0;
 }
index 16a16ea..749a50f 100644 (file)
@@ -37,9 +37,9 @@ static void print_ksym(__u64 addr)
        }
 
        printf("%s;", sym->name);
-       if (!strcmp(sym->name, "sys_read"))
+       if (!strstr(sym->name, "sys_read"))
                sys_read_seen = true;
-       else if (!strcmp(sym->name, "sys_write"))
+       else if (!strstr(sym->name, "sys_write"))
                sys_write_seen = true;
 }
 
index 6d0125c..20291ec 100644 (file)
@@ -298,14 +298,14 @@ int main(void)
                req = malloc(sizes.seccomp_notif);
                if (!req)
                        goto out_close;
-               memset(req, 0, sizeof(*req));
 
                resp = malloc(sizes.seccomp_notif_resp);
                if (!resp)
                        goto out_req;
-               memset(resp, 0, sizeof(*resp));
+               memset(resp, 0, sizes.seccomp_notif_resp);
 
                while (1) {
+                       memset(req, 0, sizes.seccomp_notif);
                        if (ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, req)) {
                                perror("ioctl recv");
                                goto out_resp;
index 7affc3b..cfc1595 100644 (file)
@@ -36,6 +36,7 @@ static int __init trace_printk_init(void)
 
        /* Kick off printing in irq context */
        irq_work_queue(&irqwork);
+       irq_work_sync(&irqwork);
 
        trace_printk("This is a %s that will use trace_bprintk()\n",
                     "static string");
index 7cbe6e7..a63380c 100755 (executable)
@@ -4125,15 +4125,6 @@ sub process {
                             "Prefer [subsystem eg: netdev]_$level2([subsystem]dev, ... then dev_$level2(dev, ... then pr_$level(...  to printk(KERN_$orig ...\n" . $herecurr);
                }
 
-               if ($line =~ /\bpr_warning\s*\(/) {
-                       if (WARN("PREFER_PR_LEVEL",
-                                "Prefer pr_warn(... to pr_warning(...\n" . $herecurr) &&
-                           $fix) {
-                               $fixed[$fixlinenr] =~
-                                   s/\bpr_warning\b/pr_warn/;
-                       }
-               }
-
                if ($line =~ /\bdev_printk\s*\(\s*KERN_([A-Z]+)/) {
                        my $orig = $1;
                        my $level = lc($orig);
index d33de0b..e356954 100644 (file)
@@ -14,8 +14,8 @@ config HAVE_GCC_PLUGINS
          An arch should select this symbol if it supports building with
          GCC plugins.
 
-config GCC_PLUGINS
-       bool
+menuconfig GCC_PLUGINS
+       bool "GCC plugins"
        depends on HAVE_GCC_PLUGINS
        depends on PLUGIN_HOSTCC != ""
        default y
@@ -25,8 +25,7 @@ config GCC_PLUGINS
 
          See Documentation/core-api/gcc-plugins.rst for details.
 
-menu "GCC plugins"
-       depends on GCC_PLUGINS
+if GCC_PLUGINS
 
 config GCC_PLUGIN_CYC_COMPLEXITY
        bool "Compute the cyclomatic complexity of a function" if EXPERT
@@ -113,4 +112,4 @@ config GCC_PLUGIN_ARM_SSP_PER_TASK
        bool
        depends on GCC_PLUGINS && ARM
 
-endmenu
+endif
index fb55f26..9415373 100644 (file)
@@ -310,6 +310,15 @@ static void output_label(const char *label)
        printf("%s:\n", label);
 }
 
+/* Provide proper symbols relocatability by their '_text' relativeness. */
+static void output_address(unsigned long long addr)
+{
+       if (_text <= addr)
+               printf("\tPTR\t_text + %#llx\n", addr - _text);
+       else
+               printf("\tPTR\t_text - %#llx\n", _text - addr);
+}
+
 /* uncompress a compressed symbol. When this function is called, the best table
  * might still be compressed itself, so the function needs to be recursive */
 static int expand_symbol(const unsigned char *data, int len, char *result)
@@ -360,19 +369,6 @@ static void write_src(void)
 
        printf("\t.section .rodata, \"a\"\n");
 
-       /* Provide proper symbols relocatability by their relativeness
-        * to a fixed anchor point in the runtime image, either '_text'
-        * for absolute address tables, in which case the linker will
-        * emit the final addresses at build time. Otherwise, use the
-        * offset relative to the lowest value encountered of all relative
-        * symbols, and emit non-relocatable fixed offsets that will be fixed
-        * up at runtime.
-        *
-        * The symbol names cannot be used to construct normal symbol
-        * references as the list of symbols contains symbols that are
-        * declared static and are private to their .o files.  This prevents
-        * .tmp_kallsyms.o or any other object from referencing them.
-        */
        if (!base_relative)
                output_label("kallsyms_addresses");
        else
@@ -380,6 +376,13 @@ static void write_src(void)
 
        for (i = 0; i < table_cnt; i++) {
                if (base_relative) {
+                       /*
+                        * Use the offset relative to the lowest value
+                        * encountered of all relative symbols, and emit
+                        * non-relocatable fixed offsets that will be fixed
+                        * up at runtime.
+                        */
+
                        long long offset;
                        int overflow;
 
@@ -402,12 +405,7 @@ static void write_src(void)
                        }
                        printf("\t.long\t%#x\n", (int)offset);
                } else if (!symbol_absolute(&table[i])) {
-                       if (_text <= table[i].addr)
-                               printf("\tPTR\t_text + %#llx\n",
-                                       table[i].addr - _text);
-                       else
-                               printf("\tPTR\t_text - %#llx\n",
-                                       _text - table[i].addr);
+                       output_address(table[i].addr);
                } else {
                        printf("\tPTR\t%#llx\n", table[i].addr);
                }
@@ -416,7 +414,7 @@ static void write_src(void)
 
        if (base_relative) {
                output_label("kallsyms_relative_base");
-               printf("\tPTR\t_text - %#llx\n", _text - relative_base);
+               output_address(relative_base);
                printf("\n");
        }
 
index 77ffff3..9f1de58 100644 (file)
@@ -254,6 +254,13 @@ static int expr_eq(struct expr *e1, struct expr *e2)
 {
        int res, old_count;
 
+       /*
+        * A NULL expr is taken to be yes, but there's also a different way to
+        * represent yes. expr_is_yes() checks for either representation.
+        */
+       if (!e1 || !e2)
+               return expr_is_yes(e1) && expr_is_yes(e2);
+
        if (e1->type != e2->type)
                return 0;
        switch (e1->type) {
index d1d757c..3a5a4b2 100755 (executable)
@@ -55,12 +55,10 @@ CONFIG_FLAGS=""
 if [ -n "$SMP" ] ; then CONFIG_FLAGS="SMP"; fi
 if [ -n "$PREEMPT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT"; fi
 if [ -n "$PREEMPT_RT" ] ; then CONFIG_FLAGS="$CONFIG_FLAGS PREEMPT_RT"; fi
-UTS_VERSION="$UTS_VERSION $CONFIG_FLAGS $TIMESTAMP"
 
 # Truncate to maximum length
-
 UTS_LEN=64
-UTS_TRUNCATE="cut -b -$UTS_LEN"
+UTS_VERSION="$(echo $UTS_VERSION $CONFIG_FLAGS $TIMESTAMP | cut -b -$UTS_LEN)"
 
 # Generate a temporary compile.h
 
@@ -69,10 +67,10 @@ UTS_TRUNCATE="cut -b -$UTS_LEN"
 
   echo \#define UTS_MACHINE \"$ARCH\"
 
-  echo \#define UTS_VERSION \"`echo $UTS_VERSION | $UTS_TRUNCATE`\"
+  echo \#define UTS_VERSION \"$UTS_VERSION\"
 
-  echo \#define LINUX_COMPILE_BY \"`echo $LINUX_COMPILE_BY | $UTS_TRUNCATE`\"
-  echo \#define LINUX_COMPILE_HOST \"`echo $LINUX_COMPILE_HOST | $UTS_TRUNCATE`\"
+  printf '#define LINUX_COMPILE_BY "%s"\n' "$LINUX_COMPILE_BY"
+  echo \#define LINUX_COMPILE_HOST \"$LINUX_COMPILE_HOST\"
 
   echo \#define LINUX_COMPILER \"`$CC -v 2>&1 | grep ' version ' | sed 's/[[:space:]]*$//'`\"
 } > .tmpcompile
index e0750b7..357dc56 100755 (executable)
@@ -136,7 +136,7 @@ mkdir -p debian/source/
 echo "1.0" > debian/source/format
 
 echo $debarch > debian/arch
-extra_build_depends=", $(if_enabled_echo CONFIG_UNWINDER_ORC libelf-dev)"
+extra_build_depends=", $(if_enabled_echo CONFIG_UNWINDER_ORC libelf-dev:native)"
 extra_build_depends="$extra_build_depends, $(if_enabled_echo CONFIG_SYSTEM_TRUSTED_KEYRING libssl-dev:native)"
 
 # Generate a simple changelog template
@@ -174,7 +174,7 @@ Source: $sourcename
 Section: kernel
 Priority: optional
 Maintainer: $maintainer
-Build-Depends: bc, kmod, cpio, bison, flex | flex:native $extra_build_depends
+Build-Depends: bc, rsync, kmod, cpio, bison, flex | flex:native $extra_build_depends
 Homepage: http://www.kernel.org/
 
 Package: $packagename
index 09996f2..47aff87 100644 (file)
@@ -623,7 +623,7 @@ static __poll_t ns_revision_poll(struct file *file, poll_table *pt)
 
 void __aa_bump_ns_revision(struct aa_ns *ns)
 {
-       ns->revision++;
+       WRITE_ONCE(ns->revision, ns->revision + 1);
        wake_up_interruptible(&ns->wait);
 }
 
index 9be7ccb..6ceb74e 100644 (file)
@@ -317,6 +317,7 @@ static int aa_xattrs_match(const struct linux_binprm *bprm,
 
        if (!bprm || !profile->xattr_count)
                return 0;
+       might_sleep();
 
        /* transition from exec match to xattr set */
        state = aa_dfa_null_transition(profile->xmatch, state);
@@ -361,10 +362,11 @@ out:
 }
 
 /**
- * __attach_match_ - find an attachment match
+ * find_attach - do attachment search for unconfined processes
  * @bprm - binprm structure of transitioning task
- * @name - to match against  (NOT NULL)
+ * @ns: the current namespace  (NOT NULL)
  * @head - profile list to walk  (NOT NULL)
+ * @name - to match against  (NOT NULL)
  * @info - info message if there was an error (NOT NULL)
  *
  * Do a linear search on the profiles in the list.  There is a matching
@@ -374,12 +376,11 @@ out:
  *
  * Requires: @head not be shared or have appropriate locks held
  *
- * Returns: profile or NULL if no match found
+ * Returns: label or NULL if no match found
  */
-static struct aa_profile *__attach_match(const struct linux_binprm *bprm,
-                                        const char *name,
-                                        struct list_head *head,
-                                        const char **info)
+static struct aa_label *find_attach(const struct linux_binprm *bprm,
+                                   struct aa_ns *ns, struct list_head *head,
+                                   const char *name, const char **info)
 {
        int candidate_len = 0, candidate_xattrs = 0;
        bool conflict = false;
@@ -388,6 +389,8 @@ static struct aa_profile *__attach_match(const struct linux_binprm *bprm,
        AA_BUG(!name);
        AA_BUG(!head);
 
+       rcu_read_lock();
+restart:
        list_for_each_entry_rcu(profile, head, base.list) {
                if (profile->label.flags & FLAG_NULL &&
                    &profile->label == ns_unconfined(profile->ns))
@@ -413,16 +416,32 @@ static struct aa_profile *__attach_match(const struct linux_binprm *bprm,
                        perm = dfa_user_allow(profile->xmatch, state);
                        /* any accepting state means a valid match. */
                        if (perm & MAY_EXEC) {
-                               int ret;
+                               int ret = 0;
 
                                if (count < candidate_len)
                                        continue;
 
-                               ret = aa_xattrs_match(bprm, profile, state);
-                               /* Fail matching if the xattrs don't match */
-                               if (ret < 0)
-                                       continue;
-
+                               if (bprm && profile->xattr_count) {
+                                       long rev = READ_ONCE(ns->revision);
+
+                                       if (!aa_get_profile_not0(profile))
+                                               goto restart;
+                                       rcu_read_unlock();
+                                       ret = aa_xattrs_match(bprm, profile,
+                                                             state);
+                                       rcu_read_lock();
+                                       aa_put_profile(profile);
+                                       if (rev !=
+                                           READ_ONCE(ns->revision))
+                                               /* policy changed */
+                                               goto restart;
+                                       /*
+                                        * Fail matching if the xattrs don't
+                                        * match
+                                        */
+                                       if (ret < 0)
+                                               continue;
+                               }
                                /*
                                 * TODO: allow for more flexible best match
                                 *
@@ -445,43 +464,28 @@ static struct aa_profile *__attach_match(const struct linux_binprm *bprm,
                                candidate_xattrs = ret;
                                conflict = false;
                        }
-               } else if (!strcmp(profile->base.name, name))
+               } else if (!strcmp(profile->base.name, name)) {
                        /*
                         * old exact non-re match, without conditionals such
                         * as xattrs. no more searching required
                         */
-                       return profile;
+                       candidate = profile;
+                       goto out;
+               }
        }
 
-       if (conflict) {
-               *info = "conflicting profile attachments";
+       if (!candidate || conflict) {
+               if (conflict)
+                       *info = "conflicting profile attachments";
+               rcu_read_unlock();
                return NULL;
        }
 
-       return candidate;
-}
-
-/**
- * find_attach - do attachment search for unconfined processes
- * @bprm - binprm structure of transitioning task
- * @ns: the current namespace  (NOT NULL)
- * @list: list to search  (NOT NULL)
- * @name: the executable name to match against  (NOT NULL)
- * @info: info message if there was an error
- *
- * Returns: label or NULL if no match found
- */
-static struct aa_label *find_attach(const struct linux_binprm *bprm,
-                                   struct aa_ns *ns, struct list_head *list,
-                                   const char *name, const char **info)
-{
-       struct aa_profile *profile;
-
-       rcu_read_lock();
-       profile = aa_get_profile(__attach_match(bprm, name, list, info));
+out:
+       candidate = aa_get_newest_profile(candidate);
        rcu_read_unlock();
 
-       return profile ? &profile->label : NULL;
+       return &candidate->label;
 }
 
 static const char *next_name(int xtype, const char *name)
index fe2ebe5..f1caf36 100644 (file)
@@ -618,8 +618,7 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
        fctx = file_ctx(file);
 
        rcu_read_lock();
-       flabel  = aa_get_newest_label(rcu_dereference(fctx->label));
-       rcu_read_unlock();
+       flabel  = rcu_dereference(fctx->label);
        AA_BUG(!flabel);
 
        /* revalidate access, if task is unconfined, or the cached cred
@@ -631,9 +630,13 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
         */
        denied = request & ~fctx->allow;
        if (unconfined(label) || unconfined(flabel) ||
-           (!denied && aa_label_is_subset(flabel, label)))
+           (!denied && aa_label_is_subset(flabel, label))) {
+               rcu_read_unlock();
                goto done;
+       }
 
+       flabel  = aa_get_newest_label(flabel);
+       rcu_read_unlock();
        /* TODO: label cross check */
 
        if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry))
@@ -643,8 +646,9 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
        else if (S_ISSOCK(file_inode(file)->i_mode))
                error = __file_sock_perm(op, label, flabel, file, request,
                                         denied);
-done:
        aa_put_label(flabel);
+
+done:
        return error;
 }
 
index 4ed6688..e0828ee 100644 (file)
@@ -442,7 +442,7 @@ int aa_bind_mount(struct aa_label *label, const struct path *path,
        buffer = aa_get_buffer(false);
        old_buffer = aa_get_buffer(false);
        error = -ENOMEM;
-       if (!buffer || old_buffer)
+       if (!buffer || !old_buffer)
                goto out;
 
        error = fn_for_each_confined(label, profile,
index 0310483..269f2f5 100644 (file)
@@ -1125,8 +1125,8 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj,
        if (!name) {
                /* remove namespace - can only happen if fqname[0] == ':' */
                mutex_lock_nested(&ns->parent->lock, ns->level);
-               __aa_remove_ns(ns);
                __aa_bump_ns_revision(ns);
+               __aa_remove_ns(ns);
                mutex_unlock(&ns->parent->lock);
        } else {
                /* remove profile */
@@ -1138,9 +1138,9 @@ ssize_t aa_remove_profiles(struct aa_ns *policy_ns, struct aa_label *subj,
                        goto fail_ns_lock;
                }
                name = profile->base.hname;
+               __aa_bump_ns_revision(ns);
                __remove_profile(profile);
                __aa_labelset_update_subtree(ns);
-               __aa_bump_ns_revision(ns);
                mutex_unlock(&ns->lock);
        }
 
index f19a895..ef8dfd4 100644 (file)
@@ -45,7 +45,7 @@
 #define DONT_HASH      0x0200
 
 #define INVALID_PCR(a) (((a) < 0) || \
-       (a) >= (FIELD_SIZEOF(struct integrity_iint_cache, measured_pcrs) * 8))
+       (a) >= (sizeof_field(struct integrity_iint_cache, measured_pcrs) * 8))
 
 int ima_policy_flag;
 static int temp_ima_appraise;
@@ -274,7 +274,7 @@ static struct ima_rule_entry *ima_lsm_copy_rule(struct ima_rule_entry *entry)
         * lsm rules can change
         */
        memcpy(nentry, entry, sizeof(*nentry));
-       memset(nentry->lsm, 0, FIELD_SIZEOF(struct ima_rule_entry, lsm));
+       memset(nentry->lsm, 0, sizeof_field(struct ima_rule_entry, lsm));
 
        for (i = 0; i < MAX_LSM_RULES; i++) {
                if (!entry->lsm[i].rule)
index dd31343..47c0415 100644 (file)
@@ -21,10 +21,6 @@ config KEYS
 
          If you are unsure as to whether this is required, answer N.
 
-config KEYS_COMPAT
-       def_bool y
-       depends on COMPAT && KEYS
-
 config KEYS_REQUEST_CACHE
        bool "Enable temporary caching of the last request_key() result"
        depends on KEYS
index 074f275..5f40807 100644 (file)
@@ -17,7 +17,7 @@ obj-y := \
        request_key_auth.o \
        user_defined.o
 compat-obj-$(CONFIG_KEY_DH_OPERATIONS) += compat_dh.o
-obj-$(CONFIG_KEYS_COMPAT) += compat.o $(compat-obj-y)
+obj-$(CONFIG_COMPAT) += compat.o $(compat-obj-y)
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
 obj-$(CONFIG_PERSISTENT_KEYRINGS) += persistent.o
index 9bcc404..b975f8f 100644 (file)
@@ -46,11 +46,6 @@ static long compat_keyctl_instantiate_key_iov(
 
 /*
  * The key control system call, 32-bit compatibility version for 64-bit archs
- *
- * This should only be called if the 64-bit arch uses weird pointers in 32-bit
- * mode or doesn't guarantee that the top 32-bits of the argument registers on
- * taking a 32-bit syscall are zero.  If you can, you should call sys_keyctl()
- * directly.
  */
 COMPAT_SYSCALL_DEFINE5(keyctl, u32, option,
                       u32, arg2, u32, arg3, u32, arg4, u32, arg5)
index c039373..ba3e2da 100644 (file)
@@ -264,7 +264,7 @@ extern long keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
                              size_t, struct keyctl_kdf_params __user *);
 extern long __keyctl_dh_compute(struct keyctl_dh_params __user *, char __user *,
                                size_t, struct keyctl_kdf_params *);
-#ifdef CONFIG_KEYS_COMPAT
+#ifdef CONFIG_COMPAT
 extern long compat_keyctl_dh_compute(struct keyctl_dh_params __user *params,
                                char __user *buffer, size_t buflen,
                                struct compat_keyctl_kdf_params __user *kdf);
@@ -279,7 +279,7 @@ static inline long keyctl_dh_compute(struct keyctl_dh_params __user *params,
        return -EOPNOTSUPP;
 }
 
-#ifdef CONFIG_KEYS_COMPAT
+#ifdef CONFIG_COMPAT
 static inline long compat_keyctl_dh_compute(
                                struct keyctl_dh_params __user *params,
                                char __user *buffer, size_t buflen,
index a9810ac..08ec7f4 100644 (file)
@@ -309,6 +309,7 @@ int tpm2_unseal_trusted(struct tpm_chip *chip,
                return rc;
 
        rc = tpm2_unseal_cmd(chip, payload, options, blob_handle);
+       tpm2_flush_context(chip, blob_handle);
 
        return rc;
 }
index dd3d594..c36bafb 100644 (file)
@@ -951,7 +951,8 @@ static bool tomoyo_manager(void)
        exe = tomoyo_get_exe();
        if (!exe)
                return false;
-       list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], head.list) {
+       list_for_each_entry_rcu(ptr, &tomoyo_kernel_namespace.policy_list[TOMOYO_ID_MANAGER], head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (!ptr->head.is_deleted &&
                    (!tomoyo_pathcmp(domainname, ptr->manager) ||
                     !strcmp(exe, ptr->manager->name))) {
@@ -1095,7 +1096,8 @@ static int tomoyo_delete_domain(char *domainname)
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                return -EINTR;
        /* Is there an active domain? */
-       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                /* Never delete tomoyo_kernel_domain */
                if (domain == &tomoyo_kernel_domain)
                        continue;
@@ -2778,7 +2780,8 @@ void tomoyo_check_profile(void)
 
        tomoyo_policy_loaded = true;
        pr_info("TOMOYO: 2.6.0\n");
-       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                const u8 profile = domain->profile;
                struct tomoyo_policy_namespace *ns = domain->ns;
 
index 8526a0a..7869d6a 100644 (file)
@@ -41,7 +41,8 @@ int tomoyo_update_policy(struct tomoyo_acl_head *new_entry, const int size,
 
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                return -ENOMEM;
-       list_for_each_entry_rcu(entry, list, list) {
+       list_for_each_entry_rcu(entry, list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS)
                        continue;
                if (!check_duplicate(entry, new_entry))
@@ -119,7 +120,8 @@ int tomoyo_update_domain(struct tomoyo_acl_info *new_entry, const int size,
        }
        if (mutex_lock_interruptible(&tomoyo_policy_lock))
                goto out;
-       list_for_each_entry_rcu(entry, list, list) {
+       list_for_each_entry_rcu(entry, list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (entry->is_deleted == TOMOYO_GC_IN_PROGRESS)
                        continue;
                if (!tomoyo_same_acl_head(entry, new_entry) ||
@@ -166,7 +168,8 @@ void tomoyo_check_acl(struct tomoyo_request_info *r,
        u16 i = 0;
 
 retry:
-       list_for_each_entry_rcu(ptr, list, list) {
+       list_for_each_entry_rcu(ptr, list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (ptr->is_deleted || ptr->type != r->param_type)
                        continue;
                if (!check_entry(r, ptr))
@@ -298,7 +301,8 @@ static inline bool tomoyo_scan_transition
 {
        const struct tomoyo_transition_control *ptr;
 
-       list_for_each_entry_rcu(ptr, list, head.list) {
+       list_for_each_entry_rcu(ptr, list, head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (ptr->head.is_deleted || ptr->type != type)
                        continue;
                if (ptr->domainname) {
@@ -735,7 +739,8 @@ retry:
 
                /* Check 'aggregator' directive. */
                candidate = &exename;
-               list_for_each_entry_rcu(ptr, list, head.list) {
+               list_for_each_entry_rcu(ptr, list, head.list,
+                                       srcu_read_lock_held(&tomoyo_ss)) {
                        if (ptr->head.is_deleted ||
                            !tomoyo_path_matches_pattern(&exename,
                                                         ptr->original_name))
index a37c7dc..1cecdd7 100644 (file)
@@ -133,7 +133,8 @@ tomoyo_path_matches_group(const struct tomoyo_path_info *pathname,
 {
        struct tomoyo_path_group *member;
 
-       list_for_each_entry_rcu(member, &group->member_list, head.list) {
+       list_for_each_entry_rcu(member, &group->member_list, head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (member->head.is_deleted)
                        continue;
                if (!tomoyo_path_matches_pattern(pathname, member->member_name))
@@ -161,7 +162,8 @@ bool tomoyo_number_matches_group(const unsigned long min,
        struct tomoyo_number_group *member;
        bool matched = false;
 
-       list_for_each_entry_rcu(member, &group->member_list, head.list) {
+       list_for_each_entry_rcu(member, &group->member_list, head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (member->head.is_deleted)
                        continue;
                if (min > member->number.values[1] ||
@@ -191,7 +193,8 @@ bool tomoyo_address_matches_group(const bool is_ipv6, const __be32 *address,
        bool matched = false;
        const u8 size = is_ipv6 ? 16 : 4;
 
-       list_for_each_entry_rcu(member, &group->member_list, head.list) {
+       list_for_each_entry_rcu(member, &group->member_list, head.list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (member->head.is_deleted)
                        continue;
                if (member->address.is_ipv6 != is_ipv6)
index e783244..bf38fc1 100644 (file)
@@ -218,31 +218,6 @@ out:
 }
 
 /**
- * tomoyo_get_socket_name - Get the name of a socket.
- *
- * @path:   Pointer to "struct path".
- * @buffer: Pointer to buffer to return value in.
- * @buflen: Sizeof @buffer.
- *
- * Returns the buffer.
- */
-static char *tomoyo_get_socket_name(const struct path *path, char * const buffer,
-                                   const int buflen)
-{
-       struct inode *inode = d_backing_inode(path->dentry);
-       struct socket *sock = inode ? SOCKET_I(inode) : NULL;
-       struct sock *sk = sock ? sock->sk : NULL;
-
-       if (sk) {
-               snprintf(buffer, buflen, "socket:[family=%u:type=%u:protocol=%u]",
-                        sk->sk_family, sk->sk_type, sk->sk_protocol);
-       } else {
-               snprintf(buffer, buflen, "socket:[unknown]");
-       }
-       return buffer;
-}
-
-/**
  * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
  *
  * @path: Pointer to "struct path".
@@ -279,12 +254,7 @@ char *tomoyo_realpath_from_path(const struct path *path)
                        break;
                /* To make sure that pos is '\0' terminated. */
                buf[buf_len - 1] = '\0';
-               /* Get better name for socket. */
-               if (sb->s_magic == SOCKFS_MAGIC) {
-                       pos = tomoyo_get_socket_name(path, buf, buf_len - 1);
-                       goto encode;
-               }
-               /* For "pipe:[\$]". */
+               /* For "pipe:[\$]" and "socket:[\$]". */
                if (dentry->d_op && dentry->d_op->d_dname) {
                        pos = dentry->d_op->d_dname(dentry, buf, buf_len - 1);
                        goto encode;
index 52752e1..eba0b33 100644 (file)
@@ -594,7 +594,8 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname)
 
        name.name = domainname;
        tomoyo_fill_path_info(&name);
-       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) {
+       list_for_each_entry_rcu(domain, &tomoyo_domain_list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                if (!domain->is_deleted &&
                    !tomoyo_pathcmp(&name, domain->domainname))
                        return domain;
@@ -1028,7 +1029,8 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
                return false;
        if (!domain)
                return true;
-       list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
+       list_for_each_entry_rcu(ptr, &domain->acl_info_list, list,
+                               srcu_read_lock_held(&tomoyo_ss)) {
                u16 perm;
                u8 i;
 
index 715daf1..d2479bb 100644 (file)
@@ -53,7 +53,7 @@ static unsigned short compat_ac97_read(struct snd_ac97 *ac97,
        return actrl->ops->read(actrl, ac97->num, reg);
 }
 
-static struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
+static const struct snd_ac97_bus_ops compat_snd_ac97_bus_ops = {
        .reset = compat_ac97_reset,
        .warm_reset = compat_ac97_warm_reset,
        .write = compat_ac97_write,
index 3732a63..b4685c5 100644 (file)
@@ -55,7 +55,7 @@ static bool snd_ac97_check_id(struct snd_ac97 *ac97, unsigned int id,
 int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
        unsigned int id_mask)
 {
-       struct snd_ac97_bus_ops *ops = ac97->bus->ops;
+       const struct snd_ac97_bus_ops *ops = ac97->bus->ops;
 
        if (try_warm && ops->warm_reset) {
                ops->warm_reset(ac97);
index 60ce9de..3d2d03f 100644 (file)
@@ -116,7 +116,7 @@ struct aoa_card {
 };
         
 extern int aoa_snd_device_new(enum snd_device_type type,
-       void * device_data, struct snd_device_ops * ops);
+       void *device_data, const struct snd_device_ops *ops);
 extern struct snd_card *aoa_get_card(void);
 extern int aoa_snd_ctl_add(struct snd_kcontrol* control);
 
index 9827bee..12028b3 100644 (file)
@@ -97,7 +97,7 @@ static int onyx_dev_register(struct snd_device *dev)
        return 0;
 }
 
-static struct snd_device_ops ops = {
+static const struct snd_device_ops ops = {
        .dev_register = onyx_dev_register,
 };
 
@@ -413,7 +413,7 @@ static int onyx_snd_single_bit_put(struct snd_kcontrol *kcontrol,
 }
 
 #define SINGLE_BIT(n, type, description, address, mask, flags)         \
-static struct snd_kcontrol_new n##_control = {                         \
+static const struct snd_kcontrol_new n##_control = {                   \
        .iface = SNDRV_CTL_ELEM_IFACE_##type,                           \
        .name = description,                                            \
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,                      \
@@ -543,7 +543,7 @@ static const struct snd_kcontrol_new onyx_spdif_ctrl = {
 
 /* our registers */
 
-static u8 register_map[] = {
+static const u8 register_map[] = {
        ONYX_REG_DAC_ATTEN_LEFT,
        ONYX_REG_DAC_ATTEN_RIGHT,
        ONYX_REG_CONTROL,
@@ -559,7 +559,7 @@ static u8 register_map[] = {
        ONYX_REG_DIG_INFO4
 };
 
-static u8 initial_values[ARRAY_SIZE(register_map)] = {
+static const u8 initial_values[ARRAY_SIZE(register_map)] = {
        0x80, 0x80, /* muted */
        ONYX_MRST | ONYX_SRST, /* but handled specially! */
        ONYX_MUTE_LEFT | ONYX_MUTE_RIGHT,
index 770935a..14dc4e9 100644 (file)
@@ -13,7 +13,7 @@
 #define TAS3004_TREBLE_ZERO    36
 #define TAS3004_BASS_ZERO      36
 
-static u8 tas3004_treble_table[] = {
+static const u8 tas3004_treble_table[] = {
        150, /* -18 dB */
        149,
        148,
@@ -99,7 +99,7 @@ static inline u8 tas3004_treble(int idx)
  * I have also ignored completely differences of
  * +/- 1
  */
-static s8 tas3004_bass_diff_to_treble[] = {
+static const s8 tas3004_bass_diff_to_treble[] = {
        2, /* 7 dB, offset 50 */
        2,
        2,
index 77b8e7d..c9ea014 100644 (file)
@@ -27,7 +27,7 @@ int main() {
  * as easy as calculating
  *      hwvalue = 1048576.0*exp(0.057564628*dB*2)
  * :) */
-static int tas_gaintable[] = {
+static const int tas_gaintable[] = {
        0x000000, /* -infinity dB */
        0x00014b, /* -70.0 dB */
        0x00015f, /* -69.5 dB */
index 7af6129..d3e3757 100644 (file)
@@ -217,7 +217,7 @@ static int tas_dev_register(struct snd_device *dev)
        return 0;
 }
 
-static struct snd_device_ops ops = {
+static const struct snd_device_ops ops = {
        .dev_register = tas_dev_register,
 };
 
@@ -369,7 +369,7 @@ static int tas_snd_mixer_put(struct snd_kcontrol *kcontrol,
 }
 
 #define MIXER_CONTROL(n,descr,idx)                     \
-static struct snd_kcontrol_new n##_control = {         \
+static const struct snd_kcontrol_new n##_control = {   \
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,            \
        .name = descr " Playback Volume",               \
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,      \
index b43469f..c2d0144 100644 (file)
@@ -30,7 +30,7 @@ static int toonie_dev_register(struct snd_device *dev)
        return 0;
 }
 
-static struct snd_device_ops ops = {
+static const struct snd_device_ops ops = {
        .dev_register = toonie_dev_register,
 };
 
index fcf30f0..b610813 100644 (file)
@@ -59,7 +59,7 @@ void aoa_alsa_cleanup(void)
 }
 
 int aoa_snd_device_new(enum snd_device_type type,
-                      void * device_data, struct snd_device_ops * ops)
+                      void *device_data, const struct snd_device_ops *ops)
 {
        struct snd_card *card = aoa_get_card();
        int err;
index 801b2f7..d2e85b8 100644 (file)
@@ -655,7 +655,7 @@ static int n##_control_put(struct snd_kcontrol *kcontrol,           \
                        !!ucontrol->value.integer.value[0]);            \
        return 1;                                                       \
 }                                                                      \
-static struct snd_kcontrol_new n##_ctl = {                             \
+static const struct snd_kcontrol_new n##_ctl = {                       \
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,                            \
        .name = description,                                            \
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,                      \
index 17df288..faf6b03 100644 (file)
@@ -160,7 +160,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
        static const char *rnames[] = { "i2sbus: %pOFn (control)",
                                        "i2sbus: %pOFn (tx)",
                                        "i2sbus: %pOFn (rx)" };
-       static irq_handler_t ints[] = {
+       static const irq_handler_t ints[] = {
                i2sbus_bus_intr,
                i2sbus_tx_intr,
                i2sbus_rx_intr
index a94e402..d350dbd 100644 (file)
@@ -294,12 +294,6 @@ void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev)
 }
 #endif
 
-static int i2sbus_hw_params(struct snd_pcm_substream *substream,
-                           struct snd_pcm_hw_params *params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-}
-
 static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
 {
        struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
@@ -308,7 +302,6 @@ static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
        get_pcm_info(i2sdev, in, &pi, NULL);
        if (pi->dbdma_ring.stopping)
                i2sbus_wait_for_stop(i2sdev, pi);
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -780,8 +773,6 @@ static snd_pcm_uframes_t i2sbus_playback_pointer(struct snd_pcm_substream
 static const struct snd_pcm_ops i2sbus_playback_ops = {
        .open =         i2sbus_playback_open,
        .close =        i2sbus_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    i2sbus_hw_params,
        .hw_free =      i2sbus_playback_hw_free,
        .prepare =      i2sbus_playback_prepare,
        .trigger =      i2sbus_playback_trigger,
@@ -850,8 +841,6 @@ static snd_pcm_uframes_t i2sbus_record_pointer(struct snd_pcm_substream
 static const struct snd_pcm_ops i2sbus_record_ops = {
        .open =         i2sbus_record_open,
        .close =        i2sbus_record_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    i2sbus_hw_params,
        .hw_free =      i2sbus_record_hw_free,
        .prepare =      i2sbus_record_prepare,
        .trigger =      i2sbus_record_trigger,
@@ -1026,7 +1015,7 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
        dev->pcm->private_free = i2sbus_private_free;
 
        /* well, we really should support scatter/gather DMA */
-       snd_pcm_lib_preallocate_pages_for_all(
+       snd_pcm_set_managed_buffer_all(
                dev->pcm, SNDRV_DMA_TYPE_DEV,
                &macio_get_pci_dev(i2sdev->macio)->dev,
                64 * 1024, 64 * 1024);
index b5399b0..a0996c4 100644 (file)
@@ -380,7 +380,7 @@ static const struct snd_pcm_hardware aaci_hw_info = {
 static int aaci_rule_channels(struct snd_pcm_hw_params *p,
        struct snd_pcm_hw_rule *rule)
 {
-       static unsigned int channel_list[] = { 2, 4, 6 };
+       static const unsigned int channel_list[] = { 2, 4, 6 };
        struct aaci *aaci = rule->private;
        unsigned int mask = 1 << 0, slots;
 
@@ -483,11 +483,6 @@ static int aaci_pcm_hw_free(struct snd_pcm_substream *substream)
                snd_ac97_pcm_close(aacirun->pcm);
        aacirun->pcm_open = 0;
 
-       /*
-        * Clear out the DMA and any allocated buffers.
-        */
-       snd_pcm_lib_free_pages(substream);
-
        return 0;
 }
 
@@ -502,6 +497,7 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
                              struct snd_pcm_hw_params *params)
 {
        struct aaci_runtime *aacirun = substream->runtime->private_data;
+       struct aaci *aaci = substream->private_data;
        unsigned int channels = params_channels(params);
        unsigned int rate = params_rate(params);
        int dbl = rate > 48000;
@@ -517,25 +513,19 @@ static int aaci_pcm_hw_params(struct snd_pcm_substream *substream,
        if (dbl && channels != 2)
                return -EINVAL;
 
-       err = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(params));
-       if (err >= 0) {
-               struct aaci *aaci = substream->private_data;
+       err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,
+                               aacirun->pcm->r[dbl].slots);
 
-               err = snd_ac97_pcm_open(aacirun->pcm, rate, channels,
-                                       aacirun->pcm->r[dbl].slots);
+       aacirun->pcm_open = err == 0;
+       aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
+       aacirun->cr |= channels_to_slotmask[channels + dbl * 2];
 
-               aacirun->pcm_open = err == 0;
-               aacirun->cr = CR_FEN | CR_COMPACT | CR_SZ16;
-               aacirun->cr |= channels_to_slotmask[channels + dbl * 2];
-
-               /*
-                * fifo_bytes is the number of bytes we transfer to/from
-                * the FIFO, including padding.  So that's x4.  As we're
-                * in compact mode, the FIFO is half the size.
-                */
-               aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2;
-       }
+       /*
+        * fifo_bytes is the number of bytes we transfer to/from
+        * the FIFO, including padding.  So that's x4.  As we're
+        * in compact mode, the FIFO is half the size.
+        */
+       aacirun->fifo_bytes = aaci->fifo_depth * 4 / 2;
 
        return err;
 }
@@ -635,7 +625,6 @@ static int aaci_pcm_playback_trigger(struct snd_pcm_substream *substream, int cm
 static const struct snd_pcm_ops aaci_playback_ops = {
        .open           = aaci_pcm_open,
        .close          = aaci_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = aaci_pcm_hw_params,
        .hw_free        = aaci_pcm_hw_free,
        .prepare        = aaci_pcm_prepare,
@@ -738,7 +727,6 @@ static int aaci_pcm_capture_prepare(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops aaci_capture_ops = {
        .open           = aaci_pcm_open,
        .close          = aaci_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = aaci_pcm_hw_params,
        .hw_free        = aaci_pcm_hw_free,
        .prepare        = aaci_pcm_capture_prepare,
@@ -823,7 +811,7 @@ static const struct ac97_pcm ac97_defs[] = {
        }
 };
 
-static struct snd_ac97_bus_ops aaci_bus_ops = {
+static const struct snd_ac97_bus_ops aaci_bus_ops = {
        .write  = aaci_ac97_write,
        .read   = aaci_ac97_read,
 };
@@ -937,9 +925,9 @@ static int aaci_init_pcm(struct aaci *aaci)
 
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &aaci_playback_ops);
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &aaci_capture_ops);
-               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                     aaci->card->dev,
-                                                     0, 64 * 1024);
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                              aaci->card->dev,
+                                              0, 64 * 1024);
        }
 
        return ret;
index acfaf1d..ea8e233 100644 (file)
@@ -52,7 +52,7 @@ static void pxa2xx_ac97_legacy_write(struct snd_ac97 *ac97,
        ret = pxa2xx_ac97_write(ac97->num, reg, val);
 }
 
-static struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
+static const struct snd_ac97_bus_ops pxa2xx_ac97_ops = {
        .read   = pxa2xx_ac97_legacy_read,
        .write  = pxa2xx_ac97_legacy_write,
        .reset  = pxa2xx_ac97_legacy_reset,
@@ -173,7 +173,6 @@ static SIMPLE_DEV_PM_OPS(pxa2xx_ac97_pm_ops, pxa2xx_ac97_suspend, pxa2xx_ac97_re
 static const struct snd_pcm_ops pxa2xx_ac97_pcm_ops = {
        .open           = pxa2xx_ac97_pcm_open,
        .close          = pxa2xx_ac97_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = pxa2xx_pcm_hw_params,
        .hw_free        = pxa2xx_pcm_hw_free,
        .prepare        = pxa2xx_ac97_pcm_prepare,
index eef7ec7..a1dce97 100644 (file)
@@ -159,12 +159,6 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
                struct snd_pcm_hw_params *hw_params)
 {
        struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
-       int retval;
-
-       retval = snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-       if (retval < 0)
-               return retval;
 
        /* Set restrictions to params. */
        mutex_lock(&opened_mutex);
@@ -172,19 +166,13 @@ static int atmel_ac97c_playback_hw_params(struct snd_pcm_substream *substream,
        chip->cur_format = params_format(hw_params);
        mutex_unlock(&opened_mutex);
 
-       return retval;
+       return 0;
 }
 
 static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
                struct snd_pcm_hw_params *hw_params)
 {
        struct atmel_ac97c *chip = snd_pcm_substream_chip(substream);
-       int retval;
-
-       retval = snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-       if (retval < 0)
-               return retval;
 
        /* Set restrictions to params. */
        mutex_lock(&opened_mutex);
@@ -192,7 +180,7 @@ static int atmel_ac97c_capture_hw_params(struct snd_pcm_substream *substream,
        chip->cur_format = params_format(hw_params);
        mutex_unlock(&opened_mutex);
 
-       return retval;
+       return 0;
 }
 
 static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
@@ -459,9 +447,7 @@ atmel_ac97c_capture_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops atmel_ac97_playback_ops = {
        .open           = atmel_ac97c_playback_open,
        .close          = atmel_ac97c_playback_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = atmel_ac97c_playback_hw_params,
-       .hw_free        = snd_pcm_lib_free_pages,
        .prepare        = atmel_ac97c_playback_prepare,
        .trigger        = atmel_ac97c_playback_trigger,
        .pointer        = atmel_ac97c_playback_pointer,
@@ -470,9 +456,7 @@ static const struct snd_pcm_ops atmel_ac97_playback_ops = {
 static const struct snd_pcm_ops atmel_ac97_capture_ops = {
        .open           = atmel_ac97c_capture_open,
        .close          = atmel_ac97c_capture_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = atmel_ac97c_capture_hw_params,
-       .hw_free        = snd_pcm_lib_free_pages,
        .prepare        = atmel_ac97c_capture_prepare,
        .trigger        = atmel_ac97c_capture_trigger,
        .pointer        = atmel_ac97c_capture_pointer,
@@ -600,7 +584,7 @@ static int atmel_ac97c_pcm_new(struct atmel_ac97c *chip)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &atmel_ac97_capture_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &atmel_ac97_playback_ops);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
                        &chip->pdev->dev, hw.periods_min * hw.period_bytes_min,
                        hw.buffer_bytes_max);
 
@@ -718,7 +702,7 @@ static int atmel_ac97c_probe(struct platform_device *pdev)
        struct atmel_ac97c              *chip;
        struct resource                 *regs;
        struct clk                      *pclk;
-       static struct snd_ac97_bus_ops  ops = {
+       static const struct snd_ac97_bus_ops    ops = {
                .write  = atmel_ac97c_write,
                .read   = atmel_ac97c_read,
        };
index 4044c42..d4554f3 100644 (file)
@@ -178,6 +178,15 @@ config SND_PCM_XRUN_DEBUG
          sound clicking when system is loaded, it may help to determine
          the process or driver which causes the scheduling gaps.
 
+config SND_CTL_VALIDATION
+       bool "Perform sanity-checks for each control element access"
+       depends on SND_DEBUG
+       help
+         Say Y to enable the additional validation of each control element
+         access, including sanity-checks like whether the values returned
+         from the driver are in the proper ranges or the check of the invalid
+         access at out-of-array areas.
+
 config SND_VMASTER
        bool
 
index f34ce56..9de1c9a 100644 (file)
@@ -1099,7 +1099,7 @@ static int snd_compress_dev_free(struct snd_device *device)
 int snd_compress_new(struct snd_card *card, int device,
                        int dirn, const char *id, struct snd_compr *compr)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_compress_dev_free,
                .dev_register = snd_compress_dev_register,
                .dev_disconnect = snd_compress_dev_disconnect,
index 7a4d869..aa0c0cf 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/vmalloc.h>
 #include <linux/time.h>
 #include <linux/mm.h>
+#include <linux/math64.h>
 #include <linux/sched/signal.h>
 #include <sound/core.h>
 #include <sound/minors.h>
@@ -248,7 +249,8 @@ struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new *ncontrol,
                   SNDRV_CTL_ELEM_ACCESS_INACTIVE |
                   SNDRV_CTL_ELEM_ACCESS_TLV_READWRITE |
                   SNDRV_CTL_ELEM_ACCESS_TLV_COMMAND |
-                  SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
+                  SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK |
+                  SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK);
 
        err = snd_ctl_new(&kctl, count, access, NULL);
        if (err < 0)
@@ -758,51 +760,199 @@ static int snd_ctl_elem_list(struct snd_card *card,
        return err;
 }
 
-static bool validate_element_member_dimension(struct snd_ctl_elem_info *info)
+/* Check whether the given kctl info is valid */
+static int snd_ctl_check_elem_info(struct snd_card *card,
+                                  const struct snd_ctl_elem_info *info)
 {
-       unsigned int members;
-       unsigned int i;
+       static const unsigned int max_value_counts[] = {
+               [SNDRV_CTL_ELEM_TYPE_BOOLEAN]   = 128,
+               [SNDRV_CTL_ELEM_TYPE_INTEGER]   = 128,
+               [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128,
+               [SNDRV_CTL_ELEM_TYPE_BYTES]     = 512,
+               [SNDRV_CTL_ELEM_TYPE_IEC958]    = 1,
+               [SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64,
+       };
+
+       if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
+           info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64) {
+               if (card)
+                       dev_err(card->dev,
+                               "control %i:%i:%i:%s:%i: invalid type %d\n",
+                               info->id.iface, info->id.device,
+                               info->id.subdevice, info->id.name,
+                               info->id.index, info->type);
+               return -EINVAL;
+       }
+       if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
+           info->value.enumerated.items == 0) {
+               if (card)
+                       dev_err(card->dev,
+                               "control %i:%i:%i:%s:%i: zero enum items\n",
+                               info->id.iface, info->id.device,
+                               info->id.subdevice, info->id.name,
+                               info->id.index);
+               return -EINVAL;
+       }
+       if (info->count > max_value_counts[info->type]) {
+               if (card)
+                       dev_err(card->dev,
+                               "control %i:%i:%i:%s:%i: invalid count %d\n",
+                               info->id.iface, info->id.device,
+                               info->id.subdevice, info->id.name,
+                               info->id.index, info->count);
+               return -EINVAL;
+       }
+
+       return 0;
+}
 
-       if (info->dimen.d[0] == 0)
-               return true;
+/* The capacity of struct snd_ctl_elem_value.value.*/
+static const unsigned int value_sizes[] = {
+       [SNDRV_CTL_ELEM_TYPE_BOOLEAN]   = sizeof(long),
+       [SNDRV_CTL_ELEM_TYPE_INTEGER]   = sizeof(long),
+       [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int),
+       [SNDRV_CTL_ELEM_TYPE_BYTES]     = sizeof(unsigned char),
+       [SNDRV_CTL_ELEM_TYPE_IEC958]    = sizeof(struct snd_aes_iec958),
+       [SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long),
+};
 
-       members = 1;
-       for (i = 0; i < ARRAY_SIZE(info->dimen.d); ++i) {
-               if (info->dimen.d[i] == 0)
-                       break;
-               members *= info->dimen.d[i];
-
-               /*
-                * info->count should be validated in advance, to guarantee
-                * calculation soundness.
-                */
-               if (members > info->count)
-                       return false;
+#ifdef CONFIG_SND_CTL_VALIDATION
+/* fill the remaining snd_ctl_elem_value data with the given pattern */
+static void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
+                                     struct snd_ctl_elem_info *info,
+                                     u32 pattern)
+{
+       size_t offset = value_sizes[info->type] * info->count;
+
+       offset = (offset + sizeof(u32) - 1) / sizeof(u32);
+       memset32((u32 *)control->value.bytes.data + offset, pattern,
+                sizeof(control->value) / sizeof(u32) - offset);
+}
+
+/* check whether the given integer ctl value is valid */
+static int sanity_check_int_value(struct snd_card *card,
+                                 const struct snd_ctl_elem_value *control,
+                                 const struct snd_ctl_elem_info *info,
+                                 int i)
+{
+       long long lval, lmin, lmax, lstep;
+       u64 rem;
+
+       switch (info->type) {
+       default:
+       case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+               lval = control->value.integer.value[i];
+               lmin = 0;
+               lmax = 1;
+               lstep = 0;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_INTEGER:
+               lval = control->value.integer.value[i];
+               lmin = info->value.integer.min;
+               lmax = info->value.integer.max;
+               lstep = info->value.integer.step;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+               lval = control->value.integer64.value[i];
+               lmin = info->value.integer64.min;
+               lmax = info->value.integer64.max;
+               lstep = info->value.integer64.step;
+               break;
+       case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+               lval = control->value.enumerated.item[i];
+               lmin = 0;
+               lmax = info->value.enumerated.items - 1;
+               lstep = 0;
+               break;
        }
 
-       for (++i; i < ARRAY_SIZE(info->dimen.d); ++i) {
-               if (info->dimen.d[i] > 0)
-                       return false;
+       if (lval < lmin || lval > lmax) {
+               dev_err(card->dev,
+                       "control %i:%i:%i:%s:%i: value out of range %lld (%lld/%lld) at count %i\n",
+                       control->id.iface, control->id.device,
+                       control->id.subdevice, control->id.name,
+                       control->id.index, lval, lmin, lmax, i);
+               return -EINVAL;
+       }
+       if (lstep) {
+               div64_u64_rem(lval, lstep, &rem);
+               if (rem) {
+                       dev_err(card->dev,
+                               "control %i:%i:%i:%s:%i: unaligned value %lld (step %lld) at count %i\n",
+                               control->id.iface, control->id.device,
+                               control->id.subdevice, control->id.name,
+                               control->id.index, lval, lstep, i);
+                       return -EINVAL;
+               }
        }
 
-       return members == info->count;
+       return 0;
 }
 
-static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
-                            struct snd_ctl_elem_info *info)
+/* perform sanity checks to the given snd_ctl_elem_value object */
+static int sanity_check_elem_value(struct snd_card *card,
+                                  const struct snd_ctl_elem_value *control,
+                                  const struct snd_ctl_elem_info *info,
+                                  u32 pattern)
+{
+       size_t offset;
+       int i, ret = 0;
+       u32 *p;
+
+       switch (info->type) {
+       case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
+       case SNDRV_CTL_ELEM_TYPE_INTEGER:
+       case SNDRV_CTL_ELEM_TYPE_INTEGER64:
+       case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+               for (i = 0; i < info->count; i++) {
+                       ret = sanity_check_int_value(card, control, info, i);
+                       if (ret < 0)
+                               return ret;
+               }
+               break;
+       default:
+               break;
+       }
+
+       /* check whether the remaining area kept untouched */
+       offset = value_sizes[info->type] * info->count;
+       offset = (offset + sizeof(u32) - 1) / sizeof(u32);
+       p = (u32 *)control->value.bytes.data + offset;
+       for (; offset < sizeof(control->value) / sizeof(u32); offset++, p++) {
+               if (*p != pattern) {
+                       ret = -EINVAL;
+                       break;
+               }
+               *p = 0; /* clear the checked area */
+       }
+
+       return ret;
+}
+#else
+static inline void fill_remaining_elem_value(struct snd_ctl_elem_value *control,
+                                            struct snd_ctl_elem_info *info,
+                                            u32 pattern)
+{
+}
+
+static inline int sanity_check_elem_value(struct snd_card *card,
+                                         struct snd_ctl_elem_value *control,
+                                         struct snd_ctl_elem_info *info,
+                                         u32 pattern)
+{
+       return 0;
+}
+#endif
+
+static int __snd_ctl_elem_info(struct snd_card *card,
+                              struct snd_kcontrol *kctl,
+                              struct snd_ctl_elem_info *info,
+                              struct snd_ctl_file *ctl)
 {
-       struct snd_card *card = ctl->card;
-       struct snd_kcontrol *kctl;
        struct snd_kcontrol_volatile *vd;
        unsigned int index_offset;
        int result;
 
-       down_read(&card->controls_rwsem);
-       kctl = snd_ctl_find_id(card, &info->id);
-       if (kctl == NULL) {
-               up_read(&card->controls_rwsem);
-               return -ENOENT;
-       }
 #ifdef CONFIG_SND_DEBUG
        info->access = 0;
 #endif
@@ -821,7 +971,26 @@ static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
                } else {
                        info->owner = -1;
                }
+               if (!snd_ctl_skip_validation(info) &&
+                   snd_ctl_check_elem_info(card, info) < 0)
+                       result = -EINVAL;
        }
+       return result;
+}
+
+static int snd_ctl_elem_info(struct snd_ctl_file *ctl,
+                            struct snd_ctl_elem_info *info)
+{
+       struct snd_card *card = ctl->card;
+       struct snd_kcontrol *kctl;
+       int result;
+
+       down_read(&card->controls_rwsem);
+       kctl = snd_ctl_find_id(card, &info->id);
+       if (kctl == NULL)
+               result = -ENOENT;
+       else
+               result = __snd_ctl_elem_info(card, kctl, info, ctl);
        up_read(&card->controls_rwsem);
        return result;
 }
@@ -840,6 +1009,8 @@ static int snd_ctl_elem_info_user(struct snd_ctl_file *ctl,
        result = snd_ctl_elem_info(ctl, &info);
        if (result < 0)
                return result;
+       /* drop internal access flags */
+       info.access &= ~SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK;
        if (copy_to_user(_info, &info, sizeof(info)))
                return -EFAULT;
        return result;
@@ -851,6 +1022,9 @@ static int snd_ctl_elem_read(struct snd_card *card,
        struct snd_kcontrol *kctl;
        struct snd_kcontrol_volatile *vd;
        unsigned int index_offset;
+       struct snd_ctl_elem_info info;
+       const u32 pattern = 0xdeadbeef;
+       int ret;
 
        kctl = snd_ctl_find_id(card, &control->id);
        if (kctl == NULL)
@@ -862,7 +1036,31 @@ static int snd_ctl_elem_read(struct snd_card *card,
                return -EPERM;
 
        snd_ctl_build_ioff(&control->id, kctl, index_offset);
-       return kctl->get(kctl, control);
+
+#ifdef CONFIG_SND_CTL_VALIDATION
+       /* info is needed only for validation */
+       memset(&info, 0, sizeof(info));
+       info.id = control->id;
+       ret = __snd_ctl_elem_info(card, kctl, &info, NULL);
+       if (ret < 0)
+               return ret;
+#endif
+
+       if (!snd_ctl_skip_validation(&info))
+               fill_remaining_elem_value(control, &info, pattern);
+       ret = kctl->get(kctl, control);
+       if (ret < 0)
+               return ret;
+       if (!snd_ctl_skip_validation(&info) &&
+           sanity_check_elem_value(card, control, &info, pattern) < 0) {
+               dev_err(card->dev,
+                       "control %i:%i:%i:%s:%i: access overflow\n",
+                       control->id.iface, control->id.device,
+                       control->id.subdevice, control->id.name,
+                       control->id.index);
+               return -EINVAL;
+       }
+       return ret;
 }
 
 static int snd_ctl_elem_read_user(struct snd_card *card,
@@ -1203,23 +1401,6 @@ static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
 static int snd_ctl_elem_add(struct snd_ctl_file *file,
                            struct snd_ctl_elem_info *info, int replace)
 {
-       /* The capacity of struct snd_ctl_elem_value.value.*/
-       static const unsigned int value_sizes[] = {
-               [SNDRV_CTL_ELEM_TYPE_BOOLEAN]   = sizeof(long),
-               [SNDRV_CTL_ELEM_TYPE_INTEGER]   = sizeof(long),
-               [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = sizeof(unsigned int),
-               [SNDRV_CTL_ELEM_TYPE_BYTES]     = sizeof(unsigned char),
-               [SNDRV_CTL_ELEM_TYPE_IEC958]    = sizeof(struct snd_aes_iec958),
-               [SNDRV_CTL_ELEM_TYPE_INTEGER64] = sizeof(long long),
-       };
-       static const unsigned int max_value_counts[] = {
-               [SNDRV_CTL_ELEM_TYPE_BOOLEAN]   = 128,
-               [SNDRV_CTL_ELEM_TYPE_INTEGER]   = 128,
-               [SNDRV_CTL_ELEM_TYPE_ENUMERATED] = 128,
-               [SNDRV_CTL_ELEM_TYPE_BYTES]     = 512,
-               [SNDRV_CTL_ELEM_TYPE_IEC958]    = 1,
-               [SNDRV_CTL_ELEM_TYPE_INTEGER64] = 64,
-       };
        struct snd_card *card = file->card;
        struct snd_kcontrol *kctl;
        unsigned int count;
@@ -1271,16 +1452,12 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
         * Check information and calculate the size of data specific to
         * this userspace control.
         */
-       if (info->type < SNDRV_CTL_ELEM_TYPE_BOOLEAN ||
-           info->type > SNDRV_CTL_ELEM_TYPE_INTEGER64)
-               return -EINVAL;
-       if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED &&
-           info->value.enumerated.items == 0)
-               return -EINVAL;
-       if (info->count < 1 ||
-           info->count > max_value_counts[info->type])
-               return -EINVAL;
-       if (!validate_element_member_dimension(info))
+       /* pass NULL to card for suppressing error messages */
+       err = snd_ctl_check_elem_info(NULL, info);
+       if (err < 0)
+               return err;
+       /* user-space control doesn't allow zero-size data */
+       if (info->count < 1)
                return -EINVAL;
        private_size = value_sizes[info->type] * info->count;
 
@@ -1430,8 +1607,9 @@ static int call_tlv_handler(struct snd_ctl_file *file, int op_flag,
        if (kctl->tlv.c == NULL)
                return -ENXIO;
 
-       /* When locked, this is unavailable. */
-       if (vd->owner != NULL && vd->owner != file)
+       /* Write and command operations are not allowed for locked element. */
+       if (op_flag != SNDRV_CTL_TLV_OP_READ &&
+           vd->owner != NULL && vd->owner != file)
                return -EPERM;
 
        return kctl->tlv.c(kctl, op_flag, size, buf);
@@ -1854,7 +2032,7 @@ static int snd_ctl_dev_free(struct snd_device *device)
  */
 int snd_ctl_create(struct snd_card *card)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_ctl_dev_free,
                .dev_register = snd_ctl_dev_register,
                .dev_disconnect = snd_ctl_dev_disconnect,
index 708b919..cdc5af5 100644 (file)
@@ -27,7 +27,7 @@
  * Return: Zero if successful, or a negative error code on failure.
  */
 int snd_device_new(struct snd_card *card, enum snd_device_type type,
-                  void *device_data, struct snd_device_ops *ops)
+                  void *device_data, const struct snd_device_ops *ops)
 {
        struct snd_device *dev;
        struct list_head *p;
index 00cb5ae..b412d3b 100644 (file)
@@ -353,7 +353,7 @@ int snd_hwdep_new(struct snd_card *card, char *id, int device,
 {
        struct snd_hwdep *hwdep;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_hwdep_dev_free,
                .dev_register = snd_hwdep_dev_register,
                .dev_disconnect = snd_hwdep_dev_disconnect,
index e051a02..6801d81 100644 (file)
@@ -20,7 +20,7 @@
 
 int snd_info_check_reserved_words(const char *str)
 {
-       static char *reserved[] =
+       static const char * const reserved[] =
        {
                "version",
                "meminfo",
@@ -35,7 +35,7 @@ int snd_info_check_reserved_words(const char *str)
                "seq",
                NULL
        };
-       char **xstr = reserved;
+       const char * const *xstr = reserved;
 
        while (*xstr) {
                if (!strcmp(*xstr, str))
index faa9f03..b02a997 100644 (file)
@@ -211,6 +211,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
        INIT_LIST_HEAD(&card->ctl_files);
        spin_lock_init(&card->files_lock);
        INIT_LIST_HEAD(&card->files_list);
+       mutex_init(&card->memory_mutex);
 #ifdef CONFIG_PM
        init_waitqueue_head(&card->power_sleep);
 #endif
index fb26196..503c8af 100644 (file)
@@ -19,7 +19,7 @@ struct snd_jack_kctl {
 };
 
 #ifdef CONFIG_SND_JACK_INPUT_DEV
-static int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
+static const int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
        SW_HEADPHONE_INSERT,
        SW_MICROPHONE_INSERT,
        SW_LINEOUT_INSERT,
@@ -201,7 +201,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
        struct snd_jack *jack;
        struct snd_jack_kctl *jack_kctl = NULL;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_jack_dev_free,
 #ifdef CONFIG_SND_JACK_INPUT_DEV
                .dev_register = snd_jack_dev_register,
index 7eb54df..f702c96 100644 (file)
@@ -486,7 +486,7 @@ struct slot {
        unsigned int channels;
        unsigned int numid[SNDRV_MIXER_OSS_ITEM_COUNT];
        unsigned int capture_item;
-       struct snd_mixer_oss_assign_table *assigned;
+       const struct snd_mixer_oss_assign_table *assigned;
        unsigned int allocated: 1;
 };
 
@@ -934,8 +934,8 @@ static void snd_mixer_oss_slot_free(struct snd_mixer_oss_slot *chn)
        struct slot *p = chn->private_data;
        if (p) {
                if (p->allocated && p->assigned) {
-                       kfree(p->assigned->name);
-                       kfree(p->assigned);
+                       kfree_const(p->assigned->name);
+                       kfree_const(p->assigned);
                }
                kfree(p);
        }
@@ -953,7 +953,7 @@ static void mixer_slot_clear(struct snd_mixer_oss_slot *rslot)
 /* In a separate function to keep gcc 3.2 happy - do NOT merge this in
    snd_mixer_oss_build_input! */
 static int snd_mixer_oss_build_test_all(struct snd_mixer_oss *mixer,
-                                       struct snd_mixer_oss_assign_table *ptr,
+                                       const struct snd_mixer_oss_assign_table *ptr,
                                        struct slot *slot)
 {
        char str[64];
@@ -1017,7 +1017,9 @@ static int snd_mixer_oss_build_test_all(struct snd_mixer_oss *mixer,
  * ptr_allocated means the entry is dynamically allocated (change via proc file).
  * when replace_old = 1, the old entry is replaced with the new one.
  */
-static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mixer_oss_assign_table *ptr, int ptr_allocated, int replace_old)
+static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer,
+                                    const struct snd_mixer_oss_assign_table *ptr,
+                                    int ptr_allocated, int replace_old)
 {
        struct slot slot;
        struct slot *pslot;
@@ -1107,7 +1109,7 @@ static int snd_mixer_oss_build_input(struct snd_mixer_oss *mixer, struct snd_mix
 /*
  */
 #define MIXER_VOL(name) [SOUND_MIXER_##name] = #name
-static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
+static const char * const oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
        MIXER_VOL(VOLUME),
        MIXER_VOL(BASS),
        MIXER_VOL(TREBLE),
@@ -1255,7 +1257,7 @@ static void snd_mixer_oss_proc_done(struct snd_mixer_oss *mixer)
 
 static void snd_mixer_oss_build(struct snd_mixer_oss *mixer)
 {
-       static struct snd_mixer_oss_assign_table table[] = {
+       static const struct snd_mixer_oss_assign_table table[] = {
                { SOUND_MIXER_VOLUME,   "Master",               0 },
                { SOUND_MIXER_VOLUME,   "Front",                0 }, /* fallback */
                { SOUND_MIXER_BASS,     "Tone Control - Bass",  0 },
index 31cb2ac..240e470 100644 (file)
@@ -288,7 +288,7 @@ static int snd_pcm_plug_formats(const struct snd_mask *mask,
        return snd_mask_test(&formats, (__force int)format);
 }
 
-static snd_pcm_format_t preferred_formats[] = {
+static const snd_pcm_format_t preferred_formats[] = {
        SNDRV_PCM_FORMAT_S16_LE,
        SNDRV_PCM_FORMAT_S16_BE,
        SNDRV_PCM_FORMAT_U16_LE,
index 9a72d64..a141a30 100644 (file)
@@ -163,7 +163,7 @@ static int snd_pcm_control_ioctl(struct snd_card *card,
 
 #define FORMAT(v) [SNDRV_PCM_FORMAT_##v] = #v
 
-static char *snd_pcm_format_names[] = {
+static const char * const snd_pcm_format_names[] = {
        FORMAT(S8),
        FORMAT(U8),
        FORMAT(S16_LE),
@@ -237,12 +237,12 @@ EXPORT_SYMBOL_GPL(snd_pcm_format_name);
 #define START(v) [SNDRV_PCM_START_##v] = #v
 #define SUBFORMAT(v) [SNDRV_PCM_SUBFORMAT_##v] = #v 
 
-static char *snd_pcm_stream_names[] = {
+static const char * const snd_pcm_stream_names[] = {
        STREAM(PLAYBACK),
        STREAM(CAPTURE),
 };
 
-static char *snd_pcm_state_names[] = {
+static const char * const snd_pcm_state_names[] = {
        STATE(OPEN),
        STATE(SETUP),
        STATE(PREPARED),
@@ -253,7 +253,7 @@ static char *snd_pcm_state_names[] = {
        STATE(SUSPENDED),
 };
 
-static char *snd_pcm_access_names[] = {
+static const char * const snd_pcm_access_names[] = {
        ACCESS(MMAP_INTERLEAVED), 
        ACCESS(MMAP_NONINTERLEAVED),
        ACCESS(MMAP_COMPLEX),
@@ -261,11 +261,11 @@ static char *snd_pcm_access_names[] = {
        ACCESS(RW_NONINTERLEAVED),
 };
 
-static char *snd_pcm_subformat_names[] = {
+static const char * const snd_pcm_subformat_names[] = {
        SUBFORMAT(STD), 
 };
 
-static char *snd_pcm_tstamp_mode_names[] = {
+static const char * const snd_pcm_tstamp_mode_names[] = {
        TSTAMP(NONE),
        TSTAMP(ENABLE),
 };
@@ -443,7 +443,7 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
 {
        struct snd_pcm_substream *substream = entry->private_data;
        struct snd_pcm_runtime *runtime;
-       struct snd_pcm_status status;
+       struct snd_pcm_status64 status;
        int err;
 
        mutex_lock(&substream->pcm->open_mutex);
@@ -453,17 +453,17 @@ static void snd_pcm_substream_proc_status_read(struct snd_info_entry *entry,
                goto unlock;
        }
        memset(&status, 0, sizeof(status));
-       err = snd_pcm_status(substream, &status);
+       err = snd_pcm_status64(substream, &status);
        if (err < 0) {
                snd_iprintf(buffer, "error %d\n", err);
                goto unlock;
        }
        snd_iprintf(buffer, "state: %s\n", snd_pcm_state_name(status.state));
        snd_iprintf(buffer, "owner_pid   : %d\n", pid_vnr(substream->pid));
-       snd_iprintf(buffer, "trigger_time: %ld.%09ld\n",
-               status.trigger_tstamp.tv_sec, status.trigger_tstamp.tv_nsec);
-       snd_iprintf(buffer, "tstamp      : %ld.%09ld\n",
-               status.tstamp.tv_sec, status.tstamp.tv_nsec);
+       snd_iprintf(buffer, "trigger_time: %lld.%09lld\n",
+               status.trigger_tstamp_sec, status.trigger_tstamp_nsec);
+       snd_iprintf(buffer, "tstamp      : %lld.%09lld\n",
+               status.tstamp_sec, status.tstamp_nsec);
        snd_iprintf(buffer, "delay       : %ld\n", status.delay);
        snd_iprintf(buffer, "avail       : %ld\n", status.avail);
        snd_iprintf(buffer, "avail_max   : %ld\n", status.avail_max);
@@ -706,12 +706,12 @@ static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
 {
        struct snd_pcm *pcm;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_pcm_dev_free,
                .dev_register = snd_pcm_dev_register,
                .dev_disconnect = snd_pcm_dev_disconnect,
        };
-       static struct snd_device_ops internal_ops = {
+       static const struct snd_device_ops internal_ops = {
                .dev_free = snd_pcm_dev_free,
        };
 
index 6f9003b..590a46a 100644 (file)
@@ -83,19 +83,6 @@ struct snd_pcm_sw_params32 {
        unsigned char reserved[56];
 };
 
-/* recalcuate the boundary within 32bit */
-static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
-{
-       snd_pcm_uframes_t boundary;
-
-       if (! runtime->buffer_size)
-               return 0;
-       boundary = runtime->buffer_size;
-       while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
-               boundary *= 2;
-       return boundary;
-}
-
 static int snd_pcm_ioctl_sw_params_compat(struct snd_pcm_substream *substream,
                                          struct snd_pcm_sw_params32 __user *src)
 {
@@ -168,97 +155,39 @@ static int snd_pcm_channel_info_user(struct snd_pcm_substream *substream,
        snd_pcm_channel_info_user(s, p)
 #endif /* CONFIG_X86_X32 */
 
-struct snd_pcm_status32 {
-       s32 state;
-       struct compat_timespec trigger_tstamp;
-       struct compat_timespec tstamp;
+struct compat_snd_pcm_status64 {
+       snd_pcm_state_t state;
+       u8 rsvd[4]; /* alignment */
+       s64 trigger_tstamp_sec;
+       s64 trigger_tstamp_nsec;
+       s64 tstamp_sec;
+       s64 tstamp_nsec;
        u32 appl_ptr;
        u32 hw_ptr;
        s32 delay;
        u32 avail;
        u32 avail_max;
        u32 overrange;
-       s32 suspended_state;
+       snd_pcm_state_t suspended_state;
        u32 audio_tstamp_data;
-       struct compat_timespec audio_tstamp;
-       struct compat_timespec driver_tstamp;
+       s64 audio_tstamp_sec;
+       s64 audio_tstamp_nsec;
+       s64 driver_tstamp_sec;
+       s64 driver_tstamp_nsec;
        u32 audio_tstamp_accuracy;
-       unsigned char reserved[52-2*sizeof(struct compat_timespec)];
-} __attribute__((packed));
-
-
-static int snd_pcm_status_user_compat(struct snd_pcm_substream *substream,
-                                     struct snd_pcm_status32 __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) ||
-           compat_put_timespec(&status.trigger_tstamp, &src->trigger_tstamp) ||
-           compat_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) ||
-           compat_put_timespec(&status.audio_tstamp, &src->audio_tstamp) ||
-           compat_put_timespec(&status.driver_tstamp, &src->driver_tstamp) ||
-           put_user(status.audio_tstamp_accuracy, &src->audio_tstamp_accuracy))
-               return -EFAULT;
-
-       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)];
+       unsigned char reserved[52-4*sizeof(s64)];
 } __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)
+static int snd_pcm_status_user_compat64(struct snd_pcm_substream *substream,
+                                       struct compat_snd_pcm_status64 __user *src,
+                                       bool ext)
 {
-       struct snd_pcm_status status;
+       struct snd_pcm_status64 status;
+       struct compat_snd_pcm_status64 compat_status64;
        int err;
 
        memset(&status, 0, sizeof(status));
+       memset(&compat_status64, 0, sizeof(compat_status64));
        /*
         * with extension, parameters are read/write,
         * get audio_tstamp_data from user,
@@ -267,31 +196,39 @@ static int snd_pcm_status_user_x32(struct snd_pcm_substream *substream,
        if (ext && get_user(status.audio_tstamp_data,
                                (u32 __user *)(&src->audio_tstamp_data)))
                return -EFAULT;
-       err = snd_pcm_status(substream, &status);
+       err = snd_pcm_status64(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))
+
+       compat_status64 = (struct compat_snd_pcm_status64) {
+               .state = status.state,
+               .trigger_tstamp_sec = status.trigger_tstamp_sec,
+               .trigger_tstamp_nsec = status.trigger_tstamp_nsec,
+               .tstamp_sec = status.tstamp_sec,
+               .tstamp_nsec = status.tstamp_nsec,
+               .appl_ptr = status.appl_ptr,
+               .hw_ptr = status.hw_ptr,
+               .delay = status.delay,
+               .avail = status.avail,
+               .avail_max = status.avail_max,
+               .overrange = status.overrange,
+               .suspended_state = status.suspended_state,
+               .audio_tstamp_data = status.audio_tstamp_data,
+               .audio_tstamp_sec = status.audio_tstamp_sec,
+               .audio_tstamp_nsec = status.audio_tstamp_nsec,
+               .driver_tstamp_sec = status.audio_tstamp_sec,
+               .driver_tstamp_nsec = status.audio_tstamp_nsec,
+               .audio_tstamp_accuracy = status.audio_tstamp_accuracy,
+       };
+
+       if (copy_to_user(src, &compat_status64, sizeof(compat_status64)))
                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,
@@ -436,102 +373,19 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
        return err;
 }
 
-
-struct snd_pcm_mmap_status32 {
-       s32 state;
-       s32 pad1;
-       u32 hw_ptr;
-       struct compat_timespec tstamp;
-       s32 suspended_state;
-       struct compat_timespec audio_tstamp;
-} __attribute__((packed));
-
-struct snd_pcm_mmap_control32 {
-       u32 appl_ptr;
-       u32 avail_min;
-};
-
-struct snd_pcm_sync_ptr32 {
-       u32 flags;
-       union {
-               struct snd_pcm_mmap_status32 status;
-               unsigned char reserved[64];
-       } s;
-       union {
-               struct snd_pcm_mmap_control32 control;
-               unsigned char reserved[64];
-       } c;
-} __attribute__((packed));
-
-static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
-                                        struct snd_pcm_sync_ptr32 __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) ||
-           compat_put_timespec(&sstatus.tstamp, &src->s.status.tstamp) ||
-           put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
-           compat_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;
-}
-
 #ifdef CONFIG_X86_X32
 /* X32 ABI has 64bit timespec and 64bit alignment */
 struct snd_pcm_mmap_status_x32 {
-       s32 state;
+       snd_pcm_state_t state;
        s32 pad1;
        u32 hw_ptr;
        u32 pad2; /* alignment */
-       struct timespec tstamp;
-       s32 suspended_state;
+       s64 tstamp_sec;
+       s64 tstamp_nsec;
+       snd_pcm_state_t suspended_state;
        s32 pad3;
-       struct timespec audio_tstamp;
+       s64 audio_tstamp_sec;
+       s64 audio_tstamp_nsec;
 } __packed;
 
 struct snd_pcm_mmap_control_x32 {
@@ -599,9 +453,11 @@ static int snd_pcm_ioctl_sync_ptr_x32(struct snd_pcm_substream *substream,
        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.tstamp.tv_sec, &src->s.status.tstamp_sec) ||
+           put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) ||
            put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
-           put_timespec(&sstatus.audio_tstamp, &src->s.status.audio_tstamp) ||
+           put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) ||
+           put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) ||
            put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
            put_user(scontrol.avail_min, &src->c.control.avail_min))
                return -EFAULT;
@@ -616,8 +472,8 @@ enum {
        SNDRV_PCM_IOCTL_HW_REFINE32 = _IOWR('A', 0x10, struct snd_pcm_hw_params32),
        SNDRV_PCM_IOCTL_HW_PARAMS32 = _IOWR('A', 0x11, struct snd_pcm_hw_params32),
        SNDRV_PCM_IOCTL_SW_PARAMS32 = _IOWR('A', 0x13, struct snd_pcm_sw_params32),
-       SNDRV_PCM_IOCTL_STATUS32 = _IOR('A', 0x20, struct snd_pcm_status32),
-       SNDRV_PCM_IOCTL_STATUS_EXT32 = _IOWR('A', 0x24, struct snd_pcm_status32),
+       SNDRV_PCM_IOCTL_STATUS_COMPAT32 = _IOR('A', 0x20, struct snd_pcm_status32),
+       SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32 = _IOWR('A', 0x24, struct snd_pcm_status32),
        SNDRV_PCM_IOCTL_DELAY32 = _IOR('A', 0x21, s32),
        SNDRV_PCM_IOCTL_CHANNEL_INFO32 = _IOR('A', 0x32, struct snd_pcm_channel_info32),
        SNDRV_PCM_IOCTL_REWIND32 = _IOW('A', 0x46, u32),
@@ -626,11 +482,10 @@ enum {
        SNDRV_PCM_IOCTL_READI_FRAMES32 = _IOR('A', 0x51, struct snd_xferi32),
        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),
+       SNDRV_PCM_IOCTL_STATUS_COMPAT64 = _IOR('A', 0x20, struct compat_snd_pcm_status64),
+       SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64 = _IOWR('A', 0x24, struct compat_snd_pcm_status64),
 #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 */
 };
@@ -650,8 +505,8 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
 
        /*
         * When PCM is used on 32bit mode, we need to disable
-        * mmap of PCM status/control records because of the size
-        * incompatibility.
+        * mmap of the old PCM status/control records because
+        * of the size incompatibility.
         */
        pcm_file->no_compat_mmap = 1;
 
@@ -673,6 +528,13 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
        case SNDRV_PCM_IOCTL_XRUN:
        case SNDRV_PCM_IOCTL_LINK:
        case SNDRV_PCM_IOCTL_UNLINK:
+       case __SNDRV_PCM_IOCTL_SYNC_PTR32:
+               return snd_pcm_common_ioctl(file, substream, cmd, argp);
+       case __SNDRV_PCM_IOCTL_SYNC_PTR64:
+#ifdef CONFIG_X86_X32
+               if (in_x32_syscall())
+                       return snd_pcm_ioctl_sync_ptr_x32(substream, argp);
+#endif /* CONFIG_X86_X32 */
                return snd_pcm_common_ioctl(file, substream, cmd, argp);
        case SNDRV_PCM_IOCTL_HW_REFINE32:
                return snd_pcm_ioctl_hw_params_compat(substream, 1, argp);
@@ -680,12 +542,10 @@ static long snd_pcm_ioctl_compat(struct file *file, unsigned int cmd, unsigned l
                return snd_pcm_ioctl_hw_params_compat(substream, 0, argp);
        case SNDRV_PCM_IOCTL_SW_PARAMS32:
                return snd_pcm_ioctl_sw_params_compat(substream, argp);
-       case SNDRV_PCM_IOCTL_STATUS32:
-               return snd_pcm_status_user_compat(substream, argp, false);
-       case SNDRV_PCM_IOCTL_STATUS_EXT32:
-               return snd_pcm_status_user_compat(substream, argp, true);
-       case SNDRV_PCM_IOCTL_SYNC_PTR32:
-               return snd_pcm_ioctl_sync_ptr_compat(substream, argp);
+       case SNDRV_PCM_IOCTL_STATUS_COMPAT32:
+               return snd_pcm_status_user32(substream, argp, false);
+       case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT32:
+               return snd_pcm_status_user32(substream, argp, true);
        case SNDRV_PCM_IOCTL_CHANNEL_INFO32:
                return snd_pcm_ioctl_channel_info_compat(substream, argp);
        case SNDRV_PCM_IOCTL_WRITEI_FRAMES32:
@@ -702,13 +562,11 @@ 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);
+       case SNDRV_PCM_IOCTL_STATUS_COMPAT64:
+               return snd_pcm_status_user_compat64(substream, argp, false);
+       case SNDRV_PCM_IOCTL_STATUS_EXT_COMPAT64:
+               return snd_pcm_status_user_compat64(substream, argp, true);
 #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 */
index 2236b5e..872a852 100644 (file)
@@ -144,8 +144,13 @@ void __snd_pcm_xrun(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
 
        trace_xrun(substream);
-       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
-               snd_pcm_gettime(runtime, (struct timespec *)&runtime->status->tstamp);
+       if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
+               struct timespec64 tstamp;
+
+               snd_pcm_gettime(runtime, &tstamp);
+               runtime->status->tstamp.tv_sec = tstamp.tv_sec;
+               runtime->status->tstamp.tv_nsec = tstamp.tv_nsec;
+       }
        snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
        if (xrun_debug(substream, XRUN_DEBUG_BASIC)) {
                char name[16];
@@ -200,12 +205,12 @@ int snd_pcm_update_state(struct snd_pcm_substream *substream,
 }
 
 static void update_audio_tstamp(struct snd_pcm_substream *substream,
-                               struct timespec *curr_tstamp,
-                               struct timespec *audio_tstamp)
+                               struct timespec64 *curr_tstamp,
+                               struct timespec64 *audio_tstamp)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        u64 audio_frames, audio_nsecs;
-       struct timespec driver_tstamp;
+       struct timespec64 driver_tstamp;
 
        if (runtime->tstamp_mode != SNDRV_PCM_TSTAMP_ENABLE)
                return;
@@ -229,18 +234,23 @@ static void update_audio_tstamp(struct snd_pcm_substream *substream,
                }
                audio_nsecs = div_u64(audio_frames * 1000000000LL,
                                runtime->rate);
-               *audio_tstamp = ns_to_timespec(audio_nsecs);
+               *audio_tstamp = ns_to_timespec64(audio_nsecs);
        }
-       if (!timespec_equal(&runtime->status->audio_tstamp, audio_tstamp)) {
-               runtime->status->audio_tstamp = *audio_tstamp;
-               runtime->status->tstamp = *curr_tstamp;
+
+       if (runtime->status->audio_tstamp.tv_sec != audio_tstamp->tv_sec ||
+           runtime->status->audio_tstamp.tv_nsec != audio_tstamp->tv_nsec) {
+               runtime->status->audio_tstamp.tv_sec = audio_tstamp->tv_sec;
+               runtime->status->audio_tstamp.tv_nsec = audio_tstamp->tv_nsec;
+               runtime->status->tstamp.tv_sec = curr_tstamp->tv_sec;
+               runtime->status->tstamp.tv_nsec = curr_tstamp->tv_nsec;
        }
 
+
        /*
         * re-take a driver timestamp to let apps detect if the reference tstamp
         * read by low-level hardware was provided with a delay
         */
-       snd_pcm_gettime(substream->runtime, (struct timespec *)&driver_tstamp);
+       snd_pcm_gettime(substream->runtime, &driver_tstamp);
        runtime->driver_tstamp = driver_tstamp;
 }
 
@@ -253,8 +263,8 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
        snd_pcm_sframes_t hdelta, delta;
        unsigned long jdelta;
        unsigned long curr_jiffies;
-       struct timespec curr_tstamp;
-       struct timespec audio_tstamp;
+       struct timespec64 curr_tstamp;
+       struct timespec64 audio_tstamp;
        int crossed_boundary = 0;
 
        old_hw_ptr = runtime->status->hw_ptr;
@@ -277,9 +287,9 @@ static int snd_pcm_update_hw_ptr0(struct snd_pcm_substream *substream,
 
                        /* re-test in case tstamp type is not supported in hardware and was demoted to DEFAULT */
                        if (runtime->audio_tstamp_report.actual_type == SNDRV_PCM_AUDIO_TSTAMP_TYPE_DEFAULT)
-                               snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
+                               snd_pcm_gettime(runtime, &curr_tstamp);
                } else
-                       snd_pcm_gettime(runtime, (struct timespec *)&curr_tstamp);
+                       snd_pcm_gettime(runtime, &curr_tstamp);
        }
 
        if (pos == SNDRV_PCM_POS_XRUN) {
@@ -1442,7 +1452,7 @@ EXPORT_SYMBOL(snd_pcm_hw_constraint_step);
 
 static int snd_pcm_hw_rule_pow2(struct snd_pcm_hw_params *params, struct snd_pcm_hw_rule *rule)
 {
-       static unsigned int pow2_sizes[] = {
+       static const unsigned int pow2_sizes[] = {
                1<<0, 1<<1, 1<<2, 1<<3, 1<<4, 1<<5, 1<<6, 1<<7,
                1<<8, 1<<9, 1<<10, 1<<11, 1<<12, 1<<13, 1<<14, 1<<15,
                1<<16, 1<<17, 1<<18, 1<<19, 1<<20, 1<<21, 1<<22, 1<<23,
@@ -2308,7 +2318,6 @@ static int pcm_chmap_ctl_info(struct snd_kcontrol *kcontrol,
        struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-       uinfo->count = 0;
        uinfo->count = info->max_channels;
        uinfo->value.integer.min = 0;
        uinfo->value.integer.max = SNDRV_CHMAP_LAST;
@@ -2332,7 +2341,7 @@ static int pcm_chmap_ctl_get(struct snd_kcontrol *kcontrol,
        if (!substream)
                return -ENODEV;
        memset(ucontrol->value.integer.value, 0,
-              sizeof(ucontrol->value.integer.value));
+              sizeof(long) * info->max_channels);
        if (!substream->runtime)
                return 0; /* no channels set */
        for (map = info->chmap; map->channels; map++) {
index 384efd0..17a1a5d 100644 (file)
@@ -20,9 +20,6 @@ void snd_interval_muldivk(const struct snd_interval *a,
 void snd_interval_mulkdiv(const struct snd_interval *a, unsigned int k,
                          const struct snd_interval *b, struct snd_interval *c);
 
-int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream);
-int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream);
-
 int snd_pcm_hw_constraint_mask(struct snd_pcm_runtime *runtime,
                               snd_pcm_hw_param_t var, u_int32_t mask);
 
index d4702cc..fcab37e 100644 (file)
@@ -27,6 +27,38 @@ MODULE_PARM_DESC(maximum_substreams, "Maximum substreams with preallocated DMA m
 
 static const size_t snd_minimum_buffer = 16384;
 
+static unsigned long max_alloc_per_card = 32UL * 1024UL * 1024UL;
+module_param(max_alloc_per_card, ulong, 0644);
+MODULE_PARM_DESC(max_alloc_per_card, "Max total allocation bytes per card.");
+
+static int do_alloc_pages(struct snd_card *card, int type, struct device *dev,
+                         size_t size, struct snd_dma_buffer *dmab)
+{
+       int err;
+
+       if (max_alloc_per_card &&
+           card->total_pcm_alloc_bytes + size > max_alloc_per_card)
+               return -ENOMEM;
+       err = snd_dma_alloc_pages(type, dev, size, dmab);
+       if (!err) {
+               mutex_lock(&card->memory_mutex);
+               card->total_pcm_alloc_bytes += dmab->bytes;
+               mutex_unlock(&card->memory_mutex);
+       }
+       return err;
+}
+
+static void do_free_pages(struct snd_card *card, struct snd_dma_buffer *dmab)
+{
+       if (!dmab->area)
+               return;
+       mutex_lock(&card->memory_mutex);
+       WARN_ON(card->total_pcm_alloc_bytes < dmab->bytes);
+       card->total_pcm_alloc_bytes -= dmab->bytes;
+       mutex_unlock(&card->memory_mutex);
+       snd_dma_free_pages(dmab);
+       dmab->area = NULL;
+}
 
 /*
  * try to allocate as the large pages as possible.
@@ -37,16 +69,15 @@ static const size_t snd_minimum_buffer = 16384;
 static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t size)
 {
        struct snd_dma_buffer *dmab = &substream->dma_buffer;
+       struct snd_card *card = substream->pcm->card;
        size_t orig_size = size;
        int err;
 
        do {
-               if ((err = snd_dma_alloc_pages(dmab->dev.type, dmab->dev.dev,
-                                              size, dmab)) < 0) {
-                       if (err != -ENOMEM)
-                               return err; /* fatal error */
-               } else
-                       return 0;
+               err = do_alloc_pages(card, dmab->dev.type, dmab->dev.dev,
+                                    size, dmab);
+               if (err != -ENOMEM)
+                       return err;
                size >>= 1;
        } while (size >= snd_minimum_buffer);
        dmab->bytes = 0; /* tell error */
@@ -62,10 +93,7 @@ static int preallocate_pcm_pages(struct snd_pcm_substream *substream, size_t siz
  */
 static void snd_pcm_lib_preallocate_dma_free(struct snd_pcm_substream *substream)
 {
-       if (substream->dma_buffer.area == NULL)
-               return;
-       snd_dma_free_pages(&substream->dma_buffer);
-       substream->dma_buffer.area = NULL;
+       do_free_pages(substream->pcm->card, &substream->dma_buffer);
 }
 
 /**
@@ -130,6 +158,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
                                               struct snd_info_buffer *buffer)
 {
        struct snd_pcm_substream *substream = entry->private_data;
+       struct snd_card *card = substream->pcm->card;
        char line[64], str[64];
        size_t size;
        struct snd_dma_buffer new_dmab;
@@ -150,9 +179,10 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
                memset(&new_dmab, 0, sizeof(new_dmab));
                new_dmab.dev = substream->dma_buffer.dev;
                if (size > 0) {
-                       if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
-                                               substream->dma_buffer.dev.dev,
-                                               size, &new_dmab) < 0) {
+                       if (do_alloc_pages(card,
+                                          substream->dma_buffer.dev.type,
+                                          substream->dma_buffer.dev.dev,
+                                          size, &new_dmab) < 0) {
                                buffer->error = -ENOMEM;
                                return;
                        }
@@ -161,7 +191,7 @@ static void snd_pcm_lib_preallocate_proc_write(struct snd_info_entry *entry,
                        substream->buffer_bytes_max = UINT_MAX;
                }
                if (substream->dma_buffer.area)
-                       snd_dma_free_pages(&substream->dma_buffer);
+                       do_free_pages(card, &substream->dma_buffer);
                substream->dma_buffer = new_dmab;
        } else {
                buffer->error = -EINVAL;
@@ -346,6 +376,7 @@ struct page *snd_pcm_sgbuf_ops_page(struct snd_pcm_substream *substream, unsigne
  */
 int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
 {
+       struct snd_card *card = substream->pcm->card;
        struct snd_pcm_runtime *runtime;
        struct snd_dma_buffer *dmab = NULL;
 
@@ -374,9 +405,10 @@ int snd_pcm_lib_malloc_pages(struct snd_pcm_substream *substream, size_t size)
                if (! dmab)
                        return -ENOMEM;
                dmab->dev = substream->dma_buffer.dev;
-               if (snd_dma_alloc_pages(substream->dma_buffer.dev.type,
-                                       substream->dma_buffer.dev.dev,
-                                       size, dmab) < 0) {
+               if (do_alloc_pages(card,
+                                  substream->dma_buffer.dev.type,
+                                  substream->dma_buffer.dev.dev,
+                                  size, dmab) < 0) {
                        kfree(dmab);
                        return -ENOMEM;
                }
@@ -397,6 +429,7 @@ EXPORT_SYMBOL(snd_pcm_lib_malloc_pages);
  */
 int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
 {
+       struct snd_card *card = substream->pcm->card;
        struct snd_pcm_runtime *runtime;
 
        if (PCM_RUNTIME_CHECK(substream))
@@ -406,7 +439,7 @@ int snd_pcm_lib_free_pages(struct snd_pcm_substream *substream)
                return 0;
        if (runtime->dma_buffer_p != &substream->dma_buffer) {
                /* it's a newly allocated buffer.  release it now. */
-               snd_dma_free_pages(runtime->dma_buffer_p);
+               do_free_pages(card, runtime->dma_buffer_p);
                kfree(runtime->dma_buffer_p);
        }
        snd_pcm_set_runtime_buffer(substream, NULL);
index c4eb561..a6a5415 100644 (file)
@@ -42,7 +42,7 @@ struct pcm_format_data {
 /* we do lots of calculations on snd_pcm_format_t; shut up sparse */
 #define INT    __force int
 
-static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
+static const struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
        [SNDRV_PCM_FORMAT_S8] = {
                .width = 8, .phys = 8, .le = -1, .signd = 1,
                .silence = {},
@@ -415,7 +415,8 @@ EXPORT_SYMBOL(snd_pcm_format_silence_64);
 int snd_pcm_format_set_silence(snd_pcm_format_t format, void *data, unsigned int samples)
 {
        int width;
-       unsigned char *dst, *pat;
+       unsigned char *dst;
+       const unsigned char *pat;
 
        if ((INT)format < 0 || (INT)format > (INT)SNDRV_PCM_FORMAT_LAST)
                return -EINVAL;
index 1fe5811..336406b 100644 (file)
@@ -4,6 +4,7 @@
  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  */
 
+#include <linux/compat.h>
 #include <linux/mm.h>
 #include <linux/module.h>
 #include <linux/file.h>
@@ -550,7 +551,8 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)
        return usecs;
 }
 
-static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_set_state(struct snd_pcm_substream *substream,
+                             snd_pcm_state_t state)
 {
        snd_pcm_stream_lock_irq(substream);
        if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED)
@@ -739,6 +741,10 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,
        while (runtime->boundary * 2 <= LONG_MAX - runtime->buffer_size)
                runtime->boundary *= 2;
 
+       /* clear the buffer for avoiding possible kernel info leaks */
+       if (runtime->dma_area && !substream->ops->copy_user)
+               memset(runtime->dma_area, 0, runtime->dma_bytes);
+
        snd_pcm_timer_resolution_change(substream);
        snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);
 
@@ -781,10 +787,22 @@ end:
        return err;
 }
 
+static int do_hw_free(struct snd_pcm_substream *substream)
+{
+       int result = 0;
+
+       snd_pcm_sync_stop(substream);
+       if (substream->ops->hw_free)
+               result = substream->ops->hw_free(substream);
+       if (substream->managed_buffer_alloc)
+               snd_pcm_lib_free_pages(substream);
+       return result;
+}
+
 static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime;
-       int result = 0;
+       int result;
 
        if (PCM_RUNTIME_CHECK(substream))
                return -ENXIO;
@@ -801,11 +819,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)
        snd_pcm_stream_unlock_irq(substream);
        if (atomic_read(&substream->mmap_count))
                return -EBADFD;
-       snd_pcm_sync_stop(substream);
-       if (substream->ops->hw_free)
-               result = substream->ops->hw_free(substream);
-       if (substream->managed_buffer_alloc)
-               snd_pcm_lib_free_pages(substream);
+       result = do_hw_free(substream);
        snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);
        pm_qos_remove_request(&substream->latency_pm_qos_req);
        return result;
@@ -891,8 +905,8 @@ snd_pcm_calc_delay(struct snd_pcm_substream *substream)
        return delay + substream->runtime->delay;
 }
 
-int snd_pcm_status(struct snd_pcm_substream *substream,
-                  struct snd_pcm_status *status)
+int snd_pcm_status64(struct snd_pcm_substream *substream,
+                    struct snd_pcm_status64 *status)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
 
@@ -918,14 +932,22 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
        status->suspended_state = runtime->status->suspended_state;
        if (status->state == SNDRV_PCM_STATE_OPEN)
                goto _end;
-       status->trigger_tstamp = runtime->trigger_tstamp;
+       status->trigger_tstamp_sec = runtime->trigger_tstamp.tv_sec;
+       status->trigger_tstamp_nsec = runtime->trigger_tstamp.tv_nsec;
        if (snd_pcm_running(substream)) {
                snd_pcm_update_hw_ptr(substream);
                if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
-                       status->tstamp = runtime->status->tstamp;
-                       status->driver_tstamp = runtime->driver_tstamp;
-                       status->audio_tstamp =
-                               runtime->status->audio_tstamp;
+                       status->tstamp_sec = runtime->status->tstamp.tv_sec;
+                       status->tstamp_nsec =
+                               runtime->status->tstamp.tv_nsec;
+                       status->driver_tstamp_sec =
+                               runtime->driver_tstamp.tv_sec;
+                       status->driver_tstamp_nsec =
+                               runtime->driver_tstamp.tv_nsec;
+                       status->audio_tstamp_sec =
+                               runtime->status->audio_tstamp.tv_sec;
+                       status->audio_tstamp_nsec =
+                               runtime->status->audio_tstamp.tv_nsec;
                        if (runtime->audio_tstamp_report.valid == 1)
                                /* backwards compatibility, no report provided in COMPAT mode */
                                snd_pcm_pack_audio_tstamp_report(&status->audio_tstamp_data,
@@ -936,8 +958,13 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
                }
        } else {
                /* get tstamp only in fallback mode and only if enabled */
-               if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE)
-                       snd_pcm_gettime(runtime, &status->tstamp);
+               if (runtime->tstamp_mode == SNDRV_PCM_TSTAMP_ENABLE) {
+                       struct timespec64 tstamp;
+
+                       snd_pcm_gettime(runtime, &tstamp);
+                       status->tstamp_sec = tstamp.tv_sec;
+                       status->tstamp_nsec = tstamp.tv_nsec;
+               }
        }
  _tstamp_end:
        status->appl_ptr = runtime->control->appl_ptr;
@@ -954,11 +981,11 @@ int snd_pcm_status(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_pcm_status_user(struct snd_pcm_substream *substream,
-                              struct snd_pcm_status __user * _status,
-                              bool ext)
+static int snd_pcm_status_user64(struct snd_pcm_substream *substream,
+                                struct snd_pcm_status64 __user * _status,
+                                bool ext)
 {
-       struct snd_pcm_status status;
+       struct snd_pcm_status64 status;
        int res;
 
        memset(&status, 0, sizeof(status));
@@ -970,7 +997,7 @@ static int snd_pcm_status_user(struct snd_pcm_substream *substream,
        if (ext && get_user(status.audio_tstamp_data,
                                (u32 __user *)(&_status->audio_tstamp_data)))
                return -EFAULT;
-       res = snd_pcm_status(substream, &status);
+       res = snd_pcm_status64(substream, &status);
        if (res < 0)
                return res;
        if (copy_to_user(_status, &status, sizeof(status)))
@@ -978,6 +1005,55 @@ static int snd_pcm_status_user(struct snd_pcm_substream *substream,
        return 0;
 }
 
+static int snd_pcm_status_user32(struct snd_pcm_substream *substream,
+                                struct snd_pcm_status32 __user * _status,
+                                bool ext)
+{
+       struct snd_pcm_status64 status64;
+       struct snd_pcm_status32 status32;
+       int res;
+
+       memset(&status64, 0, sizeof(status64));
+       memset(&status32, 0, sizeof(status32));
+       /*
+        * with extension, parameters are read/write,
+        * get audio_tstamp_data from user,
+        * ignore rest of status structure
+        */
+       if (ext && get_user(status64.audio_tstamp_data,
+                           (u32 __user *)(&_status->audio_tstamp_data)))
+               return -EFAULT;
+       res = snd_pcm_status64(substream, &status64);
+       if (res < 0)
+               return res;
+
+       status32 = (struct snd_pcm_status32) {
+               .state = status64.state,
+               .trigger_tstamp_sec = status64.trigger_tstamp_sec,
+               .trigger_tstamp_nsec = status64.trigger_tstamp_nsec,
+               .tstamp_sec = status64.tstamp_sec,
+               .tstamp_nsec = status64.tstamp_nsec,
+               .appl_ptr = status64.appl_ptr,
+               .hw_ptr = status64.hw_ptr,
+               .delay = status64.delay,
+               .avail = status64.avail,
+               .avail_max = status64.avail_max,
+               .overrange = status64.overrange,
+               .suspended_state = status64.suspended_state,
+               .audio_tstamp_data = status64.audio_tstamp_data,
+               .audio_tstamp_sec = status64.audio_tstamp_sec,
+               .audio_tstamp_nsec = status64.audio_tstamp_nsec,
+               .driver_tstamp_sec = status64.audio_tstamp_sec,
+               .driver_tstamp_nsec = status64.audio_tstamp_nsec,
+               .audio_tstamp_accuracy = status64.audio_tstamp_accuracy,
+       };
+
+       if (copy_to_user(_status, &status32, sizeof(status32)))
+               return -EFAULT;
+
+       return 0;
+}
+
 static int snd_pcm_channel_info(struct snd_pcm_substream *substream,
                                struct snd_pcm_channel_info * info)
 {
@@ -1030,11 +1106,17 @@ static void snd_pcm_trigger_tstamp(struct snd_pcm_substream *substream)
        runtime->trigger_master = NULL;
 }
 
+#define ACTION_ARG_IGNORE      (__force snd_pcm_state_t)0
+
 struct action_ops {
-       int (*pre_action)(struct snd_pcm_substream *substream, int state);
-       int (*do_action)(struct snd_pcm_substream *substream, int state);
-       void (*undo_action)(struct snd_pcm_substream *substream, int state);
-       void (*post_action)(struct snd_pcm_substream *substream, int state);
+       int (*pre_action)(struct snd_pcm_substream *substream,
+                         snd_pcm_state_t state);
+       int (*do_action)(struct snd_pcm_substream *substream,
+                        snd_pcm_state_t state);
+       void (*undo_action)(struct snd_pcm_substream *substream,
+                           snd_pcm_state_t state);
+       void (*post_action)(struct snd_pcm_substream *substream,
+                           snd_pcm_state_t state);
 };
 
 /*
@@ -1044,7 +1126,8 @@ struct action_ops {
  */
 static int snd_pcm_action_group(const struct action_ops *ops,
                                struct snd_pcm_substream *substream,
-                               int state, int do_lock)
+                               snd_pcm_state_t state,
+                               bool do_lock)
 {
        struct snd_pcm_substream *s = NULL;
        struct snd_pcm_substream *s1;
@@ -1101,7 +1184,7 @@ static int snd_pcm_action_group(const struct action_ops *ops,
  */
 static int snd_pcm_action_single(const struct action_ops *ops,
                                 struct snd_pcm_substream *substream,
-                                int state)
+                                snd_pcm_state_t state)
 {
        int res;
        
@@ -1182,14 +1265,14 @@ snd_pcm_stream_group_ref(struct snd_pcm_substream *substream)
  */
 static int snd_pcm_action(const struct action_ops *ops,
                          struct snd_pcm_substream *substream,
-                         int state)
+                         snd_pcm_state_t state)
 {
        struct snd_pcm_group *group;
        int res;
 
        group = snd_pcm_stream_group_ref(substream);
        if (group)
-               res = snd_pcm_action_group(ops, substream, state, 1);
+               res = snd_pcm_action_group(ops, substream, state, true);
        else
                res = snd_pcm_action_single(ops, substream, state);
        snd_pcm_group_unref(group, substream);
@@ -1201,7 +1284,7 @@ static int snd_pcm_action(const struct action_ops *ops,
  */
 static int snd_pcm_action_lock_irq(const struct action_ops *ops,
                                   struct snd_pcm_substream *substream,
-                                  int state)
+                                  snd_pcm_state_t state)
 {
        int res;
 
@@ -1215,14 +1298,14 @@ static int snd_pcm_action_lock_irq(const struct action_ops *ops,
  */
 static int snd_pcm_action_nonatomic(const struct action_ops *ops,
                                    struct snd_pcm_substream *substream,
-                                   int state)
+                                   snd_pcm_state_t state)
 {
        int res;
 
        /* Guarantee the group members won't change during non-atomic action */
        down_read(&snd_pcm_link_rwsem);
        if (snd_pcm_stream_linked(substream))
-               res = snd_pcm_action_group(ops, substream, state, 0);
+               res = snd_pcm_action_group(ops, substream, state, false);
        else
                res = snd_pcm_action_single(ops, substream, state);
        up_read(&snd_pcm_link_rwsem);
@@ -1232,7 +1315,8 @@ static int snd_pcm_action_nonatomic(const struct action_ops *ops,
 /*
  * start callbacks
  */
-static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_pre_start(struct snd_pcm_substream *substream,
+                            snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (runtime->status->state != SNDRV_PCM_STATE_PREPARED)
@@ -1245,20 +1329,23 @@ static int snd_pcm_pre_start(struct snd_pcm_substream *substream, int state)
        return 0;
 }
 
-static int snd_pcm_do_start(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_do_start(struct snd_pcm_substream *substream,
+                           snd_pcm_state_t state)
 {
        if (substream->runtime->trigger_master != substream)
                return 0;
        return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_START);
 }
 
-static void snd_pcm_undo_start(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_undo_start(struct snd_pcm_substream *substream,
+                              snd_pcm_state_t state)
 {
        if (substream->runtime->trigger_master == substream)
                substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_STOP);
 }
 
-static void snd_pcm_post_start(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_post_start(struct snd_pcm_substream *substream,
+                              snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_trigger_tstamp(substream);
@@ -1302,7 +1389,8 @@ static int snd_pcm_start_lock_irq(struct snd_pcm_substream *substream)
 /*
  * stop callbacks
  */
-static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_pre_stop(struct snd_pcm_substream *substream,
+                           snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
@@ -1311,7 +1399,8 @@ static int snd_pcm_pre_stop(struct snd_pcm_substream *substream, int state)
        return 0;
 }
 
-static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_do_stop(struct snd_pcm_substream *substream,
+                          snd_pcm_state_t state)
 {
        if (substream->runtime->trigger_master == substream &&
            snd_pcm_running(substream))
@@ -1319,7 +1408,8 @@ static int snd_pcm_do_stop(struct snd_pcm_substream *substream, int state)
        return 0; /* unconditonally stop all substreams */
 }
 
-static void snd_pcm_post_stop(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_post_stop(struct snd_pcm_substream *substream,
+                             snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (runtime->status->state != state) {
@@ -1390,14 +1480,17 @@ int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
 EXPORT_SYMBOL_GPL(snd_pcm_stop_xrun);
 
 /*
- * pause callbacks
+ * pause callbacks: pass boolean (to start pause or resume) as state argument
  */
-static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
+#define pause_pushed(state)    (__force bool)(state)
+
+static int snd_pcm_pre_pause(struct snd_pcm_substream *substream,
+                            snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (!(runtime->info & SNDRV_PCM_INFO_PAUSE))
                return -ENOSYS;
-       if (push) {
+       if (pause_pushed(state)) {
                if (runtime->status->state != SNDRV_PCM_STATE_RUNNING)
                        return -EBADFD;
        } else if (runtime->status->state != SNDRV_PCM_STATE_PAUSED)
@@ -1406,13 +1499,14 @@ static int snd_pcm_pre_pause(struct snd_pcm_substream *substream, int push)
        return 0;
 }
 
-static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
+static int snd_pcm_do_pause(struct snd_pcm_substream *substream,
+                           snd_pcm_state_t state)
 {
        if (substream->runtime->trigger_master != substream)
                return 0;
        /* some drivers might use hw_ptr to recover from the pause -
           update the hw_ptr now */
-       if (push)
+       if (pause_pushed(state))
                snd_pcm_update_hw_ptr(substream);
        /* The jiffies check in snd_pcm_update_hw_ptr*() is done by
         * a delta between the current jiffies, this gives a large enough
@@ -1420,23 +1514,27 @@ static int snd_pcm_do_pause(struct snd_pcm_substream *substream, int push)
         */
        substream->runtime->hw_ptr_jiffies = jiffies - HZ * 1000;
        return substream->ops->trigger(substream,
-                                      push ? SNDRV_PCM_TRIGGER_PAUSE_PUSH :
-                                             SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+                                      pause_pushed(state) ?
+                                      SNDRV_PCM_TRIGGER_PAUSE_PUSH :
+                                      SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
 }
 
-static void snd_pcm_undo_pause(struct snd_pcm_substream *substream, int push)
+static void snd_pcm_undo_pause(struct snd_pcm_substream *substream,
+                              snd_pcm_state_t state)
 {
        if (substream->runtime->trigger_master == substream)
                substream->ops->trigger(substream,
-                                       push ? SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
+                                       pause_pushed(state) ?
+                                       SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
                                        SNDRV_PCM_TRIGGER_PAUSE_PUSH);
 }
 
-static void snd_pcm_post_pause(struct snd_pcm_substream *substream, int push)
+static void snd_pcm_post_pause(struct snd_pcm_substream *substream,
+                              snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_trigger_tstamp(substream);
-       if (push) {
+       if (pause_pushed(state)) {
                runtime->status->state = SNDRV_PCM_STATE_PAUSED;
                snd_pcm_timer_notify(substream, SNDRV_TIMER_EVENT_MPAUSE);
                wake_up(&runtime->sleep);
@@ -1457,15 +1555,24 @@ static const struct action_ops snd_pcm_action_pause = {
 /*
  * Push/release the pause for all linked streams.
  */
-static int snd_pcm_pause(struct snd_pcm_substream *substream, int push)
+static int snd_pcm_pause(struct snd_pcm_substream *substream, bool push)
+{
+       return snd_pcm_action(&snd_pcm_action_pause, substream,
+                             (__force snd_pcm_state_t)push);
+}
+
+static int snd_pcm_pause_lock_irq(struct snd_pcm_substream *substream,
+                                 bool push)
 {
-       return snd_pcm_action(&snd_pcm_action_pause, substream, push);
+       return snd_pcm_action_lock_irq(&snd_pcm_action_pause, substream,
+                                      (__force snd_pcm_state_t)push);
 }
 
 #ifdef CONFIG_PM
-/* suspend */
+/* suspend callback: state argument ignored */
 
-static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream,
+                              snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        switch (runtime->status->state) {
@@ -1481,7 +1588,8 @@ static int snd_pcm_pre_suspend(struct snd_pcm_substream *substream, int state)
        return 0;
 }
 
-static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_do_suspend(struct snd_pcm_substream *substream,
+                             snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (runtime->trigger_master != substream)
@@ -1492,7 +1600,8 @@ static int snd_pcm_do_suspend(struct snd_pcm_substream *substream, int state)
        return 0; /* suspend unconditionally */
 }
 
-static void snd_pcm_post_suspend(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_post_suspend(struct snd_pcm_substream *substream,
+                                snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_trigger_tstamp(substream);
@@ -1523,7 +1632,8 @@ static int snd_pcm_suspend(struct snd_pcm_substream *substream)
        unsigned long flags;
 
        snd_pcm_stream_lock_irqsave(substream, flags);
-       err = snd_pcm_action(&snd_pcm_action_suspend, substream, 0);
+       err = snd_pcm_action(&snd_pcm_action_suspend, substream,
+                            ACTION_ARG_IGNORE);
        snd_pcm_stream_unlock_irqrestore(substream, flags);
        return err;
 }
@@ -1567,9 +1677,10 @@ int snd_pcm_suspend_all(struct snd_pcm *pcm)
 }
 EXPORT_SYMBOL(snd_pcm_suspend_all);
 
-/* resume */
+/* resume callbacks: state argument ignored */
 
-static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_pre_resume(struct snd_pcm_substream *substream,
+                             snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (!(runtime->info & SNDRV_PCM_INFO_RESUME))
@@ -1578,7 +1689,8 @@ static int snd_pcm_pre_resume(struct snd_pcm_substream *substream, int state)
        return 0;
 }
 
-static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_do_resume(struct snd_pcm_substream *substream,
+                            snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (runtime->trigger_master != substream)
@@ -1591,14 +1703,16 @@ static int snd_pcm_do_resume(struct snd_pcm_substream *substream, int state)
        return substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_RESUME);
 }
 
-static void snd_pcm_undo_resume(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_undo_resume(struct snd_pcm_substream *substream,
+                               snd_pcm_state_t state)
 {
        if (substream->runtime->trigger_master == substream &&
            snd_pcm_running(substream))
                substream->ops->trigger(substream, SNDRV_PCM_TRIGGER_SUSPEND);
 }
 
-static void snd_pcm_post_resume(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_post_resume(struct snd_pcm_substream *substream,
+                               snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        snd_pcm_trigger_tstamp(substream);
@@ -1616,7 +1730,8 @@ static const struct action_ops snd_pcm_action_resume = {
 
 static int snd_pcm_resume(struct snd_pcm_substream *substream)
 {
-       return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream, 0);
+       return snd_pcm_action_lock_irq(&snd_pcm_action_resume, substream,
+                                      ACTION_ARG_IGNORE);
 }
 
 #else
@@ -1657,7 +1772,9 @@ static int snd_pcm_xrun(struct snd_pcm_substream *substream)
 /*
  * reset ioctl
  */
-static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
+/* reset callbacks:  state argument ignored */
+static int snd_pcm_pre_reset(struct snd_pcm_substream *substream,
+                            snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        switch (runtime->status->state) {
@@ -1671,7 +1788,8 @@ static int snd_pcm_pre_reset(struct snd_pcm_substream *substream, int state)
        }
 }
 
-static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_do_reset(struct snd_pcm_substream *substream,
+                           snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        int err = snd_pcm_ops_ioctl(substream, SNDRV_PCM_IOCTL1_RESET, NULL);
@@ -1685,7 +1803,8 @@ static int snd_pcm_do_reset(struct snd_pcm_substream *substream, int state)
        return 0;
 }
 
-static void snd_pcm_post_reset(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_post_reset(struct snd_pcm_substream *substream,
+                              snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        runtime->control->appl_ptr = runtime->status->hw_ptr;
@@ -1702,17 +1821,20 @@ static const struct action_ops snd_pcm_action_reset = {
 
 static int snd_pcm_reset(struct snd_pcm_substream *substream)
 {
-       return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream, 0);
+       return snd_pcm_action_nonatomic(&snd_pcm_action_reset, substream,
+                                       ACTION_ARG_IGNORE);
 }
 
 /*
  * prepare ioctl
  */
-/* we use the second argument for updating f_flags */
+/* pass f_flags as state argument */
 static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
-                              int f_flags)
+                              snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
+       int f_flags = (__force int)state;
+
        if (runtime->status->state == SNDRV_PCM_STATE_OPEN ||
            runtime->status->state == SNDRV_PCM_STATE_DISCONNECTED)
                return -EBADFD;
@@ -1722,17 +1844,19 @@ static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_pcm_do_prepare(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_do_prepare(struct snd_pcm_substream *substream,
+                             snd_pcm_state_t state)
 {
        int err;
        snd_pcm_sync_stop(substream);
        err = substream->ops->prepare(substream);
        if (err < 0)
                return err;
-       return snd_pcm_do_reset(substream, 0);
+       return snd_pcm_do_reset(substream, state);
 }
 
-static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_post_prepare(struct snd_pcm_substream *substream,
+                                snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        runtime->control->appl_ptr = runtime->status->hw_ptr;
@@ -1765,7 +1889,7 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
        snd_pcm_stream_lock_irq(substream);
        switch (substream->runtime->status->state) {
        case SNDRV_PCM_STATE_PAUSED:
-               snd_pcm_pause(substream, 0);
+               snd_pcm_pause(substream, false);
                /* fallthru */
        case SNDRV_PCM_STATE_SUSPENDED:
                snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
@@ -1774,14 +1898,17 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
        snd_pcm_stream_unlock_irq(substream);
 
        return snd_pcm_action_nonatomic(&snd_pcm_action_prepare,
-                                       substream, f_flags);
+                                       substream,
+                                       (__force snd_pcm_state_t)f_flags);
 }
 
 /*
  * drain ioctl
  */
 
-static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
+/* drain init callbacks: state argument ignored */
+static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream,
+                                 snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        switch (runtime->status->state) {
@@ -1794,7 +1921,8 @@ static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state
        return 0;
 }
 
-static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
+static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream,
+                                snd_pcm_state_t state)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
@@ -1820,7 +1948,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
        } else {
                /* stop running stream */
                if (runtime->status->state == SNDRV_PCM_STATE_RUNNING) {
-                       int new_state = snd_pcm_capture_avail(runtime) > 0 ?
+                       snd_pcm_state_t new_state;
+
+                       new_state = snd_pcm_capture_avail(runtime) > 0 ?
                                SNDRV_PCM_STATE_DRAINING : SNDRV_PCM_STATE_SETUP;
                        snd_pcm_do_stop(substream, new_state);
                        snd_pcm_post_stop(substream, new_state);
@@ -1836,7 +1966,8 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
        return 0;
 }
 
-static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream, int state)
+static void snd_pcm_post_drain_init(struct snd_pcm_substream *substream,
+                                   snd_pcm_state_t state)
 {
 }
 
@@ -1879,10 +2010,11 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
        snd_pcm_stream_lock_irq(substream);
        /* resume pause */
        if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
-               snd_pcm_pause(substream, 0);
+               snd_pcm_pause(substream, false);
 
        /* pre-start/stop - all running streams are changed to DRAINING state */
-       result = snd_pcm_action(&snd_pcm_action_drain_init, substream, 0);
+       result = snd_pcm_action(&snd_pcm_action_drain_init, substream,
+                               ACTION_ARG_IGNORE);
        if (result < 0)
                goto unlock;
        /* in non-blocking, we don't wait in ioctl but let caller poll */
@@ -1983,7 +2115,7 @@ static int snd_pcm_drop(struct snd_pcm_substream *substream)
        snd_pcm_stream_lock_irq(substream);
        /* resume pause */
        if (runtime->status->state == SNDRV_PCM_STATE_PAUSED)
-               snd_pcm_pause(substream, 0);
+               snd_pcm_pause(substream, false);
 
        snd_pcm_stop(substream, SNDRV_PCM_STATE_SETUP);
        /* runtime->control->appl_ptr = runtime->status->hw_ptr; */
@@ -2241,7 +2373,7 @@ static int snd_pcm_hw_rule_buffer_bytes_max(struct snd_pcm_hw_params *params,
        return snd_interval_refine(hw_param_interval(params, rule->var), &t);
 }              
 
-int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
+static int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_pcm_hw_constraints *constrs = &runtime->hw_constraints;
@@ -2365,7 +2497,7 @@ int snd_pcm_hw_constraints_init(struct snd_pcm_substream *substream)
        return 0;
 }
 
-int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
+static int snd_pcm_hw_constraints_complete(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_pcm_hardware *hw = &runtime->hw;
@@ -2462,9 +2594,7 @@ void snd_pcm_release_substream(struct snd_pcm_substream *substream)
 
        snd_pcm_drop(substream);
        if (substream->hw_opened) {
-               if (substream->ops->hw_free &&
-                   substream->runtime->status->state != SNDRV_PCM_STATE_OPEN)
-                       substream->ops->hw_free(substream);
+               do_hw_free(substream);
                substream->ops->close(substream);
                substream->hw_opened = 0;
        }
@@ -2826,6 +2956,107 @@ static int snd_pcm_sync_ptr(struct snd_pcm_substream *substream,
        return 0;
 }
 
+struct snd_pcm_mmap_status32 {
+       snd_pcm_state_t state;
+       s32 pad1;
+       u32 hw_ptr;
+       s32 tstamp_sec;
+       s32 tstamp_nsec;
+       snd_pcm_state_t suspended_state;
+       s32 audio_tstamp_sec;
+       s32 audio_tstamp_nsec;
+} __attribute__((packed));
+
+struct snd_pcm_mmap_control32 {
+       u32 appl_ptr;
+       u32 avail_min;
+};
+
+struct snd_pcm_sync_ptr32 {
+       u32 flags;
+       union {
+               struct snd_pcm_mmap_status32 status;
+               unsigned char reserved[64];
+       } s;
+       union {
+               struct snd_pcm_mmap_control32 control;
+               unsigned char reserved[64];
+       } c;
+} __attribute__((packed));
+
+/* recalcuate the boundary within 32bit */
+static snd_pcm_uframes_t recalculate_boundary(struct snd_pcm_runtime *runtime)
+{
+       snd_pcm_uframes_t boundary;
+
+       if (! runtime->buffer_size)
+               return 0;
+       boundary = runtime->buffer_size;
+       while (boundary * 2 <= 0x7fffffffUL - runtime->buffer_size)
+               boundary *= 2;
+       return boundary;
+}
+
+static int snd_pcm_ioctl_sync_ptr_compat(struct snd_pcm_substream *substream,
+                                        struct snd_pcm_sync_ptr32 __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_user(sstatus.tstamp.tv_sec, &src->s.status.tstamp_sec) ||
+           put_user(sstatus.tstamp.tv_nsec, &src->s.status.tstamp_nsec) ||
+           put_user(sstatus.suspended_state, &src->s.status.suspended_state) ||
+           put_user(sstatus.audio_tstamp.tv_sec, &src->s.status.audio_tstamp_sec) ||
+           put_user(sstatus.audio_tstamp.tv_nsec, &src->s.status.audio_tstamp_nsec) ||
+           put_user(scontrol.appl_ptr, &src->c.control.appl_ptr) ||
+           put_user(scontrol.avail_min, &src->c.control.avail_min))
+               return -EFAULT;
+
+       return 0;
+}
+#define __SNDRV_PCM_IOCTL_SYNC_PTR32 _IOWR('A', 0x23, struct snd_pcm_sync_ptr32)
+
 static int snd_pcm_tstamp(struct snd_pcm_substream *substream, int __user *_arg)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -2955,10 +3186,14 @@ static int snd_pcm_common_ioctl(struct file *file,
                return snd_pcm_hw_free(substream);
        case SNDRV_PCM_IOCTL_SW_PARAMS:
                return snd_pcm_sw_params_user(substream, arg);
-       case SNDRV_PCM_IOCTL_STATUS:
-               return snd_pcm_status_user(substream, arg, false);
-       case SNDRV_PCM_IOCTL_STATUS_EXT:
-               return snd_pcm_status_user(substream, arg, true);
+       case SNDRV_PCM_IOCTL_STATUS32:
+               return snd_pcm_status_user32(substream, arg, false);
+       case SNDRV_PCM_IOCTL_STATUS_EXT32:
+               return snd_pcm_status_user32(substream, arg, true);
+       case SNDRV_PCM_IOCTL_STATUS64:
+               return snd_pcm_status_user64(substream, arg, false);
+       case SNDRV_PCM_IOCTL_STATUS_EXT64:
+               return snd_pcm_status_user64(substream, arg, true);
        case SNDRV_PCM_IOCTL_CHANNEL_INFO:
                return snd_pcm_channel_info_user(substream, arg);
        case SNDRV_PCM_IOCTL_PREPARE:
@@ -2990,7 +3225,9 @@ static int snd_pcm_common_ioctl(struct file *file,
                        return -EFAULT;
                return 0;
        }
-       case SNDRV_PCM_IOCTL_SYNC_PTR:
+       case __SNDRV_PCM_IOCTL_SYNC_PTR32:
+               return snd_pcm_ioctl_sync_ptr_compat(substream, arg);
+       case __SNDRV_PCM_IOCTL_SYNC_PTR64:
                return snd_pcm_sync_ptr(substream, arg);
 #ifdef CONFIG_SND_SUPPORT_OLD_API
        case SNDRV_PCM_IOCTL_HW_REFINE_OLD:
@@ -3003,9 +3240,7 @@ static int snd_pcm_common_ioctl(struct file *file,
        case SNDRV_PCM_IOCTL_DROP:
                return snd_pcm_drop(substream);
        case SNDRV_PCM_IOCTL_PAUSE:
-               return snd_pcm_action_lock_irq(&snd_pcm_action_pause,
-                                              substream,
-                                              (int)(unsigned long)arg);
+               return snd_pcm_pause_lock_irq(substream, (unsigned long)arg);
        case SNDRV_PCM_IOCTL_WRITEI_FRAMES:
        case SNDRV_PCM_IOCTL_READI_FRAMES:
                return snd_pcm_xferi_frames_ioctl(substream, arg);
@@ -3328,8 +3563,6 @@ static int snd_pcm_mmap_control(struct snd_pcm_substream *substream, struct file
 
 static bool pcm_status_mmap_allowed(struct snd_pcm_file *pcm_file)
 {
-       if (pcm_file->no_compat_mmap)
-               return false;
        /* See pcm_control_mmap_allowed() below.
         * Since older alsa-lib requires both status and control mmaps to be
         * coupled, we have to disable the status mmap for old alsa-lib, too.
@@ -3554,11 +3787,19 @@ static int snd_pcm_mmap(struct file *file, struct vm_area_struct *area)
 
        offset = area->vm_pgoff << PAGE_SHIFT;
        switch (offset) {
-       case SNDRV_PCM_MMAP_OFFSET_STATUS:
+       case SNDRV_PCM_MMAP_OFFSET_STATUS_OLD:
+               if (pcm_file->no_compat_mmap || !IS_ENABLED(CONFIG_64BIT))
+                       return -ENXIO;
+               /* fallthrough */
+       case SNDRV_PCM_MMAP_OFFSET_STATUS_NEW:
                if (!pcm_status_mmap_allowed(pcm_file))
                        return -ENXIO;
                return snd_pcm_mmap_status(substream, file, area);
-       case SNDRV_PCM_MMAP_OFFSET_CONTROL:
+       case SNDRV_PCM_MMAP_OFFSET_CONTROL_OLD:
+               if (pcm_file->no_compat_mmap || !IS_ENABLED(CONFIG_64BIT))
+                       return -ENXIO;
+               /* fallthrough */
+       case SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW:
                if (!pcm_control_mmap_allowed(pcm_file))
                        return -ENXIO;
                return snd_pcm_mmap_control(substream, file, area);
@@ -3718,9 +3959,9 @@ static unsigned long snd_pcm_get_unmapped_area(struct file *file,
        unsigned long offset = pgoff << PAGE_SHIFT;
 
        switch (offset) {
-       case SNDRV_PCM_MMAP_OFFSET_STATUS:
+       case SNDRV_PCM_MMAP_OFFSET_STATUS_NEW:
                return (unsigned long)runtime->status;
-       case SNDRV_PCM_MMAP_OFFSET_CONTROL:
+       case SNDRV_PCM_MMAP_OFFSET_CONTROL_NEW:
                return (unsigned long)runtime->control;
        default:
                return (unsigned long)runtime->dma_area + offset;
index 7928bda..c43484b 100644 (file)
@@ -75,7 +75,7 @@ static int snd_pcm_timer_stop(struct snd_timer * timer)
        return 0;
 }
 
-static struct snd_timer_hardware snd_pcm_timer =
+static const struct snd_timer_hardware snd_pcm_timer =
 {
        .flags =        SNDRV_TIMER_HW_AUTO | SNDRV_TIMER_HW_SLAVE,
        .resolution =   0,
index 8a12a75..20dd08e 100644 (file)
@@ -50,6 +50,29 @@ static DEFINE_MUTEX(register_mutex);
 #define rmidi_dbg(rmidi, fmt, args...) \
        dev_dbg(&(rmidi)->dev, fmt, ##args)
 
+struct snd_rawmidi_status32 {
+       s32 stream;
+       s32 tstamp_sec;                 /* Timestamp */
+       s32 tstamp_nsec;
+       u32 avail;                      /* available bytes */
+       u32 xruns;                      /* count of overruns since last status (in bytes) */
+       unsigned char reserved[16];     /* reserved for future use */
+};
+
+#define SNDRV_RAWMIDI_IOCTL_STATUS32   _IOWR('W', 0x20, struct snd_rawmidi_status32)
+
+struct snd_rawmidi_status64 {
+       int stream;
+       u8 rsvd[4];                     /* alignment */
+       s64 tstamp_sec;                 /* Timestamp */
+       s64 tstamp_nsec;
+       size_t avail;                   /* available bytes */
+       size_t xruns;                   /* count of overruns since last status (in bytes) */
+       unsigned char reserved[16];     /* reserved for future use */
+};
+
+#define SNDRV_RAWMIDI_IOCTL_STATUS64   _IOWR('W', 0x20, struct snd_rawmidi_status64)
+
 static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
 {
        struct snd_rawmidi *rawmidi;
@@ -226,7 +249,7 @@ static int assign_substream(struct snd_rawmidi *rmidi, int subdevice,
 {
        struct snd_rawmidi_substream *substream;
        struct snd_rawmidi_str *s = &rmidi->streams[stream];
-       static unsigned int info_flags[2] = {
+       static const unsigned int info_flags[2] = {
                [SNDRV_RAWMIDI_STREAM_OUTPUT] = SNDRV_RAWMIDI_INFO_OUTPUT,
                [SNDRV_RAWMIDI_STREAM_INPUT] = SNDRV_RAWMIDI_INFO_INPUT,
        };
@@ -677,7 +700,7 @@ int snd_rawmidi_input_params(struct snd_rawmidi_substream *substream,
 EXPORT_SYMBOL(snd_rawmidi_input_params);
 
 static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
-                                    struct snd_rawmidi_status *status)
+                                    struct snd_rawmidi_status64 *status)
 {
        struct snd_rawmidi_runtime *runtime = substream->runtime;
 
@@ -690,7 +713,7 @@ static int snd_rawmidi_output_status(struct snd_rawmidi_substream *substream,
 }
 
 static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,
-                                   struct snd_rawmidi_status *status)
+                                   struct snd_rawmidi_status64 *status)
 {
        struct snd_rawmidi_runtime *runtime = substream->runtime;
 
@@ -704,6 +727,80 @@ static int snd_rawmidi_input_status(struct snd_rawmidi_substream *substream,
        return 0;
 }
 
+static int snd_rawmidi_ioctl_status32(struct snd_rawmidi_file *rfile,
+                                     struct snd_rawmidi_status32 __user *argp)
+{
+       int err = 0;
+       struct snd_rawmidi_status32 __user *status = argp;
+       struct snd_rawmidi_status32 status32;
+       struct snd_rawmidi_status64 status64;
+
+       if (copy_from_user(&status32, argp,
+                          sizeof(struct snd_rawmidi_status32)))
+               return -EFAULT;
+
+       switch (status32.stream) {
+       case SNDRV_RAWMIDI_STREAM_OUTPUT:
+               if (rfile->output == NULL)
+                       return -EINVAL;
+               err = snd_rawmidi_output_status(rfile->output, &status64);
+               break;
+       case SNDRV_RAWMIDI_STREAM_INPUT:
+               if (rfile->input == NULL)
+                       return -EINVAL;
+               err = snd_rawmidi_input_status(rfile->input, &status64);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (err < 0)
+               return err;
+
+       status32 = (struct snd_rawmidi_status32) {
+               .stream = status64.stream,
+               .tstamp_sec = status64.tstamp_sec,
+               .tstamp_nsec = status64.tstamp_nsec,
+               .avail = status64.avail,
+               .xruns = status64.xruns,
+       };
+
+       if (copy_to_user(status, &status32, sizeof(*status)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int snd_rawmidi_ioctl_status64(struct snd_rawmidi_file *rfile,
+                                     struct snd_rawmidi_status64 __user *argp)
+{
+       int err = 0;
+       struct snd_rawmidi_status64 status;
+
+       if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status64)))
+               return -EFAULT;
+
+       switch (status.stream) {
+       case SNDRV_RAWMIDI_STREAM_OUTPUT:
+               if (rfile->output == NULL)
+                       return -EINVAL;
+               err = snd_rawmidi_output_status(rfile->output, &status);
+               break;
+       case SNDRV_RAWMIDI_STREAM_INPUT:
+               if (rfile->input == NULL)
+                       return -EINVAL;
+               err = snd_rawmidi_input_status(rfile->input, &status);
+               break;
+       default:
+               return -EINVAL;
+       }
+       if (err < 0)
+               return err;
+       if (copy_to_user(argp, &status,
+                        sizeof(struct snd_rawmidi_status64)))
+               return -EFAULT;
+       return 0;
+}
+
 static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct snd_rawmidi_file *rfile;
@@ -750,33 +847,10 @@ static long snd_rawmidi_ioctl(struct file *file, unsigned int cmd, unsigned long
                        return -EINVAL;
                }
        }
-       case SNDRV_RAWMIDI_IOCTL_STATUS:
-       {
-               int err = 0;
-               struct snd_rawmidi_status status;
-
-               if (copy_from_user(&status, argp, sizeof(struct snd_rawmidi_status)))
-                       return -EFAULT;
-               switch (status.stream) {
-               case SNDRV_RAWMIDI_STREAM_OUTPUT:
-                       if (rfile->output == NULL)
-                               return -EINVAL;
-                       err = snd_rawmidi_output_status(rfile->output, &status);
-                       break;
-               case SNDRV_RAWMIDI_STREAM_INPUT:
-                       if (rfile->input == NULL)
-                               return -EINVAL;
-                       err = snd_rawmidi_input_status(rfile->input, &status);
-                       break;
-               default:
-                       return -EINVAL;
-               }
-               if (err < 0)
-                       return err;
-               if (copy_to_user(argp, &status, sizeof(struct snd_rawmidi_status)))
-                       return -EFAULT;
-               return 0;
-       }
+       case SNDRV_RAWMIDI_IOCTL_STATUS32:
+               return snd_rawmidi_ioctl_status32(rfile, argp);
+       case SNDRV_RAWMIDI_IOCTL_STATUS64:
+               return snd_rawmidi_ioctl_status64(rfile, argp);
        case SNDRV_RAWMIDI_IOCTL_DROP:
        {
                int val;
@@ -1547,7 +1621,7 @@ int snd_rawmidi_new(struct snd_card *card, char *id, int device,
 {
        struct snd_rawmidi *rmidi;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_rawmidi_dev_free,
                .dev_register = snd_rawmidi_dev_register,
                .dev_disconnect = snd_rawmidi_dev_disconnect,
index 66eee61..7397130 100644 (file)
@@ -41,19 +41,22 @@ static int snd_rawmidi_ioctl_params_compat(struct snd_rawmidi_file *rfile,
        return -EINVAL;
 }
 
-struct snd_rawmidi_status32 {
+struct compat_snd_rawmidi_status64 {
        s32 stream;
-       struct compat_timespec tstamp;
+       u8 rsvd[4]; /* alignment */
+       s64 tstamp_sec;
+       s64 tstamp_nsec;
        u32 avail;
        u32 xruns;
        unsigned char reserved[16];
 } __attribute__((packed));
 
-static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
-                                          struct snd_rawmidi_status32 __user *src)
+static int snd_rawmidi_ioctl_status_compat64(struct snd_rawmidi_file *rfile,
+                                            struct compat_snd_rawmidi_status64 __user *src)
 {
        int err;
-       struct snd_rawmidi_status status;
+       struct snd_rawmidi_status64 status;
+       struct compat_snd_rawmidi_status64 compat_status;
 
        if (get_user(status.stream, &src->stream))
                return -EFAULT;
@@ -75,68 +78,24 @@ static int snd_rawmidi_ioctl_status_compat(struct snd_rawmidi_file *rfile,
        if (err < 0)
                return err;
 
-       if (compat_put_timespec(&status.tstamp, &src->tstamp) ||
-           put_user(status.avail, &src->avail) ||
-           put_user(status.xruns, &src->xruns))
-               return -EFAULT;
-
-       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 (get_user(status.stream, &src->stream))
-               return -EFAULT;
-
-       switch (status.stream) {
-       case SNDRV_RAWMIDI_STREAM_OUTPUT:
-               if (!rfile->output)
-                       return -EINVAL;
-               err = snd_rawmidi_output_status(rfile->output, &status);
-               break;
-       case SNDRV_RAWMIDI_STREAM_INPUT:
-               if (!rfile->input)
-                       return -EINVAL;
-               err = snd_rawmidi_input_status(rfile->input, &status);
-               break;
-       default:
-               return -EINVAL;
-       }
-       if (err < 0)
-               return err;
+       compat_status = (struct compat_snd_rawmidi_status64) {
+               .stream = status.stream,
+               .tstamp_sec = status.tstamp_sec,
+               .tstamp_nsec = status.tstamp_nsec,
+               .avail = status.avail,
+               .xruns = status.xruns,
+       };
 
-       if (put_timespec(&status.tstamp, &src->tstamp) ||
-           put_user(status.avail, &src->avail) ||
-           put_user(status.xruns, &src->xruns))
+       if (copy_to_user(src, &compat_status, sizeof(*src)))
                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 */
+       SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32 = _IOWR('W', 0x20, struct snd_rawmidi_status32),
+       SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64 = _IOWR('W', 0x20, struct compat_snd_rawmidi_status64),
 };
 
 static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
@@ -153,12 +112,10 @@ static long snd_rawmidi_ioctl_compat(struct file *file, unsigned int cmd, unsign
                return snd_rawmidi_ioctl(file, cmd, (unsigned long)argp);
        case SNDRV_RAWMIDI_IOCTL_PARAMS32:
                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 */
+       case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT32:
+               return snd_rawmidi_ioctl_status32(rfile, argp);
+       case SNDRV_RAWMIDI_IOCTL_STATUS_COMPAT64:
+               return snd_rawmidi_ioctl_status_compat64(rfile, argp);
        }
        return -ENOIOCTLCMD;
 }
index 6dc94ef..4534a15 100644 (file)
@@ -460,10 +460,10 @@ enabled_str(int bool)
        return bool ? "enabled" : "disabled";
 }
 
-static char *
+static const char *
 filemode_str(int val)
 {
-       static char *str[] = {
+       static const char * const str[] = {
                "none", "read", "write", "read/write",
        };
        return str[val & SNDRV_SEQ_OSS_FILE_ACMODE];
index 770d3f4..198f285 100644 (file)
@@ -30,22 +30,25 @@ MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI emulation."
 MODULE_LICENSE("GPL");
 
 /* Prototypes for static functions */
-static void note_off(struct snd_midi_op *ops, void *drv,
+static void note_off(const struct snd_midi_op *ops, void *drv,
                     struct snd_midi_channel *chan,
                     int note, int vel);
-static void do_control(struct snd_midi_op *ops, void *private,
+static void do_control(const struct snd_midi_op *ops, void *private,
                       struct snd_midi_channel_set *chset,
                       struct snd_midi_channel *chan,
                       int control, int value);
-static void rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+static void rpn(const struct snd_midi_op *ops, void *drv,
+               struct snd_midi_channel *chan,
                struct snd_midi_channel_set *chset);
-static void nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+static void nrpn(const struct snd_midi_op *ops, void *drv,
+                struct snd_midi_channel *chan,
                 struct snd_midi_channel_set *chset);
-static void sysex(struct snd_midi_op *ops, void *private, unsigned char *sysex,
+static void sysex(const struct snd_midi_op *ops, void *private,
+                 unsigned char *sysex,
                  int len, struct snd_midi_channel_set *chset);
-static void all_sounds_off(struct snd_midi_op *ops, void *private,
+static void all_sounds_off(const struct snd_midi_op *ops, void *private,
                           struct snd_midi_channel *chan);
-static void all_notes_off(struct snd_midi_op *ops, void *private,
+static void all_notes_off(const struct snd_midi_op *ops, void *private,
                          struct snd_midi_channel *chan);
 static void snd_midi_reset_controllers(struct snd_midi_channel *chan);
 static void reset_all_channels(struct snd_midi_channel_set *chset);
@@ -66,7 +69,7 @@ static void reset_all_channels(struct snd_midi_channel_set *chset);
  *        be interpreted.
  */
 void
-snd_midi_process_event(struct snd_midi_op *ops,
+snd_midi_process_event(const struct snd_midi_op *ops,
                       struct snd_seq_event *ev,
                       struct snd_midi_channel_set *chanset)
 {
@@ -229,7 +232,8 @@ EXPORT_SYMBOL(snd_midi_process_event);
  * release note
  */
 static void
-note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+note_off(const struct snd_midi_op *ops, void *drv,
+        struct snd_midi_channel *chan,
         int note, int vel)
 {
        if (chan->gm_hold) {
@@ -251,7 +255,8 @@ note_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
  * events that need to take place immediately to the driver.
  */
 static void
-do_control(struct snd_midi_op *ops, void *drv, struct snd_midi_channel_set *chset,
+do_control(const struct snd_midi_op *ops, void *drv,
+          struct snd_midi_channel_set *chset,
           struct snd_midi_channel *chan, int control, int value)
 {
        int  i;
@@ -402,7 +407,7 @@ EXPORT_SYMBOL(snd_midi_channel_set_clear);
  * Process a rpn message.
  */
 static void
-rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+rpn(const struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
     struct snd_midi_channel_set *chset)
 {
        int type;
@@ -442,7 +447,7 @@ rpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
  * Process an nrpn message.
  */
 static void
-nrpn(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
+nrpn(const struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan,
      struct snd_midi_channel_set *chset)
 {
        /* parse XG NRPNs here if possible */
@@ -470,15 +475,15 @@ get_channel(unsigned char cmd)
  * Process a sysex message.
  */
 static void
-sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
+sysex(const struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
       struct snd_midi_channel_set *chset)
 {
        /* GM on */
-       static unsigned char gm_on_macro[] = {
+       static const unsigned char gm_on_macro[] = {
                0x7e,0x7f,0x09,0x01,
        };
        /* XG on */
-       static unsigned char xg_on_macro[] = {
+       static const unsigned char xg_on_macro[] = {
                0x43,0x10,0x4c,0x00,0x00,0x7e,0x00,
        };
        /* GS prefix
@@ -487,7 +492,7 @@ sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
         * chorus mode: XX=0x01, YY=0x38, ZZ=0-7
         * master vol:  XX=0x00, YY=0x04, ZZ=0-127
         */
-       static unsigned char gs_pfx_macro[] = {
+       static const unsigned char gs_pfx_macro[] = {
                0x41,0x10,0x42,0x12,0x40,/*XX,YY,ZZ*/
        };
 
@@ -584,7 +589,8 @@ sysex(struct snd_midi_op *ops, void *private, unsigned char *buf, int len,
  * all sound off
  */
 static void
-all_sounds_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan)
+all_sounds_off(const struct snd_midi_op *ops, void *drv,
+              struct snd_midi_channel *chan)
 {
        int n;
 
@@ -602,7 +608,8 @@ all_sounds_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan
  * all notes off
  */
 static void
-all_notes_off(struct snd_midi_op *ops, void *drv, struct snd_midi_channel *chan)
+all_notes_off(const struct snd_midi_op *ops, void *drv,
+             struct snd_midi_channel *chan)
 {
        int n;
 
index ae0308d..7511462 100644 (file)
@@ -422,12 +422,12 @@ static int extra_decode_xrpn(struct snd_midi_event *dev, unsigned char *buf,
                             int count, struct snd_seq_event *ev)
 {
        unsigned char cmd;
-       char *cbytes;
-       static char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
+       const char *cbytes;
+       static const char cbytes_nrpn[4] = { MIDI_CTL_NONREG_PARM_NUM_MSB,
                                       MIDI_CTL_NONREG_PARM_NUM_LSB,
                                       MIDI_CTL_MSB_DATA_ENTRY,
                                       MIDI_CTL_LSB_DATA_ENTRY };
-       static char cbytes_rpn[4] =  { MIDI_CTL_REGIST_PARM_NUM_MSB,
+       static const char cbytes_rpn[4] =  { MIDI_CTL_REGIST_PARM_NUM_MSB,
                                       MIDI_CTL_REGIST_PARM_NUM_LSB,
                                       MIDI_CTL_MSB_DATA_ENTRY,
                                       MIDI_CTL_LSB_DATA_ENTRY };
index 63dc7bd..be59b59 100644 (file)
@@ -471,15 +471,19 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
                q = queueptr(idx);
                if (q == NULL)
                        continue;
-               if ((tmr = q->timer) == NULL ||
-                   (ti = tmr->timeri) == NULL) {
-                       queuefree(q);
-                       continue;
-               }
+               mutex_lock(&q->timer_mutex);
+               tmr = q->timer;
+               if (!tmr)
+                       goto unlock;
+               ti = tmr->timeri;
+               if (!ti)
+                       goto unlock;
                snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name);
                resolution = snd_timer_resolution(ti) * tmr->ticks;
                snd_iprintf(buffer, "  Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
                snd_iprintf(buffer, "  Skew : %u / %u\n", tmr->skew, tmr->skew_base);
+unlock:
+               mutex_unlock(&q->timer_mutex);
                queuefree(q);
        }
 }
index e9dbad9..7ed13cb 100644 (file)
@@ -193,7 +193,7 @@ int snd_seq_device_new(struct snd_card *card, int device, const char *id,
 {
        struct snd_seq_device *dev;
        int err;
-       static struct snd_device_ops dops = {
+       static const struct snd_device_ops dops = {
                .dev_free = snd_seq_device_dev_free,
                .dev_register = snd_seq_device_dev_register,
                .dev_disconnect = snd_seq_device_dev_disconnect,
index 24fed5c..d9f85f2 100644 (file)
@@ -44,6 +44,28 @@ MODULE_PARM_DESC(timer_tstamp_monotonic, "Use posix monotonic clock source for t
 MODULE_ALIAS_CHARDEV(CONFIG_SND_MAJOR, SNDRV_MINOR_TIMER);
 MODULE_ALIAS("devname:snd/timer");
 
+enum timer_tread_format {
+       TREAD_FORMAT_NONE = 0,
+       TREAD_FORMAT_TIME64,
+       TREAD_FORMAT_TIME32,
+};
+
+struct snd_timer_tread32 {
+       int event;
+       s32 tstamp_sec;
+       s32 tstamp_nsec;
+       unsigned int val;
+};
+
+struct snd_timer_tread64 {
+       int event;
+       u8 pad1[4];
+       s64 tstamp_sec;
+       s64 tstamp_nsec;
+       unsigned int val;
+       u8 pad2[4];
+};
+
 struct snd_timer_user {
        struct snd_timer_instance *timeri;
        int tread;              /* enhanced read with timestamps and events */
@@ -55,16 +77,40 @@ struct snd_timer_user {
        int queue_size;
        bool disconnected;
        struct snd_timer_read *queue;
-       struct snd_timer_tread *tqueue;
+       struct snd_timer_tread64 *tqueue;
        spinlock_t qlock;
        unsigned long last_resolution;
        unsigned int filter;
-       struct timespec tstamp;         /* trigger tstamp */
+       struct timespec64 tstamp;               /* trigger tstamp */
        wait_queue_head_t qchange_sleep;
        struct fasync_struct *fasync;
        struct mutex ioctl_lock;
 };
 
+struct snd_timer_status32 {
+       s32 tstamp_sec;                 /* Timestamp - last update */
+       s32 tstamp_nsec;
+       unsigned int resolution;        /* current period resolution in ns */
+       unsigned int lost;              /* counter of master tick lost */
+       unsigned int overrun;           /* count of read queue overruns */
+       unsigned int queue;             /* used queue size */
+       unsigned char reserved[64];     /* reserved */
+};
+
+#define SNDRV_TIMER_IOCTL_STATUS32     _IOR('T', 0x14, struct snd_timer_status32)
+
+struct snd_timer_status64 {
+       s64 tstamp_sec;                 /* Timestamp - last update */
+       s64 tstamp_nsec;
+       unsigned int resolution;        /* current period resolution in ns */
+       unsigned int lost;              /* counter of master tick lost */
+       unsigned int overrun;           /* count of read queue overruns */
+       unsigned int queue;             /* used queue size */
+       unsigned char reserved[64];     /* reserved */
+};
+
+#define SNDRV_TIMER_IOCTL_STATUS64     _IOR('T', 0x14, struct snd_timer_status64)
+
 /* list of timers */
 static LIST_HEAD(snd_timer_list);
 
@@ -453,12 +499,12 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
        struct snd_timer *timer = ti->timer;
        unsigned long resolution = 0;
        struct snd_timer_instance *ts;
-       struct timespec tstamp;
+       struct timespec64 tstamp;
 
        if (timer_tstamp_monotonic)
-               ktime_get_ts(&tstamp);
+               ktime_get_ts64(&tstamp);
        else
-               getnstimeofday(&tstamp);
+               ktime_get_real_ts64(&tstamp);
        if (snd_BUG_ON(event < SNDRV_TIMER_EVENT_START ||
                       event > SNDRV_TIMER_EVENT_PAUSE))
                return;
@@ -890,7 +936,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
 {
        struct snd_timer *timer;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_timer_dev_free,
                .dev_register = snd_timer_dev_register,
                .dev_disconnect = snd_timer_dev_disconnect,
@@ -1025,7 +1071,7 @@ static int snd_timer_dev_disconnect(struct snd_device *device)
        return 0;
 }
 
-void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstamp)
+void snd_timer_notify(struct snd_timer *timer, int event, struct timespec64 *tstamp)
 {
        unsigned long flags;
        unsigned long resolution = 0;
@@ -1153,7 +1199,7 @@ static int snd_timer_s_close(struct snd_timer *timer)
        return 0;
 }
 
-static struct snd_timer_hardware snd_timer_system =
+static const struct snd_timer_hardware snd_timer_system =
 {
        .flags =        SNDRV_TIMER_HW_FIRST | SNDRV_TIMER_HW_TASKLET,
        .resolution =   1000000000L / HZ,
@@ -1305,7 +1351,7 @@ static void snd_timer_user_interrupt(struct snd_timer_instance *timeri,
 }
 
 static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu,
-                                           struct snd_timer_tread *tread)
+                                           struct snd_timer_tread64 *tread)
 {
        if (tu->qused >= tu->queue_size) {
                tu->overrun++;
@@ -1318,11 +1364,11 @@ static void snd_timer_user_append_to_tqueue(struct snd_timer_user *tu,
 
 static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
                                     int event,
-                                    struct timespec *tstamp,
+                                    struct timespec64 *tstamp,
                                     unsigned long resolution)
 {
        struct snd_timer_user *tu = timeri->callback_data;
-       struct snd_timer_tread r1;
+       struct snd_timer_tread64 r1;
        unsigned long flags;
 
        if (event >= SNDRV_TIMER_EVENT_START &&
@@ -1332,7 +1378,8 @@ static void snd_timer_user_ccallback(struct snd_timer_instance *timeri,
                return;
        memset(&r1, 0, sizeof(r1));
        r1.event = event;
-       r1.tstamp = *tstamp;
+       r1.tstamp_sec = tstamp->tv_sec;
+       r1.tstamp_nsec = tstamp->tv_nsec;
        r1.val = resolution;
        spin_lock_irqsave(&tu->qlock, flags);
        snd_timer_user_append_to_tqueue(tu, &r1);
@@ -1354,8 +1401,8 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
                                      unsigned long ticks)
 {
        struct snd_timer_user *tu = timeri->callback_data;
-       struct snd_timer_tread *r, r1;
-       struct timespec tstamp;
+       struct snd_timer_tread64 *r, r1;
+       struct timespec64 tstamp;
        int prev, append = 0;
 
        memset(&r1, 0, sizeof(r1));
@@ -1368,14 +1415,15 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
        }
        if (tu->last_resolution != resolution || ticks > 0) {
                if (timer_tstamp_monotonic)
-                       ktime_get_ts(&tstamp);
+                       ktime_get_ts64(&tstamp);
                else
-                       getnstimeofday(&tstamp);
+                       ktime_get_real_ts64(&tstamp);
        }
        if ((tu->filter & (1 << SNDRV_TIMER_EVENT_RESOLUTION)) &&
            tu->last_resolution != resolution) {
                r1.event = SNDRV_TIMER_EVENT_RESOLUTION;
-               r1.tstamp = tstamp;
+               r1.tstamp_sec = tstamp.tv_sec;
+               r1.tstamp_nsec = tstamp.tv_nsec;
                r1.val = resolution;
                snd_timer_user_append_to_tqueue(tu, &r1);
                tu->last_resolution = resolution;
@@ -1389,14 +1437,16 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
                prev = tu->qtail == 0 ? tu->queue_size - 1 : tu->qtail - 1;
                r = &tu->tqueue[prev];
                if (r->event == SNDRV_TIMER_EVENT_TICK) {
-                       r->tstamp = tstamp;
+                       r->tstamp_sec = tstamp.tv_sec;
+                       r->tstamp_nsec = tstamp.tv_nsec;
                        r->val += ticks;
                        append++;
                        goto __wake;
                }
        }
        r1.event = SNDRV_TIMER_EVENT_TICK;
-       r1.tstamp = tstamp;
+       r1.tstamp_sec = tstamp.tv_sec;
+       r1.tstamp_nsec = tstamp.tv_nsec;
        r1.val = ticks;
        snd_timer_user_append_to_tqueue(tu, &r1);
        append++;
@@ -1411,7 +1461,7 @@ static void snd_timer_user_tinterrupt(struct snd_timer_instance *timeri,
 static int realloc_user_queue(struct snd_timer_user *tu, int size)
 {
        struct snd_timer_read *queue = NULL;
-       struct snd_timer_tread *tqueue = NULL;
+       struct snd_timer_tread64 *tqueue = NULL;
 
        if (tu->tread) {
                tqueue = kcalloc(size, sizeof(*tqueue), GFP_KERNEL);
@@ -1850,11 +1900,11 @@ static int snd_timer_user_params(struct file *file,
        tu->qhead = tu->qtail = tu->qused = 0;
        if (tu->timeri->flags & SNDRV_TIMER_IFLG_EARLY_EVENT) {
                if (tu->tread) {
-                       struct snd_timer_tread tread;
+                       struct snd_timer_tread64 tread;
                        memset(&tread, 0, sizeof(tread));
                        tread.event = SNDRV_TIMER_EVENT_EARLY;
-                       tread.tstamp.tv_sec = 0;
-                       tread.tstamp.tv_nsec = 0;
+                       tread.tstamp_sec = 0;
+                       tread.tstamp_nsec = 0;
                        tread.val = 0;
                        snd_timer_user_append_to_tqueue(tu, &tread);
                } else {
@@ -1875,17 +1925,41 @@ static int snd_timer_user_params(struct file *file,
        return err;
 }
 
-static int snd_timer_user_status(struct file *file,
-                                struct snd_timer_status __user *_status)
+static int snd_timer_user_status32(struct file *file,
+                                  struct snd_timer_status32 __user *_status)
+ {
+       struct snd_timer_user *tu;
+       struct snd_timer_status32 status;
+
+       tu = file->private_data;
+       if (!tu->timeri)
+               return -EBADFD;
+       memset(&status, 0, sizeof(status));
+       status.tstamp_sec = tu->tstamp.tv_sec;
+       status.tstamp_nsec = tu->tstamp.tv_nsec;
+       status.resolution = snd_timer_resolution(tu->timeri);
+       status.lost = tu->timeri->lost;
+       status.overrun = tu->overrun;
+       spin_lock_irq(&tu->qlock);
+       status.queue = tu->qused;
+       spin_unlock_irq(&tu->qlock);
+       if (copy_to_user(_status, &status, sizeof(status)))
+               return -EFAULT;
+       return 0;
+}
+
+static int snd_timer_user_status64(struct file *file,
+                                  struct snd_timer_status64 __user *_status)
 {
        struct snd_timer_user *tu;
-       struct snd_timer_status status;
+       struct snd_timer_status64 status;
 
        tu = file->private_data;
        if (!tu->timeri)
                return -EBADFD;
        memset(&status, 0, sizeof(status));
-       status.tstamp = tu->tstamp;
+       status.tstamp_sec = tu->tstamp.tv_sec;
+       status.tstamp_nsec = tu->tstamp.tv_nsec;
        status.resolution = snd_timer_resolution(tu->timeri);
        status.lost = tu->timeri->lost;
        status.overrun = tu->overrun;
@@ -1960,6 +2034,36 @@ static int snd_timer_user_pause(struct file *file)
        return 0;
 }
 
+static int snd_timer_user_tread(void __user *argp, struct snd_timer_user *tu,
+                               unsigned int cmd, bool compat)
+{
+       int __user *p = argp;
+       int xarg, old_tread;
+
+       if (tu->timeri) /* too late */
+               return -EBUSY;
+       if (get_user(xarg, p))
+               return -EFAULT;
+
+       old_tread = tu->tread;
+
+       if (!xarg)
+               tu->tread = TREAD_FORMAT_NONE;
+       else if (cmd == SNDRV_TIMER_IOCTL_TREAD64 ||
+                (IS_ENABLED(CONFIG_64BIT) && !compat))
+               tu->tread = TREAD_FORMAT_TIME64;
+       else
+               tu->tread = TREAD_FORMAT_TIME32;
+
+       if (tu->tread != old_tread &&
+           realloc_user_queue(tu, tu->queue_size) < 0) {
+               tu->tread = old_tread;
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
 enum {
        SNDRV_TIMER_IOCTL_START_OLD = _IO('T', 0x20),
        SNDRV_TIMER_IOCTL_STOP_OLD = _IO('T', 0x21),
@@ -1968,7 +2072,7 @@ enum {
 };
 
 static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
-                                unsigned long arg)
+                                unsigned long arg, bool compat)
 {
        struct snd_timer_user *tu;
        void __user *argp = (void __user *)arg;
@@ -1980,23 +2084,9 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
                return put_user(SNDRV_TIMER_VERSION, p) ? -EFAULT : 0;
        case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
                return snd_timer_user_next_device(argp);
-       case SNDRV_TIMER_IOCTL_TREAD:
-       {
-               int xarg, old_tread;
-
-               if (tu->timeri) /* too late */
-                       return -EBUSY;
-               if (get_user(xarg, p))
-                       return -EFAULT;
-               old_tread = tu->tread;
-               tu->tread = xarg ? 1 : 0;
-               if (tu->tread != old_tread &&
-                   realloc_user_queue(tu, tu->queue_size) < 0) {
-                       tu->tread = old_tread;
-                       return -ENOMEM;
-               }
-               return 0;
-       }
+       case SNDRV_TIMER_IOCTL_TREAD_OLD:
+       case SNDRV_TIMER_IOCTL_TREAD64:
+               return snd_timer_user_tread(argp, tu, cmd, compat);
        case SNDRV_TIMER_IOCTL_GINFO:
                return snd_timer_user_ginfo(file, argp);
        case SNDRV_TIMER_IOCTL_GPARAMS:
@@ -2009,8 +2099,10 @@ static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
                return snd_timer_user_info(file, argp);
        case SNDRV_TIMER_IOCTL_PARAMS:
                return snd_timer_user_params(file, argp);
-       case SNDRV_TIMER_IOCTL_STATUS:
-               return snd_timer_user_status(file, argp);
+       case SNDRV_TIMER_IOCTL_STATUS32:
+               return snd_timer_user_status32(file, argp);
+       case SNDRV_TIMER_IOCTL_STATUS64:
+               return snd_timer_user_status64(file, argp);
        case SNDRV_TIMER_IOCTL_START:
        case SNDRV_TIMER_IOCTL_START_OLD:
                return snd_timer_user_start(file);
@@ -2034,7 +2126,7 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
        long ret;
 
        mutex_lock(&tu->ioctl_lock);
-       ret = __snd_timer_user_ioctl(file, cmd, arg);
+       ret = __snd_timer_user_ioctl(file, cmd, arg, false);
        mutex_unlock(&tu->ioctl_lock);
        return ret;
 }
@@ -2050,13 +2142,29 @@ static int snd_timer_user_fasync(int fd, struct file * file, int on)
 static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
                                   size_t count, loff_t *offset)
 {
+       struct snd_timer_tread64 *tread;
+       struct snd_timer_tread32 tread32;
        struct snd_timer_user *tu;
        long result = 0, unit;
        int qhead;
        int err = 0;
 
        tu = file->private_data;
-       unit = tu->tread ? sizeof(struct snd_timer_tread) : sizeof(struct snd_timer_read);
+       switch (tu->tread) {
+       case TREAD_FORMAT_TIME64:
+               unit = sizeof(struct snd_timer_tread64);
+               break;
+       case TREAD_FORMAT_TIME32:
+               unit = sizeof(struct snd_timer_tread32);
+               break;
+       case TREAD_FORMAT_NONE:
+               unit = sizeof(struct snd_timer_read);
+               break;
+       default:
+               WARN_ONCE(1, "Corrupt snd_timer_user\n");
+               return -ENOTSUPP;
+       }
+
        mutex_lock(&tu->ioctl_lock);
        spin_lock_irq(&tu->qlock);
        while ((long)count - result >= unit) {
@@ -2095,14 +2203,34 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
                tu->qused--;
                spin_unlock_irq(&tu->qlock);
 
-               if (tu->tread) {
-                       if (copy_to_user(buffer, &tu->tqueue[qhead],
-                                        sizeof(struct snd_timer_tread)))
+               tread = &tu->tqueue[qhead];
+
+               switch (tu->tread) {
+               case TREAD_FORMAT_TIME64:
+                       if (copy_to_user(buffer, tread,
+                                        sizeof(struct snd_timer_tread64)))
                                err = -EFAULT;
-               } else {
+                       break;
+               case TREAD_FORMAT_TIME32:
+                       memset(&tread32, 0, sizeof(tread32));
+                       tread32 = (struct snd_timer_tread32) {
+                               .event = tread->event,
+                               .tstamp_sec = tread->tstamp_sec,
+                               .tstamp_nsec = tread->tstamp_nsec,
+                               .val = tread->val,
+                       };
+
+                       if (copy_to_user(buffer, &tread32, sizeof(tread32)))
+                               err = -EFAULT;
+                       break;
+               case TREAD_FORMAT_NONE:
                        if (copy_to_user(buffer, &tu->queue[qhead],
                                         sizeof(struct snd_timer_read)))
                                err = -EFAULT;
+                       break;
+               default:
+                       err = -ENOTSUPP;
+                       break;
                }
 
                spin_lock_irq(&tu->qlock);
index bb6be48..0103d16 100644 (file)
@@ -69,54 +69,11 @@ static int snd_timer_user_info_compat(struct file *file,
        return 0;
 }
 
-struct snd_timer_status32 {
-       struct compat_timespec tstamp;
-       u32 resolution;
-       u32 lost;
-       u32 overrun;
-       u32 queue;
-       unsigned char reserved[64];
-};
-
-static int snd_timer_user_status_compat(struct file *file,
-                                       struct snd_timer_status32 __user *_status)
-{
-       struct snd_timer_user *tu;
-       struct snd_timer_status32 status;
-       
-       tu = file->private_data;
-       if (!tu->timeri)
-               return -EBADFD;
-       memset(&status, 0, sizeof(status));
-       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;
-       spin_lock_irq(&tu->qlock);
-       status.queue = tu->qused;
-       spin_unlock_irq(&tu->qlock);
-       if (copy_to_user(_status, &status, sizeof(status)))
-               return -EFAULT;
-       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_GPARAMS32 = _IOW('T', 0x04, struct snd_timer_gparams32),
        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 */
+       SNDRV_TIMER_IOCTL_STATUS_COMPAT32 = _IOW('T', 0x14, struct snd_timer_status32),
+       SNDRV_TIMER_IOCTL_STATUS_COMPAT64 = _IOW('T', 0x14, struct snd_timer_status64),
 };
 
 static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
@@ -126,7 +83,8 @@ static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
 
        switch (cmd) {
        case SNDRV_TIMER_IOCTL_PVERSION:
-       case SNDRV_TIMER_IOCTL_TREAD:
+       case SNDRV_TIMER_IOCTL_TREAD_OLD:
+       case SNDRV_TIMER_IOCTL_TREAD64:
        case SNDRV_TIMER_IOCTL_GINFO:
        case SNDRV_TIMER_IOCTL_GSTATUS:
        case SNDRV_TIMER_IOCTL_SELECT:
@@ -140,17 +98,15 @@ static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
        case SNDRV_TIMER_IOCTL_PAUSE:
        case SNDRV_TIMER_IOCTL_PAUSE_OLD:
        case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
-               return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
+               return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp, true);
        case SNDRV_TIMER_IOCTL_GPARAMS32:
                return snd_timer_user_gparams_compat(file, argp);
        case SNDRV_TIMER_IOCTL_INFO32:
                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 */
+       case SNDRV_TIMER_IOCTL_STATUS_COMPAT32:
+               return snd_timer_user_status32(file, argp);
+       case SNDRV_TIMER_IOCTL_STATUS_COMPAT64:
+               return snd_timer_user_status64(file, argp);
        }
        return -ENOIOCTLCMD;
 }
index 6bb4642..d78a272 100644 (file)
@@ -804,7 +804,7 @@ static void loopback_snd_timer_tasklet(unsigned long arg)
 
 static void loopback_snd_timer_event(struct snd_timer_instance *timeri,
                                     int event,
-                                    struct timespec *tstamp,
+                                    struct timespec64 *tstamp,
                                     unsigned long resolution)
 {
        /* Do not lock cable->lock here because timer->lock is already hold.
@@ -905,12 +905,6 @@ static void loopback_runtime_free(struct snd_pcm_runtime *runtime)
        kfree(dpcm);
 }
 
-static int loopback_hw_params(struct snd_pcm_substream *substream,
-                             struct snd_pcm_hw_params *params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-}
-
 static int loopback_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -920,7 +914,7 @@ static int loopback_hw_free(struct snd_pcm_substream *substream)
        mutex_lock(&dpcm->loopback->cable_lock);
        cable->valid &= ~(1 << substream->stream);
        mutex_unlock(&dpcm->loopback->cable_lock);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static unsigned int get_cable_index(struct snd_pcm_substream *substream)
@@ -1305,8 +1299,6 @@ static int loopback_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops loopback_pcm_ops = {
        .open =         loopback_open,
        .close =        loopback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    loopback_hw_params,
        .hw_free =      loopback_hw_free,
        .prepare =      loopback_prepare,
        .trigger =      loopback_trigger,
@@ -1325,8 +1317,7 @@ static int loopback_pcm_new(struct loopback *loopback,
                return err;
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &loopback_pcm_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &loopback_pcm_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        pcm->private_data = loopback;
        pcm->info_flags = 0;
@@ -1505,7 +1496,7 @@ static int loopback_channels_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new loopback_controls[]  = {
+static const struct snd_kcontrol_new loopback_controls[]  = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         "PCM Rate Shift 100000",
index 022a0db..02ac3f4 100644 (file)
@@ -117,7 +117,7 @@ struct dummy_model {
 
 struct snd_dummy {
        struct snd_card *card;
-       struct dummy_model *model;
+       const struct dummy_model *model;
        struct snd_pcm *pcm;
        struct snd_pcm_hardware pcm_hw;
        spinlock_t mixer_lock;
@@ -144,13 +144,13 @@ static int emu10k1_playback_constraints(struct snd_pcm_runtime *runtime)
        return 0;
 }
 
-static struct dummy_model model_emu10k1 = {
+static const struct dummy_model model_emu10k1 = {
        .name = "emu10k1",
        .playback_constraints = emu10k1_playback_constraints,
        .buffer_bytes_max = 128 * 1024,
 };
 
-static struct dummy_model model_rme9652 = {
+static const struct dummy_model model_rme9652 = {
        .name = "rme9652",
        .buffer_bytes_max = 26 * 64 * 1024,
        .formats = SNDRV_PCM_FMTBIT_S32_LE,
@@ -160,7 +160,7 @@ static struct dummy_model model_rme9652 = {
        .periods_max = 2,
 };
 
-static struct dummy_model model_ice1712 = {
+static const struct dummy_model model_ice1712 = {
        .name = "ice1712",
        .buffer_bytes_max = 256 * 1024,
        .formats = SNDRV_PCM_FMTBIT_S32_LE,
@@ -170,7 +170,7 @@ static struct dummy_model model_ice1712 = {
        .periods_max = 1024,
 };
 
-static struct dummy_model model_uda1341 = {
+static const struct dummy_model model_uda1341 = {
        .name = "uda1341",
        .buffer_bytes_max = 16380,
        .formats = SNDRV_PCM_FMTBIT_S16_LE,
@@ -180,7 +180,7 @@ static struct dummy_model model_uda1341 = {
        .periods_max = 255,
 };
 
-static struct dummy_model model_ac97 = {
+static const struct dummy_model model_ac97 = {
        .name = "ac97",
        .formats = SNDRV_PCM_FMTBIT_S16_LE,
        .channels_min = 2,
@@ -190,7 +190,7 @@ static struct dummy_model model_ac97 = {
        .rate_max = 48000,
 };
 
-static struct dummy_model model_ca0106 = {
+static const struct dummy_model model_ca0106 = {
        .name = "ca0106",
        .formats = SNDRV_PCM_FMTBIT_S16_LE,
        .buffer_bytes_max = ((65536-64)*8),
@@ -204,7 +204,7 @@ static struct dummy_model model_ca0106 = {
        .rate_max = 192000,
 };
 
-static struct dummy_model *dummy_models[] = {
+static const struct dummy_model *dummy_models[] = {
        &model_emu10k1,
        &model_rme9652,
        &model_ice1712,
@@ -529,21 +529,13 @@ static int dummy_pcm_hw_params(struct snd_pcm_substream *substream,
                substream->runtime->dma_bytes = params_buffer_bytes(hw_params);
                return 0;
        }
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-static int dummy_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       if (fake_buffer)
-               return 0;
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 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;
+       const struct dummy_model *model = dummy->model;
        struct snd_pcm_runtime *runtime = substream->runtime;
        const struct dummy_timer_ops *ops;
        int err;
@@ -652,23 +644,19 @@ static struct page *dummy_pcm_page(struct snd_pcm_substream *substream,
        return virt_to_page(dummy_page[substream->stream]); /* the same page */
 }
 
-static struct snd_pcm_ops dummy_pcm_ops = {
+static const struct snd_pcm_ops dummy_pcm_ops = {
        .open =         dummy_pcm_open,
        .close =        dummy_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    dummy_pcm_hw_params,
-       .hw_free =      dummy_pcm_hw_free,
        .prepare =      dummy_pcm_prepare,
        .trigger =      dummy_pcm_trigger,
        .pointer =      dummy_pcm_pointer,
 };
 
-static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
+static const struct snd_pcm_ops dummy_pcm_ops_no_buf = {
        .open =         dummy_pcm_open,
        .close =        dummy_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    dummy_pcm_hw_params,
-       .hw_free =      dummy_pcm_hw_free,
        .prepare =      dummy_pcm_prepare,
        .trigger =      dummy_pcm_trigger,
        .pointer =      dummy_pcm_pointer,
@@ -682,7 +670,7 @@ static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
                              int substreams)
 {
        struct snd_pcm *pcm;
-       struct snd_pcm_ops *ops;
+       const struct snd_pcm_ops *ops;
        int err;
 
        err = snd_pcm_new(dummy->card, "Dummy PCM", device,
@@ -700,7 +688,7 @@ static int snd_card_dummy_pcm(struct snd_dummy *dummy, int device,
        pcm->info_flags = 0;
        strcpy(pcm->name, "Dummy PCM");
        if (!fake_buffer) {
-               snd_pcm_lib_preallocate_pages_for_all(pcm,
+               snd_pcm_set_managed_buffer_all(pcm,
                        SNDRV_DMA_TYPE_CONTINUOUS,
                        NULL,
                        0, 64*1024);
@@ -861,7 +849,7 @@ static int snd_dummy_iobox_put(struct snd_kcontrol *kcontrol,
        return changed;
 }
 
-static struct snd_kcontrol_new snd_dummy_controls[] = {
+static const struct snd_kcontrol_new snd_dummy_controls[] = {
 DUMMY_VOLUME("Master Volume", 0, MIXER_ADDR_MASTER),
 DUMMY_CAPSRC("Master Capture Switch", 0, MIXER_ADDR_MASTER),
 DUMMY_VOLUME("Synth Volume", 0, MIXER_ADDR_SYNTH),
@@ -915,7 +903,7 @@ static void print_formats(struct snd_dummy *dummy,
 {
        int i;
 
-       for (i = 0; i < SNDRV_PCM_FORMAT_LAST; i++) {
+       for (i = 0; i <= SNDRV_PCM_FORMAT_LAST; i++) {
                if (dummy->pcm_hw.formats & (1ULL << i))
                        snd_iprintf(buffer, " %s", snd_pcm_format_name(i));
        }
@@ -924,7 +912,7 @@ static void print_formats(struct snd_dummy *dummy,
 static void print_rates(struct snd_dummy *dummy,
                        struct snd_info_buffer *buffer)
 {
-       static int rates[] = {
+       static const int rates[] = {
                5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
                64000, 88200, 96000, 176400, 192000,
        };
@@ -956,7 +944,7 @@ struct dummy_hw_field {
        .offset = offsetof(struct snd_pcm_hardware, item), \
        .size = sizeof(dummy_pcm_hardware.item) }
 
-static struct dummy_hw_field fields[] = {
+static const struct dummy_hw_field fields[] = {
        FIELD_ENTRY(formats, "%#llx"),
        FIELD_ENTRY(rates, "%#x"),
        FIELD_ENTRY(rate_min, "%d"),
@@ -1034,7 +1022,7 @@ static int snd_dummy_probe(struct platform_device *devptr)
 {
        struct snd_card *card;
        struct snd_dummy *dummy;
-       struct dummy_model *m = NULL, **mdl;
+       const struct dummy_model *m = NULL, **mdl;
        int idx, err;
        int dev = devptr->id;
 
index 70a6d18..0a039bf 100644 (file)
@@ -670,23 +670,6 @@ snd_ml403_ac97cr_pcm_capture_prepare(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int snd_ml403_ac97cr_hw_free(struct snd_pcm_substream *substream)
-{
-       PDEBUG(WORK_INFO, "hw_free()\n");
-       return snd_pcm_lib_free_pages(substream);
-}
-
-static int
-snd_ml403_ac97cr_hw_params(struct snd_pcm_substream *substream,
-                          struct snd_pcm_hw_params *hw_params)
-{
-       PDEBUG(WORK_INFO, "hw_params(): desired buffer bytes=%d, desired "
-              "period bytes=%d\n",
-              params_buffer_bytes(hw_params), params_period_bytes(hw_params));
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
 static int snd_ml403_ac97cr_playback_open(struct snd_pcm_substream *substream)
 {
        struct snd_ml403_ac97cr *ml403_ac97cr;
@@ -748,9 +731,6 @@ static int snd_ml403_ac97cr_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_ml403_ac97cr_playback_ops = {
        .open = snd_ml403_ac97cr_playback_open,
        .close = snd_ml403_ac97cr_playback_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_ml403_ac97cr_hw_params,
-       .hw_free = snd_ml403_ac97cr_hw_free,
        .prepare = snd_ml403_ac97cr_pcm_playback_prepare,
        .trigger = snd_ml403_ac97cr_pcm_playback_trigger,
        .pointer = snd_ml403_ac97cr_pcm_pointer,
@@ -759,9 +739,6 @@ static const struct snd_pcm_ops snd_ml403_ac97cr_playback_ops = {
 static const struct snd_pcm_ops snd_ml403_ac97cr_capture_ops = {
        .open = snd_ml403_ac97cr_capture_open,
        .close = snd_ml403_ac97cr_capture_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_ml403_ac97cr_hw_params,
-       .hw_free = snd_ml403_ac97cr_hw_free,
        .prepare = snd_ml403_ac97cr_pcm_capture_prepare,
        .trigger = snd_ml403_ac97cr_pcm_capture_trigger,
        .pointer = snd_ml403_ac97cr_pcm_pointer,
@@ -1099,7 +1076,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
 {
        struct snd_ml403_ac97cr *ml403_ac97cr;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_ml403_ac97cr_dev_free,
        };
        struct resource *resource;
@@ -1195,7 +1172,7 @@ snd_ml403_ac97cr_mixer(struct snd_ml403_ac97cr *ml403_ac97cr)
        struct snd_ac97_bus *bus;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_ml403_ac97cr_codec_write,
                .read = snd_ml403_ac97cr_codec_read,
        };
@@ -1241,10 +1218,10 @@ snd_ml403_ac97cr_pcm(struct snd_ml403_ac97cr *ml403_ac97cr, int device)
        strcpy(pcm->name, "ML403AC97CR DAC/ADC");
        ml403_ac97cr->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                         NULL,
-                                         64 * 1024,
-                                         128 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                      NULL,
+                                      64 * 1024,
+                                      128 * 1024);
        return 0;
 }
 
index 44776e1..9c708b6 100644 (file)
@@ -261,7 +261,7 @@ static int mts64_device_close(struct mts64 *mts)
  */
 static u8 mts64_map_midi_input(u8 c)
 {
-       static u8 map[] = { 0, 1, 4, 2, 3 };
+       static const u8 map[] = { 0, 1, 4, 2, 3 };
 
        return map[c];
 }
@@ -353,7 +353,7 @@ static void mts64_smpte_start(struct parport *p,
                              u8 seconds, u8 frames,
                              u8 idx)
 {
-       static u8 fps[5] = { MTS64_CMD_SMPTE_FPS_24, 
+       static const u8 fps[5] = { MTS64_CMD_SMPTE_FPS_24,
                             MTS64_CMD_SMPTE_FPS_25,
                             MTS64_CMD_SMPTE_FPS_2997, 
                             MTS64_CMD_SMPTE_FPS_30D,
@@ -467,7 +467,7 @@ __out:
        return changed;
 }
 
-static struct snd_kcontrol_new mts64_ctl_smpte_switch = {
+static const struct snd_kcontrol_new mts64_ctl_smpte_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Playback Switch",
        .index = 0,
@@ -540,7 +540,7 @@ static int snd_mts64_ctl_smpte_time_put(struct snd_kcontrol *kctl,
        return changed;
 }
 
-static struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
+static const struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Time Hours",
        .index = 0,
@@ -551,7 +551,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_hours = {
        .put  = snd_mts64_ctl_smpte_time_put
 };
 
-static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
+static const struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Time Minutes",
        .index = 0,
@@ -562,7 +562,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_minutes = {
        .put  = snd_mts64_ctl_smpte_time_put
 };
 
-static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
+static const struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Time Seconds",
        .index = 0,
@@ -573,7 +573,7 @@ static struct snd_kcontrol_new mts64_ctl_smpte_time_seconds = {
        .put  = snd_mts64_ctl_smpte_time_put
 };
 
-static struct snd_kcontrol_new mts64_ctl_smpte_time_frames = {
+static const struct snd_kcontrol_new mts64_ctl_smpte_time_frames = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Time Frames",
        .index = 0,
@@ -625,7 +625,7 @@ static int snd_mts64_ctl_smpte_fps_put(struct snd_kcontrol *kctl,
        return changed;
 }
 
-static struct snd_kcontrol_new mts64_ctl_smpte_fps = {
+static const struct snd_kcontrol_new mts64_ctl_smpte_fps = {
        .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI,
        .name  = "SMPTE Fps",
        .index = 0,
@@ -641,7 +641,7 @@ static int snd_mts64_ctl_create(struct snd_card *card,
                                struct mts64 *mts)
 {
        int err, i;
-       static struct snd_kcontrol_new *control[] = {
+       static const struct snd_kcontrol_new *control[] = {
                &mts64_ctl_smpte_switch,
                &mts64_ctl_smpte_time_hours,
                &mts64_ctl_smpte_time_minutes,
index cc7fb35..ccc49f3 100644 (file)
@@ -7,7 +7,7 @@
 
 #include "opl3_voice.h"
 
-static char snd_opl3_drum_table[47] =
+static const char snd_opl3_drum_table[47] =
 {
        OPL3_BASSDRUM_ON,  OPL3_BASSDRUM_ON,  OPL3_HIHAT_ON,    /* 35 - 37 */
        OPL3_SNAREDRUM_ON, OPL3_HIHAT_ON,     OPL3_SNAREDRUM_ON, /* 38 - 40 */
@@ -47,25 +47,25 @@ struct snd_opl3_drum_note {
        unsigned char feedback_connection;
 };
 
-static struct snd_opl3_drum_voice bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00};
-static struct snd_opl3_drum_voice bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00};
-static struct snd_opl3_drum_note bass_note = {6, 0x90, 0x09};
+static const struct snd_opl3_drum_voice bass_op0 = {6, 0, 0x00, 0x32, 0xf8, 0x66, 0x30, 0x00};
+static const struct snd_opl3_drum_voice bass_op1 = {6, 1, 0x00, 0x03, 0xf6, 0x57, 0x30, 0x00};
+static const struct snd_opl3_drum_note bass_note = {6, 0x90, 0x09};
 
-static struct snd_opl3_drum_voice hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00};
+static const struct snd_opl3_drum_voice hihat = {7, 0, 0x00, 0x03, 0xf0, 0x06, 0x20, 0x00};
 
-static struct snd_opl3_drum_voice snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02};
-static struct snd_opl3_drum_note snare_note = {7, 0xf4, 0x0d};
+static const struct snd_opl3_drum_voice snare = {7, 1, 0x00, 0x03, 0xf0, 0x07, 0x20, 0x02};
+static const struct snd_opl3_drum_note snare_note = {7, 0xf4, 0x0d};
 
-static struct snd_opl3_drum_voice tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00};
-static struct snd_opl3_drum_note tomtom_note = {8, 0xf4, 0x09};
+static const struct snd_opl3_drum_voice tomtom = {8, 0, 0x02, 0x03, 0xf0, 0x06, 0x10, 0x00};
+static const struct snd_opl3_drum_note tomtom_note = {8, 0xf4, 0x09};
 
-static struct snd_opl3_drum_voice cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00};
+static const struct snd_opl3_drum_voice cymbal = {8, 1, 0x04, 0x03, 0xf0, 0x06, 0x10, 0x00};
 
 /*
  * set drum voice characteristics
  */
 static void snd_opl3_drum_voice_set(struct snd_opl3 *opl3,
-                                   struct snd_opl3_drum_voice *data)
+                                   const struct snd_opl3_drum_voice *data)
 {
        unsigned char op_offset = snd_opl3_regmap[data->voice][data->op];
        unsigned char voice_offset = data->voice;
@@ -100,7 +100,7 @@ static void snd_opl3_drum_voice_set(struct snd_opl3 *opl3,
  * Set drum voice pitch
  */
 static void snd_opl3_drum_note_set(struct snd_opl3 *opl3,
-                                  struct snd_opl3_drum_note *data)
+                                  const struct snd_opl3_drum_note *data)
 {
        unsigned char voice_offset = data->voice;
        unsigned short opl3_reg;
@@ -118,7 +118,7 @@ static void snd_opl3_drum_note_set(struct snd_opl3 *opl3,
  * Set drum voice volume and position
  */
 static void snd_opl3_drum_vol_set(struct snd_opl3 *opl3,
-                                 struct snd_opl3_drum_voice *data,
+                                 const struct snd_opl3_drum_voice *data,
                                  int vel, struct snd_midi_channel *chan)
 {
        unsigned char op_offset = snd_opl3_regmap[data->voice][data->op];
@@ -170,7 +170,7 @@ void snd_opl3_drum_switch(struct snd_opl3 *opl3, int note, int vel, int on_off,
                          struct snd_midi_channel *chan)
 {
        unsigned char drum_mask;
-       struct snd_opl3_drum_voice *drum_voice;
+       const struct snd_opl3_drum_voice *drum_voice;
 
        if (!(opl3->drum_reg & OPL3_PERCUSSION_ENABLE))
                return;
index cbdec28..9259522 100644 (file)
@@ -214,7 +214,7 @@ static int snd_opl3_timer2_stop(struct snd_timer * timer)
 
  */
 
-static struct snd_timer_hardware snd_opl3_timer1 =
+static const struct snd_timer_hardware snd_opl3_timer1 =
 {
        .flags =        SNDRV_TIMER_HW_STOP,
        .resolution =   80000,
@@ -223,7 +223,7 @@ static struct snd_timer_hardware snd_opl3_timer1 =
        .stop =         snd_opl3_timer1_stop,
 };
 
-static struct snd_timer_hardware snd_opl3_timer2 =
+static const struct snd_timer_hardware snd_opl3_timer2 =
 {
        .flags =        SNDRV_TIMER_HW_STOP,
        .resolution =   320000,
@@ -332,7 +332,7 @@ int snd_opl3_new(struct snd_card *card,
                 unsigned short hardware,
                 struct snd_opl3 **ropl3)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_opl3_dev_free,
        };
        struct snd_opl3 *opl3;
index 280cc79..2f6e802 100644 (file)
@@ -23,7 +23,7 @@ static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
  * it saves a lot of log() calculations. (Rob Hooft <hooft@chem.ruu.nl>)
  */
 
-static char opl3_volume_table[128] =
+static const char opl3_volume_table[128] =
 {
        -63, -48, -40, -35, -32, -29, -27, -26,
        -24, -23, -21, -20, -19, -18, -18, -17,
@@ -69,7 +69,7 @@ void snd_opl3_calc_volume(unsigned char *volbyte, int vel,
 /*
  * Converts the note frequency to block and fnum values for the FM chip
  */
-static short opl3_note_table[16] =
+static const short opl3_note_table[16] =
 {
        305, 323,       /* for pitch bending, -2 semitones */
        343, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647,
@@ -266,7 +266,7 @@ static void snd_opl3_start_timer(struct snd_opl3 *opl3)
 /* ------------------------------ */
 
 
-static int snd_opl3_oss_map[MAX_OPL3_VOICES] = {
+static const int snd_opl3_oss_map[MAX_OPL3_VOICES] = {
        0, 1, 2, 9, 10, 11, 6, 7, 8, 15, 16, 17, 3, 4 ,5, 12, 13, 14
 };
 
index d0cf2fb..7bf0d5f 100644 (file)
@@ -16,7 +16,7 @@ static int snd_opl3_reset_seq_oss(struct snd_seq_oss_arg *arg);
 
 /* operators */
 
-static struct snd_seq_oss_callback oss_callback = {
+static const struct snd_seq_oss_callback oss_callback = {
        .owner =        THIS_MODULE,
        .open =         snd_opl3_open_seq_oss,
        .close =        snd_opl3_close_seq_oss,
index 20f2f51..cd2a01b 100644 (file)
@@ -128,7 +128,7 @@ static int snd_opl3_synth_unuse(void *private_data, struct snd_seq_port_subscrib
 /*
  * MIDI emulation operators
  */
-struct snd_midi_op opl3_ops = {
+const struct snd_midi_op opl3_ops = {
        .note_on =              snd_opl3_note_on,
        .note_off =             snd_opl3_note_off,
        .key_press =            snd_opl3_key_press,
index dc0626a..be9ccca 100644 (file)
@@ -41,6 +41,6 @@ void snd_opl3_free_seq_oss(struct snd_opl3 *opl3);
 
 extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
 extern bool use_internal_drums;
-extern struct snd_midi_op opl3_ops;
+extern const struct snd_midi_op opl3_ops;
 
 #endif
index 901d339..035645e 100644 (file)
@@ -184,7 +184,7 @@ int snd_opl4_create(struct snd_card *card,
        struct snd_opl4 *opl4;
        struct snd_opl3 *opl3;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_opl4_dev_free
        };
 
index 7d4b3cc..fa1e6ef 100644 (file)
@@ -47,7 +47,7 @@ static int snd_opl4_ctl_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
        return value != old_value;
 }
 
-static struct snd_kcontrol_new snd_opl4_controls[] = {
+static const struct snd_kcontrol_new snd_opl4_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "FM Playback Volume",
index e0516e5..f214909 100644 (file)
@@ -76,7 +76,7 @@ static ssize_t snd_opl4_mem_proc_write(struct snd_info_entry *entry,
        return count;
 }
 
-static struct snd_info_entry_ops snd_opl4_mem_proc_ops = {
+static const struct snd_info_entry_ops snd_opl4_mem_proc_ops = {
        .open = snd_opl4_mem_proc_open,
        .release = snd_opl4_mem_proc_release,
        .read = snd_opl4_mem_proc_read,
index 03d6202..f59ca66 100644 (file)
@@ -100,7 +100,7 @@ static int snd_opl4_seq_unuse(void *private_data, struct snd_seq_port_subscribe
        return 0;
 }
 
-static struct snd_midi_op opl4_ops = {
+static const struct snd_midi_op opl4_ops = {
        .note_on =              snd_opl4_note_on,
        .note_off =             snd_opl4_note_off,
        .note_terminate =       snd_opl4_terminate_note,
index 7bc1e58..34e2bd5 100644 (file)
@@ -248,7 +248,7 @@ static const s16 snd_opl4_pitch_map[0x600] = {
  * Attenuation according to GM recommendations, in -0.375 dB units.
  * table[v] = 40 * log(v / 127) / -0.375
  */
-static unsigned char snd_opl4_volume_table[128] = {
+static const unsigned char snd_opl4_volume_table[128] = {
        255,224,192,173,160,150,141,134,
        128,122,117,113,109,105,102, 99,
         96, 93, 90, 88, 85, 83, 81, 79,
index 14aacd8..fd79e57 100644 (file)
@@ -43,7 +43,7 @@ struct snd_pcsp pcsp_chip;
 
 static int snd_pcsp_create(struct snd_card *card)
 {
-       static struct snd_device_ops ops = { };
+       static const struct snd_device_ops ops = { };
        unsigned int resolution = hrtimer_resolution;
        int err, div, min_div, order;
 
index f91316b..05244b1 100644 (file)
@@ -214,12 +214,7 @@ static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
                                       struct snd_pcm_hw_params *hw_params)
 {
        struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
-       int err;
        pcsp_sync_stop(chip);
-       err = snd_pcm_lib_malloc_pages(substream,
-                                     params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        return 0;
 }
 
@@ -230,7 +225,7 @@ static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
        printk(KERN_INFO "PCSP: hw_free called\n");
 #endif
        pcsp_sync_stop(chip);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
@@ -327,7 +322,6 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_pcsp_playback_ops = {
        .open = snd_pcsp_playback_open,
        .close = snd_pcsp_playback_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_pcsp_playback_hw_params,
        .hw_free = snd_pcsp_playback_hw_free,
        .prepare = snd_pcsp_playback_prepare,
@@ -350,11 +344,11 @@ int snd_pcsp_new_pcm(struct snd_pcsp *chip)
        chip->pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
        strcpy(chip->pcm->name, "pcsp");
 
-       snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
-                                             SNDRV_DMA_TYPE_CONTINUOUS,
-                                             NULL,
-                                             PCSP_BUFFER_SIZE,
-                                             PCSP_BUFFER_SIZE);
+       snd_pcm_set_managed_buffer_all(chip->pcm,
+                                      SNDRV_DMA_TYPE_CONTINUOUS,
+                                      NULL,
+                                      PCSP_BUFFER_SIZE,
+                                      PCSP_BUFFER_SIZE);
 
        return 0;
 }
index be29904..da33e5b 100644 (file)
@@ -120,17 +120,17 @@ static int pcsp_pcspkr_put(struct snd_kcontrol *kcontrol,
        .put =          pcsp_##ctl_type##_put, \
 }
 
-static struct snd_kcontrol_new snd_pcsp_controls_pcm[] = {
+static const struct snd_kcontrol_new snd_pcsp_controls_pcm[] = {
        PCSP_MIXER_CONTROL(enable, "Master Playback Switch"),
        PCSP_MIXER_CONTROL(treble, "BaseFRQ Playback Volume"),
 };
 
-static struct snd_kcontrol_new snd_pcsp_controls_spkr[] = {
+static const struct snd_kcontrol_new snd_pcsp_controls_spkr[] = {
        PCSP_MIXER_CONTROL(pcspkr, "Beep Playback Switch"),
 };
 
 static int snd_pcsp_ctls_add(struct snd_pcsp *chip,
-                            struct snd_kcontrol_new *ctls, int num)
+                            const struct snd_kcontrol_new *ctls, int num)
 {
        int i, err;
        struct snd_card *card = chip->card;
index 4775f1b..3947f08 100644 (file)
@@ -42,7 +42,7 @@ MODULE_SUPPORTED_DEVICE("{{ALSA, MIDI serial u16550}}");
 #define SNDRV_SERIAL_MS124W_MB 3   /* Midiator MS-124W in M/B mode */
 #define SNDRV_SERIAL_GENERIC 4     /* Generic Interface */
 #define SNDRV_SERIAL_MAX_ADAPTOR SNDRV_SERIAL_GENERIC
-static char *adaptor_names[] = {
+static const char * const adaptor_names[] = {
        "Soundcanvas",
         "MS-124T",
        "MS-124W S/A",
@@ -777,7 +777,7 @@ static int snd_uart16550_create(struct snd_card *card,
                                int droponfull,
                                struct snd_uart16550 **ruart)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_uart16550_dev_free,
        };
        struct snd_uart16550 *uart;
index 77ae59a..b0970a0 100644 (file)
@@ -15,7 +15,7 @@
 /*
  * Array of DSP commands
  */
-static struct vx_cmd_info vx_dsp_cmds[] = {
+static const struct vx_cmd_info vx_dsp_cmds[] = {
 [CMD_VERSION] =                        { 0x010000, 2, RMH_SSIZE_FIXED, 1 },
 [CMD_SUPPORTED] =              { 0x020000, 1, RMH_SSIZE_FIXED, 2 },
 [CMD_TEST_IT] =                        { 0x040000, 1, RMH_SSIZE_FIXED, 1 },
index 6bbc2a4..ffab040 100644 (file)
@@ -39,7 +39,7 @@ MODULE_LICENSE("GPL");
 int snd_vx_check_reg_bit(struct vx_core *chip, int reg, int mask, int bit, int time)
 {
        unsigned long end_time = jiffies + (time * HZ + 999) / 1000;
-       static char *reg_names[VX_REG_MAX] = {
+       static const char * const reg_names[VX_REG_MAX] = {
                "ICR", "CVR", "ISR", "IVR", "RXH", "RXM", "RXL",
                "DMA", "CDSP", "RFREQ", "RUER/V2", "DATA", "MEMIRQ",
                "ACQ", "BIT0", "BIT1", "MIC0", "MIC1", "MIC2",
@@ -588,11 +588,11 @@ static void vx_reset_board(struct vx_core *chip, int cold_reset)
 static void vx_proc_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
 {
        struct vx_core *chip = entry->private_data;
-       static char *audio_src_vxp[] = { "Line", "Mic", "Digital" };
-       static char *audio_src_vx2[] = { "Analog", "Analog", "Digital" };
-       static char *clock_mode[] = { "Auto", "Internal", "External" };
-       static char *clock_src[] = { "Internal", "External" };
-       static char *uer_type[] = { "Consumer", "Professional", "Not Present" };
+       static const char * const audio_src_vxp[] = { "Line", "Mic", "Digital" };
+       static const char * const audio_src_vx2[] = { "Analog", "Analog", "Digital" };
+       static const char * const clock_mode[] = { "Auto", "Internal", "External" };
+       static const char * const clock_src[] = { "Internal", "External" };
+       static const char * const uer_type[] = { "Consumer", "Professional", "Not Present" };
        
        snd_iprintf(buffer, "%s\n", chip->card->longname);
        snd_iprintf(buffer, "Xilinx Firmware: %s\n",
@@ -765,8 +765,9 @@ EXPORT_SYMBOL(snd_vx_resume);
  *
  * return the instance pointer if successful, NULL in error.
  */
-struct vx_core *snd_vx_create(struct snd_card *card, struct snd_vx_hardware *hw,
-                             struct snd_vx_ops *ops,
+struct vx_core *snd_vx_create(struct snd_card *card,
+                             const struct snd_vx_hardware *hw,
+                             const struct snd_vx_ops *ops,
                              int extra_size)
 {
        struct vx_core *chip;
index f0d31b0..01baa6d 100644 (file)
@@ -32,7 +32,7 @@ MODULE_FIRMWARE("vx/l_1_vp4.d56");
 
 int snd_vx_setup_firmware(struct vx_core *chip)
 {
-       static char *fw_files[VX_TYPE_NUMS][4] = {
+       static const char * const fw_files[VX_TYPE_NUMS][4] = {
                [VX_TYPE_BOARD] = {
                        NULL, "x1_1_vx2.xlx", "bd56002.boot", "l_1_vx2.d56",
                },
index b17c67b..13099f8 100644 (file)
@@ -961,7 +961,7 @@ int snd_vx_mixer_new(struct vx_core *chip)
                return err;
        /* VU, peak, saturation meters */
        for (c = 0; c < 2; c++) {
-               static char *dir[2] = { "Output", "Input" };
+               static const char * const dir[2] = { "Output", "Input" };
                for (i = 0; i < chip->hw->num_ins; i++) {
                        int val = (i * 2) | (c << 8);
                        if (c == 1) {
index f17e0a7..664b9ef 100644 (file)
@@ -773,23 +773,6 @@ static snd_pcm_uframes_t vx_pcm_playback_pointer(struct snd_pcm_substream *subs)
 }
 
 /*
- * vx_pcm_hw_params - hw_params callback for playback and capture
- */
-static int vx_pcm_hw_params(struct snd_pcm_substream *subs,
-                                    struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw_params));
-}
-
-/*
- * vx_pcm_hw_free - hw_free callback for playback and capture
- */
-static int vx_pcm_hw_free(struct snd_pcm_substream *subs)
-{
-       return snd_pcm_lib_free_pages(subs);
-}
-
-/*
  * vx_pcm_prepare - prepare callback for playback and capture
  */
 static int vx_pcm_prepare(struct snd_pcm_substream *subs)
@@ -860,9 +843,6 @@ static int vx_pcm_prepare(struct snd_pcm_substream *subs)
 static const struct snd_pcm_ops vx_pcm_playback_ops = {
        .open =         vx_pcm_playback_open,
        .close =        vx_pcm_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    vx_pcm_hw_params,
-       .hw_free =      vx_pcm_hw_free,
        .prepare =      vx_pcm_prepare,
        .trigger =      vx_pcm_trigger,
        .pointer =      vx_pcm_playback_pointer,
@@ -1080,9 +1060,6 @@ static snd_pcm_uframes_t vx_pcm_capture_pointer(struct snd_pcm_substream *subs)
 static const struct snd_pcm_ops vx_pcm_capture_ops = {
        .open =         vx_pcm_capture_open,
        .close =        vx_pcm_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    vx_pcm_hw_params,
-       .hw_free =      vx_pcm_hw_free,
        .prepare =      vx_pcm_prepare,
        .trigger =      vx_pcm_trigger,
        .pointer =      vx_pcm_capture_pointer,
@@ -1230,9 +1207,9 @@ int snd_vx_pcm_new(struct vx_core *chip)
                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &vx_pcm_playback_ops);
                if (ins)
                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &vx_pcm_capture_ops);
-               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                                     snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32),
-                                                     0, 0);
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
+                                              snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32),
+                                              0, 0);
 
                pcm->private_data = chip;
                pcm->private_free = snd_vx_pcm_free;
index d4edd06..f8d9a20 100644 (file)
@@ -212,11 +212,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *hw_params)
 {
        struct snd_bebob *bebob = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -247,7 +243,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&bebob->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int
@@ -346,7 +342,6 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
        static const struct snd_pcm_ops capture_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_capture_prepare,
@@ -357,7 +352,6 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
        static const struct snd_pcm_ops playback_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_playback_prepare,
@@ -377,8 +371,7 @@ int snd_bebob_create_pcm_devices(struct snd_bebob *bebob)
                 "%s PCM", bebob->card->shortname);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 end:
        return err;
 }
index f5b3252..0916864 100644 (file)
@@ -50,3 +50,27 @@ int snd_dice_detect_alesis_formats(struct snd_dice *dice)
 
        return 0;
 }
+
+int snd_dice_detect_alesis_mastercontrol_formats(struct snd_dice *dice)
+{
+       int i;
+
+       dice->tx_pcm_chs[0][SND_DICE_RATE_MODE_LOW]     = 16;
+       dice->tx_pcm_chs[1][SND_DICE_RATE_MODE_LOW]     = 12;
+       dice->tx_pcm_chs[0][SND_DICE_RATE_MODE_MIDDLE]  = 12;
+       dice->tx_pcm_chs[1][SND_DICE_RATE_MODE_MIDDLE]  = 4;
+       dice->tx_pcm_chs[0][SND_DICE_RATE_MODE_HIGH]    = 8;
+       dice->tx_pcm_chs[1][SND_DICE_RATE_MODE_HIGH]    = 0;
+
+       for (i = 0; i < SND_DICE_RATE_MODE_COUNT; ++i) {
+               dice->rx_pcm_chs[0][i] = 6;
+               dice->rx_pcm_chs[1][i] = 0;
+       }
+
+       for (i = 0; i < MAX_STREAMS; ++i) {
+               dice->tx_midi_ports[i] = 2;
+               dice->rx_midi_ports[i] = 2;
+       }
+
+       return 0;
+}
index a63fcbc..02f4a83 100644 (file)
@@ -159,8 +159,11 @@ int snd_dice_detect_extension_formats(struct snd_dice *dice)
                int j;
 
                for (j = i + 1; j < 9; ++j) {
-                       if (pointers[i * 2] == pointers[j * 2])
+                       if (pointers[i * 2] == pointers[j * 2]) {
+                               // Fallback to limited functionality.
+                               err = -ENXIO;
                                goto end;
+                       }
                }
        }
 
index be79d65..af8a90e 100644 (file)
@@ -264,11 +264,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *hw_params)
 {
        struct snd_dice *dice = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -304,7 +300,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&dice->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int capture_prepare(struct snd_pcm_substream *substream)
@@ -409,7 +405,6 @@ int snd_dice_create_pcm(struct snd_dice *dice)
        static const struct snd_pcm_ops capture_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
-               .ioctl     = snd_pcm_lib_ioctl,
                .hw_params = pcm_hw_params,
                .hw_free   = pcm_hw_free,
                .prepare   = capture_prepare,
@@ -420,7 +415,6 @@ int snd_dice_create_pcm(struct snd_dice *dice)
        static const struct snd_pcm_ops playback_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
-               .ioctl     = snd_pcm_lib_ioctl,
                .hw_params = pcm_hw_params,
                .hw_free   = pcm_hw_free,
                .prepare   = playback_prepare,
@@ -457,9 +451,8 @@ int snd_dice_create_pcm(struct snd_dice *dice)
                        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                        &playback_ops);
 
-               snd_pcm_lib_preallocate_pages_for_all(pcm,
-                                                     SNDRV_DMA_TYPE_VMALLOC,
-                                                     NULL, 0, 0);
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
+                                              NULL, 0, 0);
        }
 
        return 0;
index 6a3d609..8e0c038 100644 (file)
@@ -224,7 +224,6 @@ static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
                struct amdtp_stream *stream;
                struct fw_iso_resources *resources;
                unsigned int pcm_cache;
-               unsigned int midi_cache;
                unsigned int pcm_chs;
                unsigned int midi_ports;
 
@@ -233,7 +232,6 @@ static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
                        resources = &dice->tx_resources[i];
 
                        pcm_cache = dice->tx_pcm_chs[i][mode];
-                       midi_cache = dice->tx_midi_ports[i];
                        err = snd_dice_transaction_read_tx(dice,
                                        params->size * i + TX_NUMBER_AUDIO,
                                        reg, sizeof(reg));
@@ -242,7 +240,6 @@ static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
                        resources = &dice->rx_resources[i];
 
                        pcm_cache = dice->rx_pcm_chs[i][mode];
-                       midi_cache = dice->rx_midi_ports[i];
                        err = snd_dice_transaction_read_rx(dice,
                                        params->size * i + RX_NUMBER_AUDIO,
                                        reg, sizeof(reg));
@@ -253,10 +250,10 @@ static int keep_dual_resources(struct snd_dice *dice, unsigned int rate,
                midi_ports = be32_to_cpu(reg[1]);
 
                // These are important for developer of this driver.
-               if (pcm_chs != pcm_cache || midi_ports != midi_cache) {
+               if (pcm_chs != pcm_cache) {
                        dev_info(&dice->unit->device,
-                                "cache mismatch: pcm: %u:%u, midi: %u:%u\n",
-                                pcm_chs, pcm_cache, midi_ports, midi_cache);
+                                "cache mismatch: pcm: %u:%u, midi: %u\n",
+                                pcm_chs, pcm_cache, midi_ports);
                        return -EPROTO;
                }
 
index 13eeb3f..06c94f0 100644 (file)
@@ -355,6 +355,14 @@ static const struct ieee1394_device_id dice_id_table[] = {
                .model_id       = MODEL_ALESIS_IO_BOTH,
                .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats,
        },
+       // Alesis MasterControl.
+       {
+               .match_flags    = IEEE1394_MATCH_VENDOR_ID |
+                                 IEEE1394_MATCH_MODEL_ID,
+               .vendor_id      = OUI_ALESIS,
+               .model_id       = 0x000002,
+               .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_mastercontrol_formats,
+       },
        /* Mytek Stereo 192 DSD-DAC. */
        {
                .match_flags    = IEEE1394_MATCH_VENDOR_ID |
index 1636677..7fbffca 100644 (file)
@@ -229,6 +229,7 @@ int snd_dice_create_midi(struct snd_dice *dice);
 
 int snd_dice_detect_tcelectronic_formats(struct snd_dice *dice);
 int snd_dice_detect_alesis_formats(struct snd_dice *dice);
+int snd_dice_detect_alesis_mastercontrol_formats(struct snd_dice *dice);
 int snd_dice_detect_extension_formats(struct snd_dice *dice);
 int snd_dice_detect_mytek_formats(struct snd_dice *dice);
 int snd_dice_detect_presonus_formats(struct snd_dice *dice);
index 57cbce4..b7f6eda 100644 (file)
@@ -188,11 +188,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *hw_params)
 {
        struct snd_dg00x *dg00x = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -223,7 +219,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&dg00x->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
@@ -329,7 +325,6 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
        static const struct snd_pcm_ops capture_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_capture_prepare,
@@ -340,7 +335,6 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
        static const struct snd_pcm_ops playback_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_playback_prepare,
@@ -360,8 +354,7 @@ int snd_dg00x_create_pcm_devices(struct snd_dg00x *dg00x)
                 "%s PCM", dg00x->card->shortname);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        return 0;
 }
index 4e3bd9a..f978cc2 100644 (file)
@@ -228,11 +228,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *hw_params)
 {
        struct snd_ff *ff = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -247,7 +243,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                mutex_unlock(&ff->mutex);
        }
 
-       return 0;
+       return err;
 }
 
 static int pcm_hw_free(struct snd_pcm_substream *substream)
@@ -263,7 +259,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&ff->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
@@ -369,7 +365,6 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff)
        static const struct snd_pcm_ops pcm_capture_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_capture_prepare,
@@ -380,7 +375,6 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff)
        static const struct snd_pcm_ops pcm_playback_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_playback_prepare,
@@ -400,8 +394,7 @@ int snd_ff_create_pcm_devices(struct snd_ff *ff)
                 "%s PCM", ff->card->shortname);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        return 0;
 }
index e69896d..980580d 100644 (file)
@@ -248,11 +248,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *hw_params)
 {
        struct snd_efw *efw = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -283,7 +279,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&efw->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
@@ -376,7 +372,6 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw)
        static const struct snd_pcm_ops capture_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_capture_prepare,
@@ -387,7 +382,6 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw)
        static const struct snd_pcm_ops playback_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_playback_prepare,
@@ -406,8 +400,7 @@ int snd_efw_create_pcm_devices(struct snd_efw *efw)
        snprintf(pcm->name, sizeof(pcm->name), "%s PCM", efw->card->shortname);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 end:
        return err;
 }
index d9f1b96..6655af5 100644 (file)
@@ -286,11 +286,6 @@ static int isight_hw_params(struct snd_pcm_substream *substream,
                            struct snd_pcm_hw_params *hw_params)
 {
        struct isight *isight = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
 
        WRITE_ONCE(isight->pcm_active, true);
 
@@ -336,7 +331,7 @@ static int isight_hw_free(struct snd_pcm_substream *substream)
        isight_stop_streaming(isight);
        mutex_unlock(&isight->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int isight_start_streaming(struct isight *isight)
@@ -446,7 +441,6 @@ static int isight_create_pcm(struct isight *isight)
        static const struct snd_pcm_ops ops = {
                .open      = isight_open,
                .close     = isight_close,
-               .ioctl     = snd_pcm_lib_ioctl,
                .hw_params = isight_hw_params,
                .hw_free   = isight_hw_free,
                .prepare   = isight_prepare,
@@ -463,8 +457,7 @@ static int isight_create_pcm(struct isight *isight)
        strcpy(pcm->name, "iSight");
        isight->pcm = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
        isight->pcm->ops = &ops;
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        return 0;
 }
index 349b4d0..2d41a1a 100644 (file)
@@ -177,18 +177,14 @@ static int pcm_open(struct snd_pcm_substream *substream)
                        err = snd_pcm_hw_constraint_minmax(substream->runtime,
                                        SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
                                        frames_per_period, frames_per_period);
-                       if (err < 0) {
-                               mutex_unlock(&motu->mutex);
+                       if (err < 0)
                                goto err_locked;
-                       }
 
                        err = snd_pcm_hw_constraint_minmax(substream->runtime,
                                        SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
                                        frames_per_buffer, frames_per_buffer);
-                       if (err < 0) {
-                               mutex_unlock(&motu->mutex);
+                       if (err < 0)
                                goto err_locked;
-                       }
                }
        }
 
@@ -216,11 +212,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *hw_params)
 {
        struct snd_motu *motu = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -251,7 +243,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&motu->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int capture_prepare(struct snd_pcm_substream *substream)
@@ -348,7 +340,6 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu)
        static const struct snd_pcm_ops capture_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
-               .ioctl     = snd_pcm_lib_ioctl,
                .hw_params = pcm_hw_params,
                .hw_free   = pcm_hw_free,
                .prepare   = capture_prepare,
@@ -359,7 +350,6 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu)
        static const struct snd_pcm_ops playback_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
-               .ioctl     = snd_pcm_lib_ioctl,
                .hw_params = pcm_hw_params,
                .hw_free   = pcm_hw_free,
                .prepare   = playback_prepare,
@@ -378,8 +368,7 @@ int snd_motu_create_pcm_devices(struct snd_motu *motu)
 
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        return 0;
 }
index 16dc337..d2e57c7 100644 (file)
@@ -38,7 +38,7 @@ int avc_stream_set_format(struct fw_unit *unit, enum avc_general_plug_dir dir,
        else if (err < len + 10)
                err = -EIO;
        else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
-               err = -ENOSYS;
+               err = -ENXIO;
        else if (buf[0] == 0x0a) /* REJECTED */
                err = -EINVAL;
        else
@@ -83,7 +83,7 @@ int avc_stream_get_format(struct fw_unit *unit,
        else if (err < 12)
                err = -EIO;
        else if (buf[0] == 0x08)        /* NOT IMPLEMENTED */
-               err = -ENOSYS;
+               err = -ENXIO;
        else if (buf[0] == 0x0a)        /* REJECTED */
                err = -EINVAL;
        else if (buf[0] == 0x0b)        /* IN TRANSITION */
@@ -147,7 +147,7 @@ int avc_general_inquiry_sig_fmt(struct fw_unit *unit, unsigned int rate,
        else if (err < 8)
                err = -EIO;
        else if (buf[0] == 0x08)        /* NOT IMPLEMENTED */
-               err = -ENOSYS;
+               err = -ENXIO;
        if (err < 0)
                goto end;
 
index 9124603..2dfa7e1 100644 (file)
@@ -237,11 +237,7 @@ static int pcm_capture_hw_params(struct snd_pcm_substream *substream,
                                 struct snd_pcm_hw_params *hw_params)
 {
        struct snd_oxfw *oxfw = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -264,11 +260,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
                                  struct snd_pcm_hw_params *hw_params)
 {
        struct snd_oxfw *oxfw = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -285,7 +277,7 @@ static int pcm_playback_hw_params(struct snd_pcm_substream *substream,
                mutex_unlock(&oxfw->mutex);
        }
 
-       return 0;
+       return err;
 }
 
 static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
@@ -301,7 +293,7 @@ static int pcm_capture_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&oxfw->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
 {
@@ -316,7 +308,7 @@ static int pcm_playback_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&oxfw->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
@@ -419,7 +411,6 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
        static const struct snd_pcm_ops capture_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
-               .ioctl     = snd_pcm_lib_ioctl,
                .hw_params = pcm_capture_hw_params,
                .hw_free   = pcm_capture_hw_free,
                .prepare   = pcm_capture_prepare,
@@ -430,7 +421,6 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
        static const struct snd_pcm_ops playback_ops = {
                .open      = pcm_open,
                .close     = pcm_close,
-               .ioctl     = snd_pcm_lib_ioctl,
                .hw_params = pcm_playback_hw_params,
                .hw_free   = pcm_playback_hw_free,
                .prepare   = pcm_playback_prepare,
@@ -454,8 +444,7 @@ int snd_oxfw_create_pcm(struct snd_oxfw *oxfw)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
        if (cap > 0)
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        return 0;
 }
index 501a800..80c9dc1 100644 (file)
@@ -513,7 +513,7 @@ int snd_oxfw_stream_parse_format(u8 *format,
         *  Level 1:    AM824 Compound  (0x40)
         */
        if ((format[0] != 0x90) || (format[1] != 0x40))
-               return -ENOSYS;
+               return -ENXIO;
 
        /* check the sampling rate */
        for (i = 0; i < ARRAY_SIZE(avc_stream_rate_table); i++) {
@@ -521,7 +521,7 @@ int snd_oxfw_stream_parse_format(u8 *format,
                        break;
        }
        if (i == ARRAY_SIZE(avc_stream_rate_table))
-               return -ENOSYS;
+               return -ENXIO;
 
        formation->rate = oxfw_rate_table[i];
 
@@ -565,13 +565,13 @@ int snd_oxfw_stream_parse_format(u8 *format,
                /* Don't care */
                case 0xff:
                default:
-                       return -ENOSYS; /* not supported */
+                       return -ENXIO;  /* not supported */
                }
        }
 
        if (formation->pcm  > AM824_MAX_CHANNELS_FOR_PCM ||
            formation->midi > AM824_MAX_CHANNELS_FOR_MIDI)
-               return -ENOSYS;
+               return -ENXIO;
 
        return 0;
 }
@@ -656,7 +656,7 @@ static int fill_stream_formats(struct snd_oxfw *oxfw,
        /* get first entry */
        len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
        err = avc_stream_get_format_list(oxfw->unit, dir, 0, buf, &len, 0);
-       if (err == -ENOSYS) {
+       if (err == -ENXIO) {
                /* LIST subfunction is not implemented */
                len = AVC_GENERIC_FRAME_MAXIMUM_BYTES;
                err = assume_stream_formats(oxfw, dir, pid, buf, &len,
@@ -728,49 +728,63 @@ int snd_oxfw_stream_discover(struct snd_oxfw *oxfw)
                        err);
                goto end;
        } else if ((plugs[0] == 0) && (plugs[1] == 0)) {
-               err = -ENOSYS;
+               err = -ENXIO;
                goto end;
        }
 
        /* use oPCR[0] if exists */
        if (plugs[1] > 0) {
                err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_OUT, 0);
-               if (err < 0)
-                       goto end;
+               if (err < 0) {
+                       if (err != -ENXIO)
+                               return err;
 
-               for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
-                       format = oxfw->tx_stream_formats[i];
-                       if (format == NULL)
-                               continue;
-                       err = snd_oxfw_stream_parse_format(format, &formation);
-                       if (err < 0)
-                               continue;
-
-                       /* Add one MIDI port. */
-                       if (formation.midi > 0)
-                               oxfw->midi_input_ports = 1;
-               }
+                       // The oPCR is not available for isoc communication.
+                       err = 0;
+               } else {
+                       for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
+                               format = oxfw->tx_stream_formats[i];
+                               if (format == NULL)
+                                       continue;
+                               err = snd_oxfw_stream_parse_format(format,
+                                                                  &formation);
+                               if (err < 0)
+                                       continue;
+
+                               /* Add one MIDI port. */
+                               if (formation.midi > 0)
+                                       oxfw->midi_input_ports = 1;
+                       }
 
-               oxfw->has_output = true;
+                       oxfw->has_output = true;
+               }
        }
 
        /* use iPCR[0] if exists */
        if (plugs[0] > 0) {
                err = fill_stream_formats(oxfw, AVC_GENERAL_PLUG_DIR_IN, 0);
-               if (err < 0)
-                       goto end;
+               if (err < 0) {
+                       if (err != -ENXIO)
+                               return err;
+
+                       // The iPCR is not available for isoc communication.
+                       err = 0;
+               } else {
+                       for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
+                               format = oxfw->rx_stream_formats[i];
+                               if (format == NULL)
+                                       continue;
+                               err = snd_oxfw_stream_parse_format(format,
+                                                                  &formation);
+                               if (err < 0)
+                                       continue;
+
+                               /* Add one MIDI port. */
+                               if (formation.midi > 0)
+                                       oxfw->midi_output_ports = 1;
+                       }
 
-               for (i = 0; i < SND_OXFW_STREAM_FORMAT_ENTRIES; i++) {
-                       format = oxfw->rx_stream_formats[i];
-                       if (format == NULL)
-                               continue;
-                       err = snd_oxfw_stream_parse_format(format, &formation);
-                       if (err < 0)
-                               continue;
-
-                       /* Add one MIDI port. */
-                       if (formation.midi > 0)
-                               oxfw->midi_output_ports = 1;
+                       oxfw->has_input = true;
                }
        }
 end:
index fb6df3f..1f1e323 100644 (file)
@@ -118,7 +118,8 @@ static void oxfw_card_free(struct snd_card *card)
 {
        struct snd_oxfw *oxfw = card->private_data;
 
-       snd_oxfw_stream_destroy_duplex(oxfw);
+       if (oxfw->has_output || oxfw->has_input)
+               snd_oxfw_stream_destroy_duplex(oxfw);
 }
 
 static int detect_quirks(struct snd_oxfw *oxfw)
@@ -206,23 +207,25 @@ static void do_registration(struct work_struct *work)
        if (err < 0)
                goto error;
 
-       err = snd_oxfw_stream_init_duplex(oxfw);
-       if (err < 0)
-               goto error;
+       if (oxfw->has_output || oxfw->has_input) {
+               err = snd_oxfw_stream_init_duplex(oxfw);
+               if (err < 0)
+                       goto error;
 
-       err = snd_oxfw_create_pcm(oxfw);
-       if (err < 0)
-               goto error;
+               err = snd_oxfw_create_pcm(oxfw);
+               if (err < 0)
+                       goto error;
 
-       snd_oxfw_proc_init(oxfw);
+               snd_oxfw_proc_init(oxfw);
 
-       err = snd_oxfw_create_midi(oxfw);
-       if (err < 0)
-               goto error;
+               err = snd_oxfw_create_midi(oxfw);
+               if (err < 0)
+                       goto error;
 
-       err = snd_oxfw_create_hwdep(oxfw);
-       if (err < 0)
-               goto error;
+               err = snd_oxfw_create_hwdep(oxfw);
+               if (err < 0)
+                       goto error;
+       }
 
        err = snd_card_register(oxfw->card);
        if (err < 0)
@@ -274,9 +277,11 @@ static void oxfw_bus_reset(struct fw_unit *unit)
        fcp_bus_reset(oxfw->unit);
 
        if (oxfw->registered) {
-               mutex_lock(&oxfw->mutex);
-               snd_oxfw_stream_update_duplex(oxfw);
-               mutex_unlock(&oxfw->mutex);
+               if (oxfw->has_output || oxfw->has_input) {
+                       mutex_lock(&oxfw->mutex);
+                       snd_oxfw_stream_update_duplex(oxfw);
+                       mutex_unlock(&oxfw->mutex);
+               }
 
                if (oxfw->entry->vendor_id == OUI_STANTON)
                        snd_oxfw_scs1x_update(oxfw);
index c30e537..fa2d7f9 100644 (file)
@@ -45,6 +45,7 @@ struct snd_oxfw {
 
        bool wrong_dbs;
        bool has_output;
+       bool has_input;
        u8 *tx_stream_formats[SND_OXFW_STREAM_FORMAT_ENTRIES];
        u8 *rx_stream_formats[SND_OXFW_STREAM_FORMAT_ENTRIES];
        bool assumed;
index e80bb84..f823a2a 100644 (file)
@@ -157,14 +157,15 @@ static void read_status_messages(struct amdtp_stream *s,
                        if ((before ^ after) & mask) {
                                struct snd_firewire_tascam_change *entry =
                                                &tscm->queue[tscm->push_pos];
+                               unsigned long flag;
 
-                               spin_lock_irq(&tscm->lock);
+                               spin_lock_irqsave(&tscm->lock, flag);
                                entry->index = index;
                                entry->before = before;
                                entry->after = after;
                                if (++tscm->push_pos >= SND_TSCM_QUEUE_COUNT)
                                        tscm->push_pos = 0;
-                               spin_unlock_irq(&tscm->lock);
+                               spin_unlock_irqrestore(&tscm->lock, flag);
 
                                wake_up(&tscm->hwdep_wait);
                        }
index 8e9b444..36c1353 100644 (file)
@@ -117,11 +117,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
                         struct snd_pcm_hw_params *hw_params)
 {
        struct snd_tscm *tscm = substream->private_data;
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
+       int err = 0;
 
        if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN) {
                unsigned int rate = params_rate(hw_params);
@@ -152,7 +148,7 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
 
        mutex_unlock(&tscm->mutex);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int pcm_capture_prepare(struct snd_pcm_substream *substream)
@@ -258,7 +254,6 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
        static const struct snd_pcm_ops capture_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_capture_prepare,
@@ -269,7 +264,6 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
        static const struct snd_pcm_ops playback_ops = {
                .open           = pcm_open,
                .close          = pcm_close,
-               .ioctl          = snd_pcm_lib_ioctl,
                .hw_params      = pcm_hw_params,
                .hw_free        = pcm_hw_free,
                .prepare        = pcm_playback_prepare,
@@ -289,8 +283,7 @@ int snd_tscm_create_pcm_devices(struct snd_tscm *tscm)
                 "%s PCM", tscm->card->shortname);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        return 0;
 }
index b0c88fe..4ca6b09 100644 (file)
@@ -21,14 +21,16 @@ config SND_HDA_EXT_CORE
        select SND_HDA_CORE
 
 config SND_HDA_PREALLOC_SIZE
-       int "Pre-allocated buffer size for HD-audio driver"
+       int "Pre-allocated buffer size for HD-audio driver" if !SND_DMA_SGBUF
        range 0 32768
-       default 64
+       default 0 if SND_DMA_SGBUF
+       default 64 if !SND_DMA_SGBUF
        help
          Specifies the default pre-allocated buffer-size in kB for the
          HD-audio driver.  A larger buffer (e.g. 2048) is preferred
          for systems using PulseAudio.  The default 64 is chosen just
          for compatibility reasons.
+         On x86 systems, the default is zero as we need no preallocation.
 
          Note that the pre-allocation size can be changed dynamically
          via a proc file (/proc/asound/card*/pcm*/sub*/prealloc), too.
index 242306d..73bfa71 100644 (file)
@@ -19,10 +19,10 @@ MODULE_LICENSE("GPL v2");
 
 /**
  * snd_hdac_ext_bus_init - initialize a HD-audio extended bus
- * @ebus: the pointer to extended bus object
+ * @bus: the pointer to HDAC bus object
  * @dev: device pointer
  * @ops: bus verb operators
- * default ops
+ * @ext_ops: operators used for ASoC HDA codec drivers
  *
  * Returns 0 if successful, or a negative error code.
  */
@@ -51,7 +51,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_init);
 
 /**
  * snd_hdac_ext_bus_exit - clean up a HD-audio extended bus
- * @ebus: the pointer to extended bus object
+ * @bus: the pointer to HDAC bus object
  */
 void snd_hdac_ext_bus_exit(struct hdac_bus *bus)
 {
@@ -67,8 +67,9 @@ static void default_release(struct device *dev)
 
 /**
  * snd_hdac_ext_bus_device_init - initialize the HDA extended codec base device
- * @ebus: hdac extended bus to attach to
+ * @bus: hdac bus to attach to
  * @addr: codec address
+ * @hdev: hdac device to init
  *
  * Returns zero for success or a negative error code.
  */
@@ -114,7 +115,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_device_exit);
 /**
  * snd_hdac_ext_bus_device_remove - remove HD-audio extended codec base devices
  *
- * @ebus: HD-audio extended bus
+ * @bus: the pointer to HDAC bus object
  */
 void snd_hdac_ext_bus_device_remove(struct hdac_bus *bus)
 {
index cfab60d..a684f05 100644 (file)
@@ -28,7 +28,7 @@
 
 /**
  * snd_hdac_ext_bus_ppcap_enable - enable/disable processing pipe capability
- * @ebus: HD-audio extended core bus
+ * @bus: the pointer to HDAC bus object
  * @enable: flag to turn on/off the capability
  */
 void snd_hdac_ext_bus_ppcap_enable(struct hdac_bus *bus, bool enable)
@@ -50,7 +50,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_enable);
 
 /**
  * snd_hdac_ext_bus_ppcap_int_enable - ppcap interrupt enable/disable
- * @ebus: HD-audio extended core bus
+ * @bus: the pointer to HDAC bus object
  * @enable: flag to enable/disable interrupt
  */
 void snd_hdac_ext_bus_ppcap_int_enable(struct hdac_bus *bus, bool enable)
@@ -77,7 +77,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_ppcap_int_enable);
 
 /**
  * snd_hdac_ext_bus_get_ml_capabilities - get multilink capability
- * @ebus: HD-audio extended core bus
+ * @bus: the pointer to HDAC bus object
  *
  * This will parse all links and read the mlink capabilities and add them
  * in hlink_list of extended hdac bus
@@ -117,7 +117,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_get_ml_capabilities);
 /**
  * snd_hdac_link_free_all- free hdac extended link objects
  *
- * @ebus: HD-audio ext core bus
+ * @bus: the pointer to HDAC bus object
  */
 
 void snd_hdac_link_free_all(struct hdac_bus *bus)
@@ -134,7 +134,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_link_free_all);
 
 /**
  * snd_hdac_ext_bus_get_link_index - get link based on codec name
- * @ebus: HD-audio extended core bus
+ * @bus: the pointer to HDAC bus object
  * @codec_name: codec name
  */
 struct hdac_ext_link *snd_hdac_ext_bus_get_link(struct hdac_bus *bus,
@@ -211,7 +211,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_down);
 
 /**
  * snd_hdac_ext_bus_link_power_up_all -power up all hda link
- * @ebus: HD-audio extended bus
+ * @bus: the pointer to HDAC bus object
  */
 int snd_hdac_ext_bus_link_power_up_all(struct hdac_bus *bus)
 {
@@ -232,7 +232,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_bus_link_power_up_all);
 
 /**
  * snd_hdac_ext_bus_link_power_down_all -power down all hda link
- * @ebus: HD-audio extended bus
+ * @bus: the pointer to HDAC bus object
  */
 int snd_hdac_ext_bus_link_power_down_all(struct hdac_bus *bus)
 {
index 6b1b4b8..c4d54a8 100644 (file)
@@ -530,7 +530,6 @@ EXPORT_SYMBOL_GPL(snd_hdac_ext_stream_set_dpibr);
 
 /**
  * snd_hdac_ext_stream_set_lpib - sets the lpib value of a stream
- * @bus: HD-audio core bus
  * @stream: hdac_ext_stream
  * @value: lpib value to set
  */
index 8f19876..3fe62be 100644 (file)
@@ -22,6 +22,7 @@ static const struct hdac_bus_ops default_ops = {
 /**
  * snd_hdac_bus_init - initialize a HD-audio bas bus
  * @bus: the pointer to bus object
+ * @dev: device pointer
  * @ops: bus verb operators
  *
  * Returns 0 if successful, or a negative error code.
@@ -43,6 +44,7 @@ int snd_hdac_bus_init(struct hdac_bus *bus, struct device *dev,
        mutex_init(&bus->cmd_mutex);
        mutex_init(&bus->lock);
        INIT_LIST_HEAD(&bus->hlink_list);
+       init_waitqueue_head(&bus->rirb_wq);
        bus->irq = -1;
        return 0;
 }
@@ -63,6 +65,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_exit);
 /**
  * snd_hdac_bus_exec_verb - execute a HD-audio verb on the given bus
  * @bus: bus object
+ * @addr: the HDAC device address
  * @cmd: HD-audio encoded verb
  * @res: pointer to store the response, NULL if performing asynchronously
  *
@@ -83,6 +86,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_exec_verb);
 /**
  * snd_hdac_bus_exec_verb_unlocked - unlocked version
  * @bus: bus object
+ * @addr: the HDAC device address
  * @cmd: HD-audio encoded verb
  * @res: pointer to store the response, NULL if performing asynchronously
  *
index dfe7e75..89126c6 100644 (file)
@@ -262,6 +262,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_acomp_register_notifier);
 /**
  * snd_hdac_acomp_init - Initialize audio component
  * @bus: HDA core bus
+ * @aops: audio component ops
  * @match_master: match function for finding components
  * @extra_size: Extra bytes to allocate
  *
index 7e7be8e..bc4a8b6 100644 (file)
@@ -181,6 +181,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_send_cmd);
  * @bus: HD-audio core bus
  *
  * Usually called from interrupt handler.
+ * The caller needs bus->reg_lock spinlock before calling this.
  */
 void snd_hdac_bus_update_rirb(struct hdac_bus *bus)
 {
@@ -216,6 +217,9 @@ void snd_hdac_bus_update_rirb(struct hdac_bus *bus)
                else if (bus->rirb.cmds[addr]) {
                        bus->rirb.res[addr] = res;
                        bus->rirb.cmds[addr]--;
+                       if (!bus->rirb.cmds[addr] &&
+                           waitqueue_active(&bus->rirb_wq))
+                               wake_up(&bus->rirb_wq);
                } else {
                        dev_err_ratelimited(bus->dev,
                                "spurious response %#x:%#x, last cmd=%#08x\n",
@@ -238,30 +242,51 @@ int snd_hdac_bus_get_response(struct hdac_bus *bus, unsigned int addr,
 {
        unsigned long timeout;
        unsigned long loopcounter;
+       wait_queue_entry_t wait;
+       bool warned = false;
 
+       init_wait_entry(&wait, 0);
        timeout = jiffies + msecs_to_jiffies(1000);
 
        for (loopcounter = 0;; loopcounter++) {
                spin_lock_irq(&bus->reg_lock);
+               if (!bus->polling_mode)
+                       prepare_to_wait(&bus->rirb_wq, &wait,
+                                       TASK_UNINTERRUPTIBLE);
                if (bus->polling_mode)
                        snd_hdac_bus_update_rirb(bus);
                if (!bus->rirb.cmds[addr]) {
                        if (res)
                                *res = bus->rirb.res[addr]; /* the last value */
+                       if (!bus->polling_mode)
+                               finish_wait(&bus->rirb_wq, &wait);
                        spin_unlock_irq(&bus->reg_lock);
                        return 0;
                }
                spin_unlock_irq(&bus->reg_lock);
                if (time_after(jiffies, timeout))
                        break;
-               if (loopcounter > 3000)
+#define LOOP_COUNT_MAX 3000
+               if (!bus->polling_mode) {
+                       schedule_timeout(msecs_to_jiffies(2));
+               } else if (bus->needs_damn_long_delay ||
+                          loopcounter > LOOP_COUNT_MAX) {
+                       if (loopcounter > LOOP_COUNT_MAX && !warned) {
+                               dev_dbg_ratelimited(bus->dev,
+                                                   "too slow response, last cmd=%#08x\n",
+                                                   bus->last_cmd[addr]);
+                               warned = true;
+                       }
                        msleep(2); /* temporary workaround */
-               else {
+               else {
                        udelay(10);
                        cond_resched();
                }
        }
 
+       if (!bus->polling_mode)
+               finish_wait(&bus->rirb_wq, &wait);
+
        return -EIO;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_bus_get_response);
@@ -536,7 +561,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_bus_stop_chip);
  * snd_hdac_bus_handle_stream_irq - interrupt handler for streams
  * @bus: HD-audio core bus
  * @status: INTSTS register value
- * @ask: callback to be called for woken streams
+ * @ack: callback to be called for woken streams
  *
  * Returns the bits of handled streams, or zero if no stream is handled.
  */
index 9f3e375..9a526ae 100644 (file)
@@ -57,6 +57,7 @@ int snd_hdac_device_init(struct hdac_device *codec, struct hdac_bus *bus,
        codec->addr = addr;
        codec->type = HDA_DEV_CORE;
        mutex_init(&codec->widget_lock);
+       mutex_init(&codec->regmap_lock);
        pm_runtime_set_active(&codec->dev);
        pm_runtime_get_noresume(&codec->dev);
        atomic_set(&codec->in_pm, 0);
@@ -134,7 +135,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_exit);
 
 /**
  * snd_hdac_device_register - register the hd-audio codec base device
- * codec: the device to register
+ * @codec: the device to register
  */
 int snd_hdac_device_register(struct hdac_device *codec)
 {
@@ -157,7 +158,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_device_register);
 
 /**
  * snd_hdac_device_unregister - unregister the hd-audio codec base device
- * codec: the device to unregister
+ * @codec: the device to unregister
  */
 void snd_hdac_device_unregister(struct hdac_device *codec)
 {
@@ -280,6 +281,10 @@ EXPORT_SYMBOL_GPL(snd_hdac_read);
 
 /**
  * _snd_hdac_read_parm - read a parmeter
+ * @codec: the codec object
+ * @nid: NID to read a parameter
+ * @parm: parameter to read
+ * @res: pointer to store the read value
  *
  * This function returns zero or an error unlike snd_hdac_read_parm().
  */
@@ -637,7 +642,7 @@ struct hda_vendor_id {
        const char *name;
 };
 
-static struct hda_vendor_id hda_vendor_ids[] = {
+static const struct hda_vendor_id hda_vendor_ids[] = {
        { 0x1002, "ATI" },
        { 0x1013, "Cirrus Logic" },
        { 0x1057, "Motorola" },
@@ -692,7 +697,7 @@ struct hda_rate_tbl {
        (AC_FMT_BASE_##base##K | (((mult) - 1) << AC_FMT_MULT_SHIFT) | \
         (((div) - 1) << AC_FMT_DIV_SHIFT))
 
-static struct hda_rate_tbl rate_bits[] = {
+static const struct hda_rate_tbl rate_bits[] = {
        /* rate in Hz, ALSA rate bitmask, HDA format value */
 
        /* autodetected value used in snd_hda_query_supported_pcm */
@@ -1061,9 +1066,9 @@ EXPORT_SYMBOL_GPL(snd_hdac_check_power_state);
  * snd_hdac_sync_power_state - wait until actual power state matches
  * with the target state
  *
- * @hdac: the HDAC device
+ * @codec: the HDAC device
  * @nid: NID to send the command
- * @target_state: target state to check for
+ * @power_state: target power state to wait for
  *
  * Return power state or PS_ERROR if codec rejects GET verb.
  */
index 906b1e2..d75f31e 100644 (file)
@@ -426,12 +426,29 @@ EXPORT_SYMBOL_GPL(snd_hdac_regmap_add_vendor_verb);
 static int reg_raw_write(struct hdac_device *codec, unsigned int reg,
                         unsigned int val)
 {
+       int err;
+
+       mutex_lock(&codec->regmap_lock);
        if (!codec->regmap)
-               return hda_reg_write(codec, reg, val);
+               err = hda_reg_write(codec, reg, val);
        else
-               return regmap_write(codec->regmap, reg, val);
+               err = regmap_write(codec->regmap, reg, val);
+       mutex_unlock(&codec->regmap_lock);
+       return err;
 }
 
+/* a helper macro to call @func_call; retry with power-up if failed */
+#define CALL_RAW_FUNC(codec, func_call)                                \
+       ({                                                      \
+               int _err = func_call;                           \
+               if (_err == -EAGAIN) {                          \
+                       _err = snd_hdac_power_up_pm(codec);     \
+                       if (_err >= 0)                          \
+                               _err = func_call;               \
+                       snd_hdac_power_down_pm(codec);          \
+               }                                               \
+               _err;})
+
 /**
  * snd_hdac_regmap_write_raw - write a pseudo register with power mgmt
  * @codec: the codec object
@@ -443,42 +460,29 @@ static int reg_raw_write(struct hdac_device *codec, unsigned int reg,
 int snd_hdac_regmap_write_raw(struct hdac_device *codec, unsigned int reg,
                              unsigned int val)
 {
-       int err;
-
-       err = reg_raw_write(codec, reg, val);
-       if (err == -EAGAIN) {
-               err = snd_hdac_power_up_pm(codec);
-               if (err >= 0)
-                       err = reg_raw_write(codec, reg, val);
-               snd_hdac_power_down_pm(codec);
-       }
-       return err;
+       return CALL_RAW_FUNC(codec, reg_raw_write(codec, reg, val));
 }
 EXPORT_SYMBOL_GPL(snd_hdac_regmap_write_raw);
 
 static int reg_raw_read(struct hdac_device *codec, unsigned int reg,
                        unsigned int *val, bool uncached)
 {
+       int err;
+
+       mutex_lock(&codec->regmap_lock);
        if (uncached || !codec->regmap)
-               return hda_reg_read(codec, reg, val);
+               err = hda_reg_read(codec, reg, val);
        else
-               return regmap_read(codec->regmap, reg, val);
+               err = regmap_read(codec->regmap, reg, val);
+       mutex_unlock(&codec->regmap_lock);
+       return err;
 }
 
 static int __snd_hdac_regmap_read_raw(struct hdac_device *codec,
                                      unsigned int reg, unsigned int *val,
                                      bool uncached)
 {
-       int err;
-
-       err = reg_raw_read(codec, reg, val, uncached);
-       if (err == -EAGAIN) {
-               err = snd_hdac_power_up_pm(codec);
-               if (err >= 0)
-                       err = reg_raw_read(codec, reg, val, uncached);
-               snd_hdac_power_down_pm(codec);
-       }
-       return err;
+       return CALL_RAW_FUNC(codec, reg_raw_read(codec, reg, val, uncached));
 }
 
 /**
@@ -505,11 +509,40 @@ int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec,
        return __snd_hdac_regmap_read_raw(codec, reg, val, true);
 }
 
+static int reg_raw_update(struct hdac_device *codec, unsigned int reg,
+                         unsigned int mask, unsigned int val)
+{
+       unsigned int orig;
+       bool change;
+       int err;
+
+       mutex_lock(&codec->regmap_lock);
+       if (codec->regmap) {
+               err = regmap_update_bits_check(codec->regmap, reg, mask, val,
+                                              &change);
+               if (!err)
+                       err = change ? 1 : 0;
+       } else {
+               err = hda_reg_read(codec, reg, &orig);
+               if (!err) {
+                       val &= mask;
+                       val |= orig & ~mask;
+                       if (val != orig) {
+                               err = hda_reg_write(codec, reg, val);
+                               if (!err)
+                                       err = 1;
+                       }
+               }
+       }
+       mutex_unlock(&codec->regmap_lock);
+       return err;
+}
+
 /**
  * snd_hdac_regmap_update_raw - update a pseudo register with power mgmt
  * @codec: the codec object
  * @reg: pseudo register
- * @mask: bit mask to udpate
+ * @mask: bit mask to update
  * @val: value to update
  *
  * Returns zero if successful or a negative error code.
@@ -517,19 +550,57 @@ int snd_hdac_regmap_read_raw_uncached(struct hdac_device *codec,
 int snd_hdac_regmap_update_raw(struct hdac_device *codec, unsigned int reg,
                               unsigned int mask, unsigned int val)
 {
+       return CALL_RAW_FUNC(codec, reg_raw_update(codec, reg, mask, val));
+}
+EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw);
+
+static int reg_raw_update_once(struct hdac_device *codec, unsigned int reg,
+                              unsigned int mask, unsigned int val)
+{
        unsigned int orig;
        int err;
 
-       val &= mask;
-       err = snd_hdac_regmap_read_raw(codec, reg, &orig);
-       if (err < 0)
-               return err;
-       val |= orig & ~mask;
-       if (val == orig)
-               return 0;
-       err = snd_hdac_regmap_write_raw(codec, reg, val);
+       if (!codec->regmap)
+               return reg_raw_update(codec, reg, mask, val);
+
+       mutex_lock(&codec->regmap_lock);
+       regcache_cache_only(codec->regmap, true);
+       err = regmap_read(codec->regmap, reg, &orig);
+       regcache_cache_only(codec->regmap, false);
        if (err < 0)
-               return err;
-       return 1;
+               err = regmap_update_bits(codec->regmap, reg, mask, val);
+       mutex_unlock(&codec->regmap_lock);
+       return err;
 }
-EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw);
+
+/**
+ * snd_hdac_regmap_update_raw_once - initialize the register value only once
+ * @codec: the codec object
+ * @reg: pseudo register
+ * @mask: bit mask to update
+ * @val: value to update
+ *
+ * Performs the update of the register bits only once when the register
+ * hasn't been initialized yet.  Used in HD-audio legacy driver.
+ * Returns zero if successful or a negative error code
+ */
+int snd_hdac_regmap_update_raw_once(struct hdac_device *codec, unsigned int reg,
+                                   unsigned int mask, unsigned int val)
+{
+       return CALL_RAW_FUNC(codec, reg_raw_update_once(codec, reg, mask, val));
+}
+EXPORT_SYMBOL_GPL(snd_hdac_regmap_update_raw_once);
+
+/**
+ * snd_hdac_regmap_sync - sync out the cached values for PM resume
+ * @codec: the codec object
+ */
+void snd_hdac_regmap_sync(struct hdac_device *codec)
+{
+       if (codec->regmap) {
+               mutex_lock(&codec->regmap_lock);
+               regcache_sync(codec->regmap);
+               mutex_unlock(&codec->regmap_lock);
+       }
+}
+EXPORT_SYMBOL_GPL(snd_hdac_regmap_sync);
index f9707fb..a314b03 100644 (file)
@@ -120,10 +120,8 @@ void snd_hdac_stream_clear(struct hdac_stream *azx_dev)
        snd_hdac_stream_updateb(azx_dev, SD_CTL,
                                SD_CTL_DMA_START | SD_INT_MASK, 0);
        snd_hdac_stream_writeb(azx_dev, SD_STS, SD_INT_MASK); /* to be sure */
-       if (azx_dev->stripe) {
+       if (azx_dev->stripe)
                snd_hdac_stream_updateb(azx_dev, SD_CTL_3B, SD_CTL_STRIPE_MASK, 0);
-               azx_dev->stripe = 0;
-       }
        azx_dev->running = false;
 }
 EXPORT_SYMBOL_GPL(snd_hdac_stream_clear);
@@ -592,7 +590,9 @@ EXPORT_SYMBOL_GPL(snd_hdac_stream_timecounter_init);
 /**
  * snd_hdac_stream_sync_trigger - turn on/off stream sync register
  * @azx_dev: HD-audio core stream (master stream)
+ * @set: true = set, false = clear
  * @streams: bit flags of streams to sync
+ * @reg: the stream sync register address
  */
 void snd_hdac_stream_sync_trigger(struct hdac_stream *azx_dev, bool set,
                                  unsigned int streams, unsigned int reg)
@@ -631,20 +631,27 @@ void snd_hdac_stream_sync(struct hdac_stream *azx_dev, bool start,
                nwait = 0;
                i = 0;
                list_for_each_entry(s, &bus->stream_list, list) {
-                       if (streams & (1 << i)) {
-                               if (start) {
-                                       /* check FIFO gets ready */
-                                       if (!(snd_hdac_stream_readb(s, SD_STS) &
-                                             SD_STS_FIFO_READY))
-                                               nwait++;
-                               } else {
-                                       /* check RUN bit is cleared */
-                                       if (snd_hdac_stream_readb(s, SD_CTL) &
-                                           SD_CTL_DMA_START)
-                                               nwait++;
+                       if (!(streams & (1 << i++)))
+                               continue;
+
+                       if (start) {
+                               /* check FIFO gets ready */
+                               if (!(snd_hdac_stream_readb(s, SD_STS) &
+                                     SD_STS_FIFO_READY))
+                                       nwait++;
+                       } else {
+                               /* check RUN bit is cleared */
+                               if (snd_hdac_stream_readb(s, SD_CTL) &
+                                   SD_CTL_DMA_START) {
+                                       nwait++;
+                                       /*
+                                        * Perform stream reset if DMA RUN
+                                        * bit not cleared within given timeout
+                                        */
+                                       if (timeout == 1)
+                                               snd_hdac_stream_reset(s);
                                }
                        }
-                       i++;
                }
                if (!nwait)
                        break;
index 886cb78..5fd6d57 100644 (file)
@@ -59,7 +59,7 @@ static const char * const cea_speaker_allocation_names[] = {
 /*
  * ELD SA bits in the CEA Speaker Allocation data block
  */
-static int eld_speaker_allocation_bits[] = {
+static const int eld_speaker_allocation_bits[] = {
        [0] = FL | FR,
        [1] = LFE,
        [2] = FC,
index 097ff6c..99a23fe 100644 (file)
@@ -7,7 +7,7 @@
 #define NHLT_ACPI_HEADER_SIG   "NHLT"
 
 /* Unique identification for getting NHLT blobs */
-static guid_t osc_guid =
+static const guid_t osc_guid =
        GUID_INIT(0xA69F886E, 0x6CEB, 0x4594,
                  0xA4, 0x1F, 0x7B, 0x5D, 0xCE, 0x24, 0xC5, 0x53);
 
index bac4f00..8634d4f 100644 (file)
@@ -459,7 +459,7 @@ static int snd_cs8427_spdif_mask_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_cs8427_iec958_controls[] = {
+static const struct snd_kcontrol_new snd_cs8427_iec958_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .info =         snd_cs8427_in_status_info,
index 37b3c69..a684faa 100644 (file)
@@ -67,7 +67,7 @@ int snd_i2c_bus_create(struct snd_card *card, const char *name,
 {
        struct snd_i2c_bus *bus;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_i2c_bus_dev_free,
        };
 
index 775f9a3..e721309 100644 (file)
@@ -60,7 +60,7 @@ int snd_ak4113_create(struct snd_card *card, ak4113_read_t *read,
        struct ak4113 *chip;
        int err;
        unsigned char reg;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ak4113_dev_free,
        };
 
@@ -349,7 +349,7 @@ static int snd_ak4113_spdif_qget(struct snd_kcontrol *kcontrol,
 }
 
 /* Don't forget to change AK4113_CONTROLS define!!! */
-static struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
+static const struct snd_kcontrol_new snd_ak4113_iec958_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         "IEC958 Parity Errors",
index 6611c7d..2ce0a97 100644 (file)
@@ -71,7 +71,7 @@ int snd_ak4114_create(struct snd_card *card,
        struct ak4114 *chip;
        int err = 0;
        unsigned char reg;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ak4114_dev_free,
        };
 
@@ -318,7 +318,7 @@ static int snd_ak4114_spdif_qget(struct snd_kcontrol *kcontrol,
 }
 
 /* Don't forget to change AK4114_CONTROLS define!!! */
-static struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
+static const struct snd_kcontrol_new snd_ak4114_iec958_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         "IEC958 Parity Errors",
index 381949c..905be2d 100644 (file)
@@ -64,7 +64,7 @@ int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t
        struct ak4117 *chip;
        int err = 0;
        unsigned char reg;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ak4117_dev_free,
        };
 
@@ -305,7 +305,7 @@ static int snd_ak4117_spdif_qget(struct snd_kcontrol *kcontrol,
 }
 
 /* Don't forget to change AK4117_CONTROLS define!!! */
-static struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
+static const struct snd_kcontrol_new snd_ak4117_iec958_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         "IEC958 Parity Errors",
index 93ca8bb..08eb6a8 100644 (file)
@@ -260,7 +260,7 @@ static int snd_tea6330t_put_treble(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_tea6330t_controls[] = {
+static const struct snd_kcontrol_new snd_tea6330t_controls[] = {
 TEA6330T_MASTER_SWITCH("Master Playback Switch", 0),
 TEA6330T_MASTER_VOLUME("Master Playback Volume", 0),
 TEA6330T_BASS("Tone Control - Bass", 0),
@@ -278,7 +278,7 @@ int snd_tea6330t_update_mixer(struct snd_card *card,
 {
        struct snd_i2c_device *device;
        struct tea6330t *tea;
-       struct snd_kcontrol_new *knew;
+       const struct snd_kcontrol_new *knew;
        unsigned int idx;
        int err = -ENOMEM;
        u8 default_treble, default_bass;
index c4c60eb..01381fe 100644 (file)
@@ -206,17 +206,6 @@ static int snd_ad1816a_capture_trigger(struct snd_pcm_substream *substream, int
                                   SNDRV_PCM_STREAM_CAPTURE, cmd, 1);
 }
 
-static int snd_ad1816a_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_ad1816a_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_ad1816a_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_ad1816a *chip = snd_pcm_substream_chip(substream);
@@ -420,7 +409,7 @@ static int snd_ad1816a_timer_stop(struct snd_timer *timer)
        return 0;
 }
 
-static struct snd_timer_hardware snd_ad1816a_timer_table = {
+static const struct snd_timer_hardware snd_ad1816a_timer_table = {
        .flags =        SNDRV_TIMER_HW_AUTO,
        .resolution =   10000,
        .ticks =        65535,
@@ -588,7 +577,7 @@ int snd_ad1816a_create(struct snd_card *card,
                       unsigned long port, int irq, int dma1, int dma2,
                       struct snd_ad1816a *chip)
 {
-        static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ad1816a_dev_free,
        };
        int error;
@@ -608,6 +597,7 @@ int snd_ad1816a_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = irq;
+       card->sync_irq = chip->irq;
        if (request_dma(dma1, "AD1816A - 1")) {
                snd_printk(KERN_ERR "ad1816a: can't grab DMA1 %d\n", dma1);
                snd_ad1816a_free(chip);
@@ -644,9 +634,6 @@ int snd_ad1816a_create(struct snd_card *card,
 static const struct snd_pcm_ops snd_ad1816a_playback_ops = {
        .open =         snd_ad1816a_playback_open,
        .close =        snd_ad1816a_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ad1816a_hw_params,
-       .hw_free =      snd_ad1816a_hw_free,
        .prepare =      snd_ad1816a_playback_prepare,
        .trigger =      snd_ad1816a_playback_trigger,
        .pointer =      snd_ad1816a_playback_pointer,
@@ -655,9 +642,6 @@ static const struct snd_pcm_ops snd_ad1816a_playback_ops = {
 static const struct snd_pcm_ops snd_ad1816a_capture_ops = {
        .open =         snd_ad1816a_capture_open,
        .close =        snd_ad1816a_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ad1816a_hw_params,
-       .hw_free =      snd_ad1816a_hw_free,
        .prepare =      snd_ad1816a_capture_prepare,
        .trigger =      snd_ad1816a_capture_trigger,
        .pointer =      snd_ad1816a_capture_pointer,
@@ -680,9 +664,8 @@ int snd_ad1816a_pcm(struct snd_ad1816a *chip, int device)
        strcpy(pcm->name, snd_ad1816a_chip_id(chip));
        snd_ad1816a_init(chip);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             chip->card->dev,
-                                             64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, chip->card->dev,
+                                      64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
 
        chip->pcm = pcm;
        return 0;
@@ -901,7 +884,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
 
-static struct snd_kcontrol_new snd_ad1816a_controls[] = {
+static const struct snd_kcontrol_new snd_ad1816a_controls[] = {
 AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
 AD1816A_DOUBLE_TLV("Master Playback Volume", AD1816A_MASTER_ATT, 8, 0, 31, 1,
                   db_scale_5bit),
index 250db35..faca5dd 100644 (file)
@@ -32,7 +32,7 @@ MODULE_LICENSE("GPL");
 #endif
 
 /* I/O port is configured by jumpers on the card to one of these */
-static int cmi8328_ports[] = { 0x530, 0xe80, 0xf40, 0x604 };
+static const int cmi8328_ports[] = { 0x530, 0xe80, 0xf40, 0x604 };
 #define CMI8328_MAX    ARRAY_SIZE(cmi8328_ports)
 
 static int index[CMI8328_MAX] =     {[0 ... (CMI8328_MAX-1)] = -1};
@@ -193,7 +193,7 @@ static int snd_cmi8328_mixer(struct snd_wss *chip)
 }
 
 /* find index of an item in "-1"-ended array */
-static int array_find(int array[], int item)
+static int array_find(const int array[], int item)
 {
        int i;
 
@@ -204,7 +204,7 @@ static int array_find(int array[], int item)
        return -1;
 }
 /* the same for long */
-static int array_find_l(long array[], long item)
+static int array_find_l(const long array[], long item)
 {
        int i;
 
@@ -224,16 +224,16 @@ static int snd_cmi8328_probe(struct device *pdev, unsigned int ndev)
        struct resource *res;
 #endif
        int err, pos;
-       static long mpu_ports[] = { 0x330, 0x300, 0x310, 0x320, 0x332, 0x334,
+       static const long mpu_ports[] = { 0x330, 0x300, 0x310, 0x320, 0x332, 0x334,
                                   0x336, -1 };
-       static u8 mpu_port_bits[] = { 3, 0, 1, 2, 4, 5, 6 };
-       static int mpu_irqs[] = { 9, 7, 5, 3, -1 };
-       static u8 mpu_irq_bits[] = { 3, 2, 1, 0 };
-       static int irqs[] = { 9, 10, 11, 7, -1 };
-       static u8 irq_bits[] = { 2, 3, 4, 1 };
-       static int dma1s[] = { 3, 1, 0, -1 };
-       static u8 dma_bits[] = { 3, 2, 1 };
-       static int dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, {0, -1} };
+       static const u8 mpu_port_bits[] = { 3, 0, 1, 2, 4, 5, 6 };
+       static const int mpu_irqs[] = { 9, 7, 5, 3, -1 };
+       static const u8 mpu_irq_bits[] = { 3, 2, 1, 0 };
+       static const int irqs[] = { 9, 10, 11, 7, -1 };
+       static const u8 irq_bits[] = { 2, 3, 4, 1 };
+       static const int dma1s[] = { 3, 1, 0, -1 };
+       static const u8 dma_bits[] = { 3, 2, 1 };
+       static const int dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, {0, -1} };
        u16 port = cmi8328_ports[ndev];
        u8 val;
 
index bb7d494..4669eb0 100644 (file)
@@ -120,7 +120,7 @@ static int pnp_registered;
 #define CMI8330_LINGAIN   25
 #define CMI8330_CDINGAIN  26
 
-static unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] =
+static const unsigned char snd_cmi8330_image[((CMI8330_CDINGAIN)-16) + 1] =
 {
        0x40,                   /* 16 - recording mux (SB-mixer-enabled) */
 #ifdef ENABLE_SB_MIXER
@@ -179,7 +179,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_cmi8330_pnpids);
 #endif
 
 
-static struct snd_kcontrol_new snd_cmi8330_controls[] = {
+static const struct snd_kcontrol_new snd_cmi8330_controls[] = {
 WSS_DOUBLE("Master Playback Volume", 0,
                CMI8330_MASTVOL, CMI8330_MASTVOL, 4, 0, 15, 0),
 WSS_SINGLE("Loud Playback Switch", 0,
@@ -235,7 +235,7 @@ WSS_SINGLE(SNDRV_CTL_NAME_IEC958("Input ", PLAYBACK, SWITCH), 0,
 };
 
 #ifdef ENABLE_SB_MIXER
-static struct sbmix_elem cmi8330_sb_mixers[] = {
+static const struct sbmix_elem cmi8330_sb_mixers[] = {
 SB_DOUBLE("SB Master Playback Volume", SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
 SB_DOUBLE("Tone Control - Bass", SB_DSP4_BASS_DEV, (SB_DSP4_BASS_DEV + 1), 4, 4, 15),
 SB_DOUBLE("Tone Control - Treble", SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15),
@@ -253,7 +253,7 @@ SB_DOUBLE("SB Playback Volume", SB_DSP4_OGAIN_DEV, (SB_DSP4_OGAIN_DEV + 1), 6, 6
 SB_SINGLE("SB Mic Auto Gain", SB_DSP4_MIC_AGC, 0, 1),
 };
 
-static unsigned char cmi8330_sb_init_values[][2] = {
+static const unsigned char cmi8330_sb_init_values[][2] = {
        { SB_DSP4_MASTER_DEV + 0, 0 },
        { SB_DSP4_MASTER_DEV + 1, 0 },
        { SB_DSP4_PCM_DEV + 0, 0 },
@@ -428,7 +428,7 @@ static int snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
        struct snd_pcm *pcm;
        const struct snd_pcm_ops *ops;
        int err;
-       static snd_pcm_open_callback_t cmi_open_callbacks[2] = {
+       static const snd_pcm_open_callback_t cmi_open_callbacks[2] = {
                snd_cmi8330_playback_open,
                snd_cmi8330_capture_open
        };
@@ -455,9 +455,8 @@ static int snd_cmi8330_pcm(struct snd_card *card, struct snd_cmi8330 *chip)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &chip->streams[SNDRV_PCM_STREAM_PLAYBACK].ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &chip->streams[SNDRV_PCM_STREAM_CAPTURE].ops);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             card->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      card->dev, 64*1024, 128*1024);
        chip->pcm = pcm;
 
        return 0;
index be48c60..4a028f4 100644 (file)
@@ -80,7 +80,7 @@
  *
  */
 
-static unsigned char snd_cs4236_ext_map[18] = {
+static const unsigned char snd_cs4236_ext_map[18] = {
        /* CS4236_LEFT_LINE */          0xff,
        /* CS4236_RIGHT_LINE */         0xff,
        /* CS4236_LEFT_MIC */           0xdf,
@@ -758,7 +758,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_2bit, -1800, 600, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
 
-static struct snd_kcontrol_new snd_cs4236_controls[] = {
+static const struct snd_kcontrol_new snd_cs4236_controls[] = {
 
 CS4236_DOUBLE("Master Digital Playback Switch", 0,
                CS4236_LEFT_MASTER, CS4236_RIGHT_MASTER, 7, 7, 1, 1),
@@ -853,7 +853,7 @@ CS4236_DOUBLE1_TLV("Loopback Digital Playback Volume", 0,
 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_6db_max, -5600, 200, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_2bit_16db_max, -2400, 800, 0);
 
-static struct snd_kcontrol_new snd_cs4235_controls[] = {
+static const struct snd_kcontrol_new snd_cs4235_controls[] = {
 
 WSS_DOUBLE("Master Playback Switch", 0,
                CS4235_LEFT_MASTER, CS4235_RIGHT_MASTER, 7, 7, 1, 1),
@@ -986,7 +986,7 @@ static int snd_cs4236_put_iec958_switch(struct snd_kcontrol *kcontrol, struct sn
        return change;
 }
 
-static struct snd_kcontrol_new snd_cs4236_iec958_controls[] = {
+static const struct snd_kcontrol_new snd_cs4236_iec958_controls[] = {
 CS4236_IEC958_ENABLE("IEC958 Output Enable", 0),
 CS4236_SINGLEC("IEC958 Output Validity", 0, 4, 4, 1, 0),
 CS4236_SINGLEC("IEC958 Output User", 0, 4, 5, 1, 0),
@@ -995,12 +995,12 @@ CS4236_SINGLEC("IEC958 Output Channel Status Low", 0, 5, 1, 127, 0),
 CS4236_SINGLEC("IEC958 Output Channel Status High", 0, 6, 0, 255, 0)
 };
 
-static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4235[] = {
+static const struct snd_kcontrol_new snd_cs4236_3d_controls_cs4235[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1)
 };
 
-static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4237[] = {
+static const struct snd_kcontrol_new snd_cs4236_3d_controls_cs4237[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 7, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
 CS4236_SINGLEC("3D Control - Center", 0, 2, 0, 15, 1),
@@ -1008,7 +1008,7 @@ CS4236_SINGLEC("3D Control - Mono", 0, 3, 6, 1, 0),
 CS4236_SINGLEC("3D Control - IEC958", 0, 3, 5, 1, 0)
 };
 
-static struct snd_kcontrol_new snd_cs4236_3d_controls_cs4238[] = {
+static const struct snd_kcontrol_new snd_cs4236_3d_controls_cs4238[] = {
 CS4236_SINGLEC("3D Control - Switch", 0, 3, 4, 1, 0),
 CS4236_SINGLEC("3D Control - Space", 0, 2, 4, 15, 1),
 CS4236_SINGLEC("3D Control - Volume", 0, 2, 0, 15, 1),
@@ -1020,7 +1020,7 @@ int snd_cs4236_mixer(struct snd_wss *chip)
        struct snd_card *card;
        unsigned int idx, count;
        int err;
-       struct snd_kcontrol_new *kcontrol;
+       const struct snd_kcontrol_new *kcontrol;
 
        if (snd_BUG_ON(!chip || !chip->card))
                return -EINVAL;
index 9be8937..ff3a05a 100644 (file)
@@ -84,9 +84,9 @@ static int snd_es1688_legacy_create(struct snd_card *card,
                                    struct device *dev, unsigned int n)
 {
        struct snd_es1688 *chip = card->private_data;
-       static long possible_ports[] = {0x220, 0x240, 0x260};
-       static int possible_irqs[] = {5, 9, 10, 7, -1};
-       static int possible_dmas[] = {1, 3, 0, -1};
+       static const long possible_ports[] = {0x220, 0x240, 0x260};
+       static const int possible_irqs[] = {5, 9, 10, 7, -1};
+       static const int possible_dmas[] = {1, 3, 0, -1};
 
        int i, error;
 
index a28daba..1816e55 100644 (file)
@@ -180,7 +180,7 @@ static int snd_es1688_probe(struct snd_es1688 *chip)
 
 static int snd_es1688_init(struct snd_es1688 * chip, int enable)
 {
-       static int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1};
+       static const int irqs[16] = {-1, -1, 0, -1, -1, 1, -1, 2, -1, 0, 3, -1, -1, -1, -1, -1};
        unsigned long flags;
        int cfg, irq_bits, dma, dma_bits, tmp, tmp1;
 
@@ -309,12 +309,6 @@ static void snd_es1688_set_rate(struct snd_es1688 *chip, struct snd_pcm_substrea
        snd_es1688_write(chip, 0xa2, divider);
 }
 
-static int snd_es1688_ioctl(struct snd_pcm_substream *substream,
-                           unsigned int cmd, void *arg)
-{
-       return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
 static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char value)
 {
        int val;
@@ -341,17 +335,6 @@ static int snd_es1688_trigger(struct snd_es1688 *chip, int cmd, unsigned char va
        return 0;
 }
 
-static int snd_es1688_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_es1688_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_es1688_playback_prepare(struct snd_pcm_substream *substream)
 {
        unsigned long flags;
@@ -629,7 +612,7 @@ int snd_es1688_create(struct snd_card *card,
                      int dma8,
                      unsigned short hardware)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_es1688_dev_free,
        };
                                 
@@ -655,6 +638,7 @@ int snd_es1688_create(struct snd_card *card,
        }
 
        chip->irq = irq;
+       card->sync_irq = chip->irq;
        err = request_dma(dma8, "ES1688");
 
        if (err < 0) {
@@ -692,9 +676,6 @@ exit:
 static const struct snd_pcm_ops snd_es1688_playback_ops = {
        .open =                 snd_es1688_playback_open,
        .close =                snd_es1688_playback_close,
-       .ioctl =                snd_es1688_ioctl,
-       .hw_params =            snd_es1688_hw_params,
-       .hw_free =              snd_es1688_hw_free,
        .prepare =              snd_es1688_playback_prepare,
        .trigger =              snd_es1688_playback_trigger,
        .pointer =              snd_es1688_playback_pointer,
@@ -703,9 +684,6 @@ static const struct snd_pcm_ops snd_es1688_playback_ops = {
 static const struct snd_pcm_ops snd_es1688_capture_ops = {
        .open =                 snd_es1688_capture_open,
        .close =                snd_es1688_capture_close,
-       .ioctl =                snd_es1688_ioctl,
-       .hw_params =            snd_es1688_hw_params,
-       .hw_free =              snd_es1688_hw_free,
        .prepare =              snd_es1688_capture_prepare,
        .trigger =              snd_es1688_capture_trigger,
        .pointer =              snd_es1688_capture_pointer,
@@ -728,9 +706,8 @@ int snd_es1688_pcm(struct snd_card *card, struct snd_es1688 *chip, int device)
        strcpy(pcm->name, snd_es1688_chip_id(chip));
        chip->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             card->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev,
+                                      64*1024, 64*1024);
        return 0;
 }
 
@@ -947,7 +924,7 @@ static int snd_es1688_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        return change;
 }
 
-static struct snd_kcontrol_new snd_es1688_controls[] = {
+static const struct snd_kcontrol_new snd_es1688_controls[] = {
 ES1688_DOUBLE("Master Playback Volume", 0, ES1688_MASTER_DEV, ES1688_MASTER_DEV, 4, 0, 15, 0),
 ES1688_DOUBLE("PCM Playback Volume", 0, ES1688_PCM_DEV, ES1688_PCM_DEV, 4, 0, 15, 0),
 ES1688_DOUBLE("Line Playback Volume", 0, ES1688_LINE_DEV, ES1688_LINE_DEV, 4, 0, 15, 0),
@@ -969,7 +946,7 @@ ES1688_SINGLE("Capture Switch", 0, ES1688_REC_DEV, 4, 1, 1),
 
 #define ES1688_INIT_TABLE_SIZE (sizeof(snd_es1688_init_table)/2)
 
-static unsigned char snd_es1688_init_table[][2] = {
+static const unsigned char snd_es1688_init_table[][2] = {
        { ES1688_MASTER_DEV, 0 },
        { ES1688_PCM_DEV, 0 },
        { ES1688_LINE_DEV, 0 },
index 01ad150..d1135f6 100644 (file)
@@ -434,7 +434,7 @@ static int snd_es18xx_playback_hw_params(struct snd_pcm_substream *substream,
                                         struct snd_pcm_hw_params *hw_params)
 {
        struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
-       int shift, err;
+       int shift;
 
        shift = 0;
        if (params_channels(hw_params) == 2)
@@ -453,16 +453,9 @@ static int snd_es18xx_playback_hw_params(struct snd_pcm_substream *substream,
        } else {
                chip->dma1_shift = shift;
        }
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
        return 0;
 }
 
-static int snd_es18xx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_es18xx_playback1_prepare(struct snd_es18xx *chip,
                                        struct snd_pcm_substream *substream)
 {
@@ -543,7 +536,7 @@ static int snd_es18xx_capture_hw_params(struct snd_pcm_substream *substream,
                                        struct snd_pcm_hw_params *hw_params)
 {
        struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
-       int shift, err;
+       int shift;
 
        shift = 0;
        if ((chip->caps & ES18XX_DUPLEX_MONO) &&
@@ -557,8 +550,6 @@ static int snd_es18xx_capture_hw_params(struct snd_pcm_substream *substream,
        if (snd_pcm_format_width(params_format(hw_params)) == 16)
                shift++;
        chip->dma1_shift = shift;
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
        return 0;
 }
 
@@ -915,7 +906,6 @@ static int snd_es18xx_playback_close(struct snd_pcm_substream *substream)
        else
                chip->playback_b_substream = NULL;
        
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -924,7 +914,6 @@ static int snd_es18xx_capture_close(struct snd_pcm_substream *substream)
         struct snd_es18xx *chip = snd_pcm_substream_chip(substream);
 
         chip->capture_a_substream = NULL;
-       snd_pcm_lib_free_pages(substream);
         return 0;
 }
 
@@ -976,7 +965,7 @@ static int snd_es18xx_info_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_ele
 
 static int snd_es18xx_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
-       static unsigned char invMap4Source[8] = {0, 0, 1, 1, 0, 0, 2, 3};
+       static const unsigned char invMap4Source[8] = {0, 0, 1, 1, 0, 0, 2, 3};
        struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
        int muxSource = snd_es18xx_mixer_read(chip, 0x1c) & 0x07;
        if (!(chip->version == 0x1869 || chip->version == 0x1879)) {
@@ -993,7 +982,7 @@ static int snd_es18xx_get_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
 
 static int snd_es18xx_put_mux(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
 {
-       static unsigned char map4Source[4] = {0, 2, 6, 7};
+       static const unsigned char map4Source[4] = {0, 2, 6, 7};
        struct snd_es18xx *chip = snd_kcontrol_chip(kcontrol);
        unsigned char val = ucontrol->value.enumerated.item[0];
        unsigned char retVal = 0;
@@ -1257,7 +1246,7 @@ static int snd_es18xx_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_e
  * The controls that are universal to all chipsets are fully initialized
  * here.
  */
-static struct snd_kcontrol_new snd_es18xx_base_controls[] = {
+static const struct snd_kcontrol_new snd_es18xx_base_controls[] = {
 ES18XX_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0),
 ES18XX_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1),
 ES18XX_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0),
@@ -1276,7 +1265,7 @@ ES18XX_DOUBLE("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0),
 }
 };
 
-static struct snd_kcontrol_new snd_es18xx_recmix_controls[] = {
+static const struct snd_kcontrol_new snd_es18xx_recmix_controls[] = {
 ES18XX_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0),
 ES18XX_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0),
 ES18XX_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0),
@@ -1288,35 +1277,35 @@ ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0)
 /*
  * The chipset specific mixer controls
  */
-static struct snd_kcontrol_new snd_es18xx_opt_speaker =
+static const struct snd_kcontrol_new snd_es18xx_opt_speaker =
        ES18XX_SINGLE("Beep Playback Volume", 0, 0x3c, 0, 7, 0);
 
-static struct snd_kcontrol_new snd_es18xx_opt_1869[] = {
+static const struct snd_kcontrol_new snd_es18xx_opt_1869[] = {
 ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, ES18XX_FL_INVERT),
 ES18XX_SINGLE("Video Playback Switch", 0, 0x7f, 0, 1, 0),
 ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0),
 ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0)
 };
 
-static struct snd_kcontrol_new snd_es18xx_opt_1878 =
+static const struct snd_kcontrol_new snd_es18xx_opt_1878 =
        ES18XX_DOUBLE("Video Playback Volume", 0, 0x68, 0x68, 4, 0, 15, 0);
 
-static struct snd_kcontrol_new snd_es18xx_opt_1879[] = {
+static const struct snd_kcontrol_new snd_es18xx_opt_1879[] = {
 ES18XX_SINGLE("Video Playback Switch", 0, 0x71, 6, 1, 0),
 ES18XX_DOUBLE("Video Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0),
 ES18XX_DOUBLE("Video Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0)
 };
 
-static struct snd_kcontrol_new snd_es18xx_pcm1_controls[] = {
+static const struct snd_kcontrol_new snd_es18xx_pcm1_controls[] = {
 ES18XX_DOUBLE("PCM Playback Volume", 0, 0x14, 0x14, 4, 0, 15, 0),
 };
 
-static struct snd_kcontrol_new snd_es18xx_pcm2_controls[] = {
+static const struct snd_kcontrol_new snd_es18xx_pcm2_controls[] = {
 ES18XX_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0),
 ES18XX_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0)
 };
 
-static struct snd_kcontrol_new snd_es18xx_spatializer_controls[] = {
+static const struct snd_kcontrol_new snd_es18xx_spatializer_controls[] = {
 ES18XX_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0),
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1327,13 +1316,13 @@ ES18XX_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0),
 }
 };
 
-static struct snd_kcontrol_new snd_es18xx_micpre1_control = 
+static const struct snd_kcontrol_new snd_es18xx_micpre1_control =
 ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0xa9, 2, 1, 0);
 
-static struct snd_kcontrol_new snd_es18xx_micpre2_control =
+static const struct snd_kcontrol_new snd_es18xx_micpre2_control =
 ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0);
 
-static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = {
+static const struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Hardware Master Playback Volume",
@@ -1351,7 +1340,7 @@ static struct snd_kcontrol_new snd_es18xx_hw_volume_controls[] = {
 ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
 };
 
-static struct snd_kcontrol_new snd_es18xx_opt_gpo_2bit[] = {
+static const struct snd_kcontrol_new snd_es18xx_opt_gpo_2bit[] = {
 ES18XX_SINGLE("GPO0 Switch", 0, ES18XX_PM, 0, 1, ES18XX_FL_PMPORT),
 ES18XX_SINGLE("GPO1 Switch", 0, ES18XX_PM, 1, 1, ES18XX_FL_PMPORT),
 };
@@ -1654,9 +1643,7 @@ static int snd_es18xx_probe(struct snd_es18xx *chip,
 static const struct snd_pcm_ops snd_es18xx_playback_ops = {
        .open =         snd_es18xx_playback_open,
        .close =        snd_es18xx_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_es18xx_playback_hw_params,
-       .hw_free =      snd_es18xx_pcm_hw_free,
        .prepare =      snd_es18xx_playback_prepare,
        .trigger =      snd_es18xx_playback_trigger,
        .pointer =      snd_es18xx_playback_pointer,
@@ -1665,9 +1652,7 @@ static const struct snd_pcm_ops snd_es18xx_playback_ops = {
 static const struct snd_pcm_ops snd_es18xx_capture_ops = {
        .open =         snd_es18xx_capture_open,
        .close =        snd_es18xx_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_es18xx_capture_hw_params,
-       .hw_free =      snd_es18xx_pcm_hw_free,
        .prepare =      snd_es18xx_capture_prepare,
        .trigger =      snd_es18xx_capture_trigger,
        .pointer =      snd_es18xx_capture_pointer,
@@ -1701,10 +1686,9 @@ static int snd_es18xx_pcm(struct snd_card *card, int device)
        sprintf(pcm->name, "ESS AudioDrive ES%x", chip->version);
         chip->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             card->dev,
-                                             64*1024,
-                                             chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, card->dev,
+                                      64*1024,
+                                      chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
        return 0;
 }
 
@@ -1769,7 +1753,7 @@ static int snd_es18xx_new_device(struct snd_card *card,
                                 int irq, int dma1, int dma2)
 {
        struct snd_es18xx *chip = card->private_data;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_es18xx_dev_free,
         };
        int err;
@@ -1797,6 +1781,7 @@ static int snd_es18xx_new_device(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = irq;
+       card->sync_irq = chip->irq;
 
        if (request_dma(dma1, "ES18xx DMA 1")) {
                snd_es18xx_free(card);
@@ -2188,8 +2173,8 @@ static int snd_es18xx_isa_probe1(int dev, struct device *devptr)
 static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
 {
        int err;
-       static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
-       static int possible_dmas[] = {1, 0, 3, 5, -1};
+       static const int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
+       static const int possible_dmas[] = {1, 0, 3, 5, -1};
 
        if (irq[dev] == SNDRV_AUTO_IRQ) {
                if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) {
@@ -2213,7 +2198,7 @@ static int snd_es18xx_isa_probe(struct device *pdev, unsigned int dev)
        if (port[dev] != SNDRV_AUTO_PORT) {
                return snd_es18xx_isa_probe1(dev, pdev);
        } else {
-               static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280};
+               static const unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280};
                int i;
                for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
                        port[dev] = possible_ports[i];
index 0ab550b..fb7b5e2 100644 (file)
@@ -403,7 +403,7 @@ void snd_gf1_select_active_voices(struct snd_gus_card * gus)
 {
        unsigned short voices;
 
-       static unsigned short voices_tbl[32 - 14 + 1] =
+       static const unsigned short voices_tbl[32 - 14 + 1] =
        {
            44100, 41160, 38587, 36317, 34300, 32494, 30870, 29400, 28063, 26843,
            25725, 24696, 23746, 22866, 22050, 21289, 20580, 19916, 19293
index af6b4d8..afc088f 100644 (file)
@@ -134,7 +134,7 @@ int snd_gus_create(struct snd_card *card,
 {
        struct snd_gus_card *gus;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_gus_dev_free,
        };
 
@@ -181,6 +181,7 @@ int snd_gus_create(struct snd_card *card,
                return -EBUSY;
        }
        gus->gf1.irq = irq;
+       card->sync_irq = irq;
        if (request_dma(dma1, "GUS - 1")) {
                snd_printk(KERN_ERR "gus: can't grab DMA1 %d\n", dma1);
                snd_gus_free(gus);
@@ -266,9 +267,9 @@ static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches)
        struct snd_card *card;
        unsigned long flags;
        int irq, dma1, dma2;
-       static unsigned char irqs[16] =
+       static const unsigned char irqs[16] =
                {0, 0, 1, 3, 0, 2, 0, 4, 0, 1, 0, 5, 6, 0, 0, 7};
-       static unsigned char dmas[8] =
+       static const unsigned char dmas[8] =
                {6, 1, 0, 2, 0, 3, 4, 5};
 
        if (snd_BUG_ON(!gus))
index 54510e2..b5e1d16 100644 (file)
@@ -37,7 +37,7 @@ static void snd_gf1_mem_proc_free(struct snd_info_entry *entry)
        kfree(priv);
 }
 
-static struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
+static const struct snd_info_entry_ops snd_gf1_mem_proc_ops = {
        .read = snd_gf1_mem_proc_dump,
 };
 
index 94e0c75..201d0c4 100644 (file)
@@ -120,13 +120,13 @@ static int snd_ics_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
        return change;
 }
 
-static struct snd_kcontrol_new snd_gf1_controls[] = {
+static const struct snd_kcontrol_new snd_gf1_controls[] = {
 GF1_SINGLE("Master Playback Switch", 0, 1, 1),
 GF1_SINGLE("Line Switch", 0, 0, 1),
 GF1_SINGLE("Mic Switch", 0, 2, 0)
 };
 
-static struct snd_kcontrol_new snd_ics_controls[] = {
+static const struct snd_kcontrol_new snd_ics_controls[] = {
 GF1_SINGLE("Master Playback Switch", 0, 1, 1),
 ICS_DOUBLE("Master Playback Volume", 0, SNDRV_ICS_MASTER_DEV),
 ICS_DOUBLE("Synth Playback Volume", 0, SNDRV_ICS_GF1_DEV),
index 6385b61..aca4ab9 100644 (file)
@@ -423,11 +423,8 @@ static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream,
        struct snd_gus_card *gus = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct gus_pcm_private *pcmp = runtime->private_data;
-       int err;
-       
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
-       if (err > 0) {  /* change */
+
+       if (runtime->buffer_changed) {
                struct snd_gf1_mem_block *block;
                if (pcmp->memory > 0) {
                        snd_gf1_mem_free(&gus->gf1.mem_alloc, pcmp->memory);
@@ -471,7 +468,6 @@ static int snd_gf1_pcm_playback_hw_free(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct gus_pcm_private *pcmp = runtime->private_data;
 
-       snd_pcm_lib_free_pages(substream);
        if (pcmp->pvoices[0]) {
                snd_gf1_free_voice(pcmp->gus, pcmp->pvoices[0]);
                pcmp->pvoices[0] = NULL;
@@ -574,12 +570,7 @@ static int snd_gf1_pcm_capture_hw_params(struct snd_pcm_substream *substream,
                gus->gf1.pcm_rcntrl_reg |= 4;
        if (snd_pcm_format_unsigned(params_format(hw_params)))
                gus->gf1.pcm_rcntrl_reg |= 0x80;
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_gf1_pcm_capture_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int snd_gf1_pcm_capture_prepare(struct snd_pcm_substream *substream)
@@ -830,7 +821,6 @@ static const struct snd_kcontrol_new snd_gf1_pcm_volume_control1 =
 static const struct snd_pcm_ops snd_gf1_pcm_playback_ops = {
        .open =         snd_gf1_pcm_playback_open,
        .close =        snd_gf1_pcm_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_gf1_pcm_playback_hw_params,
        .hw_free =      snd_gf1_pcm_playback_hw_free,
        .prepare =      snd_gf1_pcm_playback_prepare,
@@ -844,9 +834,7 @@ static const struct snd_pcm_ops snd_gf1_pcm_playback_ops = {
 static const struct snd_pcm_ops snd_gf1_pcm_capture_ops = {
        .open =         snd_gf1_pcm_capture_open,
        .close =        snd_gf1_pcm_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_gf1_pcm_capture_hw_params,
-       .hw_free =      snd_gf1_pcm_capture_hw_free,
        .prepare =      snd_gf1_pcm_capture_prepare,
        .trigger =      snd_gf1_pcm_capture_trigger,
        .pointer =      snd_gf1_pcm_capture_pointer,
@@ -875,9 +863,9 @@ int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_gf1_pcm_playback_ops);
 
        for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
-               snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
-                                             card->dev,
-                                             64*1024, gus->gf1.dma1 > 3 ? 128*1024 : 64*1024);
+               snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
+                                          card->dev,
+                                          64*1024, gus->gf1.dma1 > 3 ? 128*1024 : 64*1024);
        
        pcm->info_flags = 0;
        pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
@@ -885,9 +873,9 @@ int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index)
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_gf1_pcm_capture_ops);
                if (gus->gf1.dma2 == gus->gf1.dma1)
                        pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
-               snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
-                                             SNDRV_DMA_TYPE_DEV, card->dev,
-                                             64*1024, gus->gf1.dma2 > 3 ? 128*1024 : 64*1024);
+               snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+                                          SNDRV_DMA_TYPE_DEV, card->dev,
+                                          64*1024, gus->gf1.dma2 > 3 ? 128*1024 : 64*1024);
        }
        strcpy(pcm->name, pcm->id);
        if (gus->interwave) {
index 4e9664e..047ddbc 100644 (file)
@@ -108,7 +108,7 @@ static void snd_gf1_interrupt_timer2(struct snd_gus_card * gus)
 
  */
 
-static struct snd_timer_hardware snd_gf1_timer1 =
+static const struct snd_timer_hardware snd_gf1_timer1 =
 {
        .flags =        SNDRV_TIMER_HW_STOP,
        .resolution =   80000,
@@ -117,7 +117,7 @@ static struct snd_timer_hardware snd_gf1_timer1 =
        .stop =         snd_gf1_timer1_stop,
 };
 
-static struct snd_timer_hardware snd_gf1_timer2 =
+static const struct snd_timer_hardware snd_gf1_timer2 =
 {
        .flags =        SNDRV_TIMER_HW_STOP,
        .resolution =   320000,
index 39a2e5b..ed72196 100644 (file)
@@ -62,7 +62,7 @@ unsigned int snd_gf1_calc_ramp_rate(struct snd_gus_card * gus,
                                    unsigned short end,
                                    unsigned int us)
 {
-       static unsigned char vol_rates[19] =
+       static const unsigned char vol_rates[19] =
        {
                23, 24, 26, 28, 29, 31, 32, 34,
                36, 37, 39, 40, 42, 44, 45, 47,
@@ -113,7 +113,7 @@ unsigned short snd_gf1_translate_freq(struct snd_gus_card * gus, unsigned int fr
 
 short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
 {
-       static short vibrato_table[] =
+       static const short vibrato_table[] =
        {
                0, 0, 32, 592, 61, 1175, 93, 1808,
                124, 2433, 152, 3007, 182, 3632, 213, 4290,
@@ -121,7 +121,8 @@ short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
        };
 
        long depth;
-       short *vi1, *vi2, pcents, v1;
+       const short *vi1, *vi2;
+       short pcents, v1;
 
        pcents = cents < 0 ? -cents : cents;
        for (vi1 = vibrato_table, vi2 = vi1 + 2; pcents > *vi2; vi1 = vi2, vi2 += 2);
@@ -145,7 +146,7 @@ short snd_gf1_compute_vibrato(short cents, unsigned short fc_register)
 
 unsigned short snd_gf1_compute_pitchbend(unsigned short pitchbend, unsigned short sens)
 {
-       static long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933};
+       static const long log_table[] = {1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933};
        int wheel, sensitivity;
        unsigned int mantissa, f1, f2;
        unsigned short semitones, f1_index, f2_index, f1_power, f2_power;
index f7e8697..7419b19 100644 (file)
@@ -67,9 +67,9 @@ static int snd_gusclassic_create(struct snd_card *card,
                                 struct device *dev, unsigned int n,
                                 struct snd_gus_card **rgus)
 {
-       static long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260};
-       static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
-       static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
+       static const long possible_ports[] = {0x220, 0x230, 0x240, 0x250, 0x260};
+       static const int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, 4, -1};
+       static const int possible_dmas[] = {5, 6, 7, 1, 3, -1};
 
        int i, error;
 
index 8cf366b..ed2f9d6 100644 (file)
@@ -83,9 +83,9 @@ static int snd_gusextreme_es1688_create(struct snd_card *card,
                                        struct snd_es1688 *chip,
                                        struct device *dev, unsigned int n)
 {
-       static long possible_ports[] = {0x220, 0x240, 0x260};
-       static int possible_irqs[] = {5, 9, 10, 7, -1};
-       static int possible_dmas[] = {1, 3, 0, -1};
+       static const long possible_ports[] = {0x220, 0x240, 0x260};
+       static const int possible_irqs[] = {5, 9, 10, 7, -1};
+       static const int possible_dmas[] = {1, 3, 0, -1};
 
        int i, error;
 
@@ -122,8 +122,8 @@ static int snd_gusextreme_gus_card_create(struct snd_card *card,
                                          struct device *dev, unsigned int n,
                                          struct snd_gus_card **rgus)
 {
-       static int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1};
-       static int possible_dmas[] = {5, 6, 7, 3, 1, -1};
+       static const int possible_irqs[] = {11, 12, 15, 9, 5, 7, 3, -1};
+       static const int possible_dmas[] = {5, 6, 7, 3, 1, -1};
 
        if (gf1_irq[n] == SNDRV_AUTO_IRQ) {
                gf1_irq[n] = snd_legacy_find_free_irq(possible_irqs);
index 53eca20..05cd9be 100644 (file)
@@ -191,8 +191,8 @@ static int snd_gusmax_match(struct device *pdev, unsigned int dev)
 
 static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
 {
-       static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
-       static int possible_dmas[] = {5, 6, 7, 1, 3, -1};
+       static const int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
+       static const int possible_dmas[] = {5, 6, 7, 1, 3, -1};
        int xirq, xdma1, xdma2, err;
        struct snd_card *card;
        struct snd_gus_card *gus = NULL;
@@ -241,7 +241,7 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                                     pcm_channels[dev],
                                     0, &gus);
        } else {
-               static unsigned long possible_ports[] = {
+               static const unsigned long possible_ports[] = {
                        0x220, 0x230, 0x240, 0x250, 0x260
                };
                int i;
@@ -282,7 +282,8 @@ static int snd_gusmax_probe(struct device *pdev, unsigned int dev)
                goto _err;
        }
        maxcard->irq = xirq;
-       
+       card->sync_irq = maxcard->irq;
+
        err = snd_wss_create(card,
                             gus->gf1.port + 0x10c, -1, xirq,
                             xdma2 < 0 ? xdma1 : xdma2, xdma1,
index bc006dc..3e9ad93 100644 (file)
@@ -364,7 +364,7 @@ struct rom_hdr {
 
 static void snd_interwave_detect_memory(struct snd_gus_card *gus)
 {
-       static unsigned int lmc[13] =
+       static const unsigned int lmc[13] =
        {
                0x00000001, 0x00000101, 0x01010101, 0x00000401,
                0x04040401, 0x00040101, 0x04040101, 0x00000004,
@@ -475,7 +475,7 @@ static void snd_interwave_init(int dev, struct snd_gus_card *gus)
 
 }
 
-static struct snd_kcontrol_new snd_interwave_controls[] = {
+static const struct snd_kcontrol_new snd_interwave_controls[] = {
 WSS_DOUBLE("Master Playback Switch", 0,
                CS4231_LINE_LEFT_OUTPUT, CS4231_LINE_RIGHT_OUTPUT, 7, 7, 1, 1),
 WSS_DOUBLE("Master Playback Volume", 0,
@@ -667,6 +667,7 @@ static int snd_interwave_probe(struct snd_card *card, int dev)
                return -EBUSY;
        }
        iwcard->irq = xirq;
+       card->sync_irq = iwcard->irq;
 
        err = snd_wss_create(card,
                             gus->gf1.port + 0x10c, -1, xirq,
@@ -787,8 +788,8 @@ static int snd_interwave_isa_probe(struct device *pdev,
                                   unsigned int dev)
 {
        int err;
-       static int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
-       static int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
+       static const int possible_irqs[] = {5, 11, 12, 9, 7, 15, 3, -1};
+       static const int possible_dmas[] = {0, 1, 3, 5, 6, 7, -1};
 
        if (irq[dev] == SNDRV_AUTO_IRQ) {
                if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) {
@@ -812,7 +813,7 @@ static int snd_interwave_isa_probe(struct device *pdev,
        if (port[dev] != SNDRV_AUTO_PORT)
                return snd_interwave_isa_probe1(dev, pdev);
        else {
-               static long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260};
+               static const long possible_ports[] = {0x210, 0x220, 0x230, 0x240, 0x250, 0x260};
                int i;
                for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
                        port[dev] = possible_ports[i];
index 82d0714..4fbc22a 100644 (file)
@@ -562,7 +562,6 @@ snd_msnd_playback_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_msnd_playback_ops = {
        .open =         snd_msnd_playback_open,
        .close =        snd_msnd_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_msnd_playback_hw_params,
        .prepare =      snd_msnd_playback_prepare,
        .trigger =      snd_msnd_playback_trigger,
@@ -659,7 +658,6 @@ static int snd_msnd_capture_hw_params(struct snd_pcm_substream *substream,
 static const struct snd_pcm_ops snd_msnd_capture_ops = {
        .open =         snd_msnd_capture_open,
        .close =        snd_msnd_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_msnd_capture_hw_params,
        .prepare =      snd_msnd_capture_prepare,
        .trigger =      snd_msnd_capture_trigger,
index e435ebd..7fca418 100644 (file)
@@ -528,7 +528,7 @@ static int snd_msnd_attach(struct snd_card *card)
 {
        struct snd_msnd *chip = card->private_data;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =      snd_msnd_dev_free,
                };
 
@@ -538,6 +538,7 @@ static int snd_msnd_attach(struct snd_card *card)
                printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
                return err;
        }
+       card->sync_irq = chip->irq;
        if (request_region(chip->io, DSP_NUMIO, card->shortname) == NULL) {
                free_irq(chip->irq, chip);
                return -EBUSY;
index d0770e2..02c566f 100644 (file)
@@ -275,7 +275,7 @@ static int snd_msndmix_volume_put(struct snd_kcontrol *kcontrol,
   .private_value = addr }
 
 
-static struct snd_kcontrol_new snd_msnd_controls[] = {
+static const struct snd_kcontrol_new snd_msnd_controls[] = {
 DUMMY_VOLUME("Master Volume", 0, MSND_MIXER_VOLUME),
 DUMMY_VOLUME("PCM Volume", 0, MSND_MIXER_PCM),
 DUMMY_VOLUME("Aux Volume", 0, MSND_MIXER_AUX),
index 941d0bd..85a181a 100644 (file)
@@ -457,7 +457,7 @@ static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_
 static const DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
 
-static struct snd_kcontrol_new snd_opl3sa2_controls[] = {
+static const struct snd_kcontrol_new snd_opl3sa2_controls[] = {
 OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1),
 OPL3SA2_DOUBLE_TLV("Master Playback Volume", 0, 0x07, 0x08, 0, 0, 15, 1,
                   db_scale_master),
@@ -467,7 +467,7 @@ OPL3SA2_SINGLE_TLV("Mic Playback Volume", 0, 0x09, 0, 31, 1,
 OPL3SA2_SINGLE("ZV Port Switch", 0, 0x02, 0, 1, 0),
 };
 
-static struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = {
+static const struct snd_kcontrol_new snd_opl3sa2_tone_controls[] = {
 OPL3SA2_DOUBLE("3D Control - Wide", 0, 0x14, 0x14, 4, 0, 7, 0),
 OPL3SA2_DOUBLE("Tone Control - Bass", 0, 0x15, 0x15, 4, 0, 7, 0),
 OPL3SA2_DOUBLE("Tone Control - Treble", 0, 0x16, 0x16, 4, 0, 7, 0)
@@ -659,6 +659,7 @@ static int snd_opl3sa2_probe(struct snd_card *card, int dev)
                return -ENODEV;
        }
        chip->irq = xirq;
+       card->sync_irq = chip->irq;
        err = snd_wss_create(card,
                             wss_port[dev] + 4, -1,
                             xirq, xdma1, xdma2,
index 0458934..e764816 100644 (file)
@@ -119,7 +119,7 @@ struct snd_miro {
 
 static struct snd_miro_aci aci_device;
 
-static char * snd_opti9xx_names[] = {
+static const char * const snd_opti9xx_names[] = {
        "unknown",
        "82C928", "82C929",
        "82C924", "82C925",
@@ -577,7 +577,7 @@ static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_miro_controls[] = {
+static const struct snd_kcontrol_new snd_miro_controls[] = {
 MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
 MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
 MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
@@ -589,7 +589,7 @@ MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
 
 /* Equalizer with seven bands (only PCM20) 
    from -12dB up to +12dB on each band */
-static struct snd_kcontrol_new snd_miro_eq_controls[] = {
+static const struct snd_kcontrol_new snd_miro_eq_controls[] = {
 MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
 MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
 MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
@@ -599,15 +599,15 @@ MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
 MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
 };
 
-static struct snd_kcontrol_new snd_miro_radio_control[] = {
+static const struct snd_kcontrol_new snd_miro_radio_control[] = {
 MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
 };
 
-static struct snd_kcontrol_new snd_miro_line_control[] = {
+static const struct snd_kcontrol_new snd_miro_line_control[] = {
 MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
 };
 
-static struct snd_kcontrol_new snd_miro_preamp_control[] = {
+static const struct snd_kcontrol_new snd_miro_preamp_control[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Mic Boost",
@@ -617,7 +617,7 @@ static struct snd_kcontrol_new snd_miro_preamp_control[] = {
        .put = snd_miro_put_preamp,
 }};
 
-static struct snd_kcontrol_new snd_miro_amp_control[] = {
+static const struct snd_kcontrol_new snd_miro_amp_control[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Line Boost",
@@ -627,7 +627,7 @@ static struct snd_kcontrol_new snd_miro_amp_control[] = {
        .put = snd_miro_put_amp,
 }};
 
-static struct snd_kcontrol_new snd_miro_capture_control[] = {
+static const struct snd_kcontrol_new snd_miro_capture_control[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "PCM Capture Switch",
@@ -637,7 +637,7 @@ static struct snd_kcontrol_new snd_miro_capture_control[] = {
        .put = snd_miro_put_capture,
 }};
 
-static unsigned char aci_init_values[][2] = {
+static const unsigned char aci_init_values[][2] = {
        { ACI_SET_MUTE, 0x00 },
        { ACI_SET_POWERAMP, 0x00 },
        { ACI_SET_PREAMP, 0x00 },
@@ -764,7 +764,7 @@ static int snd_miro_mixer(struct snd_card *card,
 static int snd_miro_init(struct snd_miro *chip,
                         unsigned short hardware)
 {
-       static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
+       static const int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
 
        chip->hardware = hardware;
        strcpy(chip->name, snd_opti9xx_names[hardware]);
@@ -1387,12 +1387,12 @@ static int snd_miro_isa_match(struct device *devptr, unsigned int n)
 
 static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
 {
-       static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
-       static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
-       static int possible_irqs[] = {11, 9, 10, 7, -1};
-       static int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
-       static int possible_dma1s[] = {3, 1, 0, -1};
-       static int possible_dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1},
+       static const long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
+       static const long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
+       static const int possible_irqs[] = {11, 9, 10, 7, -1};
+       static const int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
+       static const int possible_dma1s[] = {3, 1, 0, -1};
+       static const int possible_dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1},
                                           {0, -1} };
 
        int error;
index fb36bb5..d06b296 100644 (file)
@@ -163,7 +163,7 @@ MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
 
 #define DEV_NAME KBUILD_MODNAME
 
-static char * snd_opti9xx_names[] = {
+static const char * const snd_opti9xx_names[] = {
        "unknown",
        "82C928",       "82C929",
        "82C924",       "82C925",
@@ -173,7 +173,7 @@ static char * snd_opti9xx_names[] = {
 static int snd_opti9xx_init(struct snd_opti9xx *chip,
                            unsigned short hardware)
 {
-       static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
+       static const int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
 
        chip->hardware = hardware;
        strcpy(chip->name, snd_opti9xx_names[hardware]);
@@ -550,7 +550,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_step, -9300, 300, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_4bit_12db_max, -3300, 300, 0);
 
-static struct snd_kcontrol_new snd_opti93x_controls[] = {
+static const struct snd_kcontrol_new snd_opti93x_controls[] = {
 WSS_DOUBLE("Master Playback Switch", 0,
                OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
 WSS_DOUBLE_TLV("Master Playback Volume", 0,
@@ -808,7 +808,7 @@ static void snd_card_opti9xx_free(struct snd_card *card)
 
 static int snd_opti9xx_probe(struct snd_card *card)
 {
-       static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
+       static const long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
        int error;
        int xdma2;
        struct snd_opti9xx *chip = card->private_data;
@@ -869,6 +869,7 @@ static int snd_opti9xx_probe(struct snd_card *card)
        }
 #endif
        chip->irq = irq;
+       card->sync_irq = chip->irq;
        strcpy(card->driver, chip->name);
        sprintf(card->shortname, "OPTi %s", card->driver);
 #if defined(CS4231) || defined(OPTi93X)
@@ -957,16 +958,16 @@ static int snd_opti9xx_isa_probe(struct device *devptr,
 {
        struct snd_card *card;
        int error;
-       static long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
+       static const long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
 #ifdef OPTi93X
-       static int possible_irqs[] = {5, 9, 10, 11, 7, -1};
+       static const int possible_irqs[] = {5, 9, 10, 11, 7, -1};
 #else
-       static int possible_irqs[] = {9, 10, 11, 7, -1};
+       static const int possible_irqs[] = {9, 10, 11, 7, -1};
 #endif /* OPTi93X */
-       static int possible_mpu_irqs[] = {5, 9, 10, 7, -1};
-       static int possible_dma1s[] = {3, 1, 0, -1};
+       static const int possible_mpu_irqs[] = {5, 9, 10, 7, -1};
+       static const int possible_dma1s[] = {3, 1, 0, -1};
 #if defined(CS4231) || defined(OPTi93X)
-       static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
+       static const int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
 #endif /* CS4231 || OPTi93X */
 
        if (mpu_port == SNDRV_AUTO_PORT) {
index 433e32e..0aa545a 100644 (file)
@@ -222,7 +222,7 @@ init_dma(struct snd_emu8000 *emu)
 /*
  * initialization arrays; from ADIP
  */
-static unsigned short init1[128] = {
+static const unsigned short init1[128] = {
        0x03ff, 0x0030,  0x07ff, 0x0130, 0x0bff, 0x0230,  0x0fff, 0x0330,
        0x13ff, 0x0430,  0x17ff, 0x0530, 0x1bff, 0x0630,  0x1fff, 0x0730,
        0x23ff, 0x0830,  0x27ff, 0x0930, 0x2bff, 0x0a30,  0x2fff, 0x0b30,
@@ -244,7 +244,7 @@ static unsigned short init1[128] = {
        0xf3ff, 0x0c30,  0xf7ff, 0x0d30, 0xfbff, 0x0e30,  0xffff, 0x0f30,
 };
 
-static unsigned short init2[128] = {
+static const unsigned short init2[128] = {
        0x03ff, 0x8030, 0x07ff, 0x8130, 0x0bff, 0x8230, 0x0fff, 0x8330,
        0x13ff, 0x8430, 0x17ff, 0x8530, 0x1bff, 0x8630, 0x1fff, 0x8730,
        0x23ff, 0x8830, 0x27ff, 0x8930, 0x2bff, 0x8a30, 0x2fff, 0x8b30,
@@ -266,7 +266,7 @@ static unsigned short init2[128] = {
        0xf3ff, 0x8c30, 0xf7ff, 0x8d30, 0xfbff, 0x8e30, 0xffff, 0x8f30,
 };
 
-static unsigned short init3[128] = {
+static const unsigned short init3[128] = {
        0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
        0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x8F7C, 0x167E, 0xF254,
        0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x8BAA, 0x1B6D, 0xF234,
@@ -288,7 +288,7 @@ static unsigned short init3[128] = {
        0x1342, 0xD36E, 0x3EC7, 0xB3FF, 0x0000, 0x8365, 0x1420, 0x9570,
 };
 
-static unsigned short init4[128] = {
+static const unsigned short init4[128] = {
        0x0C10, 0x8470, 0x14FE, 0xB488, 0x167F, 0xA470, 0x18E7, 0x84B5,
        0x1B6E, 0x842A, 0x1F1D, 0x852A, 0x0DA3, 0x0F7C, 0x167E, 0x7254,
        0x0000, 0x842A, 0x0001, 0x852A, 0x18E6, 0x0BAA, 0x1B6D, 0x7234,
@@ -315,10 +315,10 @@ static unsigned short init4[128] = {
  * is meant to work
  */
 static void
-send_array(struct snd_emu8000 *emu, unsigned short *data, int size)
+send_array(struct snd_emu8000 *emu, const unsigned short *data, int size)
 {
        int i;
-       unsigned short *p;
+       const unsigned short *p;
 
        p = data;
        for (i = 0; i < size; i++, p++)
@@ -548,7 +548,7 @@ snd_emu8000_init_hw(struct snd_emu8000 *emu)
  * Bass/Treble Equalizer
  *----------------------------------------------------------------*/
 
-static unsigned short bass_parm[12][3] = {
+static const unsigned short bass_parm[12][3] = {
        {0xD26A, 0xD36A, 0x0000}, /* -12 dB */
        {0xD25B, 0xD35B, 0x0000}, /*  -8 */
        {0xD24C, 0xD34C, 0x0000}, /*  -6 */
@@ -563,7 +563,7 @@ static unsigned short bass_parm[12][3] = {
        {0xC26A, 0xC36A, 0x0002}, /* +12 dB */
 };
 
-static unsigned short treble_parm[12][9] = {
+static const unsigned short treble_parm[12][9] = {
        {0x821E, 0xC26A, 0x031E, 0xC36A, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001}, /* -12 dB */
        {0x821E, 0xC25B, 0x031E, 0xC35B, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
        {0x821E, 0xC24C, 0x031E, 0xC34C, 0x021E, 0xD208, 0x831E, 0xD308, 0x0001},
@@ -855,7 +855,7 @@ static int mixer_bass_treble_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
        return change;
 }
 
-static struct snd_kcontrol_new mixer_bass_control =
+static const struct snd_kcontrol_new mixer_bass_control =
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Synth Tone Control - Bass",
@@ -865,7 +865,7 @@ static struct snd_kcontrol_new mixer_bass_control =
        .private_value = 0,
 };
 
-static struct snd_kcontrol_new mixer_treble_control =
+static const struct snd_kcontrol_new mixer_treble_control =
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Synth Tone Control - Treble",
@@ -922,7 +922,7 @@ static int mixer_chorus_reverb_put(struct snd_kcontrol *kcontrol, struct snd_ctl
        return change;
 }
 
-static struct snd_kcontrol_new mixer_chorus_mode_control =
+static const struct snd_kcontrol_new mixer_chorus_mode_control =
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Chorus Mode",
@@ -932,7 +932,7 @@ static struct snd_kcontrol_new mixer_chorus_mode_control =
        .private_value = 1,
 };
 
-static struct snd_kcontrol_new mixer_reverb_mode_control =
+static const struct snd_kcontrol_new mixer_reverb_mode_control =
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Reverb Mode",
@@ -984,7 +984,7 @@ static int mixer_fm_depth_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
        return change;
 }
 
-static struct snd_kcontrol_new mixer_fm_chorus_depth_control =
+static const struct snd_kcontrol_new mixer_fm_chorus_depth_control =
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "FM Chorus Depth",
@@ -994,7 +994,7 @@ static struct snd_kcontrol_new mixer_fm_chorus_depth_control =
        .private_value = 1,
 };
 
-static struct snd_kcontrol_new mixer_fm_reverb_depth_control =
+static const struct snd_kcontrol_new mixer_fm_reverb_depth_control =
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "FM Reverb Depth",
@@ -1005,7 +1005,7 @@ static struct snd_kcontrol_new mixer_fm_reverb_depth_control =
 };
 
 
-static struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
+static const struct snd_kcontrol_new *mixer_defs[EMU8000_NUM_CONTROLS] = {
        &mixer_bass_control,
        &mixer_treble_control,
        &mixer_chorus_mode_control,
@@ -1075,7 +1075,7 @@ snd_emu8000_new(struct snd_card *card, int index, long port, int seq_ports,
        struct snd_seq_device *awe;
        struct snd_emu8000 *hw;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_emu8000_dev_free,
        };
 
index 83b7ff5..e377ac9 100644 (file)
@@ -660,7 +660,6 @@ static snd_pcm_uframes_t emu8k_pcm_pointer(struct snd_pcm_substream *subs)
 static const struct snd_pcm_ops emu8k_pcm_ops = {
        .open =         emu8k_pcm_open,
        .close =        emu8k_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    emu8k_pcm_hw_params,
        .hw_free =      emu8k_pcm_hw_free,
        .prepare =      emu8k_pcm_prepare,
index 7a313ff..ee379bb 100644 (file)
@@ -158,9 +158,9 @@ err_unmap:
 
 static int jazz16_configure_board(struct snd_sb *chip, int mpu_irq)
 {
-       static unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4,
+       static const unsigned char jazz_irq_bits[] = { 0, 0, 2, 3, 0, 1, 0, 4,
                                                 0, 2, 5, 0, 0, 0, 0, 6 };
-       static unsigned char jazz_dma_bits[] = { 0, 1, 0, 2, 0, 3, 0, 4 };
+       static const unsigned char jazz_dma_bits[] = { 0, 1, 0, 2, 0, 3, 0, 4 };
 
        if (jazz_dma_bits[chip->dma8] == 0 ||
            jazz_dma_bits[chip->dma16] == 0 ||
@@ -224,9 +224,9 @@ static int snd_jazz16_probe(struct device *devptr, unsigned int dev)
        struct snd_card_jazz16 *jazz16;
        struct snd_sb *chip;
        struct snd_opl3 *opl3;
-       static int possible_irqs[] = {2, 3, 5, 7, 9, 10, 15, -1};
-       static int possible_dmas8[] = {1, 3, -1};
-       static int possible_dmas16[] = {5, 7, -1};
+       static const int possible_irqs[] = {2, 3, 5, 7, 9, 10, 15, -1};
+       static const int possible_dmas8[] = {1, 3, -1};
+       static const int possible_dmas16[] = {5, 7, -1};
        int err, xirq, xdma8, xdma16, xmpu_port, xmpu_irq;
 
        err = snd_card_new(devptr, index[dev], id[dev], THIS_MODULE,
index b528238..479197c 100644 (file)
@@ -509,9 +509,9 @@ static int snd_sb16_isa_match(struct device *pdev, unsigned int dev)
 static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
 {
        int err;
-       static int possible_irqs[] = {5, 9, 10, 7, -1};
-       static int possible_dmas8[] = {1, 3, 0, -1};
-       static int possible_dmas16[] = {5, 6, 7, -1};
+       static const int possible_irqs[] = {5, 9, 10, 7, -1};
+       static const int possible_dmas8[] = {1, 3, 0, -1};
+       static const int possible_dmas16[] = {5, 6, 7, -1};
 
        if (irq[dev] == SNDRV_AUTO_IRQ) {
                if ((irq[dev] = snd_legacy_find_free_irq(possible_irqs)) < 0) {
@@ -535,7 +535,7 @@ static int snd_sb16_isa_probe(struct device *pdev, unsigned int dev)
        if (port[dev] != SNDRV_AUTO_PORT)
                return snd_sb16_isa_probe1(dev, pdev);
        else {
-               static int possible_ports[] = {0x220, 0x240, 0x260, 0x280};
+               static const int possible_ports[] = {0x220, 0x240, 0x260, 0x280};
                int i;
                for (i = 0; i < ARRAY_SIZE(possible_ports); i++) {
                        port[dev] = possible_ports[i];
index 0768bbf..38dc1fd 100644 (file)
@@ -232,18 +232,6 @@ static void snd_sb16_setup_rate(struct snd_sb *chip,
        spin_unlock_irqrestore(&chip->reg_lock, flags);
 }
 
-static int snd_sb16_hw_params(struct snd_pcm_substream *substream,
-                             struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_sb16_hw_free(struct snd_pcm_substream *substream)
-{
-       snd_pcm_lib_free_pages(substream);
-       return 0;
-}
-
 static int snd_sb16_playback_prepare(struct snd_pcm_substream *substream)
 {
        unsigned long flags;
@@ -829,9 +817,6 @@ int snd_sb16dsp_configure(struct snd_sb * chip)
 static const struct snd_pcm_ops snd_sb16_playback_ops = {
        .open =         snd_sb16_playback_open,
        .close =        snd_sb16_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_sb16_hw_params,
-       .hw_free =      snd_sb16_hw_free,
        .prepare =      snd_sb16_playback_prepare,
        .trigger =      snd_sb16_playback_trigger,
        .pointer =      snd_sb16_playback_pointer,
@@ -840,9 +825,6 @@ static const struct snd_pcm_ops snd_sb16_playback_ops = {
 static const struct snd_pcm_ops snd_sb16_capture_ops = {
        .open =         snd_sb16_capture_open,
        .close =        snd_sb16_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_sb16_hw_params,
-       .hw_free =      snd_sb16_hw_free,
        .prepare =      snd_sb16_capture_prepare,
        .trigger =      snd_sb16_capture_trigger,
        .pointer =      snd_sb16_capture_pointer,
@@ -873,9 +855,8 @@ int snd_sb16dsp_pcm(struct snd_sb *chip, int device)
                pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
        }
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             card->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      card->dev, 64*1024, 128*1024);
        return 0;
 }
 
index d67eae3..438109f 100644 (file)
@@ -111,7 +111,7 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
                        goto _err;
        } else {
                /* auto-probe legacy ports */
-               static unsigned long possible_ports[] = {
+               static const unsigned long possible_ports[] = {
                        0x220, 0x240, 0x260,
                };
                int i;
index 8221b85..e33dfe1 100644 (file)
@@ -225,18 +225,6 @@ static int snd_sb8_playback_trigger(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_sb8_hw_params(struct snd_pcm_substream *substream,
-                            struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_sb8_hw_free(struct snd_pcm_substream *substream)
-{
-       snd_pcm_lib_free_pages(substream);
-       return 0;
-}
-
 static int snd_sb8_capture_prepare(struct snd_pcm_substream *substream)
 {
        unsigned long flags;
@@ -558,9 +546,6 @@ static int snd_sb8_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_sb8_playback_ops = {
        .open =                 snd_sb8_open,
        .close =                snd_sb8_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_sb8_hw_params,
-       .hw_free =              snd_sb8_hw_free,
        .prepare =              snd_sb8_playback_prepare,
        .trigger =              snd_sb8_playback_trigger,
        .pointer =              snd_sb8_playback_pointer,
@@ -569,9 +554,6 @@ static const struct snd_pcm_ops snd_sb8_playback_ops = {
 static const struct snd_pcm_ops snd_sb8_capture_ops = {
        .open =                 snd_sb8_open,
        .close =                snd_sb8_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_sb8_hw_params,
-       .hw_free =              snd_sb8_hw_free,
        .prepare =              snd_sb8_capture_prepare,
        .trigger =              snd_sb8_capture_trigger,
        .pointer =              snd_sb8_capture_pointer,
@@ -595,9 +577,8 @@ int snd_sb8dsp_pcm(struct snd_sb *chip, int device)
 
        if (chip->dma8 > 3 || chip->dma16 >= 0)
                max_prealloc = 128 * 1024;
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             card->dev,
-                                             64*1024, max_prealloc);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      card->dev, 64*1024, max_prealloc);
 
        return 0;
 }
index ff031d6..61ea407 100644 (file)
@@ -204,7 +204,7 @@ int snd_sbdsp_create(struct snd_card *card,
 {
        struct snd_sb *chip;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_sbdsp_dev_free,
        };
 
@@ -233,6 +233,7 @@ int snd_sbdsp_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = irq;
+       card->sync_irq = chip->irq;
 
        if (hardware == SB_HW_ALS4000)
                goto __skip_allocation;
index bd65ef0..3f703b4 100644 (file)
@@ -438,7 +438,7 @@ static int snd_sb16mixer_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_
  */
 int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int type, unsigned long value)
 {
-       static struct snd_kcontrol_new newctls[] = {
+       static const struct snd_kcontrol_new newctls[] = {
                [SB_MIX_SINGLE] = {
                        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                        .info = snd_sbmixer_info_single,
@@ -494,14 +494,14 @@ int snd_sbmixer_add_ctl(struct snd_sb *chip, const char *name, int index, int ty
  * SB 2.0 specific mixer elements
  */
 
-static struct sbmix_elem snd_sb20_controls[] = {
+static const struct sbmix_elem snd_sb20_controls[] = {
        SB_SINGLE("Master Playback Volume", SB_DSP20_MASTER_DEV, 1, 7),
        SB_SINGLE("PCM Playback Volume", SB_DSP20_PCM_DEV, 1, 3),
        SB_SINGLE("Synth Playback Volume", SB_DSP20_FM_DEV, 1, 7),
        SB_SINGLE("CD Playback Volume", SB_DSP20_CD_DEV, 1, 7)
 };
 
-static unsigned char snd_sb20_init_values[][2] = {
+static const unsigned char snd_sb20_init_values[][2] = {
        { SB_DSP20_MASTER_DEV, 0 },
        { SB_DSP20_FM_DEV, 0 },
 };
@@ -509,7 +509,7 @@ static unsigned char snd_sb20_init_values[][2] = {
 /*
  * SB Pro specific mixer elements
  */
-static struct sbmix_elem snd_sbpro_controls[] = {
+static const struct sbmix_elem snd_sbpro_controls[] = {
        SB_DOUBLE("Master Playback Volume",
                  SB_DSP_MASTER_DEV, SB_DSP_MASTER_DEV, 5, 1, 7),
        SB_DOUBLE("PCM Playback Volume",
@@ -529,7 +529,7 @@ static struct sbmix_elem snd_sbpro_controls[] = {
        SB_SINGLE("Capture Low-Pass Filter", SB_DSP_CAPTURE_FILT, 3, 1)
 };
 
-static unsigned char snd_sbpro_init_values[][2] = {
+static const unsigned char snd_sbpro_init_values[][2] = {
        { SB_DSP_MASTER_DEV, 0 },
        { SB_DSP_PCM_DEV, 0 },
        { SB_DSP_FM_DEV, 0 },
@@ -538,7 +538,7 @@ static unsigned char snd_sbpro_init_values[][2] = {
 /*
  * SB16 specific mixer elements
  */
-static struct sbmix_elem snd_sb16_controls[] = {
+static const struct sbmix_elem snd_sb16_controls[] = {
        SB_DOUBLE("Master Playback Volume",
                  SB_DSP4_MASTER_DEV, (SB_DSP4_MASTER_DEV + 1), 3, 3, 31),
        SB_DOUBLE("PCM Playback Volume",
@@ -576,7 +576,7 @@ static struct sbmix_elem snd_sb16_controls[] = {
                  SB_DSP4_TREBLE_DEV, (SB_DSP4_TREBLE_DEV + 1), 4, 4, 15)
 };
 
-static unsigned char snd_sb16_init_values[][2] = {
+static const unsigned char snd_sb16_init_values[][2] = {
        { SB_DSP4_MASTER_DEV + 0, 0 },
        { SB_DSP4_MASTER_DEV + 1, 0 },
        { SB_DSP4_PCM_DEV + 0, 0 },
@@ -592,7 +592,7 @@ static unsigned char snd_sb16_init_values[][2] = {
 /*
  * DT019x specific mixer elements
  */
-static struct sbmix_elem snd_dt019x_controls[] = {
+static const struct sbmix_elem snd_dt019x_controls[] = {
        /* ALS4000 below has some parts which we might be lacking,
         * e.g. snd_als4000_ctl_mono_playback_switch - check it! */
        SB_DOUBLE("Master Playback Volume",
@@ -622,7 +622,7 @@ static struct sbmix_elem snd_dt019x_controls[] = {
        }
 };
 
-static unsigned char snd_dt019x_init_values[][2] = {
+static const unsigned char snd_dt019x_init_values[][2] = {
         { SB_DT019X_MASTER_DEV, 0 },
         { SB_DT019X_PCM_DEV, 0 },
         { SB_DT019X_SYNTH_DEV, 0 },
@@ -637,7 +637,7 @@ static unsigned char snd_dt019x_init_values[][2] = {
 /*
  * ALS4000 specific mixer elements
  */
-static struct sbmix_elem snd_als4000_controls[] = {
+static const struct sbmix_elem snd_als4000_controls[] = {
        SB_DOUBLE("PCM Playback Switch",
                  SB_DT019X_OUTPUT_SW2, SB_DT019X_OUTPUT_SW2, 2, 1, 1),
        SB_DOUBLE("Synth Playback Switch",
@@ -671,7 +671,7 @@ static struct sbmix_elem snd_als4000_controls[] = {
 #endif
 };
 
-static unsigned char snd_als4000_init_values[][2] = {
+static const unsigned char snd_als4000_init_values[][2] = {
        { SB_DSP4_MASTER_DEV + 0, 0 },
        { SB_DSP4_MASTER_DEV + 1, 0 },
        { SB_DSP4_PCM_DEV + 0, 0 },
@@ -689,9 +689,9 @@ static unsigned char snd_als4000_init_values[][2] = {
 /*
  */
 static int snd_sbmixer_init(struct snd_sb *chip,
-                           struct sbmix_elem *controls,
+                           const struct sbmix_elem *controls,
                            int controls_count,
-                           unsigned char map[][2],
+                           const unsigned char map[][2],
                            int map_count,
                            char *name)
 {
@@ -800,14 +800,14 @@ int snd_sbmixer_new(struct snd_sb *chip)
 }
 
 #ifdef CONFIG_PM
-static unsigned char sb20_saved_regs[] = {
+static const unsigned char sb20_saved_regs[] = {
        SB_DSP20_MASTER_DEV,
        SB_DSP20_PCM_DEV,
        SB_DSP20_FM_DEV,
        SB_DSP20_CD_DEV,
 };
 
-static unsigned char sbpro_saved_regs[] = {
+static const unsigned char sbpro_saved_regs[] = {
        SB_DSP_MASTER_DEV,
        SB_DSP_PCM_DEV,
        SB_DSP_PLAYBACK_FILT,
@@ -819,7 +819,7 @@ static unsigned char sbpro_saved_regs[] = {
        SB_DSP_CAPTURE_FILT,
 };
 
-static unsigned char sb16_saved_regs[] = {
+static const unsigned char sb16_saved_regs[] = {
        SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
        SB_DSP4_3DSE,
        SB_DSP4_BASS_DEV, SB_DSP4_BASS_DEV + 1,
@@ -837,7 +837,7 @@ static unsigned char sb16_saved_regs[] = {
        SB_DSP4_MIC_AGC
 };
 
-static unsigned char dt019x_saved_regs[] = {
+static const unsigned char dt019x_saved_regs[] = {
        SB_DT019X_MASTER_DEV,
        SB_DT019X_PCM_DEV,
        SB_DT019X_SYNTH_DEV,
@@ -850,7 +850,7 @@ static unsigned char dt019x_saved_regs[] = {
        SB_DT019X_CAPTURE_SW,
 };
 
-static unsigned char als4000_saved_regs[] = {
+static const unsigned char als4000_saved_regs[] = {
        /* please verify in dsheet whether regs to be added
           are actually real H/W or just dummy */
        SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
@@ -872,7 +872,7 @@ static unsigned char als4000_saved_regs[] = {
        SB_ALS4000_CR3_CONFIGURATION,
 };
 
-static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
+static void save_mixer(struct snd_sb *chip, const unsigned char *regs, int num_regs)
 {
        unsigned char *val = chip->saved_regs;
        if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
@@ -881,7 +881,7 @@ static void save_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
                *val++ = snd_sbmixer_read(chip, *regs++);
 }
 
-static void restore_mixer(struct snd_sb *chip, unsigned char *regs, int num_regs)
+static void restore_mixer(struct snd_sb *chip, const unsigned char *regs, int num_regs)
 {
        unsigned char *val = chip->saved_regs;
        if (snd_BUG_ON(num_regs > ARRAY_SIZE(chip->saved_regs)))
index 395ee3b..3d0bea4 100644 (file)
@@ -534,8 +534,8 @@ static int snd_sc6000_match(struct device *devptr, unsigned int dev)
 
 static int snd_sc6000_probe(struct device *devptr, unsigned int dev)
 {
-       static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
-       static int possible_dmas[] = { 1, 3, 0, -1 };
+       static const int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
+       static const int possible_dmas[] = { 1, 3, 0, -1 };
        int err;
        int xirq = irq[dev];
        int xdma = dma[dev];
index 95e6deb..9e0f6b2 100644 (file)
@@ -409,6 +409,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
        }
        
        acard->wavefront.irq = ics2115_irq[dev];
+       card->sync_irq = acard->wavefront.irq;
        acard->wavefront.base = ics2115_port[dev];
 
        wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard);
index c43f260..ea5d3cd 100644 (file)
@@ -38,7 +38,7 @@ MODULE_LICENSE("GPL");
  *  Some variables
  */
 
-static unsigned char freq_bits[14] = {
+static const unsigned char freq_bits[14] = {
        /* 5510 */      0x00 | CS4231_XTAL2,
        /* 6620 */      0x0E | CS4231_XTAL2,
        /* 8000 */      0x00 | CS4231_XTAL1,
@@ -72,7 +72,7 @@ static int snd_wss_xrate(struct snd_pcm_runtime *runtime)
                                          &hw_constraints_rates);
 }
 
-static unsigned char snd_wss_original_image[32] =
+static const unsigned char snd_wss_original_image[32] =
 {
        0x00,                   /* 00/00 - lic */
        0x00,                   /* 01/01 - ric */
@@ -108,7 +108,7 @@ static unsigned char snd_wss_original_image[32] =
        0x00,                   /* 1f/31 - cbrl */
 };
 
-static unsigned char snd_opti93x_original_image[32] =
+static const unsigned char snd_opti93x_original_image[32] =
 {
        0x00,           /* 00/00 - l_mixout_outctrl */
        0x00,           /* 01/01 - r_mixout_outctrl */
@@ -961,7 +961,7 @@ static int snd_wss_timer_close(struct snd_timer *timer)
        return 0;
 }
 
-static struct snd_timer_hardware snd_wss_timer_table =
+static const struct snd_timer_hardware snd_wss_timer_table =
 {
        .flags =        SNDRV_TIMER_HW_AUTO,
        .resolution =   9945,
@@ -982,10 +982,7 @@ static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_wss *chip = snd_pcm_substream_chip(substream);
        unsigned char new_pdfr;
-       int err;
 
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
        new_pdfr = snd_wss_get_format(chip, params_format(hw_params),
                                params_channels(hw_params)) |
                                snd_wss_get_rate(params_rate(hw_params));
@@ -993,11 +990,6 @@ static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_wss_playback_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_wss_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_wss *chip = snd_pcm_substream_chip(substream);
@@ -1025,10 +1017,7 @@ static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_wss *chip = snd_pcm_substream_chip(substream);
        unsigned char new_cdfr;
-       int err;
 
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
        new_cdfr = snd_wss_get_format(chip, params_format(hw_params),
                           params_channels(hw_params)) |
                           snd_wss_get_rate(params_rate(hw_params));
@@ -1036,11 +1025,6 @@ static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_wss_capture_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_wss *chip = snd_pcm_substream_chip(substream);
@@ -1788,7 +1772,7 @@ int snd_wss_create(struct snd_card *card,
                      unsigned short hwshare,
                      struct snd_wss **rchip)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_wss_dev_free,
        };
        struct snd_wss *chip;
@@ -1827,6 +1811,7 @@ int snd_wss_create(struct snd_card *card,
                        return -EBUSY;
                }
        chip->irq = irq;
+       card->sync_irq = chip->irq;
        if (!(hwshare & WSS_HWSHARE_DMA1) && request_dma(dma1, "WSS - 1")) {
                snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
                snd_wss_free(chip);
@@ -1887,9 +1872,7 @@ EXPORT_SYMBOL(snd_wss_create);
 static const struct snd_pcm_ops snd_wss_playback_ops = {
        .open =         snd_wss_playback_open,
        .close =        snd_wss_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_wss_playback_hw_params,
-       .hw_free =      snd_wss_playback_hw_free,
        .prepare =      snd_wss_playback_prepare,
        .trigger =      snd_wss_trigger,
        .pointer =      snd_wss_playback_pointer,
@@ -1898,9 +1881,7 @@ static const struct snd_pcm_ops snd_wss_playback_ops = {
 static const struct snd_pcm_ops snd_wss_capture_ops = {
        .open =         snd_wss_capture_open,
        .close =        snd_wss_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_wss_capture_hw_params,
-       .hw_free =      snd_wss_capture_hw_free,
        .prepare =      snd_wss_capture_prepare,
        .trigger =      snd_wss_trigger,
        .pointer =      snd_wss_capture_pointer,
@@ -1927,9 +1908,8 @@ int snd_wss_pcm(struct snd_wss *chip, int device)
                pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
        strcpy(pcm->name, snd_wss_chip_id(chip));
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             chip->card->dev,
-                                             64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, chip->card->dev,
+                                      64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
 
        chip->pcm = pcm;
        return 0;
@@ -2177,7 +2157,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
 
-static struct snd_kcontrol_new snd_wss_controls[] = {
+static const struct snd_kcontrol_new snd_wss_controls[] = {
 WSS_DOUBLE("PCM Playback Switch", 0,
                CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 WSS_DOUBLE_TLV("PCM Playback Volume", 0,
index c9e0609..ec84bc4 100644 (file)
@@ -505,23 +505,6 @@ static const struct snd_pcm_hardware hal2_pcm_hw = {
        .periods_max =      1024,
 };
 
-static int hal2_pcm_hw_params(struct snd_pcm_substream *substream,
-                             struct snd_pcm_hw_params *params)
-{
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-       if (err < 0)
-               return err;
-
-       return 0;
-}
-
-static int hal2_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int hal2_playback_open(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -701,9 +684,6 @@ static int hal2_capture_ack(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops hal2_playback_ops = {
        .open =        hal2_playback_open,
        .close =       hal2_playback_close,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   hal2_pcm_hw_params,
-       .hw_free =     hal2_pcm_hw_free,
        .prepare =     hal2_playback_prepare,
        .trigger =     hal2_playback_trigger,
        .pointer =     hal2_playback_pointer,
@@ -713,9 +693,6 @@ static const struct snd_pcm_ops hal2_playback_ops = {
 static const struct snd_pcm_ops hal2_capture_ops = {
        .open =        hal2_capture_open,
        .close =       hal2_capture_close,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   hal2_pcm_hw_params,
-       .hw_free =     hal2_pcm_hw_free,
        .prepare =     hal2_capture_prepare,
        .trigger =     hal2_capture_trigger,
        .pointer =     hal2_capture_pointer,
@@ -740,8 +717,8 @@ static int hal2_pcm_create(struct snd_hal2 *hal2)
                        &hal2_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
                        &hal2_capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                          NULL, 0, 1024 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                      NULL, 0, 1024 * 1024);
 
        return 0;
 }
@@ -755,7 +732,7 @@ static int hal2_dev_free(struct snd_device *device)
        return 0;
 }
 
-static struct snd_device_ops hal2_ops = {
+static const struct snd_device_ops hal2_ops = {
        .dev_free = hal2_dev_free,
 };
 
index 9d20ce6..9f60a50 100644 (file)
@@ -577,20 +577,6 @@ static int snd_sgio2audio_pcm_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-
-/* hw_params callback */
-static int snd_sgio2audio_pcm_hw_params(struct snd_pcm_substream *substream,
-                                       struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-/* hw_free callback */
-static int snd_sgio2audio_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 /* prepare callback */
 static int snd_sgio2audio_pcm_prepare(struct snd_pcm_substream *substream)
 {
@@ -663,7 +649,6 @@ snd_sgio2audio_pcm_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_sgio2audio_playback1_ops = {
        .open =        snd_sgio2audio_playback1_open,
        .close =       snd_sgio2audio_pcm_close,
-       .ioctl =       snd_pcm_lib_ioctl,
        .hw_params =   snd_sgio2audio_pcm_hw_params,
        .hw_free =     snd_sgio2audio_pcm_hw_free,
        .prepare =     snd_sgio2audio_pcm_prepare,
@@ -674,7 +659,6 @@ static const struct snd_pcm_ops snd_sgio2audio_playback1_ops = {
 static const struct snd_pcm_ops snd_sgio2audio_playback2_ops = {
        .open =        snd_sgio2audio_playback2_open,
        .close =       snd_sgio2audio_pcm_close,
-       .ioctl =       snd_pcm_lib_ioctl,
        .hw_params =   snd_sgio2audio_pcm_hw_params,
        .hw_free =     snd_sgio2audio_pcm_hw_free,
        .prepare =     snd_sgio2audio_pcm_prepare,
@@ -685,7 +669,6 @@ static const struct snd_pcm_ops snd_sgio2audio_playback2_ops = {
 static const struct snd_pcm_ops snd_sgio2audio_capture_ops = {
        .open =        snd_sgio2audio_capture_open,
        .close =       snd_sgio2audio_pcm_close,
-       .ioctl =       snd_pcm_lib_ioctl,
        .hw_params =   snd_sgio2audio_pcm_hw_params,
        .hw_free =     snd_sgio2audio_pcm_hw_free,
        .prepare =     snd_sgio2audio_pcm_prepare,
@@ -716,8 +699,7 @@ static int snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
                        &snd_sgio2audio_playback1_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
                        &snd_sgio2audio_capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        /* create second  pcm device with one outputs and no input */
        err = snd_pcm_new(chip->card, "SGI O2 Audio", 1, 1, 0, &pcm);
@@ -730,8 +712,7 @@ static int snd_sgio2audio_new_pcm(struct snd_sgio2audio *chip)
        /* set operators */
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                        &snd_sgio2audio_playback2_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        return 0;
 }
@@ -806,7 +787,7 @@ static int snd_sgio2audio_dev_free(struct snd_device *device)
        return snd_sgio2audio_free(chip);
 }
 
-static struct snd_device_ops ops = {
+static const struct snd_device_ops ops = {
        .dev_free = snd_sgio2audio_dev_free,
 };
 
index 6acc59c..97241d9 100644 (file)
@@ -567,28 +567,18 @@ static int
 snd_harmony_hw_params(struct snd_pcm_substream *ss,
                      struct snd_pcm_hw_params *hw)
 {
-       int err;
        struct snd_harmony *h = snd_pcm_substream_chip(ss);
        
-       err = snd_pcm_lib_malloc_pages(ss, params_buffer_bytes(hw));
-       if (err > 0 && h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS)
+       if (h->dma.type == SNDRV_DMA_TYPE_CONTINUOUS)
                ss->runtime->dma_addr = __pa(ss->runtime->dma_area);
-       
-       return err;
-}
 
-static int 
-snd_harmony_hw_free(struct snd_pcm_substream *ss) 
-{
-       return snd_pcm_lib_free_pages(ss);
+       return 0;
 }
 
 static const struct snd_pcm_ops snd_harmony_playback_ops = {
        .open = snd_harmony_playback_open,
        .close = snd_harmony_playback_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_harmony_hw_params,
-       .hw_free = snd_harmony_hw_free,
        .prepare = snd_harmony_playback_prepare,
        .trigger = snd_harmony_playback_trigger,
        .pointer = snd_harmony_playback_pointer,
@@ -597,9 +587,7 @@ static const struct snd_pcm_ops snd_harmony_playback_ops = {
 static const struct snd_pcm_ops snd_harmony_capture_ops = {
         .open = snd_harmony_capture_open,
         .close = snd_harmony_capture_close,
-        .ioctl = snd_pcm_lib_ioctl,
         .hw_params = snd_harmony_hw_params,
-        .hw_free = snd_harmony_hw_free,
         .prepare = snd_harmony_capture_prepare,
         .trigger = snd_harmony_capture_trigger,
         .pointer = snd_harmony_capture_pointer,
@@ -656,8 +644,8 @@ snd_harmony_pcm_init(struct snd_harmony *h)
        }
 
        /* pre-allocate space for DMA */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, h->dma.type, h->dma.dev,
-                                             MAX_BUF_SIZE, MAX_BUF_SIZE);
+       snd_pcm_set_managed_buffer_all(pcm, h->dma.type, h->dma.dev,
+                                      MAX_BUF_SIZE, MAX_BUF_SIZE);
 
        h->st.format = snd_harmony_set_data_format(h,
                SNDRV_PCM_FORMAT_S16_BE, 1);
@@ -809,7 +797,7 @@ snd_harmony_captureroute_put(struct snd_kcontrol *kc,
   .private_value = ((left_shift) | ((right_shift) << 8) |            \
                    ((mask) << 16) | ((invert) << 24)) }
 
-static struct snd_kcontrol_new snd_harmony_controls[] = {
+static const struct snd_kcontrol_new snd_harmony_controls[] = {
        HARMONY_VOLUME("Master Playback Volume", HARMONY_GAIN_LO_SHIFT, 
                       HARMONY_GAIN_RO_SHIFT, HARMONY_GAIN_OUT, 1),
        HARMONY_VOLUME("Capture Volume", HARMONY_GAIN_LI_SHIFT,
@@ -893,7 +881,7 @@ snd_harmony_create(struct snd_card *card,
 {
        int err;
        struct snd_harmony *h;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_harmony_dev_free,
        };
 
index 66f6c3b..6758c07 100644 (file)
@@ -1753,10 +1753,10 @@ static unsigned int snd_ac97_determine_spdif_rates(struct snd_ac97 *ac97)
 {
        unsigned int result = 0;
        int i;
-       static unsigned short ctl_bits[] = {
+       static const unsigned short ctl_bits[] = {
                AC97_SC_SPSR_44K, AC97_SC_SPSR_32K, AC97_SC_SPSR_48K
        };
-       static unsigned int rate_bits[] = {
+       static const unsigned int rate_bits[] = {
                SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_32000, SNDRV_PCM_RATE_48000
        };
 
@@ -1894,12 +1894,13 @@ static int ac97_reset_wait(struct snd_ac97 *ac97, int timeout, int with_modem)
  *
  * Return: Zero if successful, or a negative error code on failure.
  */
-int snd_ac97_bus(struct snd_card *card, int num, struct snd_ac97_bus_ops *ops,
+int snd_ac97_bus(struct snd_card *card, int num,
+                const struct snd_ac97_bus_ops *ops,
                 void *private_data, struct snd_ac97_bus **rbus)
 {
        int err;
        struct snd_ac97_bus *bus;
-       static struct snd_device_ops dev_ops = {
+       static const struct snd_device_ops dev_ops = {
                .dev_free =     snd_ac97_bus_dev_free,
        };
 
@@ -1999,7 +2000,7 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
        unsigned long end_time;
        unsigned int reg;
        const struct ac97_codec_id *pid;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ac97_dev_free,
                .dev_register = snd_ac97_dev_register,
                .dev_disconnect =       snd_ac97_dev_disconnect,
@@ -2345,7 +2346,7 @@ struct ac97_power_reg {
 
 enum { PWIDX_ADC, PWIDX_FRONT, PWIDX_CLFE, PWIDX_SURR, PWIDX_MIC, PWIDX_SIZE };
 
-static struct ac97_power_reg power_regs[PWIDX_SIZE] = {
+static const struct ac97_power_reg power_regs[PWIDX_SIZE] = {
        [PWIDX_ADC] = { AC97_PCM_LR_ADC_RATE, AC97_POWERDOWN, AC97_PD_PR0},
        [PWIDX_FRONT] = { AC97_PCM_FRONT_DAC_RATE, AC97_POWERDOWN, AC97_PD_PR1},
        [PWIDX_CLFE] = { AC97_PCM_LFE_DAC_RATE, AC97_EXTENDED_STATUS,
@@ -2828,7 +2829,7 @@ struct quirk_table {
        int (*func)(struct snd_ac97 *);
 };
 
-static struct quirk_table applicable_quirks[] = {
+static const struct quirk_table applicable_quirks[] = {
        { "none", NULL },
        { "hp_only", tune_hp_only },
        { "swap_hp", tune_swap_hp },
@@ -2856,7 +2857,7 @@ static int apply_quirk(struct snd_ac97 *ac97, int type)
 static int apply_quirk_str(struct snd_ac97 *ac97, const char *typestr)
 {
        int i;
-       struct quirk_table *q;
+       const struct quirk_table *q;
 
        for (i = 0; i < ARRAY_SIZE(applicable_quirks); i++) {
                q = &applicable_quirks[i];
index 719a1e4..ebf9267 100644 (file)
@@ -1211,25 +1211,25 @@ static const struct snd_ac97_build_ops patch_sigmatel_stac9758_ops = {
 
 static int patch_sigmatel_stac9758(struct snd_ac97 * ac97)
 {
-       static unsigned short regs[4] = {
+       static const unsigned short regs[4] = {
                AC97_SIGMATEL_OUTSEL,
                AC97_SIGMATEL_IOMISC,
                AC97_SIGMATEL_INSEL,
                AC97_SIGMATEL_VARIOUS
        };
-       static unsigned short def_regs[4] = {
+       static const unsigned short def_regs[4] = {
                /* OUTSEL */ 0xd794, /* CL:CL, SR:SR, LO:MX, LI:DS, MI:DS */
                /* IOMISC */ 0x2001,
                /* INSEL */ 0x0201, /* LI:LI, MI:M1 */
                /* VARIOUS */ 0x0040
        };
-       static unsigned short m675_regs[4] = {
+       static const unsigned short m675_regs[4] = {
                /* OUTSEL */ 0xfc70, /* CL:MX, SR:MX, LO:DS, LI:MX, MI:DS */
                /* IOMISC */ 0x2102, /* HP amp on */
                /* INSEL */ 0x0203, /* LI:LI, MI:FR */
                /* VARIOUS */ 0x0041 /* stereo mic */
        };
-       unsigned short *pregs = def_regs;
+       const unsigned short *pregs = def_regs;
        int i;
 
        /* Gateway M675 notebook */
@@ -1361,7 +1361,7 @@ static int patch_cx20551(struct snd_ac97 *ac97)
 #ifdef CONFIG_PM
 static void ad18xx_resume(struct snd_ac97 *ac97)
 {
-       static unsigned short setup_regs[] = {
+       static const unsigned short setup_regs[] = {
                AC97_AD_MISC, AC97_AD_SERIAL_CFG, AC97_AD_JACK_SPDIF,
        };
        int i, codec;
@@ -1470,7 +1470,7 @@ static unsigned short patch_ad1881_unchained(struct snd_ac97 * ac97, int idx, un
 
 static int patch_ad1881_chained1(struct snd_ac97 * ac97, int idx, unsigned short codec_bits)
 {
-       static int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
+       static const int cfg_bits[3] = { 1<<12, 1<<14, 1<<13 };
        unsigned short val;
        
        snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG, 0x7000, cfg_bits[idx]);
@@ -1794,7 +1794,7 @@ static const struct snd_kcontrol_new snd_ac97_ad1981x_jack_sense[] = {
 /* black list to avoid HP/Line jack-sense controls
  * (SS vendor << 16 | device)
  */
-static unsigned int ad1981_jacks_blacklist[] = {
+static const unsigned int ad1981_jacks_blacklist[] = {
        0x10140523, /* Thinkpad R40 */
        0x10140534, /* Thinkpad X31 */
        0x10140537, /* Thinkpad T41p */
@@ -1838,7 +1838,7 @@ static const struct snd_ac97_build_ops patch_ad1981a_build_ops = {
 /* white list to enable HP jack-sense bits
  * (SS vendor << 16 | device)
  */
-static unsigned int ad1981_jacks_whitelist[] = {
+static const unsigned int ad1981_jacks_whitelist[] = {
        0x0e11005a, /* HP nc4000/4010 */
        0x103c0890, /* HP nc6000 */
        0x103c0938, /* HP nc4220 */
@@ -3116,22 +3116,22 @@ static void cm9761_update_jacks(struct snd_ac97 *ac97)
        /* FIXME: check the bits for each model
         *        model 83 is confirmed to work
         */
-       static unsigned short surr_on[3][2] = {
+       static const unsigned short surr_on[3][2] = {
                { 0x0008, 0x0000 }, /* 9761-78 & 82 */
                { 0x0000, 0x0008 }, /* 9761-82 rev.B */
                { 0x0000, 0x0008 }, /* 9761-83 */
        };
-       static unsigned short clfe_on[3][2] = {
+       static const unsigned short clfe_on[3][2] = {
                { 0x0000, 0x1000 }, /* 9761-78 & 82 */
                { 0x1000, 0x0000 }, /* 9761-82 rev.B */
                { 0x0000, 0x1000 }, /* 9761-83 */
        };
-       static unsigned short surr_shared[3][2] = {
+       static const unsigned short surr_shared[3][2] = {
                { 0x0000, 0x0400 }, /* 9761-78 & 82 */
                { 0x0000, 0x0400 }, /* 9761-82 rev.B */
                { 0x0000, 0x0400 }, /* 9761-83 */
        };
-       static unsigned short clfe_shared[3][2] = {
+       static const unsigned short clfe_shared[3][2] = {
                { 0x2000, 0x0880 }, /* 9761-78 & 82 */
                { 0x0000, 0x2880 }, /* 9761-82 rev.B */
                { 0x2000, 0x0800 }, /* 9761-83 */
@@ -3635,7 +3635,7 @@ struct vt1618_uaj_item {
 
 /* This list reflects the vt1618 docs for Vendor Defined Register 0x60. */
 
-static struct vt1618_uaj_item vt1618_uaj[3] = {
+static const struct vt1618_uaj_item vt1618_uaj[3] = {
        {
                /* speaker jack */
                .mask  = 0x03,
@@ -3871,7 +3871,7 @@ static int mpatch_si3036(struct snd_ac97 * ac97)
  * check_volume_resolution().
  */
 
-static struct snd_ac97_res_table lm4550_restbl[] = {
+static const struct snd_ac97_res_table lm4550_restbl[] = {
        { AC97_MASTER, 0x1f1f },
        { AC97_HEADPHONE, 0x1f1f },
        { AC97_MASTER_MONO, 0x001f },
index 1c23a0f..491de1a 100644 (file)
@@ -26,7 +26,7 @@
  *  PCM support
  */
 
-static unsigned char rate_reg_tables[2][4][9] = {
+static const unsigned char rate_reg_tables[2][4][9] = {
 {
   /* standard rates */
   {
@@ -129,7 +129,7 @@ static unsigned char rate_reg_tables[2][4][9] = {
 }};
 
 /* FIXME: more various mappings for ADC? */
-static unsigned char rate_cregs[9] = {
+static const unsigned char rate_cregs[9] = {
        AC97_PCM_LR_ADC_RATE,   /* 3 */
        AC97_PCM_LR_ADC_RATE,   /* 4 */
        0xff,                   /* 5 */
index 5b6452d..5d42c42 100644 (file)
@@ -257,20 +257,6 @@ snd_ad1889_ac97_ready(struct snd_ad1889 *chip)
        return 0;
 }
 
-static int 
-snd_ad1889_hw_params(struct snd_pcm_substream *substream,
-                       struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, 
-                                       params_buffer_bytes(hw_params));
-}
-
-static int
-snd_ad1889_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static const struct snd_pcm_hardware snd_ad1889_playback_hw = {
        .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER,
@@ -562,9 +548,6 @@ snd_ad1889_capture_pointer(struct snd_pcm_substream *ss)
 static const struct snd_pcm_ops snd_ad1889_playback_ops = {
        .open = snd_ad1889_playback_open,
        .close = snd_ad1889_playback_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_ad1889_hw_params,
-       .hw_free = snd_ad1889_hw_free,
        .prepare = snd_ad1889_playback_prepare,
        .trigger = snd_ad1889_playback_trigger,
        .pointer = snd_ad1889_playback_pointer, 
@@ -573,9 +556,6 @@ static const struct snd_pcm_ops snd_ad1889_playback_ops = {
 static const struct snd_pcm_ops snd_ad1889_capture_ops = {
        .open = snd_ad1889_capture_open,
        .close = snd_ad1889_capture_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_ad1889_hw_params,
-       .hw_free = snd_ad1889_hw_free,
        .prepare = snd_ad1889_capture_prepare,
        .trigger = snd_ad1889_capture_trigger,
        .pointer = snd_ad1889_capture_pointer, 
@@ -632,10 +612,8 @@ snd_ad1889_pcm_init(struct snd_ad1889 *chip, int device)
        chip->psubs = NULL;
        chip->csubs = NULL;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             BUFFER_BYTES_MAX / 2,
-                                             BUFFER_BYTES_MAX);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
+                                      BUFFER_BYTES_MAX / 2, BUFFER_BYTES_MAX);
 
        return 0;
 }
@@ -782,7 +760,7 @@ snd_ad1889_ac97_init(struct snd_ad1889 *chip, const char *quirk_override)
 {
        int err;
        struct snd_ac97_template ac97;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_ad1889_ac97_write,
                .read = snd_ad1889_ac97_read,
        };
@@ -869,7 +847,7 @@ snd_ad1889_create(struct snd_card *card,
        int err;
 
        struct snd_ad1889 *chip;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_ad1889_dev_free,
        };
 
@@ -921,7 +899,7 @@ snd_ad1889_create(struct snd_card *card,
        }
 
        chip->irq = pci->irq;
-       synchronize_irq(chip->irq);
+       card->sync_irq = chip->irq;
 
        /* (2) initialization of the chip hardware */
        if ((err = snd_ad1889_init(chip)) < 0) {
index 7fa8106..e0a81f9 100644 (file)
@@ -255,7 +255,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
 
-static struct snd_kcontrol_new snd_ak4531_controls[] = {
+static const struct snd_kcontrol_new snd_ak4531_controls[] = {
 
 AK4531_DOUBLE_TLV("Master Playback Switch", 0,
                  AK4531_LMASTER, AK4531_RMASTER, 7, 7, 1, 1,
@@ -335,7 +335,7 @@ static int snd_ak4531_dev_free(struct snd_device *device)
        return snd_ak4531_free(ak4531);
 }
 
-static u8 snd_ak4531_initial_map[0x19 + 1] = {
+static const u8 snd_ak4531_initial_map[0x19 + 1] = {
        0x9f,           /* 00: Master Volume Lch */
        0x9f,           /* 01: Master Volume Rch */
        0x9f,           /* 02: Voice Volume Lch */
@@ -371,7 +371,7 @@ int snd_ak4531_mixer(struct snd_card *card,
        unsigned int idx;
        int err;
        struct snd_ak4531 *ak4531;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ak4531_dev_free,
        };
 
index ae29df0..4f524a9 100644 (file)
@@ -1138,13 +1138,7 @@ static int snd_ali_playback_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_ali_voice *pvoice = runtime->private_data;
        struct snd_ali_voice *evoice = pvoice->extra;
-       int err;
 
-       err = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
-       
        /* voice management */
 
        if (params_buffer_size(hw_params) / 2 !=
@@ -1175,7 +1169,6 @@ static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream)
        struct snd_ali_voice *pvoice = runtime->private_data;
        struct snd_ali_voice *evoice = pvoice ? pvoice->extra : NULL;
 
-       snd_pcm_lib_free_pages(substream);
        if (evoice) {
                snd_ali_free_voice(codec, evoice);
                pvoice->extra = NULL;
@@ -1183,18 +1176,6 @@ static int snd_ali_playback_hw_free(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int snd_ali_hw_params(struct snd_pcm_substream *substream,
-                            struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-static int snd_ali_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_ali_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_ali *codec = snd_pcm_substream_chip(substream);
@@ -1419,7 +1400,7 @@ static snd_pcm_uframes_t snd_ali_pointer(struct snd_pcm_substream *substream)
        return cso;
 }
 
-static struct snd_pcm_hardware snd_ali_playback =
+static const struct snd_pcm_hardware snd_ali_playback =
 {
        .info =         (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                         SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1445,7 +1426,7 @@ static struct snd_pcm_hardware snd_ali_playback =
  *  Capture support device description
  */
 
-static struct snd_pcm_hardware snd_ali_capture =
+static const struct snd_pcm_hardware snd_ali_capture =
 {
        .info =         (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                         SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1476,7 +1457,7 @@ static void snd_ali_pcm_free_substream(struct snd_pcm_runtime *runtime)
 }
 
 static int snd_ali_open(struct snd_pcm_substream *substream, int rec,
-                       int channel, struct snd_pcm_hardware *phw)
+                       int channel, const struct snd_pcm_hardware *phw)
 {
        struct snd_ali *codec = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1526,7 +1507,6 @@ static int snd_ali_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_ali_playback_ops = {
        .open =         snd_ali_playback_open,
        .close =        snd_ali_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_ali_playback_hw_params,
        .hw_free =      snd_ali_playback_hw_free,
        .prepare =      snd_ali_playback_prepare,
@@ -1537,9 +1517,6 @@ static const struct snd_pcm_ops snd_ali_playback_ops = {
 static const struct snd_pcm_ops snd_ali_capture_ops = {
        .open =         snd_ali_capture_open,
        .close =        snd_ali_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ali_hw_params,
-       .hw_free =      snd_ali_hw_free,
        .prepare =      snd_ali_prepare,
        .trigger =      snd_ali_trigger,
        .pointer =      snd_ali_pointer,
@@ -1557,10 +1534,10 @@ static int snd_ali_modem_hw_params(struct snd_pcm_substream *substream,
        snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_RATE,
                       params_rate(hw_params));
        snd_ac97_write(chip->ac97[modem_num], AC97_LINE1_LEVEL, 0);
-       return snd_ali_hw_params(substream, hw_params);
+       return 0;
 }
 
-static struct snd_pcm_hardware snd_ali_modem =
+static const struct snd_pcm_hardware snd_ali_modem =
 {
        .info =         (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                         SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1612,9 +1589,7 @@ static int snd_ali_modem_capture_open(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_ali_modem_playback_ops = {
        .open =         snd_ali_modem_playback_open,
        .close =        snd_ali_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_ali_modem_hw_params,
-       .hw_free =      snd_ali_hw_free,
        .prepare =      snd_ali_prepare,
        .trigger =      snd_ali_trigger,
        .pointer =      snd_ali_pointer,
@@ -1623,9 +1598,7 @@ static const struct snd_pcm_ops snd_ali_modem_playback_ops = {
 static const struct snd_pcm_ops snd_ali_modem_capture_ops = {
        .open =         snd_ali_modem_capture_open,
        .close =        snd_ali_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_ali_modem_hw_params,
-       .hw_free =      snd_ali_hw_free,
        .prepare =      snd_ali_prepare,
        .trigger =      snd_ali_trigger,
        .pointer =      snd_ali_pointer,
@@ -1671,9 +1644,8 @@ static int snd_ali_pcm(struct snd_ali *codec, int device,
                snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
                                desc->capture_ops);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &codec->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &codec->pci->dev, 64*1024, 128*1024);
 
        pcm->info_flags = 0;
        pcm->dev_class = desc->class;
@@ -1804,7 +1776,7 @@ static int snd_ali5451_spdif_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_ali5451_mixer_spdif[] = {
+static const struct snd_kcontrol_new snd_ali5451_mixer_spdif[] = {
        /* spdif aplayback switch */
        /* FIXME: "IEC958 Playback Switch" may conflict with one on ac97_codec */
        ALI5451_SPDIF(SNDRV_CTL_NAME_IEC958("Output ",NONE,SWITCH), 0, 0),
@@ -1819,7 +1791,7 @@ static int snd_ali_mixer(struct snd_ali *codec)
        struct snd_ac97_template ac97;
        unsigned int idx;
        int i, err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_ali_codec_write,
                .read = snd_ali_codec_read,
        };
@@ -2054,6 +2026,7 @@ static int snd_ali_resources(struct snd_ali *codec)
                return -EBUSY;
        }
        codec->irq = codec->pci->irq;
+       codec->card->sync_irq = codec->irq;
        dev_dbg(codec->card->dev, "resources allocated.\n");
        return 0;
 }
@@ -2073,7 +2046,7 @@ static int snd_ali_create(struct snd_card *card,
        struct snd_ali *codec;
        int i, err;
        unsigned short cmdw;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_ali_dev_free,
         };
 
@@ -2127,8 +2100,6 @@ static int snd_ali_create(struct snd_card *card,
                return -EBUSY;
        }
 
-       synchronize_irq(pci->irq);
-
        codec->synth.chmap = 0;
        codec->synth.chcnt = 0;
        codec->spdif_mask = 0;
index cfbb8ca..8d2471e 100644 (file)
@@ -294,7 +294,7 @@ static int snd_als300_ac97(struct snd_als300 *chip)
        struct snd_ac97_bus *bus;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_als300_ac97_write,
                .read = snd_als300_ac97_read,
        };
@@ -378,7 +378,6 @@ static int snd_als300_playback_close(struct snd_pcm_substream *substream)
        data = substream->runtime->private_data;
        kfree(data);
        chip->playback_substream = NULL;
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -407,22 +406,9 @@ static int snd_als300_capture_close(struct snd_pcm_substream *substream)
        data = substream->runtime->private_data;
        kfree(data);
        chip->capture_substream = NULL;
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
-static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream,
-                                   struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-static int snd_als300_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_als300_playback_prepare(struct snd_pcm_substream *substream)
 {
        u32 tmp;
@@ -553,9 +539,6 @@ static snd_pcm_uframes_t snd_als300_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_als300_playback_ops = {
        .open =         snd_als300_playback_open,
        .close =        snd_als300_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_als300_pcm_hw_params,
-       .hw_free =      snd_als300_pcm_hw_free,
        .prepare =      snd_als300_playback_prepare,
        .trigger =      snd_als300_trigger,
        .pointer =      snd_als300_pointer,
@@ -564,9 +547,6 @@ static const struct snd_pcm_ops snd_als300_playback_ops = {
 static const struct snd_pcm_ops snd_als300_capture_ops = {
        .open =         snd_als300_capture_open,
        .close =        snd_als300_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_als300_pcm_hw_params,
-       .hw_free =      snd_als300_pcm_hw_free,
        .prepare =      snd_als300_capture_prepare,
        .trigger =      snd_als300_trigger,
        .pointer =      snd_als300_pointer,
@@ -591,9 +571,8 @@ static int snd_als300_new_pcm(struct snd_als300 *chip)
                                &snd_als300_capture_ops);
 
        /* pre-allocation of buffers */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
+                                      64*1024, 64*1024);
        return 0;
 }
 
@@ -638,7 +617,7 @@ static int snd_als300_create(struct snd_card *card,
        void *irq_handler;
        int err;
 
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_als300_dev_free,
        };
        *rchip = NULL;
@@ -685,7 +664,7 @@ static int snd_als300_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
-
+       card->sync_irq = chip->irq;
 
        snd_als300_init(chip);
 
index d6f5487..ba6390e 100644 (file)
@@ -354,18 +354,6 @@ CMD_SIGNED|CMD_STEREO,                     /* ALS4000_FORMAT_S16L_STEREO */
 };     
 #define capture_cmd(chip) (capture_cmd_vals[(chip)->capture_format])
 
-static int snd_als4000_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_als4000_hw_free(struct snd_pcm_substream *substream)
-{
-       snd_pcm_lib_free_pages(substream);
-       return 0;
-}
-
 static int snd_als4000_capture_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_sb *chip = snd_pcm_substream_chip(substream);
@@ -633,7 +621,6 @@ static int snd_als4000_playback_close(struct snd_pcm_substream *substream)
        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 
        chip->playback_substream = NULL;
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -652,7 +639,6 @@ static int snd_als4000_capture_close(struct snd_pcm_substream *substream)
        struct snd_sb *chip = snd_pcm_substream_chip(substream);
 
        chip->capture_substream = NULL;
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -661,9 +647,6 @@ static int snd_als4000_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_als4000_playback_ops = {
        .open =         snd_als4000_playback_open,
        .close =        snd_als4000_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_als4000_hw_params,
-       .hw_free =      snd_als4000_hw_free,
        .prepare =      snd_als4000_playback_prepare,
        .trigger =      snd_als4000_playback_trigger,
        .pointer =      snd_als4000_playback_pointer
@@ -672,9 +655,6 @@ static const struct snd_pcm_ops snd_als4000_playback_ops = {
 static const struct snd_pcm_ops snd_als4000_capture_ops = {
        .open =         snd_als4000_capture_open,
        .close =        snd_als4000_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_als4000_hw_params,
-       .hw_free =      snd_als4000_hw_free,
        .prepare =      snd_als4000_capture_prepare,
        .trigger =      snd_als4000_capture_trigger,
        .pointer =      snd_als4000_capture_pointer
@@ -693,9 +673,8 @@ static int snd_als4000_pcm(struct snd_sb *chip, int device)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_als4000_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_als4000_capture_ops);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 64*1024);
 
        chip->pcm = pcm;
 
index 147005f..a9540c2 100644 (file)
@@ -300,7 +300,7 @@ static void print_hwparams(struct snd_pcm_substream *substream,
 
 #define INVALID_FORMAT (__force snd_pcm_format_t)(-1)
 
-static snd_pcm_format_t hpi_to_alsa_formats[] = {
+static const snd_pcm_format_t hpi_to_alsa_formats[] = {
        INVALID_FORMAT,         /* INVALID */
        SNDRV_PCM_FORMAT_U8,    /* HPI_FORMAT_PCM8_UNSIGNED        1 */
        SNDRV_PCM_FORMAT_S16,   /* HPI_FORMAT_PCM16_SIGNED         2 */
@@ -449,9 +449,6 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
        unsigned int bytes_per_sec;
 
        print_hwparams(substream, params);
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-       if (err < 0)
-               return err;
        err = snd_card_asihpi_format_alsa2hpi(params_format(params), &format);
        if (err)
                return err;
@@ -509,7 +506,6 @@ snd_card_asihpi_hw_free(struct snd_pcm_substream *substream)
        if (dpcm->hpi_buffer_attached)
                hpi_stream_host_buffer_detach(dpcm->h_stream);
 
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -947,15 +943,6 @@ static void snd_card_asihpi_isr(struct hpi_adapter *a)
 }
 
 /***************************** PLAYBACK OPS ****************/
-static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream,
-                                         unsigned int cmd, void *arg)
-{
-       char name[16];
-       snd_pcm_debug_name(substream, name, sizeof(name));
-       snd_printddd(KERN_INFO "%s ioctl %d\n", name, cmd);
-       return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
 static int snd_card_asihpi_playback_prepare(struct snd_pcm_substream *
                                            substream)
 {
@@ -1122,7 +1109,6 @@ static int snd_card_asihpi_playback_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_card_asihpi_playback_mmap_ops = {
        .open = snd_card_asihpi_playback_open,
        .close = snd_card_asihpi_playback_close,
-       .ioctl = snd_card_asihpi_playback_ioctl,
        .hw_params = snd_card_asihpi_pcm_hw_params,
        .hw_free = snd_card_asihpi_hw_free,
        .prepare = snd_card_asihpi_playback_prepare,
@@ -1147,12 +1133,6 @@ snd_card_asihpi_capture_pointer(struct snd_pcm_substream *substream)
        return bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes);
 }
 
-static int snd_card_asihpi_capture_ioctl(struct snd_pcm_substream *substream,
-                                        unsigned int cmd, void *arg)
-{
-       return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
 static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1288,7 +1268,6 @@ static int snd_card_asihpi_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
        .open = snd_card_asihpi_capture_open,
        .close = snd_card_asihpi_capture_close,
-       .ioctl = snd_card_asihpi_capture_ioctl,
        .hw_params = snd_card_asihpi_pcm_hw_params,
        .hw_free = snd_card_asihpi_hw_free,
        .prepare = snd_card_asihpi_capture_prepare,
@@ -1324,9 +1303,9 @@ static int snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi, int device)
 
        /*? do we want to emulate MMAP for non-BBM cards?
        Jack doesn't work with ALSAs MMAP emulation - WHY NOT? */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &asihpi->pci->dev,
-                                             64*1024, BUFFER_BYTES_MAX);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &asihpi->pci->dev,
+                                      64*1024, BUFFER_BYTES_MAX);
 
        return 0;
 }
@@ -2094,7 +2073,7 @@ static int snd_asihpi_meter_info(struct snd_kcontrol *kcontrol,
 }
 
 /* linear values for 10dB steps */
-static int log2lin[] = {
+static const int log2lin[] = {
        0x7FFFFFFF, /* 0dB */
        679093956,
        214748365,
index 5fb0b98..f7427f8 100644 (file)
@@ -17,7 +17,7 @@ Extended Message Function With Response Caching
 #include "hpimsgx.h"
 #include "hpidebug.h"
 
-static struct pci_device_id asihpi_pci_tbl[] = {
+static const struct pci_device_id asihpi_pci_tbl[] = {
 #include "hpipcida.h"
 };
 
index 1e1eded..85d3b4e 100644 (file)
@@ -282,7 +282,7 @@ static const struct pci_device_id snd_atiixp_ids[] = {
 
 MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
 
-static struct snd_pci_quirk atiixp_quirks[] = {
+static const struct snd_pci_quirk atiixp_quirks[] = {
        SND_PCI_QUIRK(0x105b, 0x0c81, "Foxconn RC4107MA-RS2", 0),
        SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0),
        { } /* terminator */
@@ -952,9 +952,6 @@ static int snd_atiixp_pcm_hw_params(struct snd_pcm_substream *substream,
        struct atiixp_dma *dma = substream->runtime->private_data;
        int err;
 
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        dma->buf_addr = substream->runtime->dma_addr;
        dma->buf_bytes = params_buffer_bytes(hw_params);
 
@@ -994,7 +991,6 @@ static int snd_atiixp_pcm_hw_free(struct snd_pcm_substream *substream)
                dma->pcm_open_flag = 0;
        }
        atiixp_clear_dma_packets(chip, dma, substream);
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -1144,7 +1140,6 @@ static int snd_atiixp_spdif_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_atiixp_playback_ops = {
        .open =         snd_atiixp_playback_open,
        .close =        snd_atiixp_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_atiixp_pcm_hw_params,
        .hw_free =      snd_atiixp_pcm_hw_free,
        .prepare =      snd_atiixp_playback_prepare,
@@ -1156,7 +1151,6 @@ static const struct snd_pcm_ops snd_atiixp_playback_ops = {
 static const struct snd_pcm_ops snd_atiixp_capture_ops = {
        .open =         snd_atiixp_capture_open,
        .close =        snd_atiixp_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_atiixp_pcm_hw_params,
        .hw_free =      snd_atiixp_pcm_hw_free,
        .prepare =      snd_atiixp_capture_prepare,
@@ -1168,7 +1162,6 @@ static const struct snd_pcm_ops snd_atiixp_capture_ops = {
 static const struct snd_pcm_ops snd_atiixp_spdif_ops = {
        .open =         snd_atiixp_spdif_open,
        .close =        snd_atiixp_spdif_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_atiixp_pcm_hw_params,
        .hw_free =      snd_atiixp_pcm_hw_free,
        .prepare =      snd_atiixp_spdif_prepare,
@@ -1283,9 +1276,8 @@ static int snd_atiixp_pcm_new(struct atiixp *chip)
        strcpy(pcm->name, "ATI IXP AC97");
        chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 128*1024);
 
        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                     snd_pcm_alt_chmaps, chip->max_channels, 0,
@@ -1316,9 +1308,8 @@ static int snd_atiixp_pcm_new(struct atiixp *chip)
                strcpy(pcm->name, "ATI IXP IEC958 (Direct)");
        chip->pcmdevs[ATI_PCMDEV_DIGITAL] = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 128*1024);
 
        /* pre-select AC97 SPDIF slots 10/11 */
        for (i = 0; i < NUM_ATI_CODECS; i++) {
@@ -1412,11 +1403,11 @@ static int snd_atiixp_mixer_new(struct atiixp *chip, int clock,
        struct snd_ac97_template ac97;
        int i, err;
        int codec_count;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_atiixp_ac97_write,
                .read = snd_atiixp_ac97_read,
        };
-       static unsigned int codec_skip[NUM_ATI_CODECS] = {
+       static const unsigned int codec_skip[NUM_ATI_CODECS] = {
                ATI_REG_ISR_CODEC0_NOT_READY,
                ATI_REG_ISR_CODEC1_NOT_READY,
                ATI_REG_ISR_CODEC2_NOT_READY,
@@ -1566,7 +1557,7 @@ static int snd_atiixp_create(struct snd_card *card,
                             struct pci_dev *pci,
                             struct atiixp **r_chip)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_atiixp_dev_free,
        };
        struct atiixp *chip;
@@ -1606,8 +1597,8 @@ static int snd_atiixp_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        pci_set_master(pci);
-       synchronize_irq(chip->irq);
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
                snd_atiixp_free(chip);
index 6f088c1..ae88217 100644 (file)
@@ -783,9 +783,6 @@ static int snd_atiixp_pcm_hw_params(struct snd_pcm_substream *substream,
        int err;
        int i;
 
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        dma->buf_addr = substream->runtime->dma_addr;
        dma->buf_bytes = params_buffer_bytes(hw_params);
 
@@ -812,7 +809,6 @@ static int snd_atiixp_pcm_hw_free(struct snd_pcm_substream *substream)
        struct atiixp_dma *dma = substream->runtime->private_data;
 
        atiixp_clear_dma_packets(chip, dma, substream);
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -936,7 +932,6 @@ static int snd_atiixp_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_atiixp_playback_ops = {
        .open =         snd_atiixp_playback_open,
        .close =        snd_atiixp_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_atiixp_pcm_hw_params,
        .hw_free =      snd_atiixp_pcm_hw_free,
        .prepare =      snd_atiixp_playback_prepare,
@@ -948,7 +943,6 @@ static const struct snd_pcm_ops snd_atiixp_playback_ops = {
 static const struct snd_pcm_ops snd_atiixp_capture_ops = {
        .open =         snd_atiixp_capture_open,
        .close =        snd_atiixp_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_atiixp_pcm_hw_params,
        .hw_free =      snd_atiixp_pcm_hw_free,
        .prepare =      snd_atiixp_capture_prepare,
@@ -994,9 +988,8 @@ static int snd_atiixp_pcm_new(struct atiixp_modem *chip)
        strcpy(pcm->name, "ATI IXP MC97");
        chip->pcmdevs[ATI_PCMDEV_ANALOG] = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 128*1024);
 
        return 0;
 }
@@ -1053,11 +1046,11 @@ static int snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
        struct snd_ac97_template ac97;
        int i, err;
        int codec_count;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_atiixp_ac97_write,
                .read = snd_atiixp_ac97_read,
        };
-       static unsigned int codec_skip[NUM_ATI_CODECS] = {
+       static const unsigned int codec_skip[NUM_ATI_CODECS] = {
                ATI_REG_ISR_CODEC0_NOT_READY,
                ATI_REG_ISR_CODEC1_NOT_READY,
                ATI_REG_ISR_CODEC2_NOT_READY,
@@ -1194,7 +1187,7 @@ static int snd_atiixp_create(struct snd_card *card,
                             struct pci_dev *pci,
                             struct atiixp_modem **r_chip)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_atiixp_dev_free,
        };
        struct atiixp_modem *chip;
@@ -1234,8 +1227,8 @@ static int snd_atiixp_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        pci_set_master(pci);
-       synchronize_irq(chip->irq);
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
                snd_atiixp_free(chip);
index 782333c..be276fb 100644 (file)
@@ -142,7 +142,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
 {
        vortex_t *chip;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_vortex_dev_free,
        };
 
@@ -202,6 +202,7 @@ snd_vortex_create(struct snd_card *card, struct pci_dev *pci, vortex_t ** rchip)
                goto irq_out;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        pci_set_master(pci);
        // End of PCI setup.
index ce0564c..f5512b7 100644 (file)
@@ -1989,7 +1989,7 @@ vortex_connect_codecrec(vortex_t * vortex, int en, unsigned char mixin0,
 // Higher level ADB audio path (de)allocator.
 
 /* Resource manager */
-static int resnum[VORTEX_RESOURCE_LAST] =
+static const int resnum[VORTEX_RESOURCE_LAST] =
     { NR_ADB, NR_SRC, NR_MIXIN, NR_MIXOUT, NR_A3D };
 /*
  Checkout/Checkin resource of given type. 
index abaf9f9..58e92f2 100644 (file)
@@ -51,7 +51,7 @@ static inline u16 sign_invert(u16 a)
                return -a;
 }
 
-static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[])
+static void vortex_EqHw_SetLeftCoefs(vortex_t *vortex, const u16 coefs[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int i = 0, n /*esp2c */;
@@ -73,7 +73,7 @@ static void vortex_EqHw_SetLeftCoefs(vortex_t * vortex, u16 coefs[])
        }
 }
 
-static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[])
+static void vortex_EqHw_SetRightCoefs(vortex_t *vortex, const u16 coefs[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int i = 0, n /*esp2c */;
@@ -96,7 +96,7 @@ static void vortex_EqHw_SetRightCoefs(vortex_t * vortex, u16 coefs[])
 
 }
 
-static void vortex_EqHw_SetLeftStates(vortex_t * vortex, u16 a[], u16 b[])
+static void vortex_EqHw_SetLeftStates(vortex_t *vortex, const u16 a[], const u16 b[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int i = 0, ebx;
@@ -113,7 +113,7 @@ static void vortex_EqHw_SetLeftStates(vortex_t * vortex, u16 a[], u16 b[])
        }
 }
 
-static void vortex_EqHw_SetRightStates(vortex_t * vortex, u16 a[], u16 b[])
+static void vortex_EqHw_SetRightStates(vortex_t *vortex, const u16 a[], const u16 b[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int i = 0, ebx;
@@ -206,7 +206,7 @@ vortex_EqHw_SetRightGainsSingleTarget(vortex_t * vortex, u16 index, u16 b)
        hwwrite(vortex->mmio, 0x2b20c + (index * 0x30), b);
 }
 
-static void vortex_EqHw_SetLeftGainsTarget(vortex_t * vortex, u16 a[])
+static void vortex_EqHw_SetLeftGainsTarget(vortex_t *vortex, const u16 a[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int ebx;
@@ -216,7 +216,7 @@ static void vortex_EqHw_SetLeftGainsTarget(vortex_t * vortex, u16 a[])
        }
 }
 
-static void vortex_EqHw_SetRightGainsTarget(vortex_t * vortex, u16 a[])
+static void vortex_EqHw_SetRightGainsTarget(vortex_t *vortex, const u16 a[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int ebx;
@@ -226,7 +226,7 @@ static void vortex_EqHw_SetRightGainsTarget(vortex_t * vortex, u16 a[])
        }
 }
 
-static void vortex_EqHw_SetLeftGainsCurrent(vortex_t * vortex, u16 a[])
+static void vortex_EqHw_SetLeftGainsCurrent(vortex_t *vortex, const u16 a[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int ebx;
@@ -236,7 +236,7 @@ static void vortex_EqHw_SetLeftGainsCurrent(vortex_t * vortex, u16 a[])
        }
 }
 
-static void vortex_EqHw_SetRightGainsCurrent(vortex_t * vortex, u16 a[])
+static void vortex_EqHw_SetRightGainsCurrent(vortex_t *vortex, const u16 a[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int ebx;
@@ -309,7 +309,7 @@ static void vortex_EqHw_GetRightGainsCurrent(vortex_t * vortex, u16 a[])
 
 #endif
 /* EQ band levels settings */
-static void vortex_EqHw_SetLevels(vortex_t * vortex, u16 peaks[])
+static void vortex_EqHw_SetLevels(vortex_t *vortex, const u16 peaks[])
 {
        eqhw_t *eqhw = &(vortex->eq.this04);
        int i;
@@ -574,7 +574,7 @@ static int vortex_Eqlzr_SetAllBandsFromActiveCoeffSet(vortex_t * vortex)
 }
 
 static int
-vortex_Eqlzr_SetAllBands(vortex_t * vortex, u16 gains[], s32 count)
+vortex_Eqlzr_SetAllBands(vortex_t *vortex, const u16 gains[], s32 count)
 {
        eqlzr_t *eq = &(vortex->eq);
        int i;
@@ -852,7 +852,7 @@ static const struct snd_kcontrol_new vortex_levels_kcontrol = {
 };
 
 /* EQ band gain labels. */
-static char *EqBandLabels[10] = {
+static const char * const EqBandLabels[10] = {
        "EQ0 31Hz\0",
        "EQ1 63Hz\0",
        "EQ2 125Hz\0",
index 49a52d2..a74f266 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /* Data structs */
 
-static u16 asEqCoefsZeros[50] = {
+static const u16 asEqCoefsZeros[50] = {
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -14,7 +14,7 @@ static u16 asEqCoefsZeros[50] = {
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
 };
 
-static u16 asEqCoefsPipes[64] = {
+static const u16 asEqCoefsPipes[64] = {
        0x0000, 0x0000,
        0x0000, 0x0666, 0x0000, 0x0000, 0x0666,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
@@ -33,7 +33,7 @@ static u16 asEqCoefsPipes[64] = {
 };
 
 /* More coef sets can be found in the win2k "inf" file. */
-static auxxEqCoeffSet_t asEqCoefsNormal = {
+static const auxxEqCoeffSet_t asEqCoefsNormal = {
        .LeftCoefs = {
                      0x7e60, 0xc19e, 0x0001, 0x0002, 0x0001,
                      0x7fa0, 0xc05f, 0x004f, 0x0000, 0xffb1,
@@ -66,7 +66,7 @@ static auxxEqCoeffSet_t asEqCoefsNormal = {
                       0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96}
 };
 
-static u16 eq_gains_normal[20] = {
+static const u16 eq_gains_normal[20] = {
        0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96,
        0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96,
        0x3e96, 0x3e96, 0x3e96, 0x3e96, 0x3e96,
@@ -74,22 +74,22 @@ static u16 eq_gains_normal[20] = {
 };
 
 /* _rodatab60 */
-static u16 eq_gains_zero[10] = {
+static const u16 eq_gains_zero[10] = {
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000
 };
 
 /* _rodatab7c:  ProgramPipe */
-static u16 eq_gains_current[12] = {
+static const u16 eq_gains_current[12] = {
        0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff, 0x7fff,
        0x7fff,
        0x7fff, 0x7fff, 0x7fff
 };
 
 /* _rodatab78 */
-static u16 eq_states_zero[2] = { 0x0000, 0x0000 };
+static const u16 eq_states_zero[2] = { 0x0000, 0x0000 };
 
-static u16 asEqOutStateZeros[48] = {
+static const u16 asEqOutStateZeros[48] = {
        0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000,
@@ -105,7 +105,7 @@ static u16 asEqOutStateZeros[48] = {
 };
 
 /*_rodataba0:*/
-static u16 eq_levels[64] = {
+static const u16 eq_levels[64] = {
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
        0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
index 60dd8a0..5b64768 100644 (file)
@@ -25,7 +25,7 @@ static int snd_vortex_mixer(vortex_t *vortex)
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = vortex_codec_write,
                .read = vortex_codec_read,
        };
index a2dcf43..d019aa5 100644 (file)
@@ -209,15 +209,7 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
 {
        vortex_t *chip = snd_pcm_substream_chip(substream);
        stream_t *stream = (stream_t *) (substream->runtime->private_data);
-       int err;
 
-       // Alloc buffer memory.
-       err =
-           snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0) {
-               dev_err(chip->card->dev, "Vortex: pcm page alloc failed!\n");
-               return err;
-       }
        /*
           pr_info( "Vortex: periods %d, period_bytes %d, channels = %d\n", params_periods(hw_params),
           params_period_bytes(hw_params), params_channels(hw_params));
@@ -304,7 +296,7 @@ static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
        substream->runtime->private_data = NULL;
        spin_unlock_irq(&chip->lock);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 /* prepare callback */
@@ -430,7 +422,6 @@ static snd_pcm_uframes_t snd_vortex_pcm_pointer(struct snd_pcm_substream *substr
 static const struct snd_pcm_ops snd_vortex_playback_ops = {
        .open = snd_vortex_pcm_open,
        .close = snd_vortex_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_vortex_pcm_hw_params,
        .hw_free = snd_vortex_pcm_hw_free,
        .prepare = snd_vortex_pcm_prepare,
@@ -442,14 +433,14 @@ static const struct snd_pcm_ops snd_vortex_playback_ops = {
 *  definitions of capture are omitted here...
 */
 
-static char *vortex_pcm_prettyname[VORTEX_PCM_LAST] = {
+static const char * const vortex_pcm_prettyname[VORTEX_PCM_LAST] = {
        CARD_NAME " ADB",
        CARD_NAME " SPDIF",
        CARD_NAME " A3D",
        CARD_NAME " WT",
        CARD_NAME " I2S",
 };
-static char *vortex_pcm_name[VORTEX_PCM_LAST] = {
+static const char * const vortex_pcm_name[VORTEX_PCM_LAST] = {
        "adb",
        "spdif",
        "a3d",
@@ -506,7 +497,7 @@ static int snd_vortex_spdif_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
 }
 
 /* spdif controls */
-static struct snd_kcontrol_new snd_vortex_mixer_spdif[] = {
+static const struct snd_kcontrol_new snd_vortex_mixer_spdif[] = {
        {
                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
                .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -636,9 +627,8 @@ static int snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
        
        /* pre-allocation of Scatter-Gather buffers */
        
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci_dev->dev,
-                                             0x10000, 0x10000);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci_dev->dev, 0x10000, 0x10000);
 
        switch (VORTEX_PCM_TYPE(pcm)) {
        case VORTEX_PCM_ADB:
index 1cbfae8..b3be98e 100644 (file)
@@ -109,9 +109,6 @@ static int snd_aw2_pcm_playback_open(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_playback_close(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_capture_open(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream);
-static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params);
-static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_prepare_capture(struct snd_pcm_substream *substream);
 static int snd_aw2_pcm_trigger_playback(struct snd_pcm_substream *substream,
@@ -169,9 +166,6 @@ module_pci_driver(aw2_driver);
 static const struct snd_pcm_ops snd_aw2_playback_ops = {
        .open = snd_aw2_pcm_playback_open,
        .close = snd_aw2_pcm_playback_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_aw2_pcm_hw_params,
-       .hw_free = snd_aw2_pcm_hw_free,
        .prepare = snd_aw2_pcm_prepare_playback,
        .trigger = snd_aw2_pcm_trigger_playback,
        .pointer = snd_aw2_pcm_pointer_playback,
@@ -181,9 +175,6 @@ static const struct snd_pcm_ops snd_aw2_playback_ops = {
 static const struct snd_pcm_ops snd_aw2_capture_ops = {
        .open = snd_aw2_pcm_capture_open,
        .close = snd_aw2_pcm_capture_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_aw2_pcm_hw_params,
-       .hw_free = snd_aw2_pcm_hw_free,
        .prepare = snd_aw2_pcm_prepare_capture,
        .trigger = snd_aw2_pcm_trigger_capture,
        .pointer = snd_aw2_pcm_pointer_capture,
@@ -232,7 +223,7 @@ static int snd_aw2_create(struct snd_card *card,
 {
        struct aw2 *chip;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_aw2_dev_free,
        };
 
@@ -296,6 +287,7 @@ static int snd_aw2_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
        if (err < 0) {
@@ -411,20 +403,6 @@ static int snd_aw2_pcm_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
- /* hw_params callback */
-static int snd_aw2_pcm_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-/* hw_free callback */
-static int snd_aw2_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 /* prepare callback for playback */
 static int snd_aw2_pcm_prepare_playback(struct snd_pcm_substream *substream)
 {
@@ -611,10 +589,10 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
 
        /* pre-allocation of buffers */
        /* Preallocate continuous pages. */
-       snd_pcm_lib_preallocate_pages_for_all(pcm_playback_ana,
-                                             SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64 * 1024, 64 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm_playback_ana,
+                                      SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev,
+                                      64 * 1024, 64 * 1024);
 
        err = snd_pcm_new(chip->card, "Audiowerk2 digital playback", 1, 1, 0,
                          &pcm_playback_num);
@@ -643,10 +621,10 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
 
        /* pre-allocation of buffers */
        /* Preallocate continuous pages. */
-       snd_pcm_lib_preallocate_pages_for_all(pcm_playback_num,
-                                             SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64 * 1024, 64 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm_playback_num,
+                                      SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev,
+                                      64 * 1024, 64 * 1024);
 
        err = snd_pcm_new(chip->card, "Audiowerk2 capture", 2, 0, 1,
                          &pcm_capture);
@@ -676,10 +654,10 @@ static int snd_aw2_new_pcm(struct aw2 *chip)
 
        /* pre-allocation of buffers */
        /* Preallocate continuous pages. */
-       snd_pcm_lib_preallocate_pages_for_all(pcm_capture,
-                                             SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64 * 1024, 64 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm_capture,
+                                      SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev,
+                                      64 * 1024, 64 * 1024);
 
        /* Create control */
        err = snd_ctl_add(chip->card, snd_ctl_new1(&aw2_control, chip));
index 41fed54..2f35b08 100644 (file)
@@ -59,7 +59,7 @@
     /*      SD3:          >-------<_4-L___>-------<_4-R___> */
     /*      WS4:          -------\_______________/--------- */
 
-static int tsl1[8] = {
+static const int tsl1[8] = {
        1 * TSL_SDW_A1 | 3 * TSL_BSEL_A1 |
        0 * TSL_DIS_A1 | 0 * TSL_DOD_A1 | TSL_LF_A1,
 
@@ -85,7 +85,7 @@ static int tsl1[8] = {
        0 * TSL_DOD_A1 | TSL_WS1 | TSL_WS0 | TSL_SF_A1 | TSL_EOS,
 };
 
-static int tsl2[8] = {
+static const int tsl2[8] = {
        0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2 | TSL_LF_A2,
        0 * TSL_SDW_A2 | 2 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
        0 * TSL_SDW_A2 | 3 * TSL_BSEL_A2 | 2 * TSL_DOD_A2,
index f475370..58167d8 100644 (file)
@@ -757,7 +757,7 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip)
 {
        struct snd_ac97_bus *bus;
        struct snd_ac97_template ac97;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_azf3328_mixer_ac97_write,
                .read = snd_azf3328_mixer_ac97_read,
        };
@@ -1094,7 +1094,7 @@ snd_azf3328_put_mixer_enum(struct snd_kcontrol *kcontrol,
        return (nreg != oreg);
 }
 
-static struct snd_kcontrol_new snd_azf3328_mixer_controls[] = {
+static const struct snd_kcontrol_new snd_azf3328_mixer_controls[] = {
        AZF3328_MIXER_SWITCH("Master Playback Switch", IDX_MIXER_PLAY_MASTER, 15, 1),
        AZF3328_MIXER_VOL_STEREO("Master Playback Volume", IDX_MIXER_PLAY_MASTER, 0x1f, 1),
        AZF3328_MIXER_SWITCH("PCM Playback Switch", IDX_MIXER_WAVEOUT, 15, 1),
@@ -1152,7 +1152,7 @@ static struct snd_kcontrol_new snd_azf3328_mixer_controls[] = {
 #endif
 };
 
-static u16 snd_azf3328_init_values[][2] = {
+static const u16 snd_azf3328_init_values[][2] = {
         { IDX_MIXER_PLAY_MASTER,       MIXER_MUTE_MASK|0x1f1f },
         { IDX_MIXER_MODEMOUT,          MIXER_MUTE_MASK|0x1f1f },
        { IDX_MIXER_BASSTREBLE,         0x0000 },
@@ -1205,20 +1205,6 @@ snd_azf3328_mixer_new(struct snd_azf3328 *chip)
 }
 #endif /* AZF_USE_AC97_LAYER */
 
-static int
-snd_azf3328_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int
-snd_azf3328_hw_free(struct snd_pcm_substream *substream)
-{
-       snd_pcm_lib_free_pages(substream);
-       return 0;
-}
-
 static void
 snd_azf3328_codec_setfmt(struct snd_azf3328_codec_data *codec,
                               enum azf_freq_t bitrate,
@@ -2079,9 +2065,6 @@ snd_azf3328_pcm_close(struct snd_pcm_substream *substream
 static const struct snd_pcm_ops snd_azf3328_playback_ops = {
        .open =         snd_azf3328_pcm_playback_open,
        .close =        snd_azf3328_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_azf3328_hw_params,
-       .hw_free =      snd_azf3328_hw_free,
        .prepare =      snd_azf3328_pcm_prepare,
        .trigger =      snd_azf3328_pcm_trigger,
        .pointer =      snd_azf3328_pcm_pointer
@@ -2090,9 +2073,6 @@ static const struct snd_pcm_ops snd_azf3328_playback_ops = {
 static const struct snd_pcm_ops snd_azf3328_capture_ops = {
        .open =         snd_azf3328_pcm_capture_open,
        .close =        snd_azf3328_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_azf3328_hw_params,
-       .hw_free =      snd_azf3328_hw_free,
        .prepare =      snd_azf3328_pcm_prepare,
        .trigger =      snd_azf3328_pcm_trigger,
        .pointer =      snd_azf3328_pcm_pointer
@@ -2101,9 +2081,6 @@ static const struct snd_pcm_ops snd_azf3328_capture_ops = {
 static const struct snd_pcm_ops snd_azf3328_i2s_out_ops = {
        .open =         snd_azf3328_pcm_i2s_out_open,
        .close =        snd_azf3328_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_azf3328_hw_params,
-       .hw_free =      snd_azf3328_hw_free,
        .prepare =      snd_azf3328_pcm_prepare,
        .trigger =      snd_azf3328_pcm_trigger,
        .pointer =      snd_azf3328_pcm_pointer
@@ -2134,9 +2111,8 @@ snd_azf3328_pcm(struct snd_azf3328 *chip)
        chip->pcm[AZF_CODEC_PLAYBACK] = pcm;
        chip->pcm[AZF_CODEC_CAPTURE] = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
+                                      64*1024, 64*1024);
 
        err = snd_pcm_new(chip->card, "AZF3328 I2S OUT", AZF_PCMDEV_I2S_OUT,
                                                                1, 0, &pcm);
@@ -2150,9 +2126,8 @@ snd_azf3328_pcm(struct snd_azf3328 *chip)
        strcpy(pcm->name, chip->card->shortname);
        chip->pcm[AZF_CODEC_I2S_OUT] = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
+                                      64*1024, 64*1024);
 
        return 0;
 }
@@ -2380,7 +2355,7 @@ snd_azf3328_create(struct snd_card *card,
 {
        struct snd_azf3328 *chip;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_azf3328_dev_free,
        };
        u8 dma_init;
@@ -2448,8 +2423,8 @@ snd_azf3328_create(struct snd_card *card,
                goto out_err;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        pci_set_master(pci);
-       synchronize_irq(chip->irq);
 
        snd_azf3328_debug_show_ports(chip);
 
index 6bf5ac3..8c48864 100644 (file)
@@ -150,7 +150,7 @@ struct snd_bt87x_board {
        unsigned no_digital:1;  /* No digital input */
 };
 
-static struct snd_bt87x_board snd_bt87x_boards[] = {
+static const struct snd_bt87x_board snd_bt87x_boards[] = {
        [SND_BT87X_BOARD_UNKNOWN] = {
                .dig_rate = 32000, /* just a guess */
        },
@@ -452,12 +452,7 @@ static int snd_bt87x_hw_params(struct snd_pcm_substream *substream,
                               struct snd_pcm_hw_params *hw_params)
 {
        struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
-       int err;
 
-       err = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        return snd_bt87x_create_risc(chip, substream,
                                     params_periods(hw_params),
                                     params_period_bytes(hw_params));
@@ -468,7 +463,6 @@ static int snd_bt87x_hw_free(struct snd_pcm_substream *substream)
        struct snd_bt87x *chip = snd_pcm_substream_chip(substream);
 
        snd_bt87x_free_risc(chip);
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -539,7 +533,6 @@ static snd_pcm_uframes_t snd_bt87x_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_bt87x_pcm_ops = {
        .open = snd_bt87x_pcm_open,
        .close = snd_bt87x_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_bt87x_hw_params,
        .hw_free = snd_bt87x_hw_free,
        .prepare = snd_bt87x_prepare,
@@ -699,10 +692,10 @@ static int snd_bt87x_pcm(struct snd_bt87x *chip, int device, char *name)
        pcm->private_data = chip;
        strcpy(pcm->name, name);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_bt87x_pcm_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             128 * 1024,
-                                             ALIGN(255 * 4092, 1024));
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev,
+                                      128 * 1024,
+                                      ALIGN(255 * 4092, 1024));
        return 0;
 }
 
@@ -712,7 +705,7 @@ static int snd_bt87x_create(struct snd_card *card,
 {
        struct snd_bt87x *chip;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_bt87x_dev_free
        };
 
@@ -758,8 +751,8 @@ static int snd_bt87x_create(struct snd_card *card,
                goto fail;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        pci_set_master(pci);
-       synchronize_irq(chip->irq);
 
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
        if (err < 0)
index 986905c..62a22ca 100644 (file)
@@ -663,7 +663,7 @@ struct snd_ca0106_details {
 // definition of the chip-specific record
 struct snd_ca0106 {
        struct snd_card *card;
-       struct snd_ca0106_details *details;
+       const struct snd_ca0106_details *details;
        struct pci_dev *pci;
 
        unsigned long port;
index abc2440..70d775f 100644 (file)
@@ -156,7 +156,7 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
 
 #include "ca0106.h"
 
-static struct snd_ca0106_details ca0106_chip_details[] = {
+static const struct snd_ca0106_details ca0106_chip_details[] = {
         /* Sound Blaster X-Fi Extreme Audio. This does not have an AC97. 53SB079000000 */
         /* It is really just a normal SB Live 24bit. */
         /* Tested:
@@ -503,7 +503,7 @@ static void restore_spdif_bits(struct snd_ca0106 *chip, int idx)
 }
 
 static int snd_ca0106_channel_dac(struct snd_ca0106 *chip,
-                                 struct snd_ca0106_details *details,
+                                 const struct snd_ca0106_details *details,
                                  int channel_id)
 {
        switch (channel_id) {
@@ -707,34 +707,6 @@ static int snd_ca0106_pcm_open_3_capture(struct snd_pcm_substream *substream)
        return snd_ca0106_pcm_open_capture_channel(substream, 3);
 }
 
-/* hw_params callback */
-static int snd_ca0106_pcm_hw_params_playback(struct snd_pcm_substream *substream,
-                                     struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-/* hw_free callback */
-static int snd_ca0106_pcm_hw_free_playback(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
-/* hw_params callback */
-static int snd_ca0106_pcm_hw_params_capture(struct snd_pcm_substream *substream,
-                                     struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-/* hw_free callback */
-static int snd_ca0106_pcm_hw_free_capture(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 /* prepare playback callback */
 static int snd_ca0106_pcm_prepare_playback(struct snd_pcm_substream *substream)
 {
@@ -1096,9 +1068,6 @@ snd_ca0106_pcm_pointer_capture(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_ca0106_playback_front_ops = {
        .open =        snd_ca0106_pcm_open_playback_front,
        .close =       snd_ca0106_pcm_close_playback,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   snd_ca0106_pcm_hw_params_playback,
-       .hw_free =     snd_ca0106_pcm_hw_free_playback,
        .prepare =     snd_ca0106_pcm_prepare_playback,
        .trigger =     snd_ca0106_pcm_trigger_playback,
        .pointer =     snd_ca0106_pcm_pointer_playback,
@@ -1107,9 +1076,6 @@ static const struct snd_pcm_ops snd_ca0106_playback_front_ops = {
 static const struct snd_pcm_ops snd_ca0106_capture_0_ops = {
        .open =        snd_ca0106_pcm_open_0_capture,
        .close =       snd_ca0106_pcm_close_capture,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   snd_ca0106_pcm_hw_params_capture,
-       .hw_free =     snd_ca0106_pcm_hw_free_capture,
        .prepare =     snd_ca0106_pcm_prepare_capture,
        .trigger =     snd_ca0106_pcm_trigger_capture,
        .pointer =     snd_ca0106_pcm_pointer_capture,
@@ -1118,9 +1084,6 @@ static const struct snd_pcm_ops snd_ca0106_capture_0_ops = {
 static const struct snd_pcm_ops snd_ca0106_capture_1_ops = {
        .open =        snd_ca0106_pcm_open_1_capture,
        .close =       snd_ca0106_pcm_close_capture,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   snd_ca0106_pcm_hw_params_capture,
-       .hw_free =     snd_ca0106_pcm_hw_free_capture,
        .prepare =     snd_ca0106_pcm_prepare_capture,
        .trigger =     snd_ca0106_pcm_trigger_capture,
        .pointer =     snd_ca0106_pcm_pointer_capture,
@@ -1129,9 +1092,6 @@ static const struct snd_pcm_ops snd_ca0106_capture_1_ops = {
 static const struct snd_pcm_ops snd_ca0106_capture_2_ops = {
        .open =        snd_ca0106_pcm_open_2_capture,
        .close =       snd_ca0106_pcm_close_capture,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   snd_ca0106_pcm_hw_params_capture,
-       .hw_free =     snd_ca0106_pcm_hw_free_capture,
        .prepare =     snd_ca0106_pcm_prepare_capture,
        .trigger =     snd_ca0106_pcm_trigger_capture,
        .pointer =     snd_ca0106_pcm_pointer_capture,
@@ -1140,9 +1100,6 @@ static const struct snd_pcm_ops snd_ca0106_capture_2_ops = {
 static const struct snd_pcm_ops snd_ca0106_capture_3_ops = {
        .open =        snd_ca0106_pcm_open_3_capture,
        .close =       snd_ca0106_pcm_close_capture,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   snd_ca0106_pcm_hw_params_capture,
-       .hw_free =     snd_ca0106_pcm_hw_free_capture,
        .prepare =     snd_ca0106_pcm_prepare_capture,
        .trigger =     snd_ca0106_pcm_trigger_capture,
        .pointer =     snd_ca0106_pcm_pointer_capture,
@@ -1151,9 +1108,6 @@ static const struct snd_pcm_ops snd_ca0106_capture_3_ops = {
 static const struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
         .open =         snd_ca0106_pcm_open_playback_center_lfe,
         .close =        snd_ca0106_pcm_close_playback,
-        .ioctl =        snd_pcm_lib_ioctl,
-        .hw_params =    snd_ca0106_pcm_hw_params_playback,
-        .hw_free =      snd_ca0106_pcm_hw_free_playback,
         .prepare =      snd_ca0106_pcm_prepare_playback,     
         .trigger =      snd_ca0106_pcm_trigger_playback,  
         .pointer =      snd_ca0106_pcm_pointer_playback, 
@@ -1162,9 +1116,6 @@ static const struct snd_pcm_ops snd_ca0106_playback_center_lfe_ops = {
 static const struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
         .open =         snd_ca0106_pcm_open_playback_unknown,
         .close =        snd_ca0106_pcm_close_playback,
-        .ioctl =        snd_pcm_lib_ioctl,
-        .hw_params =    snd_ca0106_pcm_hw_params_playback,
-        .hw_free =      snd_ca0106_pcm_hw_free_playback,
         .prepare =      snd_ca0106_pcm_prepare_playback,     
         .trigger =      snd_ca0106_pcm_trigger_playback,  
         .pointer =      snd_ca0106_pcm_pointer_playback, 
@@ -1173,9 +1124,6 @@ static const struct snd_pcm_ops snd_ca0106_playback_unknown_ops = {
 static const struct snd_pcm_ops snd_ca0106_playback_rear_ops = {
         .open =         snd_ca0106_pcm_open_playback_rear,
         .close =        snd_ca0106_pcm_close_playback,
-        .ioctl =        snd_pcm_lib_ioctl,
-        .hw_params =    snd_ca0106_pcm_hw_params_playback,
-               .hw_free =      snd_ca0106_pcm_hw_free_playback,
         .prepare =      snd_ca0106_pcm_prepare_playback,     
         .trigger =      snd_ca0106_pcm_trigger_playback,  
         .pointer =      snd_ca0106_pcm_pointer_playback, 
@@ -1213,7 +1161,7 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip)
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_ca0106_ac97_write,
                .read = snd_ca0106_ac97_read,
        };
@@ -1388,17 +1336,17 @@ static int snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
        for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 
            substream; 
            substream = substream->next) {
-               snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
-                                             &emu->pci->dev,
-                                             64*1024, 64*1024);
+               snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
+                                          &emu->pci->dev,
+                                          64*1024, 64*1024);
        }
 
        for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 
              substream; 
              substream = substream->next) {
-               snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
-                                             &emu->pci->dev,
-                                             64*1024, 64*1024);
+               snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
+                                          &emu->pci->dev,
+                                          64*1024, 64*1024);
        }
   
        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2,
@@ -1412,7 +1360,7 @@ static int snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
 }
 
 #define SPI_REG(reg, value)    (((reg) << SPI_REG_SHIFT) | (value))
-static unsigned int spi_dac_init[] = {
+static const unsigned int spi_dac_init[] = {
        SPI_REG(SPI_LDA1_REG,   SPI_DA_BIT_0dB), /* 0dB dig. attenuation */
        SPI_REG(SPI_RDA1_REG,   SPI_DA_BIT_0dB),
        SPI_REG(SPI_PL_REG,     SPI_PL_BIT_L_L | SPI_PL_BIT_R_R | SPI_IZD_BIT),
@@ -1430,7 +1378,7 @@ static unsigned int spi_dac_init[] = {
        SPI_REG(SPI_DACD4_REG,  SPI_DACD4_BIT),
 };
 
-static unsigned int i2c_adc_init[][2] = {
+static const unsigned int i2c_adc_init[][2] = {
        { 0x17, 0x00 }, /* Reset */
        { 0x07, 0x00 }, /* Timeout */
        { 0x0b, 0x22 },  /* Interface control */
@@ -1645,9 +1593,9 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
                                         struct snd_ca0106 **rchip)
 {
        struct snd_ca0106 *chip;
-       struct snd_ca0106_details *c;
+       const struct snd_ca0106_details *c;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_ca0106_dev_free,
        };
 
@@ -1690,6 +1638,7 @@ static int snd_ca0106_create(int dev, struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        /* This stores the periods table. */
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
index 38f7f0a..3b8ec67 100644 (file)
@@ -550,7 +550,7 @@ static int spi_mute_put(struct snd_kcontrol *kcontrol,
        .private_value = ((chid) << 8) | (reg)                  \
 }
 
-static struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
+static const struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
        CA_VOLUME("Analog Front Playback Volume",
                  CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
         CA_VOLUME("Analog Rear Playback Volume",
@@ -631,7 +631,7 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] = {
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
+static const struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] = {
         I2C_VOLUME("Phone Capture Volume", 0),
         I2C_VOLUME("Mic Capture Volume", 1),
         I2C_VOLUME("Line in Capture Volume", 2),
@@ -654,7 +654,7 @@ static const int spi_dmute_bit[] = {
 };
 
 static struct snd_kcontrol_new
-snd_ca0106_volume_spi_dac_ctl(struct snd_ca0106_details *details,
+snd_ca0106_volume_spi_dac_ctl(const struct snd_ca0106_details *details,
                              int channel_id)
 {
        struct snd_kcontrol_new spi_switch = {0};
@@ -739,7 +739,7 @@ static int rename_ctl(struct snd_card *card, const char *src, const char *dst)
 static
 DECLARE_TLV_DB_SCALE(snd_ca0106_master_db_scale, -6375, 25, 1);
 
-static char *slave_vols[] = {
+static const char * const slave_vols[] = {
        "Analog Front Playback Volume",
         "Analog Rear Playback Volume",
        "Analog Center/LFE Playback Volume",
@@ -752,7 +752,7 @@ static char *slave_vols[] = {
        NULL
 };
 
-static char *slave_sws[] = {
+static const char * const slave_sws[] = {
        "Analog Front Playback Switch",
        "Analog Rear Playback Switch",
        "Analog Center/LFE Playback Switch",
@@ -762,7 +762,7 @@ static char *slave_sws[] = {
 };
 
 static void add_slaves(struct snd_card *card,
-                                struct snd_kcontrol *master, char **list)
+                      struct snd_kcontrol *master, const char * const *list)
 {
        for (; *list; list++) {
                struct snd_kcontrol *slave = ctl_find(card, *list);
@@ -775,9 +775,9 @@ int snd_ca0106_mixer(struct snd_ca0106 *emu)
 {
        int err;
         struct snd_card *card = emu->card;
-       char **c;
+       const char * const *c;
        struct snd_kcontrol *vmaster;
-       static char *ca0106_remove_ctls[] = {
+       static const char * const ca0106_remove_ctls[] = {
                "Master Mono Playback Switch",
                "Master Mono Playback Volume",
                "3D Control - Switch",
@@ -801,7 +801,7 @@ int snd_ca0106_mixer(struct snd_ca0106 *emu)
                "Surround Phase Inversion Playback Switch",
                NULL
        };
-       static char *ca0106_rename_ctls[] = {
+       static const char * const ca0106_rename_ctls[] = {
                "Master Playback Switch", "Capture Switch",
                "Master Playback Volume", "Capture Volume",
                "Line Playback Switch", "AC97 Line Capture Switch",
@@ -875,7 +875,7 @@ struct ca0106_vol_tbl {
        unsigned int reg;
 };
 
-static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
+static const struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
        { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
        { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
        { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
index 15272c9..c99603e 100644 (file)
@@ -66,7 +66,7 @@ struct snd_ca0106_category_str {
        const char *name;
 };
 
-static struct snd_ca0106_category_str snd_ca0106_con_category[] = {
+static const struct snd_ca0106_category_str snd_ca0106_con_category[] = {
        { IEC958_AES1_CON_DAT, "DAT" },
        { IEC958_AES1_CON_VCR, "VCR" },
        { IEC958_AES1_CON_MICROPHONE, "microphone" },
index dd9d62e..7363d61 100644 (file)
@@ -42,7 +42,7 @@ MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8738},"
 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;     /* Index 0-MAX */
 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;      /* ID for this card */
 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;    /* Enable switches */
-static long mpu_port[SNDRV_CARDS];
+static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
 static long fm_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
 static bool soft_ac3[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
 #ifdef SUPPORT_JOYSTICK
@@ -586,7 +586,7 @@ static int snd_cmipci_clear_bit_b(struct cmipci *cm, unsigned int cmd, unsigned
  * calculate frequency
  */
 
-static unsigned int rates[] = { 5512, 11025, 22050, 44100, 8000, 16000, 32000, 48000 };
+static const unsigned int rates[] = { 5512, 11025, 22050, 44100, 8000, 16000, 32000, 48000 };
 
 static unsigned int snd_cmipci_rate_freq(unsigned int rate)
 {
@@ -666,12 +666,6 @@ static void snd_cmipci_set_pll(struct cmipci *cm, unsigned int rate, unsigned in
 }
 #endif /* USE_VAR48KRATE */
 
-static int snd_cmipci_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
 static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream,
                                          struct snd_pcm_hw_params *hw_params)
 {
@@ -686,7 +680,7 @@ static int snd_cmipci_playback2_hw_params(struct snd_pcm_substream *substream,
                cm->opened[CM_CH_PLAY] = CM_OPEN_PLAYBACK_MULTI;
                mutex_unlock(&cm->open_mutex);
        }
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+       return 0;
 }
 
 static void snd_cmipci_ch_reset(struct cmipci *cm, int ch)
@@ -697,11 +691,6 @@ static void snd_cmipci_ch_reset(struct cmipci *cm, int ch)
        udelay(10);
 }
 
-static int snd_cmipci_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 
 /*
  */
@@ -1371,14 +1360,14 @@ static int snd_cmipci_playback_hw_free(struct snd_pcm_substream *substream)
        setup_spdif_playback(cm, substream, 0, 0);
        restore_mixer_state(cm);
        snd_cmipci_silence_hack(cm, &cm->channel[0]);
-       return snd_cmipci_hw_free(substream);
+       return 0;
 }
 
 static int snd_cmipci_playback2_hw_free(struct snd_pcm_substream *substream)
 {
        struct cmipci *cm = snd_pcm_substream_chip(substream);
        snd_cmipci_silence_hack(cm, &cm->channel[1]);
-       return snd_cmipci_hw_free(substream);
+       return 0;
 }
 
 /* capture */
@@ -1420,7 +1409,7 @@ static int snd_cmipci_capture_spdif_hw_free(struct snd_pcm_substream *subs)
        snd_cmipci_clear_bit(cm, CM_REG_MISC_CTRL, CM_SPD32SEL);
        spin_unlock_irq(&cm->reg_lock);
 
-       return snd_cmipci_hw_free(subs);
+       return 0;
 }
 
 
@@ -1828,8 +1817,6 @@ static int snd_cmipci_capture_spdif_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_cmipci_playback_ops = {
        .open =         snd_cmipci_playback_open,
        .close =        snd_cmipci_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_cmipci_hw_params,
        .hw_free =      snd_cmipci_playback_hw_free,
        .prepare =      snd_cmipci_playback_prepare,
        .trigger =      snd_cmipci_playback_trigger,
@@ -1839,9 +1826,6 @@ static const struct snd_pcm_ops snd_cmipci_playback_ops = {
 static const struct snd_pcm_ops snd_cmipci_capture_ops = {
        .open =         snd_cmipci_capture_open,
        .close =        snd_cmipci_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_cmipci_hw_params,
-       .hw_free =      snd_cmipci_hw_free,
        .prepare =      snd_cmipci_capture_prepare,
        .trigger =      snd_cmipci_capture_trigger,
        .pointer =      snd_cmipci_capture_pointer,
@@ -1850,7 +1834,6 @@ static const struct snd_pcm_ops snd_cmipci_capture_ops = {
 static const struct snd_pcm_ops snd_cmipci_playback2_ops = {
        .open =         snd_cmipci_playback2_open,
        .close =        snd_cmipci_playback2_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_cmipci_playback2_hw_params,
        .hw_free =      snd_cmipci_playback2_hw_free,
        .prepare =      snd_cmipci_capture_prepare,     /* channel B */
@@ -1861,8 +1844,6 @@ static const struct snd_pcm_ops snd_cmipci_playback2_ops = {
 static const struct snd_pcm_ops snd_cmipci_playback_spdif_ops = {
        .open =         snd_cmipci_playback_spdif_open,
        .close =        snd_cmipci_playback_spdif_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_cmipci_hw_params,
        .hw_free =      snd_cmipci_playback_hw_free,
        .prepare =      snd_cmipci_playback_spdif_prepare,      /* set up rate */
        .trigger =      snd_cmipci_playback_trigger,
@@ -1872,8 +1853,6 @@ static const struct snd_pcm_ops snd_cmipci_playback_spdif_ops = {
 static const struct snd_pcm_ops snd_cmipci_capture_spdif_ops = {
        .open =         snd_cmipci_capture_spdif_open,
        .close =        snd_cmipci_capture_spdif_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_cmipci_hw_params,
        .hw_free =      snd_cmipci_capture_spdif_hw_free,
        .prepare =      snd_cmipci_capture_spdif_prepare,
        .trigger =      snd_cmipci_capture_trigger,
@@ -1901,8 +1880,8 @@ static int snd_cmipci_pcm_new(struct cmipci *cm, int device)
        strcpy(pcm->name, "C-Media PCI DAC/ADC");
        cm->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &cm->pci->dev, 64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &cm->pci->dev, 64*1024, 128*1024);
 
        return 0;
 }
@@ -1923,8 +1902,8 @@ static int snd_cmipci_pcm2_new(struct cmipci *cm, int device)
        strcpy(pcm->name, "C-Media PCI 2nd DAC");
        cm->pcm2 = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &cm->pci->dev, 64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &cm->pci->dev, 64*1024, 128*1024);
 
        return 0;
 }
@@ -1946,8 +1925,8 @@ static int snd_cmipci_pcm_spdif_new(struct cmipci *cm, int device)
        strcpy(pcm->name, "C-Media PCI IEC958");
        cm->pcm_spdif = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &cm->pci->dev, 64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &cm->pci->dev, 64*1024, 128*1024);
 
        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                     snd_pcm_alt_chmaps, cm->max_channels, 0,
@@ -2277,7 +2256,7 @@ static int snd_cmipci_put_native_mixer_sensitive(struct snd_kcontrol *kcontrol,
 }
 
 
-static struct snd_kcontrol_new snd_cmipci_mixers[] = {
+static const struct snd_kcontrol_new snd_cmipci_mixers[] = {
        CMIPCI_SB_VOL_STEREO("Master Playback Volume", SB_DSP4_MASTER_DEV, 3, 31),
        CMIPCI_MIXER_SW_MONO("3D Control - Switch", CM_REG_MIXER1, CM_X3DEN_SHIFT, 0),
        CMIPCI_SB_VOL_STEREO("PCM Playback Volume", SB_DSP4_PCM_DEV, 3, 31),
@@ -2588,7 +2567,7 @@ static int snd_cmipci_mic_in_mode_put(struct snd_kcontrol *kcontrol,
 }
 
 /* both for CM8338/8738 */
-static struct snd_kcontrol_new snd_cmipci_mixer_switches[] = {
+static const struct snd_kcontrol_new snd_cmipci_mixer_switches[] = {
        DEFINE_MIXER_SWITCH("Four Channel Mode", fourch),
        {
                .name = "Line-In Mode",
@@ -2600,11 +2579,11 @@ static struct snd_kcontrol_new snd_cmipci_mixer_switches[] = {
 };
 
 /* for non-multichannel chips */
-static struct snd_kcontrol_new snd_cmipci_nomulti_switch =
+static const struct snd_kcontrol_new snd_cmipci_nomulti_switch =
 DEFINE_MIXER_SWITCH("Exchange DAC", exchange_dac);
 
 /* only for CM8738 */
-static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] = {
+static const struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] = {
 #if 0 /* controlled in pcm device */
        DEFINE_MIXER_SWITCH("IEC958 In Record", spdif_in),
        DEFINE_MIXER_SWITCH("IEC958 Out", spdif_out),
@@ -2626,14 +2605,14 @@ static struct snd_kcontrol_new snd_cmipci_8738_mixer_switches[] = {
 };
 
 /* only for model 033/037 */
-static struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] = {
+static const struct snd_kcontrol_new snd_cmipci_old_mixer_switches[] = {
        DEFINE_MIXER_SWITCH("IEC958 Mix Analog", spdif_dac_out),
        DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase),
        DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel1),
 };
 
 /* only for model 039 or later */
-static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] = {
+static const struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] = {
        DEFINE_MIXER_SWITCH("IEC958 In Select", spdif_in_sel2),
        DEFINE_MIXER_SWITCH("IEC958 In Phase Inverse", spdi_phase2),
        {
@@ -2646,14 +2625,14 @@ static struct snd_kcontrol_new snd_cmipci_extra_mixer_switches[] = {
 };
 
 /* card control switches */
-static struct snd_kcontrol_new snd_cmipci_modem_switch =
+static const struct snd_kcontrol_new snd_cmipci_modem_switch =
 DEFINE_CARD_SWITCH("Modem", modem);
 
 
 static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
 {
        struct snd_card *card;
-       struct snd_kcontrol_new *sw;
+       const struct snd_kcontrol_new *sw;
        struct snd_kcontrol *kctl;
        unsigned int idx;
        int err;
@@ -2847,7 +2826,7 @@ static void query_chip(struct cmipci *cm)
 #ifdef SUPPORT_JOYSTICK
 static int snd_cmipci_create_gameport(struct cmipci *cm, int dev)
 {
-       static int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
+       static const int ports[] = { 0x201, 0x200, 0 }; /* FIXME: majority is 0x201? */
        struct gameport *gp;
        struct resource *r = NULL;
        int i, io_port = 0;
@@ -2997,7 +2976,7 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
 {
        struct cmipci *cm;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_cmipci_dev_free,
        };
        unsigned int val;
@@ -3045,6 +3024,7 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
                return -EBUSY;
        }
        cm->irq = pci->irq;
+       card->sync_irq = cm->irq;
 
        pci_set_master(cm->pci);
 
@@ -3152,7 +3132,8 @@ static int snd_cmipci_create(struct snd_card *card, struct pci_dev *pci,
        if (cm->chip_version >= 39) {
                val = snd_cmipci_read_b(cm, CM_REG_MPU_PCI + 1);
                if (val != 0x00 && val != 0xff) {
-                       iomidi = cm->iobase + CM_REG_MPU_PCI;
+                       if (mpu_port[dev])
+                               iomidi = cm->iobase + CM_REG_MPU_PCI;
                        integrated_midi = 1;
                }
        }
@@ -3308,7 +3289,7 @@ static void snd_cmipci_remove(struct pci_dev *pci)
 /*
  * power management
  */
-static unsigned char saved_regs[] = {
+static const unsigned char saved_regs[] = {
        CM_REG_FUNCTRL1, CM_REG_CHFORMAT, CM_REG_LEGACY_CTRL, CM_REG_MISC_CTRL,
        CM_REG_MIXER0, CM_REG_MIXER1, CM_REG_MIXER2, CM_REG_MIXER3, CM_REG_PLL,
        CM_REG_CH0_FRAME1, CM_REG_CH0_FRAME2,
@@ -3316,7 +3297,7 @@ static unsigned char saved_regs[] = {
        CM_REG_INT_STATUS, CM_REG_INT_HLDCLR, CM_REG_FUNCTRL0,
 };
 
-static unsigned char saved_mixers[] = {
+static const unsigned char saved_mixers[] = {
        SB_DSP4_MASTER_DEV, SB_DSP4_MASTER_DEV + 1,
        SB_DSP4_PCM_DEV, SB_DSP4_PCM_DEV + 1,
        SB_DSP4_SYNTH_DEV, SB_DSP4_SYNTH_DEV + 1,
index 058c141..94d2a6a 100644 (file)
@@ -780,17 +780,6 @@ static void snd_cs4281_mode(struct cs4281 *chip, struct cs4281_dma *dma,
        snd_cs4281_pokeBA0(chip, dma->regFSIC, 0);
 }
 
-static int snd_cs4281_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_cs4281_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_cs4281_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -938,9 +927,6 @@ static int snd_cs4281_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_cs4281_playback_ops = {
        .open =         snd_cs4281_playback_open,
        .close =        snd_cs4281_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_cs4281_hw_params,
-       .hw_free =      snd_cs4281_hw_free,
        .prepare =      snd_cs4281_playback_prepare,
        .trigger =      snd_cs4281_trigger,
        .pointer =      snd_cs4281_pointer,
@@ -949,9 +935,6 @@ static const struct snd_pcm_ops snd_cs4281_playback_ops = {
 static const struct snd_pcm_ops snd_cs4281_capture_ops = {
        .open =         snd_cs4281_capture_open,
        .close =        snd_cs4281_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_cs4281_hw_params,
-       .hw_free =      snd_cs4281_hw_free,
        .prepare =      snd_cs4281_capture_prepare,
        .trigger =      snd_cs4281_trigger,
        .pointer =      snd_cs4281_pointer,
@@ -974,9 +957,8 @@ static int snd_cs4281_pcm(struct cs4281 *chip, int device)
        strcpy(pcm->name, "CS4281");
        chip->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 512*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &chip->pci->dev,
+                                      64*1024, 512*1024);
 
        return 0;
 }
@@ -1082,7 +1064,7 @@ static int snd_cs4281_mixer(struct cs4281 *chip)
        struct snd_card *card = chip->card;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_cs4281_ac97_write,
                .read = snd_cs4281_ac97_read,
        };
@@ -1147,11 +1129,11 @@ static ssize_t snd_cs4281_BA1_read(struct snd_info_entry *entry,
        return count;
 }
 
-static struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {
+static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA0 = {
        .read = snd_cs4281_BA0_read,
 };
 
-static struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = {
+static const struct snd_info_entry_ops snd_cs4281_proc_ops_BA1 = {
        .read = snd_cs4281_BA1_read,
 };
 
@@ -1286,9 +1268,6 @@ static int snd_cs4281_free(struct cs4281 *chip)
 {
        snd_cs4281_free_gameport(chip);
 
-       if (chip->irq >= 0)
-               synchronize_irq(chip->irq);
-
        /* Mask interrupts */
        snd_cs4281_pokeBA0(chip, BA0_HIMR, 0x7fffffff);
        /* Stop the DLL Clock logic. */
@@ -1325,7 +1304,7 @@ static int snd_cs4281_create(struct snd_card *card,
        struct cs4281 *chip;
        unsigned int tmp;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_cs4281_dev_free,
        };
 
@@ -1370,6 +1349,7 @@ static int snd_cs4281_create(struct snd_card *card,
                return -ENOMEM;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        tmp = snd_cs4281_chip_init(chip);
        if (tmp) {
@@ -1618,7 +1598,6 @@ static int snd_cs4281_chip_init(struct cs4281 *chip)
                                        BA0_HISR_DMA(1) |
                                        BA0_HISR_DMA(2) |
                                        BA0_HISR_DMA(3)));
-       synchronize_irq(chip->irq);
 
        return 0;
 }
@@ -1960,7 +1939,7 @@ static void snd_cs4281_remove(struct pci_dev *pci)
  */
 #ifdef CONFIG_PM_SLEEP
 
-static int saved_regs[SUSPEND_REGISTERS] = {
+static const int saved_regs[SUSPEND_REGISTERS] = {
        BA0_JSCTL,
        BA0_GPIOR,
        BA0_SSCR,
index 102a629..e46efae 100644 (file)
@@ -1645,7 +1645,6 @@ static int snd_cs46xx_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
        .open =                 snd_cs46xx_playback_open_rear,
        .close =                snd_cs46xx_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_playback_hw_params,
        .hw_free =              snd_cs46xx_playback_hw_free,
        .prepare =              snd_cs46xx_playback_prepare,
@@ -1656,7 +1655,6 @@ static const struct snd_pcm_ops snd_cs46xx_playback_rear_ops = {
 static const struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
        .open =                 snd_cs46xx_playback_open_rear,
        .close =                snd_cs46xx_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_playback_hw_params,
        .hw_free =              snd_cs46xx_playback_hw_free,
        .prepare =              snd_cs46xx_playback_prepare,
@@ -1668,7 +1666,6 @@ static const struct snd_pcm_ops snd_cs46xx_playback_indirect_rear_ops = {
 static const struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
        .open =                 snd_cs46xx_playback_open_clfe,
        .close =                snd_cs46xx_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_playback_hw_params,
        .hw_free =              snd_cs46xx_playback_hw_free,
        .prepare =              snd_cs46xx_playback_prepare,
@@ -1679,7 +1676,6 @@ static const struct snd_pcm_ops snd_cs46xx_playback_clfe_ops = {
 static const struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
        .open =                 snd_cs46xx_playback_open_clfe,
        .close =                snd_cs46xx_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_playback_hw_params,
        .hw_free =              snd_cs46xx_playback_hw_free,
        .prepare =              snd_cs46xx_playback_prepare,
@@ -1691,7 +1687,6 @@ static const struct snd_pcm_ops snd_cs46xx_playback_indirect_clfe_ops = {
 static const struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
        .open =                 snd_cs46xx_playback_open_iec958,
        .close =                snd_cs46xx_playback_close_iec958,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_playback_hw_params,
        .hw_free =              snd_cs46xx_playback_hw_free,
        .prepare =              snd_cs46xx_playback_prepare,
@@ -1702,7 +1697,6 @@ static const struct snd_pcm_ops snd_cs46xx_playback_iec958_ops = {
 static const struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
        .open =                 snd_cs46xx_playback_open_iec958,
        .close =                snd_cs46xx_playback_close_iec958,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_playback_hw_params,
        .hw_free =              snd_cs46xx_playback_hw_free,
        .prepare =              snd_cs46xx_playback_prepare,
@@ -1716,7 +1710,6 @@ static const struct snd_pcm_ops snd_cs46xx_playback_indirect_iec958_ops = {
 static const struct snd_pcm_ops snd_cs46xx_playback_ops = {
        .open =                 snd_cs46xx_playback_open,
        .close =                snd_cs46xx_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_playback_hw_params,
        .hw_free =              snd_cs46xx_playback_hw_free,
        .prepare =              snd_cs46xx_playback_prepare,
@@ -1727,7 +1720,6 @@ static const struct snd_pcm_ops snd_cs46xx_playback_ops = {
 static const struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
        .open =                 snd_cs46xx_playback_open,
        .close =                snd_cs46xx_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_playback_hw_params,
        .hw_free =              snd_cs46xx_playback_hw_free,
        .prepare =              snd_cs46xx_playback_prepare,
@@ -1739,7 +1731,6 @@ static const struct snd_pcm_ops snd_cs46xx_playback_indirect_ops = {
 static const struct snd_pcm_ops snd_cs46xx_capture_ops = {
        .open =                 snd_cs46xx_capture_open,
        .close =                snd_cs46xx_capture_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_capture_hw_params,
        .hw_free =              snd_cs46xx_capture_hw_free,
        .prepare =              snd_cs46xx_capture_prepare,
@@ -1750,7 +1741,6 @@ static const struct snd_pcm_ops snd_cs46xx_capture_ops = {
 static const struct snd_pcm_ops snd_cs46xx_capture_indirect_ops = {
        .open =                 snd_cs46xx_capture_open,
        .close =                snd_cs46xx_capture_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_cs46xx_capture_hw_params,
        .hw_free =              snd_cs46xx_capture_hw_free,
        .prepare =              snd_cs46xx_capture_prepare,
@@ -2248,7 +2238,7 @@ static int snd_cs46xx_spdif_stream_put(struct snd_kcontrol *kcontrol,
 #endif /* CONFIG_SND_CS46XX_NEW_DSP */
 
 
-static struct snd_kcontrol_new snd_cs46xx_controls[] = {
+static const struct snd_kcontrol_new snd_cs46xx_controls[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "DAC Volume",
@@ -2374,7 +2364,7 @@ static const struct snd_kcontrol_new snd_cs46xx_front_dup_ctl = {
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
 /* Only available on the Hercules Game Theater XP soundcard */
-static struct snd_kcontrol_new snd_hercules_controls[] = {
+static const struct snd_kcontrol_new snd_hercules_controls[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Optical/Coaxial SPDIF Input Switch",
@@ -2475,7 +2465,7 @@ int snd_cs46xx_mixer(struct snd_cs46xx *chip, int spdif_device)
        struct snd_ctl_elem_id id;
        int err;
        unsigned int idx;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
                .reset = snd_cs46xx_codec_reset,
 #endif
@@ -2825,7 +2815,7 @@ static ssize_t snd_cs46xx_io_read(struct snd_info_entry *entry,
        return count;
 }
 
-static struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
+static const struct snd_info_entry_ops snd_cs46xx_proc_io_ops = {
        .read = snd_cs46xx_io_read,
 };
 
@@ -3755,7 +3745,7 @@ static struct cs_card_type cards[] = {
  * APM support
  */
 #ifdef CONFIG_PM_SLEEP
-static unsigned int saved_regs[] = {
+static const unsigned int saved_regs[] = {
        BA0_ACOSV,
        /*BA0_ASER_FADDR,*/
        BA0_ASER_MASTER,
@@ -3874,7 +3864,7 @@ int snd_cs46xx_create(struct snd_card *card,
        struct snd_cs46xx_region *region;
        struct cs_card_type *cp;
        u16 ss_card, ss_vendor;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_cs46xx_dev_free,
        };
        
@@ -3999,6 +3989,7 @@ int snd_cs46xx_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
 #ifdef CONFIG_SND_CS46XX_NEW_DSP
        chip->dsp_spos_instance = cs46xx_dsp_spos_create(chip);
index 887790a..05f3f6d 100644 (file)
@@ -27,7 +27,7 @@
 static int cs46xx_dsp_async_init (struct snd_cs46xx *chip,
                                  struct dsp_scb_descriptor * fg_entry);
 
-static enum wide_opcode wide_opcodes[] = { 
+static const enum wide_opcode wide_opcodes[] = {
        WIDE_FOR_BEGIN_LOOP,
        WIDE_FOR_BEGIN_LOOP2,
        WIDE_COND_GOTO_ADDR,
@@ -1038,7 +1038,7 @@ int cs46xx_dsp_scb_and_task_init (struct snd_cs46xx *chip)
        
        int fifo_addr, fifo_span, valid_slots;
 
-       static struct dsp_spos_control_block sposcb = {
+       static const struct dsp_spos_control_block sposcb = {
                /* 0 */ HFG_TREE_SCB,HFG_STACK,
                /* 1 */ SPOSCB_ADDR,BG_TREE_SCB_ADDR,
                /* 2 */ DSP_SPOS_DC,0,
index 715ead5..6b536fc 100644 (file)
@@ -1145,7 +1145,7 @@ find_next_free_scb (struct snd_cs46xx * chip, struct dsp_scb_descriptor * from)
        return scb;
 }
 
-static u32 pcm_reader_buffer_addr[DSP_MAX_PCM_CHANNELS] = {
+static const u32 pcm_reader_buffer_addr[DSP_MAX_PCM_CHANNELS] = {
        0x0600, /* 1 */
        0x1500, /* 2 */
        0x1580, /* 3 */
@@ -1180,7 +1180,7 @@ static u32 pcm_reader_buffer_addr[DSP_MAX_PCM_CHANNELS] = {
        0x2400, /* 32 */
 };
 
-static u32 src_output_buffer_addr[DSP_MAX_SRC_NR] = {
+static const u32 src_output_buffer_addr[DSP_MAX_SRC_NR] = {
        0x2B80,
        0x2BA0,
        0x2BC0,
@@ -1197,7 +1197,7 @@ static u32 src_output_buffer_addr[DSP_MAX_SRC_NR] = {
        0x2E20
 };
 
-static u32 src_delay_buffer_addr[DSP_MAX_SRC_NR] = {
+static const u32 src_delay_buffer_addr[DSP_MAX_SRC_NR] = {
        0x2480,
        0x2500,
        0x2580,
@@ -1293,7 +1293,7 @@ cs46xx_dsp_create_pcm_channel (struct snd_cs46xx * chip,
        if (src_scb == NULL) {
                if (ins->nsrc_scb >= DSP_MAX_SRC_NR) {
                        dev_err(chip->card->dev,
-                               "dsp_spos: to many SRC instances\n!");
+                               "dsp_spos: too many SRC instances\n!");
                        return NULL;
                }
 
index 3ab7ec5..20b4fae 100644 (file)
@@ -104,7 +104,7 @@ static int snd_cs5530_create(struct snd_card *card,
        void __iomem *mem;
        int err;
 
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_cs5530_dev_free,
        };
        *rchip = NULL;
index 68db7de..11ce3c4 100644 (file)
@@ -138,7 +138,7 @@ static int snd_cs5535audio_mixer(struct cs5535audio *cs5535au)
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_cs5535audio_ac97_codec_write,
                .read = snd_cs5535audio_ac97_codec_read,
        };
@@ -237,7 +237,6 @@ static irqreturn_t snd_cs5535audio_interrupt(int irq, void *dev_id)
 
 static int snd_cs5535audio_free(struct cs5535audio *cs5535au)
 {
-       synchronize_irq(cs5535au->irq);
        pci_set_power_state(cs5535au->pci, PCI_D3hot);
 
        if (cs5535au->irq >= 0)
@@ -262,7 +261,7 @@ static int snd_cs5535audio_create(struct snd_card *card,
        struct cs5535audio *cs5535au;
 
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_cs5535audio_dev_free,
        };
 
@@ -303,6 +302,7 @@ static int snd_cs5535audio_create(struct snd_card *card,
        }
 
        cs5535au->irq = pci->irq;
+       card->sync_irq = cs5535au->irq;
        pci_set_master(pci);
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
index bd246b1..4e29530 100644 (file)
@@ -111,7 +111,7 @@ static int olpc_mic_put(struct snd_kcontrol *kctl, struct snd_ctl_elem_value *v)
        return 1;
 }
 
-static struct snd_kcontrol_new olpc_cs5535audio_ctls[] = {
+static const struct snd_kcontrol_new olpc_cs5535audio_ctls[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "DC Mode Enable",
index 4642e53..4032b89 100644 (file)
@@ -236,10 +236,6 @@ static int snd_cs5535audio_hw_params(struct snd_pcm_substream *substream,
        struct cs5535audio_dma *dma = substream->runtime->private_data;
        int err;
 
-       err = snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        dma->buf_addr = substream->runtime->dma_addr;
        dma->buf_bytes = params_buffer_bytes(hw_params);
 
@@ -267,7 +263,7 @@ static int snd_cs5535audio_hw_free(struct snd_pcm_substream *substream)
                dma->pcm_open_flag = 0;
        }
        cs5535audio_clear_dma_packets(cs5535au, dma, substream);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int snd_cs5535audio_playback_prepare(struct snd_pcm_substream *substream)
@@ -370,7 +366,6 @@ static int snd_cs5535audio_capture_prepare(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_cs5535audio_playback_ops = {
        .open =         snd_cs5535audio_playback_open,
        .close =        snd_cs5535audio_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_cs5535audio_hw_params,
        .hw_free =      snd_cs5535audio_hw_free,
        .prepare =      snd_cs5535audio_playback_prepare,
@@ -381,7 +376,6 @@ static const struct snd_pcm_ops snd_cs5535audio_playback_ops = {
 static const struct snd_pcm_ops snd_cs5535audio_capture_ops = {
        .open =         snd_cs5535audio_capture_open,
        .close =        snd_cs5535audio_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_cs5535audio_hw_params,
        .hw_free =      snd_cs5535audio_hw_free,
        .prepare =      snd_cs5535audio_capture_prepare,
@@ -431,9 +425,9 @@ int snd_cs5535audio_pcm(struct cs5535audio *cs5535au)
        pcm->info_flags = 0;
        strcpy(pcm->name, "CS5535 Audio");
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &cs5535au->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &cs5535au->pci->dev,
+                                      64*1024, 128*1024);
        cs5535au->pcm = pcm;
 
        return 0;
index 055a71b..e56a230 100644 (file)
@@ -35,7 +35,7 @@
                            | (0x10 << 16) \
                            | ((IEC958_AES3_CON_FS_48000) << 24))
 
-static struct snd_pci_quirk subsys_20k1_list[] = {
+static const struct snd_pci_quirk subsys_20k1_list[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0022, "SB055x", CTSB055X),
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x002f, "SB055x", CTSB055X),
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, 0x0029, "SB073x", CTSB073X),
@@ -45,7 +45,7 @@ static struct snd_pci_quirk subsys_20k1_list[] = {
        { } /* terminator */
 };
 
-static struct snd_pci_quirk subsys_20k2_list[] = {
+static const struct snd_pci_quirk subsys_20k2_list[] = {
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB0760,
                      "SB0760", CTSB0760),
        SND_PCI_QUIRK(PCI_VENDOR_ID_CREATIVE, PCI_SUBDEVICE_ID_CREATIVE_SB1270,
@@ -1669,7 +1669,7 @@ int ct_atc_create(struct snd_card *card, struct pci_dev *pci,
                  struct ct_atc **ratc)
 {
        struct ct_atc *atc;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = atc_dev_free,
        };
        int err;
index 27441d4..4cb47b5 100644 (file)
@@ -29,7 +29,7 @@ struct daio_rsc_idx {
        unsigned short right;
 };
 
-static struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
+static const struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
        [LINEO1] = {.left = 0x00, .right = 0x01},
        [LINEO2] = {.left = 0x18, .right = 0x19},
        [LINEO3] = {.left = 0x08, .right = 0x09},
@@ -40,7 +40,7 @@ static struct daio_rsc_idx idx_20k1[NUM_DAIOTYP] = {
        [SPDIFI1] = {.left = 0x95, .right = 0x9d},
 };
 
-static struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
+static const struct daio_rsc_idx idx_20k2[NUM_DAIOTYP] = {
        [LINEO1] = {.left = 0x40, .right = 0x41},
        [LINEO2] = {.left = 0x60, .right = 0x61},
        [LINEO3] = {.left = 0x50, .right = 0x51},
index 4ff7ecd..6e3177b 100644 (file)
@@ -1937,6 +1937,7 @@ static int hw_card_start(struct hw *hw)
                        goto error2;
                }
                hw->irq = pci->irq;
+               hw->card->sync_irq = hw->irq;
        }
 
        pci_set_master(pci);
@@ -1962,9 +1963,6 @@ static int hw_card_stop(struct hw *hw)
        data = hw_read_20kx(hw, PLLCTL);
        hw_write_20kx(hw, PLLCTL, (data & (~(0x0F<<12))));
 
-       /* TODO: Disable interrupt and so on... */
-       if (hw->irq >= 0)
-               synchronize_irq(hw->irq);
        return 0;
 }
 
index 3cd4b7d..ce44cbe 100644 (file)
@@ -2061,6 +2061,7 @@ static int hw_card_start(struct hw *hw)
                        goto error2;
                }
                hw->irq = pci->irq;
+               hw->card->sync_irq = hw->irq;
        }
 
        pci_set_master(pci);
index 7ae5b23..6ee6a96 100644 (file)
@@ -178,15 +178,10 @@ static int ct_pcm_hw_params(struct snd_pcm_substream *substream,
 {
        struct ct_atc *atc = snd_pcm_substream_chip(substream);
        struct ct_atc_pcm *apcm = substream->runtime->private_data;
-       int err;
 
-       err = snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        /* clear previous resources */
        atc->pcm_release_resources(atc, apcm);
-       return err;
+       return 0;
 }
 
 static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
@@ -196,8 +191,7 @@ static int ct_pcm_hw_free(struct snd_pcm_substream *substream)
 
        /* clear previous resources */
        atc->pcm_release_resources(atc, apcm);
-       /* Free snd-allocated pages */
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 
@@ -373,7 +367,6 @@ ct_pcm_capture_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops ct_pcm_playback_ops = {
        .open           = ct_pcm_playback_open,
        .close          = ct_pcm_playback_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = ct_pcm_hw_params,
        .hw_free        = ct_pcm_hw_free,
        .prepare        = ct_pcm_playback_prepare,
@@ -385,7 +378,6 @@ static const struct snd_pcm_ops ct_pcm_playback_ops = {
 static const struct snd_pcm_ops ct_pcm_capture_ops = {
        .open           = ct_pcm_capture_open,
        .close          = ct_pcm_capture_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = ct_pcm_hw_params,
        .hw_free        = ct_pcm_hw_free,
        .prepare        = ct_pcm_capture_prepare,
@@ -449,9 +441,8 @@ int ct_alsa_pcm_create(struct ct_atc *atc,
                snd_pcm_set_ops(pcm,
                                SNDRV_PCM_STREAM_CAPTURE, &ct_pcm_capture_ops);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &atc->pci->dev,
-                                             128*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &atc->pci->dev, 128*1024, 128*1024);
 
        chs = 2;
        switch (device) {
index 0bb5696..61e51e3 100644 (file)
@@ -92,7 +92,7 @@ int mgr_put_resource(struct rsc_mgr *mgr, unsigned int n, unsigned int idx)
        return 0;
 }
 
-static unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
+static const unsigned char offset_in_audio_slot_block[NUM_RSCTYP] = {
        /* SRC channel is at Audio Ring slot 1 every 16 slots. */
        [SRC]           = 0x1,
        [AMIXER]        = 0x4,
index 0f1c65d..e295c71 100644 (file)
@@ -56,7 +56,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 6dd7bfd..ae816e7 100644 (file)
@@ -61,7 +61,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 8a03c4b..3d37bb4 100644 (file)
@@ -74,7 +74,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 1465813..565c5a3 100644 (file)
@@ -23,7 +23,7 @@ MODULE_PARM_DESC(id, "ID string for " ECHOCARD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard.");
 
-static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999};
+static const unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999};
 static const DECLARE_TLV_DB_SCALE(db_scale_output_gain, -12800, 100, 1);
 
 
@@ -547,16 +547,6 @@ static int init_engine(struct snd_pcm_substream *substream,
                "pcm_hw_params (bufsize=%dB periods=%d persize=%dB)\n",
                params_buffer_bytes(hw_params), params_periods(hw_params),
                params_period_bytes(hw_params));
-       err = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-       if (err < 0) {
-               dev_err(chip->card->dev, "malloc_pages err=%d\n", err);
-               spin_lock_irq(&chip->lock);
-               free_pipes(chip, pipe);
-               spin_unlock_irq(&chip->lock);
-               pipe->index = -1;
-               return err;
-       }
 
        sglist_init(chip, pipe);
        edge = PAGE_SIZE;
@@ -671,7 +661,6 @@ static int pcm_hw_free(struct snd_pcm_substream *substream)
        }
        spin_unlock_irq(&chip->lock);
 
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -818,7 +807,6 @@ static snd_pcm_uframes_t pcm_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops analog_playback_ops = {
        .open = pcm_analog_out_open,
        .close = pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = pcm_analog_out_hw_params,
        .hw_free = pcm_hw_free,
        .prepare = pcm_prepare,
@@ -828,7 +816,6 @@ static const struct snd_pcm_ops analog_playback_ops = {
 static const struct snd_pcm_ops analog_capture_ops = {
        .open = pcm_analog_in_open,
        .close = pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = pcm_analog_in_hw_params,
        .hw_free = pcm_hw_free,
        .prepare = pcm_prepare,
@@ -840,7 +827,6 @@ static const struct snd_pcm_ops analog_capture_ops = {
 static const struct snd_pcm_ops digital_playback_ops = {
        .open = pcm_digital_out_open,
        .close = pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = pcm_digital_out_hw_params,
        .hw_free = pcm_hw_free,
        .prepare = pcm_prepare,
@@ -851,7 +837,6 @@ static const struct snd_pcm_ops digital_playback_ops = {
 static const struct snd_pcm_ops digital_capture_ops = {
        .open = pcm_digital_in_open,
        .close = pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = pcm_digital_in_hw_params,
        .hw_free = pcm_hw_free,
        .prepare = pcm_prepare,
@@ -872,10 +857,10 @@ static void snd_echo_preallocate_pages(struct snd_pcm *pcm, struct device *dev)
 
        for (stream = 0; stream < 2; stream++)
                for (ss = pcm->streams[stream].substream; ss; ss = ss->next)
-                       snd_pcm_lib_preallocate_pages(ss, SNDRV_DMA_TYPE_DEV_SG,
-                                                     dev,
-                                                     ss->number ? 0 : 128<<10,
-                                                     256<<10);
+                       snd_pcm_set_managed_buffer(ss, SNDRV_DMA_TYPE_DEV_SG,
+                                                  dev,
+                                                  ss->number ? 0 : 128<<10,
+                                                  256<<10);
 }
 
 
@@ -1245,15 +1230,10 @@ static const struct snd_kcontrol_new snd_echo_intput_nominal_level = {
 static int snd_echo_mixer_info(struct snd_kcontrol *kcontrol,
                               struct snd_ctl_elem_info *uinfo)
 {
-       struct echoaudio *chip;
-
-       chip = snd_kcontrol_chip(kcontrol);
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 1;
        uinfo->value.integer.min = ECHOGAIN_MINOUT;
        uinfo->value.integer.max = ECHOGAIN_MAXOUT;
-       uinfo->dimen.d[0] = num_busses_out(chip);
-       uinfo->dimen.d[1] = num_busses_in(chip);
        return 0;
 }
 
@@ -1317,15 +1297,10 @@ static struct snd_kcontrol_new snd_echo_monitor_mixer = {
 static int snd_echo_vmixer_info(struct snd_kcontrol *kcontrol,
                                struct snd_ctl_elem_info *uinfo)
 {
-       struct echoaudio *chip;
-
-       chip = snd_kcontrol_chip(kcontrol);
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 1;
        uinfo->value.integer.min = ECHOGAIN_MINOUT;
        uinfo->value.integer.max = ECHOGAIN_MAXOUT;
-       uinfo->dimen.d[0] = num_busses_out(chip);
-       uinfo->dimen.d[1] = num_pipes_out(chip);
        return 0;
 }
 
@@ -1708,13 +1683,6 @@ static int snd_echo_vumeters_info(struct snd_kcontrol *kcontrol,
        uinfo->count = 96;
        uinfo->value.integer.min = ECHOGAIN_MINOUT;
        uinfo->value.integer.max = 0;
-#ifdef ECHOCARD_HAS_VMIXER
-       uinfo->dimen.d[0] = 3;  /* Out, In, Virt */
-#else
-       uinfo->dimen.d[0] = 2;  /* Out, In */
-#endif
-       uinfo->dimen.d[1] = 16; /* 16 channels */
-       uinfo->dimen.d[2] = 2;  /* 0=level, 1=peak */
        return 0;
 }
 
@@ -1882,7 +1850,7 @@ static int snd_echo_create(struct snd_card *card,
        struct echoaudio *chip;
        int err;
        size_t sz;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_echo_dev_free,
        };
 
@@ -1943,6 +1911,7 @@ static int snd_echo_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        dev_dbg(card->dev, "pci=%p irq=%d subdev=%04x Init hardware...\n",
                chip->pci, chip->irq, chip->pci->subsystem_device);
 
@@ -2166,6 +2135,7 @@ static int snd_echo_suspend(struct device *dev)
        chip->dsp_code = NULL;
        free_irq(chip->irq, chip);
        chip->irq = -1;
+       chip->card->sync_irq = -1;
        return 0;
 }
 
@@ -2219,6 +2189,7 @@ static int snd_echo_resume(struct device *dev)
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       chip->card->sync_irq = chip->irq;
        dev_dbg(dev, "resume irq=%d\n", chip->irq);
 
 #ifdef ECHOCARD_HAS_MIDI
index 50d4a87..f02f5b1 100644 (file)
@@ -635,36 +635,30 @@ This function assumes there are no more than 16 in/out busses or pipes
 Meters is an array [3][16][2] of long. */
 static void get_audio_meters(struct echoaudio *chip, long *meters)
 {
-       int i, m, n;
+       unsigned int i, m, n;
 
-       m = 0;
-       n = 0;
-       for (i = 0; i < num_busses_out(chip); i++, m++) {
+       for (i = 0 ; i < 96; i++)
+               meters[i] = 0;
+
+       for (m = 0, n = 0, i = 0; i < num_busses_out(chip); i++, m++) {
                meters[n++] = chip->comm_page->vu_meter[m];
                meters[n++] = chip->comm_page->peak_meter[m];
        }
-       for (; n < 32; n++)
-               meters[n] = 0;
 
 #ifdef ECHOCARD_ECHO3G
        m = E3G_MAX_OUTPUTS;    /* Skip unused meters */
 #endif
 
-       for (i = 0; i < num_busses_in(chip); i++, m++) {
+       for (n = 32, i = 0; i < num_busses_in(chip); i++, m++) {
                meters[n++] = chip->comm_page->vu_meter[m];
                meters[n++] = chip->comm_page->peak_meter[m];
        }
-       for (; n < 64; n++)
-               meters[n] = 0;
-
 #ifdef ECHOCARD_HAS_VMIXER
-       for (i = 0; i < num_pipes_out(chip); i++, m++) {
+       for (n = 64, i = 0; i < num_pipes_out(chip); i++, m++) {
                meters[n++] = chip->comm_page->vu_meter[m];
                meters[n++] = chip->comm_page->peak_meter[m];
        }
 #endif
-       for (; n < 96; n++)
-               meters[n] = 0;
 }
 
 
index fa1208f..4f864dd 100644 (file)
@@ -60,7 +60,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 3089c32..eff69e8 100644 (file)
@@ -81,7 +81,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 0e85070..a9f2efc 100644 (file)
@@ -61,7 +61,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 0ad0221..14e9769 100644 (file)
@@ -61,7 +61,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 38f17d3..a14a7dc 100644 (file)
@@ -61,7 +61,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 29e0137..97e0244 100644 (file)
@@ -62,7 +62,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index f5c9ef6..a017c96 100644 (file)
@@ -62,7 +62,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 74906c3..7e38bc9 100644 (file)
@@ -70,7 +70,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 6974232..95c5221 100644 (file)
@@ -80,7 +80,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index ee9722d..a2d4b00 100644 (file)
@@ -71,7 +71,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 3e5747e..1b45a2b 100644 (file)
@@ -90,7 +90,7 @@ static const struct pci_device_id snd_echo_ids[] = {
        {0,}
 };
 
-static struct snd_pcm_hardware pcm_hardware_skel = {
+static const struct snd_pcm_hardware pcm_hardware_skel = {
        .info = SNDRV_PCM_INFO_MMAP |
                SNDRV_PCM_INFO_INTERLEAVED |
                SNDRV_PCM_INFO_BLOCK_TRANSFER |
index 8c1e968..a89a7e6 100644 (file)
@@ -100,7 +100,7 @@ void snd_emu10k1_voice_init(struct snd_emu10k1 *emu, int ch)
        }
 }
 
-static unsigned int spi_dac_init[] = {
+static const unsigned int spi_dac_init[] = {
                0x00ff,
                0x02ff,
                0x0400,
@@ -124,7 +124,7 @@ static unsigned int spi_dac_init[] = {
                0x1400,
 };
 
-static unsigned int i2c_adc_init[][2] = {
+static const unsigned int i2c_adc_init[][2] = {
        { 0x17, 0x00 }, /* Reset */
        { 0x07, 0x00 }, /* Timeout */
        { 0x0b, 0x22 },  /* Interface control */
@@ -1283,7 +1283,7 @@ static int snd_emu10k1_dev_free(struct snd_device *device)
        return snd_emu10k1_free(emu);
 }
 
-static struct snd_emu_chip_details emu_chip_details[] = {
+static const struct snd_emu_chip_details emu_chip_details[] = {
        /* Audigy 5/Rx SB1550 */
        /* Tested by michael@gernoth.net 28 Mar 2015 */
        /* DSP: CA10300-IAT LF
@@ -1791,7 +1791,7 @@ int snd_emu10k1_create(struct snd_card *card,
        size_t page_table_size;
        unsigned int silent_page;
        const struct snd_emu_chip_details *c;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_emu10k1_dev_free,
        };
 
@@ -1984,6 +1984,7 @@ int snd_emu10k1_create(struct snd_card *card,
                goto error;
        }
        emu->irq = pci->irq;
+       card->sync_irq = emu->irq;
 
        /*
         *  Init to 0x02109204 :
@@ -2049,7 +2050,7 @@ int snd_emu10k1_create(struct snd_card *card,
 }
 
 #ifdef CONFIG_PM_SLEEP
-static unsigned char saved_regs[] = {
+static const unsigned char saved_regs[] = {
        CPF, PTRX, CVCF, VTFT, Z1, Z2, PSST, DSL, CCCA, CCR, CLP,
        FXRT, MAPA, MAPB, ENVVOL, ATKHLDV, DCYSUSV, LFOVAL1, ENVVAL,
        ATKHLDM, DCYSUSM, LFOVAL2, IP, IFATN, PEFE, FMMOD, TREMFRQ, FM2FRQ2,
@@ -2058,7 +2059,7 @@ static unsigned char saved_regs[] = {
        SPBYPASS, AC97SLOT, CDSRCS, GPSRCS, ZVSRCS, MICIDX, ADCIDX, FXIDX,
        0xff /* end */
 };
-static unsigned char saved_regs_audigy[] = {
+static const unsigned char saved_regs_audigy[] = {
        A_ADCIDX, A_MICIDX, A_FXWC1, A_FXWC2, A_SAMPLE_RATE,
        A_FXRT2, A_SENDAMOUNTS, A_FXRT1,
        0xff /* end */
@@ -2093,7 +2094,7 @@ static void free_pm_buffer(struct snd_emu10k1 *emu)
 void snd_emu10k1_suspend_regs(struct snd_emu10k1 *emu)
 {
        int i;
-       unsigned char *reg;
+       const unsigned char *reg;
        unsigned int *val;
 
        val = emu->saved_ptr;
@@ -2126,7 +2127,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
 void snd_emu10k1_resume_regs(struct snd_emu10k1 *emu)
 {
        int i;
-       unsigned char *reg;
+       const unsigned char *reg;
        unsigned int *val;
 
        snd_emu10k1_audio_enable(emu);
index 241b4a0..ddb7c2c 100644 (file)
@@ -411,8 +411,7 @@ static int snd_emu10k1x_pcm_hw_params(struct snd_pcm_substream *substream,
                epcm->voice->epcm = epcm;
        }
 
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
+       return 0;
 }
 
 /* hw_free callback */
@@ -432,7 +431,7 @@ static int snd_emu10k1x_pcm_hw_free(struct snd_pcm_substream *substream)
                epcm->voice = NULL;
        }
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 /* prepare callback */
@@ -537,7 +536,6 @@ snd_emu10k1x_pcm_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_emu10k1x_playback_ops = {
        .open =        snd_emu10k1x_playback_open,
        .close =       snd_emu10k1x_playback_close,
-       .ioctl =       snd_pcm_lib_ioctl,
        .hw_params =   snd_emu10k1x_pcm_hw_params,
        .hw_free =     snd_emu10k1x_pcm_hw_free,
        .prepare =     snd_emu10k1x_pcm_prepare,
@@ -594,8 +592,7 @@ static int snd_emu10k1x_pcm_hw_params_capture(struct snd_pcm_substream *substrea
                epcm->voice->use = 1;
        }
 
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
+       return 0;
 }
 
 /* hw_free callback */
@@ -615,7 +612,7 @@ static int snd_emu10k1x_pcm_hw_free_capture(struct snd_pcm_substream *substream)
                epcm->voice = NULL;
        }
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 /* prepare capture callback */
@@ -683,7 +680,6 @@ snd_emu10k1x_pcm_pointer_capture(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_emu10k1x_capture_ops = {
        .open =        snd_emu10k1x_pcm_open_capture,
        .close =       snd_emu10k1x_pcm_close_capture,
-       .ioctl =       snd_pcm_lib_ioctl,
        .hw_params =   snd_emu10k1x_pcm_hw_params_capture,
        .hw_free =     snd_emu10k1x_pcm_hw_free_capture,
        .prepare =     snd_emu10k1x_pcm_prepare_capture,
@@ -722,7 +718,7 @@ static int snd_emu10k1x_ac97(struct emu10k1x *chip)
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_emu10k1x_ac97_write,
                .read = snd_emu10k1x_ac97_read,
        };
@@ -876,9 +872,8 @@ static int snd_emu10k1x_pcm(struct emu10k1x *emu, int device)
        }
        emu->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &emu->pci->dev,
-                                             32*1024, 32*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &emu->pci->dev, 32*1024, 32*1024);
   
        return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK, map, 2,
                                     1 << 2, NULL);
@@ -891,7 +886,7 @@ static int snd_emu10k1x_create(struct snd_card *card,
        struct emu10k1x *chip;
        int err;
        int ch;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_emu10k1x_dev_free,
        };
 
@@ -935,6 +930,7 @@ static int snd_emu10k1x_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
   
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
                                4 * 1024, &chip->dma_buffer) < 0) {
index a31adec..4e76ed0 100644 (file)
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(high_res_gpr_volume, "GPR mixer controls use 31-bit range.");
  *  Tables
  */ 
 
-static char *fxbuses[16] = {
+static const char * const fxbuses[16] = {
        /* 0x00 */ "PCM Left",
        /* 0x01 */ "PCM Right",
        /* 0x02 */ "PCM Surround Left",
@@ -65,7 +65,7 @@ static char *fxbuses[16] = {
        /* 0x0f */ NULL
 };
 
-static char *creative_ins[16] = {
+static const char * const creative_ins[16] = {
        /* 0x00 */ "AC97 Left",
        /* 0x01 */ "AC97 Right",
        /* 0x02 */ "TTL IEC958 Left",
@@ -84,7 +84,7 @@ static char *creative_ins[16] = {
        /* 0x0f */ NULL
 };
 
-static char *audigy_ins[16] = {
+static const char * const audigy_ins[16] = {
        /* 0x00 */ "AC97 Left",
        /* 0x01 */ "AC97 Right",
        /* 0x02 */ "Audigy CD Left",
@@ -103,7 +103,7 @@ static char *audigy_ins[16] = {
        /* 0x0f */ NULL
 };
 
-static char *creative_outs[32] = {
+static const char * const creative_outs[32] = {
        /* 0x00 */ "AC97 Left",
        /* 0x01 */ "AC97 Right",
        /* 0x02 */ "Optical IEC958 Left",
@@ -138,7 +138,7 @@ static char *creative_outs[32] = {
        /* 0x1f */ NULL,
 };
 
-static char *audigy_outs[32] = {
+static const char * const audigy_outs[32] = {
        /* 0x00 */ "Digital Front Left",
        /* 0x01 */ "Digital Front Right",
        /* 0x02 */ "Digital Center",
@@ -463,7 +463,7 @@ static void snd_emu10k1_write_op(struct snd_emu10k1_fx8010_code *icode,
        u_int32_t *code;
        if (snd_BUG_ON(*ptr >= 512))
                return;
-       code = (u_int32_t __force *)icode->code + (*ptr) * 2;
+       code = icode->code + (*ptr) * 2;
        set_bit(*ptr, icode->code_valid);
        code[0] = ((x & 0x3ff) << 10) | (y & 0x3ff);
        code[1] = ((op & 0x0f) << 20) | ((r & 0x3ff) << 10) | (a & 0x3ff);
@@ -480,7 +480,7 @@ static void snd_emu10k1_audigy_write_op(struct snd_emu10k1_fx8010_code *icode,
        u_int32_t *code;
        if (snd_BUG_ON(*ptr >= 1024))
                return;
-       code = (u_int32_t __force *)icode->code + (*ptr) * 2;
+       code = icode->code + (*ptr) * 2;
        set_bit(*ptr, icode->code_valid);
        code[0] = ((x & 0x7ff) << 12) | (y & 0x7ff);
        code[1] = ((op & 0x0f) << 24) | ((r & 0x7ff) << 12) | (a & 0x7ff);
@@ -513,8 +513,8 @@ static int snd_emu10k1_gpr_poke(struct snd_emu10k1 *emu,
                if (!test_bit(gpr, icode->gpr_valid))
                        continue;
                if (in_kernel)
-                       val = *(__force u32 *)&icode->gpr_map[gpr];
-               else if (get_user(val, &icode->gpr_map[gpr]))
+                       val = icode->gpr_map[gpr];
+               else if (get_user(val, (__user u32 *)&icode->gpr_map[gpr]))
                        return -EFAULT;
                snd_emu10k1_ptr_write(emu, emu->gpr_base + gpr, 0, val);
        }
@@ -530,7 +530,7 @@ static int snd_emu10k1_gpr_peek(struct snd_emu10k1 *emu,
        for (gpr = 0; gpr < (emu->audigy ? 0x200 : 0x100); gpr++) {
                set_bit(gpr, icode->gpr_valid);
                val = snd_emu10k1_ptr_read(emu, emu->gpr_base + gpr, 0);
-               if (put_user(val, &icode->gpr_map[gpr]))
+               if (put_user(val, (__user u32 *)&icode->gpr_map[gpr]))
                        return -EFAULT;
        }
        return 0;
@@ -547,11 +547,11 @@ static int snd_emu10k1_tram_poke(struct snd_emu10k1 *emu,
                if (!test_bit(tram, icode->tram_valid))
                        continue;
                if (in_kernel) {
-                       val = *(__force u32 *)&icode->tram_data_map[tram];
-                       addr = *(__force u32 *)&icode->tram_addr_map[tram];
+                       val = icode->tram_data_map[tram];
+                       addr = icode->tram_addr_map[tram];
                } else {
-                       if (get_user(val, &icode->tram_data_map[tram]) ||
-                           get_user(addr, &icode->tram_addr_map[tram]))
+                       if (get_user(val, (__user __u32 *)&icode->tram_data_map[tram]) ||
+                           get_user(addr, (__user __u32 *)&icode->tram_addr_map[tram]))
                                return -EFAULT;
                }
                snd_emu10k1_ptr_write(emu, TANKMEMDATAREGBASE + tram, 0, val);
@@ -581,8 +581,8 @@ static int snd_emu10k1_tram_peek(struct snd_emu10k1 *emu,
                        addr = snd_emu10k1_ptr_read(emu, TANKMEMADDRREGBASE + tram, 0) >> 12;
                        addr |= snd_emu10k1_ptr_read(emu, A_TANKMEMCTLREGBASE + tram, 0) << 20;
                }
-               if (put_user(val, &icode->tram_data_map[tram]) ||
-                   put_user(addr, &icode->tram_addr_map[tram]))
+               if (put_user(val, (__user u32 *)&icode->tram_data_map[tram]) ||
+                   put_user(addr, (__user u32 *)&icode->tram_addr_map[tram]))
                        return -EFAULT;
        }
        return 0;
@@ -598,11 +598,11 @@ static int snd_emu10k1_code_poke(struct snd_emu10k1 *emu,
                if (!test_bit(pc / 2, icode->code_valid))
                        continue;
                if (in_kernel) {
-                       lo = *(__force u32 *)&icode->code[pc + 0];
-                       hi = *(__force u32 *)&icode->code[pc + 1];
+                       lo = icode->code[pc + 0];
+                       hi = icode->code[pc + 1];
                } else {
-                       if (get_user(lo, &icode->code[pc + 0]) ||
-                           get_user(hi, &icode->code[pc + 1]))
+                       if (get_user(lo, (__user u32 *)&icode->code[pc + 0]) ||
+                           get_user(hi, (__user u32 *)&icode->code[pc + 1]))
                                return -EFAULT;
                }
                snd_emu10k1_efx_write(emu, pc + 0, lo);
@@ -619,17 +619,21 @@ static int snd_emu10k1_code_peek(struct snd_emu10k1 *emu,
        memset(icode->code_valid, 0, sizeof(icode->code_valid));
        for (pc = 0; pc < (emu->audigy ? 2*1024 : 2*512); pc += 2) {
                set_bit(pc / 2, icode->code_valid);
-               if (put_user(snd_emu10k1_efx_read(emu, pc + 0), &icode->code[pc + 0]))
+               if (put_user(snd_emu10k1_efx_read(emu, pc + 0),
+                            (__user u32 *)&icode->code[pc + 0]))
                        return -EFAULT;
-               if (put_user(snd_emu10k1_efx_read(emu, pc + 1), &icode->code[pc + 1]))
+               if (put_user(snd_emu10k1_efx_read(emu, pc + 1),
+                            (__user u32 *)&icode->code[pc + 1]))
                        return -EFAULT;
        }
        return 0;
 }
 
 static struct snd_emu10k1_fx8010_ctl *
-snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id)
+snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu,
+                        struct emu10k1_ctl_elem_id *_id)
 {
+       struct snd_ctl_elem_id *id = (struct snd_ctl_elem_id *)_id;
        struct snd_emu10k1_fx8010_ctl *ctl;
        struct snd_kcontrol *kcontrol;
 
@@ -672,41 +676,60 @@ static unsigned int *copy_tlv(const unsigned int __user *_tlv, bool in_kernel)
 }
 
 static int copy_gctl(struct snd_emu10k1 *emu,
-                    struct snd_emu10k1_fx8010_control_gpr *gctl,
-                    struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
+                    struct snd_emu10k1_fx8010_control_gpr *dst,
+                    struct snd_emu10k1_fx8010_control_gpr *src,
                     int idx, bool in_kernel)
 {
-       struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
+       struct snd_emu10k1_fx8010_control_gpr __user *_src;
+       struct snd_emu10k1_fx8010_control_old_gpr *octl;
+       struct snd_emu10k1_fx8010_control_old_gpr __user *_octl;
 
+       _src = (struct snd_emu10k1_fx8010_control_gpr __user *)src;
        if (emu->support_tlv) {
                if (in_kernel)
-                       memcpy(gctl, (__force void *)&_gctl[idx], sizeof(*gctl));
-               else if (copy_from_user(gctl, &_gctl[idx], sizeof(*gctl)))
+                       *dst = src[idx];
+               else if (copy_from_user(dst, &_src[idx], sizeof(*src)))
                        return -EFAULT;
                return 0;
        }
 
-       octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
+       octl = (struct snd_emu10k1_fx8010_control_old_gpr *)src;
+       _octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)octl;
        if (in_kernel)
-               memcpy(gctl, (__force void *)&octl[idx], sizeof(*octl));
-       else if (copy_from_user(gctl, &octl[idx], sizeof(*octl)))
+               memcpy(dst, &octl[idx], sizeof(*octl));
+       else if (copy_from_user(dst, &_octl[idx], sizeof(*octl)))
                return -EFAULT;
-       gctl->tlv = NULL;
+       dst->tlv = NULL;
        return 0;
 }
 
 static int copy_gctl_to_user(struct snd_emu10k1 *emu,
-                    struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
-                    struct snd_emu10k1_fx8010_control_gpr *gctl,
+                    struct snd_emu10k1_fx8010_control_gpr *dst,
+                    struct snd_emu10k1_fx8010_control_gpr *src,
                     int idx)
 {
+       struct snd_emu10k1_fx8010_control_gpr __user *_dst;
        struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
 
+       _dst = (struct snd_emu10k1_fx8010_control_gpr __user *)dst;
        if (emu->support_tlv)
-               return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl));
+               return copy_to_user(&_dst[idx], src, sizeof(*src));
        
-       octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
-       return copy_to_user(&octl[idx], gctl, sizeof(*octl));
+       octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)dst;
+       return copy_to_user(&octl[idx], src, sizeof(*octl));
+}
+
+static int copy_ctl_elem_id(const struct emu10k1_ctl_elem_id *list, int i,
+                           struct emu10k1_ctl_elem_id *ret, bool in_kernel)
+{
+       struct emu10k1_ctl_elem_id __user *_id =
+               (struct emu10k1_ctl_elem_id __user *)&list[i];
+
+       if (in_kernel)
+               *ret = list[i];
+       else if (copy_from_user(ret, _id, sizeof(*ret)))
+               return -EFAULT;
+       return 0;
 }
 
 static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
@@ -714,17 +737,16 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
                                       bool in_kernel)
 {
        unsigned int i;
-       struct snd_ctl_elem_id __user *_id;
-       struct snd_ctl_elem_id id;
+       struct emu10k1_ctl_elem_id id;
        struct snd_emu10k1_fx8010_control_gpr *gctl;
+       struct snd_ctl_elem_id *gctl_id;
        int err;
        
-       for (i = 0, _id = icode->gpr_del_controls;
-            i < icode->gpr_del_control_count; i++, _id++) {
-               if (in_kernel)
-                       id = *(__force struct snd_ctl_elem_id *)_id;
-               else if (copy_from_user(&id, _id, sizeof(id)))
-                       return -EFAULT;
+       for (i = 0; i < icode->gpr_del_control_count; i++) {
+               err = copy_ctl_elem_id(icode->gpr_del_controls, i, &id,
+                                      in_kernel);
+               if (err < 0)
+                       return err;
                if (snd_emu10k1_look_for_ctl(emu, &id) == NULL)
                        return -ENOENT;
        }
@@ -740,15 +762,16 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
                }
                if (snd_emu10k1_look_for_ctl(emu, &gctl->id))
                        continue;
+               gctl_id = (struct snd_ctl_elem_id *)&gctl->id;
                down_read(&emu->card->controls_rwsem);
-               if (snd_ctl_find_id(emu->card, &gctl->id) != NULL) {
+               if (snd_ctl_find_id(emu->card, gctl_id)) {
                        up_read(&emu->card->controls_rwsem);
                        err = -EEXIST;
                        goto __error;
                }
                up_read(&emu->card->controls_rwsem);
-               if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
-                   gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
+               if (gctl_id->iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
+                   gctl_id->iface != SNDRV_CTL_ELEM_IFACE_PCM) {
                        err = -EINVAL;
                        goto __error;
                }
@@ -783,6 +806,7 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
 {
        unsigned int i, j;
        struct snd_emu10k1_fx8010_control_gpr *gctl;
+       struct snd_ctl_elem_id *gctl_id;
        struct snd_emu10k1_fx8010_ctl *ctl, *nctl;
        struct snd_kcontrol_new knew;
        struct snd_kcontrol *kctl;
@@ -803,24 +827,25 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
                        err = -EFAULT;
                        goto __error;
                }
-               if (gctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
-                   gctl->id.iface != SNDRV_CTL_ELEM_IFACE_PCM) {
+               gctl_id = (struct snd_ctl_elem_id *)&gctl->id;
+               if (gctl_id->iface != SNDRV_CTL_ELEM_IFACE_MIXER &&
+                   gctl_id->iface != SNDRV_CTL_ELEM_IFACE_PCM) {
                        err = -EINVAL;
                        goto __error;
                }
-               if (! gctl->id.name[0]) {
+               if (!*gctl_id->name) {
                        err = -EINVAL;
                        goto __error;
                }
                ctl = snd_emu10k1_look_for_ctl(emu, &gctl->id);
                memset(&knew, 0, sizeof(knew));
-               knew.iface = gctl->id.iface;
-               knew.name = gctl->id.name;
-               knew.index = gctl->id.index;
-               knew.device = gctl->id.device;
-               knew.subdevice = gctl->id.subdevice;
+               knew.iface = gctl_id->iface;
+               knew.name = gctl_id->name;
+               knew.index = gctl_id->index;
+               knew.device = gctl_id->device;
+               knew.subdevice = gctl_id->subdevice;
                knew.info = snd_emu10k1_gpr_ctl_info;
-               knew.tlv.p = copy_tlv((__force const unsigned int __user *)gctl->tlv, in_kernel);
+               knew.tlv.p = copy_tlv((const unsigned int __user *)gctl->tlv, in_kernel);
                if (knew.tlv.p)
                        knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
                                SNDRV_CTL_ELEM_ACCESS_TLV_READ;
@@ -876,17 +901,16 @@ static int snd_emu10k1_del_controls(struct snd_emu10k1 *emu,
                                    bool in_kernel)
 {
        unsigned int i;
-       struct snd_ctl_elem_id id;
-       struct snd_ctl_elem_id __user *_id;
+       struct emu10k1_ctl_elem_id id;
        struct snd_emu10k1_fx8010_ctl *ctl;
        struct snd_card *card = emu->card;
+       int err;
        
-       for (i = 0, _id = icode->gpr_del_controls;
-            i < icode->gpr_del_control_count; i++, _id++) {
-               if (in_kernel)
-                       id = *(__force struct snd_ctl_elem_id *)_id;
-               else if (copy_from_user(&id, _id, sizeof(id)))
-                       return -EFAULT;
+       for (i = 0; i < icode->gpr_del_control_count; i++) {
+               err = copy_ctl_elem_id(icode->gpr_del_controls, i, &id,
+                                      in_kernel);
+               if (err < 0)
+                       return err;
                down_write(&card->controls_rwsem);
                ctl = snd_emu10k1_look_for_ctl(emu, &id);
                if (ctl)
@@ -915,7 +939,7 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
                    i < icode->gpr_list_control_count) {
                        memset(gctl, 0, sizeof(*gctl));
                        id = &ctl->kcontrol->id;
-                       gctl->id.iface = id->iface;
+                       gctl->id.iface = (__force int)id->iface;
                        strlcpy(gctl->id.name, id->name, sizeof(gctl->id.name));
                        gctl->id.index = id->index;
                        gctl->id.device = id->device;
@@ -1093,7 +1117,7 @@ static void
 snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
                              const char *name, int gpr, int defval)
 {
-       ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(ctl->id.name, name);
        ctl->vcount = ctl->count = 1;
        ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
@@ -1114,7 +1138,7 @@ static void
 snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
                                const char *name, int gpr, int defval)
 {
-       ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(ctl->id.name, name);
        ctl->vcount = ctl->count = 2;
        ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
@@ -1136,7 +1160,7 @@ static void
 snd_emu10k1_init_mono_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
                                    const char *name, int gpr, int defval)
 {
-       ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(ctl->id.name, name);
        ctl->vcount = ctl->count = 1;
        ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
@@ -1149,7 +1173,7 @@ static void
 snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
                                      const char *name, int gpr, int defval)
 {
-       ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(ctl->id.name, name);
        ctl->vcount = ctl->count = 2;
        ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
@@ -1202,8 +1226,8 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
        if (!icode)
                return err;
 
-       icode->gpr_map = (u_int32_t __user *) kcalloc(512 + 256 + 256 + 2 * 1024,
-                                                     sizeof(u_int32_t), GFP_KERNEL);
+       icode->gpr_map = kcalloc(512 + 256 + 256 + 2 * 1024,
+                                sizeof(u_int32_t), GFP_KERNEL);
        if (!icode->gpr_map)
                goto __err_gpr;
        controls = kcalloc(SND_EMU10K1_GPR_CONTROLS,
@@ -1211,7 +1235,7 @@ static int _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
        if (!controls)
                goto __err_ctrls;
 
-       gpr_map = (u32 __force *)icode->gpr_map;
+       gpr_map = icode->gpr_map;
 
        icode->tram_data_map = icode->gpr_map + 512;
        icode->tram_addr_map = icode->tram_data_map + 256;
@@ -1466,7 +1490,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        
 
        ctl = &controls[nctl + 0];
-       ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(ctl->id.name, "Tone Control - Bass");
        ctl->vcount = 2;
        ctl->count = 10;
@@ -1475,7 +1499,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
        ctl->value[0] = ctl->value[1] = 20;
        ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
        ctl = &controls[nctl + 1];
-       ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(ctl->id.name, "Tone Control - Treble");
        ctl->vcount = 2;
        ctl->count = 10;
@@ -1756,7 +1780,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
                A_OP(icode, &ptr, 0x0f, 0xc0, 0xc0, 0xcf, 0xc0);
 
        icode->gpr_add_control_count = nctl;
-       icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
+       icode->gpr_add_controls = controls;
        emu->support_tlv = 1; /* support TLV */
        err = snd_emu10k1_icode_poke(emu, icode, true);
        emu->support_tlv = 0; /* clear again */
@@ -1764,7 +1788,7 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
 __err:
        kfree(controls);
 __err_ctrls:
-       kfree((void __force *)icode->gpr_map);
+       kfree(icode->gpr_map);
 __err_gpr:
        kfree(icode);
        return err;
@@ -1837,8 +1861,8 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
        if (!icode)
                return err;
 
-       icode->gpr_map = (u_int32_t __user *) kcalloc(256 + 160 + 160 + 2 * 512,
-                                                     sizeof(u_int32_t), GFP_KERNEL);
+       icode->gpr_map = kcalloc(256 + 160 + 160 + 2 * 512,
+                                sizeof(u_int32_t), GFP_KERNEL);
        if (!icode->gpr_map)
                goto __err_gpr;
 
@@ -1852,7 +1876,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
        if (!ipcm)
                goto __err_ipcm;
 
-       gpr_map = (u32 __force *)icode->gpr_map;
+       gpr_map = icode->gpr_map;
 
        icode->tram_data_map = icode->gpr_map + 256;
        icode->tram_addr_map = icode->tram_data_map + 160;
@@ -2186,7 +2210,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
        OP(icode, &ptr, iACC3, GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + 5), GPR(playback + 5), C_00000000, C_00000000); /* LFE */
 
        ctl = &controls[i + 0];
-       ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(ctl->id.name, "Tone Control - Bass");
        ctl->vcount = 2;
        ctl->count = 10;
@@ -2196,7 +2220,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
        ctl->tlv = snd_emu10k1_bass_treble_db_scale;
        ctl->translation = EMU10K1_GPR_TRANSLATION_BASS;
        ctl = &controls[i + 1];
-       ctl->id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
+       ctl->id.iface = (__force int)SNDRV_CTL_ELEM_IFACE_MIXER;
        strcpy(ctl->id.name, "Tone Control - Treble");
        ctl->vcount = 2;
        ctl->count = 10;
@@ -2382,7 +2406,7 @@ static int _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
        if ((err = snd_emu10k1_fx8010_tram_setup(emu, ipcm->buffer_size)) < 0)
                goto __err;
        icode->gpr_add_control_count = i;
-       icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
+       icode->gpr_add_controls = controls;
        emu->support_tlv = 1; /* support TLV */
        err = snd_emu10k1_icode_poke(emu, icode, true);
        emu->support_tlv = 0; /* clear again */
@@ -2393,7 +2417,7 @@ __err:
 __err_ipcm:
        kfree(controls);
 __err_ctrls:
-       kfree((void __force *)icode->gpr_map);
+       kfree(icode->gpr_map);
 __err_gpr:
        kfree(icode);
        return err;
@@ -2483,7 +2507,7 @@ static int snd_emu10k1_fx8010_open(struct snd_hwdep * hw, struct file *file)
        return 0;
 }
 
-static void copy_string(char *dst, char *src, char *null, int idx)
+static void copy_string(char *dst, const char *src, const char *null, int idx)
 {
        if (src == NULL)
                sprintf(dst, "%s %02X", null, idx);
@@ -2494,7 +2518,7 @@ static void copy_string(char *dst, char *src, char *null, int idx)
 static void snd_emu10k1_fx8010_info(struct snd_emu10k1 *emu,
                                   struct snd_emu10k1_fx8010_info *info)
 {
-       char **fxbus, **extin, **extout;
+       const char * const *fxbus, * const *extin, * const *extout;
        unsigned short fxbus_mask, extin_mask, extout_mask;
        int res;
 
index 7c04172..8a6cbe6 100644 (file)
@@ -183,7 +183,7 @@ static const char * const emu1616_src_texts[] = {
 /*
  * List of data sources available for each destination
  */
-static unsigned int emu1010_src_regs[] = {
+static const unsigned int emu1010_src_regs[] = {
        EMU_SRC_SILENCE,/* 0 */
        EMU_SRC_DOCK_MIC_A1, /* 1 */
        EMU_SRC_DOCK_MIC_B1, /* 2 */
@@ -240,7 +240,7 @@ static unsigned int emu1010_src_regs[] = {
 };
 
 /* 1616(m) cardbus */
-static unsigned int emu1616_src_regs[] = {
+static const unsigned int emu1616_src_regs[] = {
        EMU_SRC_SILENCE,
        EMU_SRC_DOCK_MIC_A1,
        EMU_SRC_DOCK_MIC_B1,
@@ -296,7 +296,7 @@ static unsigned int emu1616_src_regs[] = {
  * Data destinations - physical EMU outputs.
  * Each destination has an enum mixer control to choose a data source
  */
-static unsigned int emu1010_output_dst[] = {
+static const unsigned int emu1010_output_dst[] = {
        EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
        EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
        EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
@@ -324,7 +324,7 @@ static unsigned int emu1010_output_dst[] = {
 };
 
 /* 1616(m) cardbus */
-static unsigned int emu1616_output_dst[] = {
+static const unsigned int emu1616_output_dst[] = {
        EMU_DST_DOCK_DAC1_LEFT1,
        EMU_DST_DOCK_DAC1_RIGHT1,
        EMU_DST_DOCK_DAC2_LEFT1,
@@ -350,7 +350,7 @@ static unsigned int emu1616_output_dst[] = {
  *   capture (EMU32 + I2S links)
  * Each destination has an enum mixer control to choose a data source
  */
-static unsigned int emu1010_input_dst[] = {
+static const unsigned int emu1010_input_dst[] = {
        EMU_DST_ALICE2_EMU32_0,
        EMU_DST_ALICE2_EMU32_1,
        EMU_DST_ALICE2_EMU32_2,
@@ -484,7 +484,7 @@ static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] = {
+static const struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] = {
        EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
        EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
        EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
@@ -513,7 +513,7 @@ static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] = {
 
 
 /* 1616(m) cardbus */
-static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] = {
+static const struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] = {
        EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
        EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
        EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
@@ -545,7 +545,7 @@ static struct snd_kcontrol_new snd_emu1616_output_enum_ctls[] = {
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] = {
+static const struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] = {
        EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
        EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
        EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
@@ -613,7 +613,7 @@ static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_emu1010_adc_pads[] = {
+static const struct snd_kcontrol_new snd_emu1010_adc_pads[] = {
        EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
        EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
        EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
@@ -661,7 +661,7 @@ static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ct
        .private_value = chid                                   \
 }
 
-static struct snd_kcontrol_new snd_emu1010_dac_pads[] = {
+static const struct snd_kcontrol_new snd_emu1010_dac_pads[] = {
        EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
        EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
        EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
@@ -1051,7 +1051,7 @@ static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
 }
 
 
-static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] = {
+static const struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] = {
        I2C_VOLUME("Mic Capture Volume", 0),
        I2C_VOLUME("Line Capture Volume", 0)
 };
@@ -1125,7 +1125,7 @@ static int snd_audigy_spdif_output_rate_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new snd_audigy_spdif_output_rate =
+static const struct snd_kcontrol_new snd_audigy_spdif_output_rate =
 {
        .access =       SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .iface =        SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -1778,8 +1778,8 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
        int err, pcm;
        struct snd_kcontrol *kctl;
        struct snd_card *card = emu->card;
-       char **c;
-       static char *emu10k1_remove_ctls[] = {
+       const char * const *c;
+       static const char * const emu10k1_remove_ctls[] = {
                /* no AC97 mono, surround, center/lfe */
                "Master Mono Playback Switch",
                "Master Mono Playback Volume",
@@ -1793,13 +1793,13 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                "LFE Playback Volume",
                NULL
        };
-       static char *emu10k1_rename_ctls[] = {
+       static const char * const emu10k1_rename_ctls[] = {
                "Surround Digital Playback Volume", "Surround Playback Volume",
                "Center Digital Playback Volume", "Center Playback Volume",
                "LFE Digital Playback Volume", "LFE Playback Volume",
                NULL
        };
-       static char *audigy_remove_ctls[] = {
+       static const char * const audigy_remove_ctls[] = {
                /* Master/PCM controls on ac97 of Audigy has no effect */
                /* On the Audigy2 the AC97 playback is piped into
                 * the Philips ADC for 24bit capture */
@@ -1826,7 +1826,7 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                "External Amplifier",
                NULL
        };
-       static char *audigy_rename_ctls[] = {
+       static const char * const audigy_rename_ctls[] = {
                /* use conventional names */
                "Wave Playback Volume", "PCM Playback Volume",
                /* "Wave Capture Volume", "PCM Capture Volume", */
@@ -1836,7 +1836,7 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                "Master Mono Playback Volume", "Phone Output Playback Volume",
                NULL
        };
-       static char *audigy_rename_ctls_i2c_adc[] = {
+       static const char * const audigy_rename_ctls_i2c_adc[] = {
                //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
                "Line Capture Volume", "Analog Mix Capture Volume",
                "Wave Playback Volume", "OLD PCM Playback Volume",
@@ -1845,7 +1845,7 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                "CD Capture Volume", "IEC958 Optical Capture Volume",
                NULL
        };
-       static char *audigy_remove_ctls_i2c_adc[] = {
+       static const char * const audigy_remove_ctls_i2c_adc[] = {
                /* On the Audigy2 ZS Notebook
                 * Capture via WM8775  */
                "Mic Capture Volume",
@@ -1854,7 +1854,7 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                "IEC958 Optical Capture Volume",
                NULL
        };
-       static char *audigy_remove_ctls_1361t_adc[] = {
+       static const char * const audigy_remove_ctls_1361t_adc[] = {
                /* On the Audigy2 the AC97 playback is piped into
                 * the Philips ADC for 24bit capture */
                "PCM Playback Switch",
@@ -1872,7 +1872,7 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
                "Line2 Capture Volume",
                NULL
        };
-       static char *audigy_rename_ctls_1361t_adc[] = {
+       static const char * const audigy_rename_ctls_1361t_adc[] = {
                "Master Playback Switch", "Master Capture Switch",
                "Master Playback Volume", "Master Capture Volume",
                "Wave Master Playback Volume", "Master Playback Volume",
@@ -1898,7 +1898,7 @@ int snd_emu10k1_mixer(struct snd_emu10k1 *emu,
        if (emu->card_capabilities->ac97_chip) {
                struct snd_ac97_bus *pbus;
                struct snd_ac97_template ac97;
-               static struct snd_ac97_bus_ops ops = {
+               static const struct snd_ac97_bus_ops ops = {
                        .write = snd_emu10k1_ac97_write,
                        .read = snd_emu10k1_ac97_read,
                };
index 9a8cf3c..b934c6a 100644 (file)
@@ -569,17 +569,6 @@ static const struct snd_pcm_hardware snd_emu10k1_efx_playback =
        .fifo_size =            0,
 };
 
-static int snd_emu10k1_capture_hw_params(struct snd_pcm_substream *substream,
-                                        struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_emu10k1_capture_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_emu10k1_capture_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
@@ -1360,7 +1349,6 @@ static int snd_emu10k1_capture_efx_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_emu10k1_playback_ops = {
        .open =                 snd_emu10k1_playback_open,
        .close =                snd_emu10k1_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_emu10k1_playback_hw_params,
        .hw_free =              snd_emu10k1_playback_hw_free,
        .prepare =              snd_emu10k1_playback_prepare,
@@ -1371,9 +1359,6 @@ static const struct snd_pcm_ops snd_emu10k1_playback_ops = {
 static const struct snd_pcm_ops snd_emu10k1_capture_ops = {
        .open =                 snd_emu10k1_capture_open,
        .close =                snd_emu10k1_capture_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_emu10k1_capture_hw_params,
-       .hw_free =              snd_emu10k1_capture_hw_free,
        .prepare =              snd_emu10k1_capture_prepare,
        .trigger =              snd_emu10k1_capture_trigger,
        .pointer =              snd_emu10k1_capture_pointer,
@@ -1383,7 +1368,6 @@ static const struct snd_pcm_ops snd_emu10k1_capture_ops = {
 static const struct snd_pcm_ops snd_emu10k1_efx_playback_ops = {
        .open =                 snd_emu10k1_efx_playback_open,
        .close =                snd_emu10k1_efx_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_emu10k1_playback_hw_params,
        .hw_free =              snd_emu10k1_efx_playback_hw_free,
        .prepare =              snd_emu10k1_efx_playback_prepare,
@@ -1410,15 +1394,15 @@ int snd_emu10k1_pcm(struct snd_emu10k1 *emu, int device)
        strcpy(pcm->name, "ADC Capture/Standard PCM Playback");
        emu->pcm = pcm;
 
+       /* playback substream can't use managed buffers due to alignment */
        for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
                snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
                                              &emu->pci->dev,
                                              64*1024, 64*1024);
 
        for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; substream; substream = substream->next)
-               snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
-                                             &emu->pci->dev,
-                                             64*1024, 64*1024);
+               snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
+                                          &emu->pci->dev, 64*1024, 64*1024);
 
        return 0;
 }
@@ -1453,9 +1437,6 @@ int snd_emu10k1_pcm_multi(struct snd_emu10k1 *emu, int device)
 static const struct snd_pcm_ops snd_emu10k1_capture_mic_ops = {
        .open =                 snd_emu10k1_capture_mic_open,
        .close =                snd_emu10k1_capture_mic_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_emu10k1_capture_hw_params,
-       .hw_free =              snd_emu10k1_capture_hw_free,
        .prepare =              snd_emu10k1_capture_prepare,
        .trigger =              snd_emu10k1_capture_trigger,
        .pointer =              snd_emu10k1_capture_pointer,
@@ -1477,9 +1458,8 @@ int snd_emu10k1_pcm_mic(struct snd_emu10k1 *emu, int device)
        strcpy(pcm->name, "Mic Capture");
        emu->pcm_mic = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &emu->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &emu->pci->dev,
+                                      64*1024, 64*1024);
 
        return 0;
 }
@@ -1550,9 +1530,6 @@ static const struct snd_kcontrol_new snd_emu10k1_pcm_efx_voices_mask = {
 static const struct snd_pcm_ops snd_emu10k1_capture_efx_ops = {
        .open =                 snd_emu10k1_capture_efx_open,
        .close =                snd_emu10k1_capture_efx_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_emu10k1_capture_hw_params,
-       .hw_free =              snd_emu10k1_capture_hw_free,
        .prepare =              snd_emu10k1_capture_prepare,
        .trigger =              snd_emu10k1_capture_trigger,
        .pointer =              snd_emu10k1_capture_pointer,
@@ -1633,12 +1610,6 @@ static int snd_emu10k1_fx8010_playback_transfer(struct snd_pcm_substream *substr
                                                  fx8010_pb_trans_copy);
 }
 
-static int snd_emu10k1_fx8010_playback_hw_params(struct snd_pcm_substream *substream,
-                                                struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
 static int snd_emu10k1_fx8010_playback_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
@@ -1647,7 +1618,6 @@ static int snd_emu10k1_fx8010_playback_hw_free(struct snd_pcm_substream *substre
 
        for (i = 0; i < pcm->channels; i++)
                snd_emu10k1_ptr_write(emu, TANKMEMADDRREGBASE + 0x80 + pcm->etram[i], 0, 0);
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -1792,8 +1762,6 @@ static int snd_emu10k1_fx8010_playback_close(struct snd_pcm_substream *substream
 static const struct snd_pcm_ops snd_emu10k1_fx8010_playback_ops = {
        .open =                 snd_emu10k1_fx8010_playback_open,
        .close =                snd_emu10k1_fx8010_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_emu10k1_fx8010_playback_hw_params,
        .hw_free =              snd_emu10k1_fx8010_playback_hw_free,
        .prepare =              snd_emu10k1_fx8010_playback_prepare,
        .trigger =              snd_emu10k1_fx8010_playback_trigger,
@@ -1852,9 +1820,8 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device)
        if (err < 0)
                return err;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &emu->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &emu->pci->dev,
+                                      64*1024, 64*1024);
 
        return 0;
 }
index d32f256..6e20cca 100644 (file)
@@ -26,10 +26,10 @@ static void snd_emu10k1_proc_spdif_status(struct snd_emu10k1 * emu,
                                          int status_reg,
                                          int rate_reg)
 {
-       static char *clkaccy[4] = { "1000ppm", "50ppm", "variable", "unknown" };
-       static int samplerate[16] = { 44100, 1, 48000, 32000, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
-       static char *channel[16] = { "unspec", "left", "right", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
-       static char *emphasis[8] = { "none", "50/15 usec 2 channel", "2", "3", "4", "5", "6", "7" };
+       static const char * const clkaccy[4] = { "1000ppm", "50ppm", "variable", "unknown" };
+       static const int samplerate[16] = { 44100, 1, 48000, 32000, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+       static const char * const channel[16] = { "unspec", "left", "right", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
+       static const char * const emphasis[8] = { "none", "50/15 usec 2 channel", "2", "3", "4", "5", "6", "7" };
        unsigned int status, rate = 0;
        
        status = snd_emu10k1_ptr_read(emu, status_reg, 0);
@@ -67,7 +67,7 @@ static void snd_emu10k1_proc_read(struct snd_info_entry *entry,
                                  struct snd_info_buffer *buffer)
 {
        /* FIXME - output names are in emufx.c too */
-       static char *creative_outs[32] = {
+       static const char * const creative_outs[32] = {
                /* 00 */ "AC97 Left",
                /* 01 */ "AC97 Right",
                /* 02 */ "Optical IEC958 Left",
@@ -102,7 +102,7 @@ static void snd_emu10k1_proc_read(struct snd_info_entry *entry,
                /* 31 */ "???"
        };
 
-       static char *audigy_outs[64] = {
+       static const char * const audigy_outs[64] = {
                /* 00 */ "Digital Front Left",
                /* 01 */ "Digital Front Right",
                /* 02 */ "Digital Center",
@@ -172,7 +172,7 @@ static void snd_emu10k1_proc_read(struct snd_info_entry *entry,
        struct snd_emu10k1 *emu = entry->private_data;
        unsigned int val, val1;
        int nefx = emu->audigy ? 64 : 32;
-       char **outputs = emu->audigy ? audigy_outs : creative_outs;
+       const char * const *outputs = emu->audigy ? audigy_outs : creative_outs;
        int idx;
        
        snd_iprintf(buffer, "EMU10K1\n\n");
@@ -262,7 +262,7 @@ static void snd_emu10k1_proc_spdif_read(struct snd_info_entry *entry,
 static void snd_emu10k1_proc_rates_read(struct snd_info_entry *entry, 
                                  struct snd_info_buffer *buffer)
 {
-       static int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 };
+       static const int samplerate[8] = { 44100, 48000, 96000, 192000, 4, 5, 6, 7 };
        struct snd_emu10k1 *emu = entry->private_data;
        unsigned int val, tmp, n;
        val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
@@ -545,7 +545,7 @@ static void snd_emu_proc_ptr_reg_read20c(struct snd_info_entry *entry,
 }
 #endif
 
-static struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = {
+static const struct snd_info_entry_ops snd_emu10k1_proc_ops_fx8010 = {
        .read = snd_emu10k1_fx8010_read,
 };
 
index a3f1de7..e15092c 100644 (file)
@@ -510,7 +510,7 @@ void snd_emu10k1_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigned
 
 unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)
 {
-       static u32 logMagTable[128] = {
+       static const u32 logMagTable[128] = {
                0x00000, 0x02dfc, 0x05b9e, 0x088e6, 0x0b5d6, 0x0e26f, 0x10eb3, 0x13aa2,
                0x1663f, 0x1918a, 0x1bc84, 0x1e72e, 0x2118b, 0x23b9a, 0x2655d, 0x28ed5,
                0x2b803, 0x2e0e8, 0x30985, 0x331db, 0x359eb, 0x381b6, 0x3a93d, 0x3d081,
@@ -528,7 +528,7 @@ unsigned int snd_emu10k1_rate_to_pitch(unsigned int rate)
                0xe829f, 0xe9b31, 0xeb3a9, 0xecc08, 0xee44c, 0xefc78, 0xf148a, 0xf2c83,
                0xf4463, 0xf5c2a, 0xf73da, 0xf8b71, 0xfa2f0, 0xfba57, 0xfd1a7, 0xfe8df
        };
-       static char logSlopeTable[128] = {
+       static const char logSlopeTable[128] = {
                0x5c, 0x5c, 0x5b, 0x5a, 0x5a, 0x59, 0x58, 0x58,
                0x57, 0x56, 0x56, 0x55, 0x55, 0x54, 0x53, 0x53,
                0x52, 0x52, 0x51, 0x51, 0x50, 0x50, 0x4f, 0x4f,
index ab88768..1099f10 100644 (file)
@@ -282,36 +282,6 @@ static int snd_p16v_pcm_open_capture(struct snd_pcm_substream *substream)
        return snd_p16v_pcm_open_capture_channel(substream, 0);
 }
 
-/* hw_params callback */
-static int snd_p16v_pcm_hw_params_playback(struct snd_pcm_substream *substream,
-                                     struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-/* hw_params callback */
-static int snd_p16v_pcm_hw_params_capture(struct snd_pcm_substream *substream,
-                                     struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-
-/* hw_free callback */
-static int snd_p16v_pcm_hw_free_playback(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
-/* hw_free callback */
-static int snd_p16v_pcm_hw_free_capture(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
-
 /* prepare playback callback */
 static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
 {
@@ -582,9 +552,6 @@ snd_p16v_pcm_pointer_capture(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_p16v_playback_front_ops = {
        .open =        snd_p16v_pcm_open_playback_front,
        .close =       snd_p16v_pcm_close_playback,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   snd_p16v_pcm_hw_params_playback,
-       .hw_free =     snd_p16v_pcm_hw_free_playback,
        .prepare =     snd_p16v_pcm_prepare_playback,
        .trigger =     snd_p16v_pcm_trigger_playback,
        .pointer =     snd_p16v_pcm_pointer_playback,
@@ -593,9 +560,6 @@ static const struct snd_pcm_ops snd_p16v_playback_front_ops = {
 static const struct snd_pcm_ops snd_p16v_capture_ops = {
        .open =        snd_p16v_pcm_open_capture,
        .close =       snd_p16v_pcm_close_capture,
-       .ioctl =       snd_pcm_lib_ioctl,
-       .hw_params =   snd_p16v_pcm_hw_params_capture,
-       .hw_free =     snd_p16v_pcm_hw_free_capture,
        .prepare =     snd_p16v_pcm_prepare_capture,
        .trigger =     snd_p16v_pcm_trigger_capture,
        .pointer =     snd_p16v_pcm_pointer_capture,
@@ -642,10 +606,10 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
        for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; 
            substream; 
            substream = substream->next) {
-               snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
-                                             &emu->pci->dev,
-                                             (65536 - 64) * 8,
-                                             (65536 - 64) * 8);
+               snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
+                                          &emu->pci->dev,
+                                          (65536 - 64) * 8,
+                                          (65536 - 64) * 8);
                /*
                dev_dbg(emu->card->dev,
                           "preallocate playback substream: err=%d\n", err);
@@ -655,9 +619,9 @@ int snd_p16v_pcm(struct snd_emu10k1 *emu, int device)
        for (substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream; 
              substream; 
              substream = substream->next) {
-               snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV,
-                                             &emu->pci->dev,
-                                             65536 - 64, 65536 - 64);
+               snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV,
+                                          &emu->pci->dev,
+                                          65536 - 64, 65536 - 64);
                /*
                dev_dbg(emu->card->dev,
                           "preallocate capture substream: err=%d\n", err);
@@ -812,7 +776,7 @@ static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
        .private_value = ((xreg) | ((xhl) << 8)) \
 }
 
-static struct snd_kcontrol_new p16v_mixer_controls[] = {
+static const struct snd_kcontrol_new p16v_mixer_controls[] = {
        P16V_VOL("HD Analog Front Playback Volume", PLAYBACK_VOLUME_MIXER9, 0),
        P16V_VOL("HD Analog Rear Playback Volume", PLAYBACK_VOLUME_MIXER10, 1),
        P16V_VOL("HD Analog Center/LFE Playback Volume", PLAYBACK_VOLUME_MIXER9, 1),
index 9ef3b99..c280300 100644 (file)
@@ -52,7 +52,7 @@ static int snd_emu10k1_timer_precise_resolution(struct snd_timer *timer,
        return 0;
 }
 
-static struct snd_timer_hardware snd_emu10k1_timer_hw = {
+static const struct snd_timer_hardware snd_emu10k1_timer_hw = {
        .flags = SNDRV_TIMER_HW_AUTO,
        .resolution = 20833, /* 1 sample @ 48KHZ = 20.833...us */
        .ticks = 1024,
index 0499dc8..d9acef0 100644 (file)
@@ -856,17 +856,6 @@ static int snd_ensoniq_trigger(struct snd_pcm_substream *substream, int cmd)
  *  PCM part
  */
 
-static int snd_ensoniq_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_ensoniq_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_ensoniq_playback1_prepare(struct snd_pcm_substream *substream)
 {
        struct ensoniq *ensoniq = snd_pcm_substream_chip(substream);
@@ -1215,9 +1204,6 @@ static int snd_ensoniq_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_ensoniq_playback1_ops = {
        .open =         snd_ensoniq_playback1_open,
        .close =        snd_ensoniq_playback1_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ensoniq_hw_params,
-       .hw_free =      snd_ensoniq_hw_free,
        .prepare =      snd_ensoniq_playback1_prepare,
        .trigger =      snd_ensoniq_trigger,
        .pointer =      snd_ensoniq_playback1_pointer,
@@ -1226,9 +1212,6 @@ static const struct snd_pcm_ops snd_ensoniq_playback1_ops = {
 static const struct snd_pcm_ops snd_ensoniq_playback2_ops = {
        .open =         snd_ensoniq_playback2_open,
        .close =        snd_ensoniq_playback2_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ensoniq_hw_params,
-       .hw_free =      snd_ensoniq_hw_free,
        .prepare =      snd_ensoniq_playback2_prepare,
        .trigger =      snd_ensoniq_trigger,
        .pointer =      snd_ensoniq_playback2_pointer,
@@ -1237,9 +1220,6 @@ static const struct snd_pcm_ops snd_ensoniq_playback2_ops = {
 static const struct snd_pcm_ops snd_ensoniq_capture_ops = {
        .open =         snd_ensoniq_capture_open,
        .close =        snd_ensoniq_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ensoniq_hw_params,
-       .hw_free =      snd_ensoniq_hw_free,
        .prepare =      snd_ensoniq_capture_prepare,
        .trigger =      snd_ensoniq_trigger,
        .pointer =      snd_ensoniq_capture_pointer,
@@ -1274,9 +1254,8 @@ static int snd_ensoniq_pcm(struct ensoniq *ensoniq, int device)
        strcpy(pcm->name, CHIP_NAME " DAC2/ADC");
        ensoniq->pcm1 = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &ensoniq->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &ensoniq->pci->dev, 64*1024, 128*1024);
 
 #ifdef CHIP1370
        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
@@ -1307,9 +1286,8 @@ static int snd_ensoniq_pcm2(struct ensoniq *ensoniq, int device)
        strcpy(pcm->name, CHIP_NAME " DAC1");
        ensoniq->pcm2 = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &ensoniq->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &ensoniq->pci->dev, 64*1024, 128*1024);
 
 #ifdef CHIP1370
        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
@@ -1455,7 +1433,7 @@ static int snd_es1371_spdif_put(struct snd_kcontrol *kcontrol,
 
 
 /* spdif controls */
-static struct snd_kcontrol_new snd_es1371_mixer_spdif[] = {
+static const struct snd_kcontrol_new snd_es1371_mixer_spdif[] = {
        ES1371_SPDIF(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH)),
        {
                .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1584,7 +1562,7 @@ struct es1371_quirk {
 };
 
 static int es1371_quirk_lookup(struct ensoniq *ensoniq,
-                               struct es1371_quirk *list)
+                              const struct es1371_quirk *list)
 {
        while (list->vid != (unsigned short)PCI_ANY_ID) {
                if (ensoniq->pci->vendor == list->vid &&
@@ -1596,7 +1574,7 @@ static int es1371_quirk_lookup(struct ensoniq *ensoniq,
        return 0;
 }
 
-static struct es1371_quirk es1371_spdif_present[] = {
+static const struct es1371_quirk es1371_spdif_present[] = {
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -1605,7 +1583,7 @@ static struct es1371_quirk es1371_spdif_present[] = {
        { .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
 };
 
-static struct snd_pci_quirk ens1373_line_quirk[] = {
+static const struct snd_pci_quirk ens1373_line_quirk[] = {
        SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */
        SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */
        { } /* end */
@@ -1618,7 +1596,7 @@ static int snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_es1371_codec_write,
                .read = snd_es1371_codec_read,
                .wait = snd_es1371_codec_wait,
@@ -1720,7 +1698,7 @@ static int snd_ensoniq_control_put(struct snd_kcontrol *kcontrol,
  * ENS1370 mixer
  */
 
-static struct snd_kcontrol_new snd_es1370_controls[2] = {
+static const struct snd_kcontrol_new snd_es1370_controls[2] = {
 ENSONIQ_CONTROL("PCM 0 Output also on Line-In Jack", ES_1370_XCTL0),
 ENSONIQ_CONTROL("Mic +5V bias", ES_1370_XCTL1)
 };
@@ -1910,8 +1888,6 @@ static int snd_ensoniq_free(struct ensoniq *ensoniq)
        outl(0, ES_REG(ensoniq, CONTROL));      /* switch everything off */
        outl(0, ES_REG(ensoniq, SERIAL));       /* clear serial interface */
 #endif
-       if (ensoniq->irq >= 0)
-               synchronize_irq(ensoniq->irq);
        pci_set_power_state(ensoniq->pci, PCI_D3hot);
       __hw_end:
 #ifdef CHIP1370
@@ -1933,7 +1909,7 @@ static int snd_ensoniq_dev_free(struct snd_device *device)
 }
 
 #ifdef CHIP1371
-static struct snd_pci_quirk es1371_amplifier_hack[] = {
+static const struct snd_pci_quirk es1371_amplifier_hack[] = {
        SND_PCI_QUIRK_ID(0x107b, 0x2150),       /* Gateway Solo 2150 */
        SND_PCI_QUIRK_ID(0x13bd, 0x100c),       /* EV1938 on Mebius PC-MJ100V */
        SND_PCI_QUIRK_ID(0x1102, 0x5938),       /* Targa Xtender300 */
@@ -1941,7 +1917,7 @@ static struct snd_pci_quirk es1371_amplifier_hack[] = {
        { } /* end */
 };
 
-static struct es1371_quirk es1371_ac97_reset_hack[] = {
+static const struct es1371_quirk es1371_ac97_reset_hack[] = {
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
        { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -2012,7 +1988,6 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
        outb(ensoniq->uartc = 0x00, ES_REG(ensoniq, UART_CONTROL));
        outb(0x00, ES_REG(ensoniq, UART_RES));
        outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
-       synchronize_irq(ensoniq->irq);
 }
 
 #ifdef CONFIG_PM_SLEEP
@@ -2066,7 +2041,7 @@ static int snd_ensoniq_create(struct snd_card *card,
 {
        struct ensoniq *ensoniq;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ensoniq_dev_free,
        };
 
@@ -2096,6 +2071,7 @@ static int snd_ensoniq_create(struct snd_card *card,
                return -EBUSY;
        }
        ensoniq->irq = pci->irq;
+       card->sync_irq = ensoniq->irq;
 #ifdef CHIP1370
        if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
                                16, &ensoniq->dma_bug) < 0) {
index c571c5d..b4a0adf 100644 (file)
@@ -863,25 +863,6 @@ static int snd_es1938_capture_copy_kernel(struct snd_pcm_substream *substream,
        return 0;
 }
 
-/*
- * buffer management
- */
-static int snd_es1938_pcm_hw_params(struct snd_pcm_substream *substream,
-                                   struct snd_pcm_hw_params *hw_params)
-
-{
-       int err;
-
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
-       return 0;
-}
-
-static int snd_es1938_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 /* ----------------------------------------------------------------------
  * Audio1 Capture (ADC)
  * ----------------------------------------------------------------------*/
@@ -996,9 +977,6 @@ static int snd_es1938_playback_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_es1938_playback_ops = {
        .open =         snd_es1938_playback_open,
        .close =        snd_es1938_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_es1938_pcm_hw_params,
-       .hw_free =      snd_es1938_pcm_hw_free,
        .prepare =      snd_es1938_playback_prepare,
        .trigger =      snd_es1938_playback_trigger,
        .pointer =      snd_es1938_playback_pointer,
@@ -1007,9 +985,6 @@ static const struct snd_pcm_ops snd_es1938_playback_ops = {
 static const struct snd_pcm_ops snd_es1938_capture_ops = {
        .open =         snd_es1938_capture_open,
        .close =        snd_es1938_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_es1938_pcm_hw_params,
-       .hw_free =      snd_es1938_pcm_hw_free,
        .prepare =      snd_es1938_capture_prepare,
        .trigger =      snd_es1938_capture_trigger,
        .pointer =      snd_es1938_capture_pointer,
@@ -1031,9 +1006,8 @@ static int snd_es1938_new_pcm(struct es1938 *chip, int device)
        pcm->info_flags = 0;
        strcpy(pcm->name, "ESS Solo-1");
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 64*1024);
 
        chip->pcm = pcm;
        return 0;
@@ -1333,7 +1307,7 @@ static const DECLARE_TLV_DB_RANGE(db_scale_line,
 
 static const DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0);
 
-static struct snd_kcontrol_new snd_es1938_controls[] = {
+static const struct snd_kcontrol_new snd_es1938_controls[] = {
 ES1938_DOUBLE_TLV("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0,
                  db_scale_master),
 ES1938_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1),
@@ -1446,7 +1420,7 @@ static void snd_es1938_chip_init(struct es1938 *chip)
  * PM support
  */
 
-static unsigned char saved_regs[SAVED_REG_SIZE+1] = {
+static const unsigned char saved_regs[SAVED_REG_SIZE+1] = {
        0x14, 0x1a, 0x1c, 0x3a, 0x3c, 0x3e, 0x36, 0x38,
        0x50, 0x52, 0x60, 0x61, 0x62, 0x63, 0x64, 0x68,
        0x69, 0x6a, 0x6b, 0x6d, 0x6e, 0x6f, 0x7c, 0x7d,
@@ -1458,7 +1432,8 @@ static int es1938_suspend(struct device *dev)
 {
        struct snd_card *card = dev_get_drvdata(dev);
        struct es1938 *chip = card->private_data;
-       unsigned char *s, *d;
+       const unsigned char *s;
+       unsigned char *d;
 
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
 
@@ -1470,6 +1445,7 @@ static int es1938_suspend(struct device *dev)
        if (chip->irq >= 0) {
                free_irq(chip->irq, chip);
                chip->irq = -1;
+               card->sync_irq = -1;
        }
        return 0;
 }
@@ -1479,7 +1455,8 @@ static int es1938_resume(struct device *dev)
        struct pci_dev *pci = to_pci_dev(dev);
        struct snd_card *card = dev_get_drvdata(dev);
        struct es1938 *chip = card->private_data;
-       unsigned char *s, *d;
+       const unsigned char *s;
+       unsigned char *d;
 
        if (request_irq(pci->irq, snd_es1938_interrupt,
                        IRQF_SHARED, KBUILD_MODNAME, chip)) {
@@ -1489,6 +1466,7 @@ static int es1938_resume(struct device *dev)
                return -EIO;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        snd_es1938_chip_init(chip);
 
        /* restore mixer-related registers */
@@ -1572,7 +1550,7 @@ static int snd_es1938_create(struct snd_card *card,
 {
        struct es1938 *chip;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_es1938_dev_free,
        };
 
@@ -1617,6 +1595,7 @@ static int snd_es1938_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        dev_dbg(card->dev,
                "create: io: 0x%lx, sb: 0x%lx, vc: 0x%lx, mpu: 0x%lx, game: 0x%lx\n",
                   chip->io_port, chip->sb_port, chip->vc_port, chip->mpu_port, chip->game_port);
index 7017ca9..d26004b 100644 (file)
@@ -1664,7 +1664,6 @@ static int snd_es1968_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_es1968_playback_ops = {
        .open =         snd_es1968_playback_open,
        .close =        snd_es1968_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_es1968_hw_params,
        .hw_free =      snd_es1968_hw_free,
        .prepare =      snd_es1968_pcm_prepare,
@@ -1675,7 +1674,6 @@ static const struct snd_pcm_ops snd_es1968_playback_ops = {
 static const struct snd_pcm_ops snd_es1968_capture_ops = {
        .open =         snd_es1968_capture_open,
        .close =        snd_es1968_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_es1968_hw_params,
        .hw_free =      snd_es1968_hw_free,
        .prepare =      snd_es1968_pcm_prepare,
@@ -2009,7 +2007,7 @@ snd_es1968_mixer(struct es1968 *chip)
        struct snd_ctl_elem_id elem_id;
 #endif
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_es1968_ac97_write,
                .read = snd_es1968_ac97_read,
        };
@@ -2531,7 +2529,7 @@ struct snd_es1968_tea575x_gpio {
        char *name;
 };
 
-static struct snd_es1968_tea575x_gpio snd_es1968_tea575x_gpios[] = {
+static const struct snd_es1968_tea575x_gpio snd_es1968_tea575x_gpios[] = {
        { .data = 6, .clk = 7, .wren = 8, .most = 9, .name = "SF64-PCE2" },
        { .data = 7, .clk = 8, .wren = 6, .most = 10, .name = "M56VAP" },
 };
@@ -2604,8 +2602,6 @@ static int snd_es1968_free(struct es1968 *chip)
 #endif
 
        if (chip->io_port) {
-               if (chip->irq >= 0)
-                       synchronize_irq(chip->irq);
                outw(1, chip->io_port + 0x04); /* clear WP interrupts */
                outw(0, chip->io_port + ESM_PORT_HOST_IRQ); /* disable IRQ */
        }
@@ -2635,7 +2631,7 @@ struct ess_device_list {
        unsigned short vendor;  /* subsystem vendor id */
 };
 
-static struct ess_device_list pm_whitelist[] = {
+static const struct ess_device_list pm_whitelist[] = {
        { TYPE_MAESTRO2E, 0x0e11 },     /* Compaq Armada */
        { TYPE_MAESTRO2E, 0x1028 },
        { TYPE_MAESTRO2E, 0x103c },
@@ -2646,7 +2642,7 @@ static struct ess_device_list pm_whitelist[] = {
        { TYPE_MAESTRO2, 0x125d },      /* a PCI card, e.g. SF64-PCE2 */
 };
 
-static struct ess_device_list mpu_blacklist[] = {
+static const struct ess_device_list mpu_blacklist[] = {
        { TYPE_MAESTRO2, 0x125d },
 };
 
@@ -2660,7 +2656,7 @@ static int snd_es1968_create(struct snd_card *card,
                             int radio_nr,
                             struct es1968 **chip_ret)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_es1968_dev_free,
        };
        struct es1968 *chip;
@@ -2714,6 +2710,7 @@ static int snd_es1968_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
                
        /* Clear Maestro_map */
        for (i = 0; i < 32; i++)
index a7f8109..181ebaf 100644 (file)
@@ -435,17 +435,6 @@ static int snd_fm801_capture_trigger(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_fm801_hw_params(struct snd_pcm_substream *substream,
-                              struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_fm801_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_fm801_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct fm801 *chip = snd_pcm_substream_chip(substream);
@@ -684,9 +673,6 @@ static int snd_fm801_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_fm801_playback_ops = {
        .open =         snd_fm801_playback_open,
        .close =        snd_fm801_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_fm801_hw_params,
-       .hw_free =      snd_fm801_hw_free,
        .prepare =      snd_fm801_playback_prepare,
        .trigger =      snd_fm801_playback_trigger,
        .pointer =      snd_fm801_playback_pointer,
@@ -695,9 +681,6 @@ static const struct snd_pcm_ops snd_fm801_playback_ops = {
 static const struct snd_pcm_ops snd_fm801_capture_ops = {
        .open =         snd_fm801_capture_open,
        .close =        snd_fm801_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_fm801_hw_params,
-       .hw_free =      snd_fm801_hw_free,
        .prepare =      snd_fm801_capture_prepare,
        .trigger =      snd_fm801_capture_trigger,
        .pointer =      snd_fm801_capture_pointer,
@@ -720,9 +703,8 @@ static int snd_fm801_pcm(struct fm801 *chip, int device)
        strcpy(pcm->name, "FM801");
        chip->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &pdev->dev,
-                                             chip->multichannel ? 128*1024 : 64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, &pdev->dev,
+                                      chip->multichannel ? 128*1024 : 64*1024, 128*1024);
 
        return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                     snd_pcm_alt_chmaps,
@@ -742,7 +724,7 @@ struct snd_fm801_tea575x_gpio {
        char *name;
 };
 
-static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = {
+static const struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = {
        { .data = 1, .clk = 3, .wren = 2, .most = 0, .name = "SF256-PCS" },
        { .data = 1, .clk = 0, .wren = 2, .most = 3, .name = "SF256-PCP" },
        { .data = 2, .clk = 0, .wren = 1, .most = 3, .name = "SF64-PCR" },
@@ -987,7 +969,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
 
 #define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls)
 
-static struct snd_kcontrol_new snd_fm801_controls[] = {
+static const struct snd_kcontrol_new snd_fm801_controls[] = {
 FM801_DOUBLE_TLV("Wave Playback Volume", FM801_PCM_VOL, 0, 8, 31, 1,
                 db_scale_dsp),
 FM801_SINGLE("Wave Playback Switch", FM801_PCM_VOL, 15, 1, 1),
@@ -1008,7 +990,7 @@ FM801_SINGLE("FM Playback Switch", FM801_FM_VOL, 15, 1, 1),
 
 #define FM801_CONTROLS_MULTI ARRAY_SIZE(snd_fm801_controls_multi)
 
-static struct snd_kcontrol_new snd_fm801_controls_multi[] = {
+static const struct snd_kcontrol_new snd_fm801_controls_multi[] = {
 FM801_SINGLE("AC97 2ch->4ch Copy Switch", FM801_CODEC_CTRL, 7, 1, 0),
 FM801_SINGLE("AC97 18-bit Switch", FM801_CODEC_CTRL, 10, 1, 0),
 FM801_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), FM801_I2S_MODE, 8, 1, 0),
@@ -1038,7 +1020,7 @@ static int snd_fm801_mixer(struct fm801 *chip)
        struct snd_ac97_template ac97;
        unsigned int i;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_fm801_codec_write,
                .read = snd_fm801_codec_read,
        };
@@ -1201,7 +1183,7 @@ static int snd_fm801_create(struct snd_card *card,
 {
        struct fm801 *chip;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_fm801_dev_free,
        };
 
@@ -1241,6 +1223,7 @@ static int snd_fm801_create(struct snd_card *card,
                        return -EBUSY;
                }
                chip->irq = pci->irq;
+               card->sync_irq = chip->irq;
                pci_set_master(pci);
        }
 
@@ -1377,7 +1360,7 @@ static void snd_card_fm801_remove(struct pci_dev *pci)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static unsigned char saved_regs[] = {
+static const unsigned char saved_regs[] = {
        FM801_PCM_VOL, FM801_I2S_VOL, FM801_FM_VOL, FM801_REC_SRC,
        FM801_PLY_CTRL, FM801_PLY_COUNT, FM801_PLY_BUF1, FM801_PLY_BUF2,
        FM801_CAP_CTRL, FM801_CAP_COUNT, FM801_CAP_BUF1, FM801_CAP_BUF2,
index b7d9160..f5fd62e 100644 (file)
@@ -192,7 +192,7 @@ static int beep_dev_free(struct snd_device *device)
  */
 int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_register = beep_dev_register,
                .dev_disconnect = beep_dev_disconnect,
                .dev_free = beep_dev_free,
index a2fb191..5dc42f9 100644 (file)
@@ -891,6 +891,7 @@ static int snd_hda_codec_device_init(struct hda_bus *bus, struct snd_card *card,
 /**
  * snd_hda_codec_new - create a HDA codec
  * @bus: the bus to assign
+ * @card: card for this codec
  * @codec_addr: the codec address
  * @codecp: the pointer to store the generated codec
  *
@@ -915,7 +916,7 @@ int snd_hda_codec_device_new(struct hda_bus *bus, struct snd_card *card,
        char component[31];
        hda_nid_t fg;
        int err;
-       static struct snd_device_ops dev_ops = {
+       static const struct snd_device_ops dev_ops = {
                .dev_register = snd_hda_codec_dev_register,
                .dev_free = snd_hda_codec_dev_free,
        };
@@ -1267,6 +1268,18 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
 }
 EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
 
+static unsigned int encode_amp(struct hda_codec *codec, hda_nid_t nid,
+                              int ch, int dir, int idx)
+{
+       unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx);
+
+       /* enable fake mute if no h/w mute but min=mute */
+       if ((query_amp_caps(codec, nid, dir) &
+            (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) == AC_AMPCAP_MIN_MUTE)
+               cmd |= AC_AMP_FAKE_MUTE;
+       return cmd;
+}
+
 /**
  * snd_hda_codec_amp_update - update the AMP mono value
  * @codec: HD-audio codec
@@ -1282,12 +1295,8 @@ EXPORT_SYMBOL_GPL(snd_hda_override_amp_caps);
 int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid,
                             int ch, int dir, int idx, int mask, int val)
 {
-       unsigned int cmd = snd_hdac_regmap_encode_amp(nid, ch, dir, idx);
+       unsigned int cmd = encode_amp(codec, nid, ch, dir, idx);
 
-       /* enable fake mute if no h/w mute but min=mute */
-       if ((query_amp_caps(codec, nid, dir) &
-            (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)) == AC_AMPCAP_MIN_MUTE)
-               cmd |= AC_AMP_FAKE_MUTE;
        return snd_hdac_regmap_update_raw(&codec->core, cmd, mask, val);
 }
 EXPORT_SYMBOL_GPL(snd_hda_codec_amp_update);
@@ -1335,16 +1344,11 @@ EXPORT_SYMBOL_GPL(snd_hda_codec_amp_stereo);
 int snd_hda_codec_amp_init(struct hda_codec *codec, hda_nid_t nid, int ch,
                           int dir, int idx, int mask, int val)
 {
-       int orig;
+       unsigned int cmd = encode_amp(codec, nid, ch, dir, idx);
 
        if (!codec->core.regmap)
                return -EINVAL;
-       regcache_cache_only(codec->core.regmap, true);
-       orig = snd_hda_codec_amp_read(codec, nid, ch, dir, idx);
-       regcache_cache_only(codec->core.regmap, false);
-       if (orig >= 0)
-               return 0;
-       return snd_hda_codec_amp_update(codec, nid, ch, dir, idx, mask, val);
+       return snd_hdac_regmap_update_raw_once(&codec->core, cmd, mask, val);
 }
 EXPORT_SYMBOL_GPL(snd_hda_codec_amp_init);
 
@@ -2387,7 +2391,7 @@ static int snd_hda_spdif_out_switch_put(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new dig_mixes[] = {
+static const struct snd_kcontrol_new dig_mixes[] = {
        {
                .access = SNDRV_CTL_ELEM_ACCESS_READ,
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -2437,7 +2441,7 @@ int snd_hda_create_dig_out_ctls(struct hda_codec *codec,
 {
        int err;
        struct snd_kcontrol *kctl;
-       struct snd_kcontrol_new *dig_mix;
+       const struct snd_kcontrol_new *dig_mix;
        int idx = 0;
        int val = 0;
        const int spdif_index = 16;
@@ -2655,7 +2659,7 @@ static int snd_hda_spdif_in_status_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new dig_in_ctls[] = {
+static const struct snd_kcontrol_new dig_in_ctls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
@@ -2687,7 +2691,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
 {
        int err;
        struct snd_kcontrol *kctl;
-       struct snd_kcontrol_new *dig_mix;
+       const struct snd_kcontrol_new *dig_mix;
        int idx;
 
        idx = find_empty_mixer_ctl_idx(codec, "IEC958 Capture Switch", 0);
@@ -2905,8 +2909,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
        else {
                if (codec->patch_ops.init)
                        codec->patch_ops.init(codec);
-               if (codec->core.regmap)
-                       regcache_sync(codec->core.regmap);
+               snd_hda_regmap_sync(codec);
        }
 
        if (codec->jackpoll_interval)
@@ -3201,7 +3204,7 @@ static int get_empty_pcm_device(struct hda_bus *bus, unsigned int type)
        /* assigned to static slots up to dev#10; if more needed, assign
         * the later slot dynamically (when CONFIG_SND_DYNAMIC_MINORS=y)
         */
-       static int audio_idx[HDA_PCM_NTYPES][5] = {
+       static const int audio_idx[HDA_PCM_NTYPES][5] = {
                [HDA_PCM_TYPE_AUDIO] = { 0, 2, 4, 5, -1 },
                [HDA_PCM_TYPE_SPDIF] = { 1, -1 },
                [HDA_PCM_TYPE_HDMI]  = { 3, 7, 8, 9, -1 },
@@ -3869,7 +3872,7 @@ EXPORT_SYMBOL_GPL(snd_hda_get_default_vref);
 unsigned int snd_hda_correct_pin_ctl(struct hda_codec *codec,
                                     hda_nid_t pin, unsigned int val)
 {
-       static unsigned int cap_lists[][2] = {
+       static const unsigned int cap_lists[][2] = {
                { AC_PINCTL_VREF_100, AC_PINCAP_VREF_100 },
                { AC_PINCTL_VREF_80, AC_PINCAP_VREF_80 },
                { AC_PINCTL_VREF_50, AC_PINCAP_VREF_50 },
@@ -4014,7 +4017,7 @@ void snd_hda_bus_reset_codecs(struct hda_bus *bus)
  */
 void snd_print_pcm_bits(int pcm, char *buf, int buflen)
 {
-       static unsigned int bits[] = { 8, 16, 20, 24, 32 };
+       static const unsigned int bits[] = { 8, 16, 20, 24, 32 };
        int i, j;
 
        for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
index 2f3b7a3..9757667 100644 (file)
@@ -107,7 +107,7 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
        struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
        struct azx *chip = apcm->chip;
        struct azx_dev *azx_dev = get_azx_dev(substream);
-       int ret;
+       int ret = 0;
 
        trace_azx_pcm_hw_params(chip, azx_dev);
        dsp_lock(azx_dev);
@@ -119,8 +119,6 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
        azx_dev->core.bufsize = 0;
        azx_dev->core.period_bytes = 0;
        azx_dev->core.format_val = 0;
-       ret = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
 
 unlock:
        dsp_unlock(azx_dev);
@@ -132,7 +130,6 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
        struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
        struct azx_dev *azx_dev = get_azx_dev(substream);
        struct hda_pcm_stream *hinfo = to_hda_pcm_stream(substream);
-       int err;
 
        /* reset BDL address */
        dsp_lock(azx_dev);
@@ -141,10 +138,9 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
 
        snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
 
-       err = snd_pcm_lib_free_pages(substream);
        azx_stream(azx_dev)->prepared = 0;
        dsp_unlock(azx_dev);
-       return err;
+       return 0;
 }
 
 static int azx_pcm_prepare(struct snd_pcm_substream *substream)
@@ -491,7 +487,7 @@ static inline bool is_link_time_supported(struct snd_pcm_runtime *runtime,
 }
 
 static int azx_get_time_info(struct snd_pcm_substream *substream,
-                       struct timespec *system_ts, struct timespec *audio_ts,
+                       struct timespec64 *system_ts, struct timespec64 *audio_ts,
                        struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
                        struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
 {
@@ -511,7 +507,7 @@ static int azx_get_time_info(struct snd_pcm_substream *substream,
                if (audio_tstamp_config->report_delay)
                        nsec = azx_adjust_codec_delay(substream, nsec);
 
-               *audio_ts = ns_to_timespec(nsec);
+               *audio_ts = ns_to_timespec64(nsec);
 
                audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
                audio_tstamp_report->accuracy_report = 1; /* rest of structure is valid */
@@ -528,16 +524,16 @@ static int azx_get_time_info(struct snd_pcm_substream *substream,
                        return -EINVAL;
 
                case SNDRV_PCM_TSTAMP_TYPE_MONOTONIC_RAW:
-                       *system_ts = ktime_to_timespec(xtstamp.sys_monoraw);
+                       *system_ts = ktime_to_timespec64(xtstamp.sys_monoraw);
                        break;
 
                default:
-                       *system_ts = ktime_to_timespec(xtstamp.sys_realtime);
+                       *system_ts = ktime_to_timespec64(xtstamp.sys_realtime);
                        break;
 
                }
 
-               *audio_ts = ktime_to_timespec(xtstamp.device);
+               *audio_ts = ktime_to_timespec64(xtstamp.device);
 
                audio_tstamp_report->actual_type =
                        SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK_SYNCHRONIZED;
@@ -552,7 +548,7 @@ static int azx_get_time_info(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static struct snd_pcm_hardware azx_pcm_hw = {
+static const struct snd_pcm_hardware azx_pcm_hw = {
        .info =                 (SNDRV_PCM_INFO_MMAP |
                                 SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -693,7 +689,6 @@ static int azx_pcm_mmap(struct snd_pcm_substream *substream,
 static const struct snd_pcm_ops azx_pcm_ops = {
        .open = azx_pcm_open,
        .close = azx_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = azx_pcm_hw_params,
        .hw_free = azx_pcm_hw_free,
        .prepare = azx_pcm_prepare,
@@ -766,9 +761,8 @@ int snd_hda_attach_pcm_stream(struct hda_bus *_bus, struct hda_codec *codec,
                size = MAX_PREALLOC_SIZE;
        if (chip->uc_buffer)
                type = SNDRV_DMA_TYPE_DEV_UC_SG;
-       snd_pcm_lib_preallocate_pages_for_all(pcm, type,
-                                             chip->card->dev,
-                                             size, MAX_PREALLOC_SIZE);
+       snd_pcm_set_managed_buffer_all(pcm, type, chip->card->dev,
+                                      size, MAX_PREALLOC_SIZE);
        return 0;
 }
 
@@ -790,58 +784,16 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
 {
        struct azx *chip = bus_to_azx(bus);
        struct hda_bus *hbus = &chip->bus;
-       unsigned long timeout;
-       unsigned long loopcounter;
-       int do_poll = 0;
-       bool warned = false;
+       int err;
 
  again:
-       timeout = jiffies + msecs_to_jiffies(1000);
-
-       for (loopcounter = 0;; loopcounter++) {
-               spin_lock_irq(&bus->reg_lock);
-               if (bus->polling_mode || do_poll)
-                       snd_hdac_bus_update_rirb(bus);
-               if (!bus->rirb.cmds[addr]) {
-                       if (!do_poll)
-                               bus->poll_count = 0;
-                       if (res)
-                               *res = bus->rirb.res[addr]; /* the last value */
-                       spin_unlock_irq(&bus->reg_lock);
-                       return 0;
-               }
-               spin_unlock_irq(&bus->reg_lock);
-               if (time_after(jiffies, timeout))
-                       break;
-#define LOOP_COUNT_MAX 3000
-               if (hbus->needs_damn_long_delay ||
-                   loopcounter > LOOP_COUNT_MAX) {
-                       if (loopcounter > LOOP_COUNT_MAX && !warned) {
-                               dev_dbg_ratelimited(chip->card->dev,
-                                                   "too slow response, last cmd=%#08x\n",
-                                                   bus->last_cmd[addr]);
-                               warned = true;
-                       }
-                       msleep(2); /* temporary workaround */
-               } else {
-                       udelay(10);
-                       cond_resched();
-               }
-       }
+       err = snd_hdac_bus_get_response(bus, addr, res);
+       if (!err)
+               return 0;
 
        if (hbus->no_response_fallback)
                return -EIO;
 
-       if (!bus->polling_mode && bus->poll_count < 2) {
-               dev_dbg(chip->card->dev,
-                       "azx_get_response timeout, polling the codec once: last cmd=0x%08x\n",
-                       bus->last_cmd[addr]);
-               do_poll = 1;
-               bus->poll_count++;
-               goto again;
-       }
-
-
        if (!bus->polling_mode) {
                dev_warn(chip->card->dev,
                         "azx_get_response timeout, switching to polling mode: last cmd=0x%08x\n",
@@ -883,7 +835,7 @@ static int azx_rirb_get_response(struct hdac_bus *bus, unsigned int addr,
                return -EAGAIN; /* give a chance to retry */
        }
 
-       dev_WARN(chip->card->dev,
+       dev_err(chip->card->dev,
                "azx_get_response timeout, switching to single_cmd mode: last cmd=0x%08x\n",
                bus->last_cmd[addr]);
        chip->single_cmd = 1;
index d081fb2..bb46c89 100644 (file)
@@ -98,7 +98,7 @@ static const char * const cea_audio_coding_type_names[] = {
 /*
  * SS1:SS0 index => sample size
  */
-static int cea_sample_sizes[4] = {
+static const int cea_sample_sizes[4] = {
        0,                      /* 0: Refer to Stream Header */
        AC_SUPPCM_BITS_16,      /* 1: 16 bits */
        AC_SUPPCM_BITS_20,      /* 2: 20 bits */
@@ -108,7 +108,7 @@ static int cea_sample_sizes[4] = {
 /*
  * SF2:SF1:SF0 index => sampling frequency
  */
-static int cea_sampling_frequencies[8] = {
+static const int cea_sampling_frequencies[8] = {
        0,                      /* 0: Refer to Stream Header */
        SNDRV_PCM_RATE_32000,   /* 1:  32000Hz */
        SNDRV_PCM_RATE_44100,   /* 2:  44100Hz */
@@ -352,7 +352,7 @@ error:
  */
 static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
 {
-       static unsigned int alsa_rates[] = {
+       static const unsigned int alsa_rates[] = {
                5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
                88200, 96000, 176400, 192000, 384000
        };
index 10d5023..f4e9d94 100644 (file)
@@ -4042,6 +4042,11 @@ static void call_ledtrig_micmute(struct hda_codec *codec)
  *
  * Note that this fixup has to be called after other fixup that sets
  * cap_sync_hook.  Otherwise the chaining wouldn't work.
+ *
+ * @codec: the HDA codec
+ * @fix: fixup pointer
+ * @action: only supports HDA_FIXUP_ACT_PROBE value
+ *
  */
 void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec,
                                   const struct hda_fixup *fix, int action)
@@ -4401,7 +4406,7 @@ EXPORT_SYMBOL_GPL(snd_hda_gen_fix_pin_power);
  */
 
 /* check each pin in the given array; returns true if any of them is plugged */
-static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
+static bool detect_jacks(struct hda_codec *codec, int num_pins, const hda_nid_t *pins)
 {
        int i;
        bool present = false;
@@ -4420,7 +4425,7 @@ static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
 }
 
 /* standard HP/line-out auto-mute helper */
-static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
+static void do_automute(struct hda_codec *codec, int num_pins, const hda_nid_t *pins,
                        int *paths, bool mute)
 {
        struct hda_gen_spec *spec = codec->spec;
@@ -6027,7 +6032,7 @@ int snd_hda_gen_init(struct hda_codec *codec)
        /* call init functions of standard auto-mute helpers */
        update_automute_all(codec);
 
-       regcache_sync(codec->core.regmap);
+       snd_hda_regmap_sync(codec);
 
        if (spec->vmaster_mute.sw_kctl && spec->vmaster_mute.hook)
                snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
index 35b4526..92a042e 100644 (file)
@@ -125,7 +125,7 @@ static char *patch[SNDRV_CARDS];
 static bool beep_mode[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] =
                                        CONFIG_SND_HDA_INPUT_BEEP_MODE};
 #endif
-static bool dsp_driver = 1;
+static bool dmic_detect = 1;
 
 module_param_array(index, int, NULL, 0444);
 MODULE_PARM_DESC(index, "Index value for Intel HD audio interface.");
@@ -160,9 +160,10 @@ module_param_array(beep_mode, bool, NULL, 0444);
 MODULE_PARM_DESC(beep_mode, "Select HDA Beep registration mode "
                            "(0=off, 1=on) (default=1).");
 #endif
-module_param(dsp_driver, bool, 0444);
-MODULE_PARM_DESC(dsp_driver, "Allow DSP driver selection (bypass this driver) "
-                            "(0=off, 1=on) (default=1)");
+module_param(dmic_detect, bool, 0444);
+MODULE_PARM_DESC(dmic_detect, "Allow DSP driver selection (bypass this driver) "
+                            "(0=off, 1=on) (default=1); "
+                "deprecated, use snd-intel-dspcfg.dsp_driver option instead");
 
 #ifdef CONFIG_PM
 static int param_set_xint(const char *val, const struct kernel_param *kp);
@@ -282,12 +283,13 @@ enum {
 
 /* quirks for old Intel chipsets */
 #define AZX_DCAPS_INTEL_ICH \
-       (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE)
+       (AZX_DCAPS_OLD_SSYNC | AZX_DCAPS_NO_ALIGN_BUFSIZE |\
+        AZX_DCAPS_SYNC_WRITE)
 
 /* quirks for Intel PCH */
 #define AZX_DCAPS_INTEL_PCH_BASE \
        (AZX_DCAPS_NO_ALIGN_BUFSIZE | AZX_DCAPS_COUNT_LPIB_DELAY |\
-        AZX_DCAPS_SNOOP_TYPE(SCH))
+        AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE)
 
 /* PCH up to IVB; no runtime PM; bind with i915 gfx */
 #define AZX_DCAPS_INTEL_PCH_NOPM \
@@ -302,13 +304,13 @@ enum {
 #define AZX_DCAPS_INTEL_HASWELL \
        (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_COUNT_LPIB_DELAY |\
         AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\
-        AZX_DCAPS_SNOOP_TYPE(SCH))
+        AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE)
 
 /* Broadwell HDMI can't use position buffer reliably, force to use LPIB */
 #define AZX_DCAPS_INTEL_BROADWELL \
        (/*AZX_DCAPS_ALIGN_BUFSIZE |*/ AZX_DCAPS_POSFIX_LPIB |\
         AZX_DCAPS_PM_RUNTIME | AZX_DCAPS_I915_COMPONENT |\
-        AZX_DCAPS_SNOOP_TYPE(SCH))
+        AZX_DCAPS_SNOOP_TYPE(SCH) | AZX_DCAPS_SYNC_WRITE)
 
 #define AZX_DCAPS_INTEL_BAYTRAIL \
        (AZX_DCAPS_INTEL_PCH_BASE | AZX_DCAPS_I915_COMPONENT)
@@ -371,7 +373,7 @@ enum {
 
 #define IS_BXT(pci) ((pci)->vendor == 0x8086 && (pci)->device == 0x5a98)
 
-static char *driver_short_names[] = {
+static const char * const driver_short_names[] = {
        [AZX_DRIVER_ICH] = "HDA Intel",
        [AZX_DRIVER_PCH] = "HDA Intel PCH",
        [AZX_DRIVER_SCH] = "HDA Intel MID",
@@ -498,7 +500,7 @@ static void bxt_reduce_dma_latency(struct azx *chip)
 static int intel_get_lctl_scf(struct azx *chip)
 {
        struct hdac_bus *bus = azx_bus(chip);
-       static int preferred_bits[] = { 2, 3, 1, 4, 5 };
+       static const int preferred_bits[] = { 2, 3, 1, 4, 5 };
        u32 val, t;
        int i;
 
@@ -790,6 +792,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
                return -1;
        }
        bus->irq = chip->pci->irq;
+       chip->card->sync_irq = bus->irq;
        pci_intx(chip->pci, !chip->msi);
        return 0;
 }
@@ -1028,6 +1031,7 @@ static int azx_suspend(struct device *dev)
        if (bus->irq >= 0) {
                free_irq(bus->irq, chip);
                bus->irq = -1;
+               chip->card->sync_irq = -1;
        }
 
        if (chip->msi)
@@ -1410,7 +1414,17 @@ static bool atpx_present(void)
        acpi_handle dhandle, atpx_handle;
        acpi_status status;
 
-       while ((pdev = pci_get_class(PCI_BASE_CLASS_DISPLAY << 16, pdev)) != NULL) {
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
+               dhandle = ACPI_HANDLE(&pdev->dev);
+               if (dhandle) {
+                       status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
+                       if (!ACPI_FAILURE(status)) {
+                               pci_dev_put(pdev);
+                               return true;
+                       }
+               }
+       }
+       while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
                dhandle = ACPI_HANDLE(&pdev->dev);
                if (dhandle) {
                        status = acpi_get_handle(dhandle, "ATPX", &atpx_handle);
@@ -1419,7 +1433,6 @@ static bool atpx_present(void)
                                return true;
                        }
                }
-               pci_dev_put(pdev);
        }
        return false;
 }
@@ -1489,7 +1502,7 @@ static bool check_hdmi_disabled(struct pci_dev *pci)
 /*
  * white/black-listing for position_fix
  */
-static struct snd_pci_quirk position_fix_list[] = {
+static const struct snd_pci_quirk position_fix_list[] = {
        SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1028, 0x01de, "Dell Precision 390", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x103c, 0x306d, "HP dv3", POS_FIX_LPIB),
@@ -1552,7 +1565,7 @@ static int check_position_fix(struct azx *chip, int fix)
 
 static void assign_position_fix(struct azx *chip, int fix)
 {
-       static azx_get_pos_callback_t callbacks[] = {
+       static const azx_get_pos_callback_t callbacks[] = {
                [POS_FIX_AUTO] = NULL,
                [POS_FIX_LPIB] = azx_get_pos_lpib,
                [POS_FIX_POSBUF] = azx_get_pos_posbuf,
@@ -1582,7 +1595,7 @@ static void assign_position_fix(struct azx *chip, int fix)
 /*
  * black-lists for probe_mask
  */
-static struct snd_pci_quirk probe_mask_list[] = {
+static const struct snd_pci_quirk probe_mask_list[] = {
        /* Thinkpad often breaks the controller communication when accessing
         * to the non-working (or non-existing) modem codec slot.
         */
@@ -1630,7 +1643,7 @@ static void check_probe_mask(struct azx *chip, int dev)
 /*
  * white/black-list for enable_msi
  */
-static struct snd_pci_quirk msi_black_list[] = {
+static const struct snd_pci_quirk msi_black_list[] = {
        SND_PCI_QUIRK(0x103c, 0x2191, "HP", 0), /* AMD Hudson */
        SND_PCI_QUIRK(0x103c, 0x2192, "HP", 0), /* AMD Hudson */
        SND_PCI_QUIRK(0x103c, 0x21f7, "HP", 0), /* AMD Hudson */
@@ -1742,7 +1755,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
                      int dev, unsigned int driver_caps,
                      struct azx **rchip)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_disconnect = azx_dev_disconnect,
                .dev_free = azx_dev_free,
        };
@@ -1808,7 +1821,7 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
 
        if (chip->driver_type == AZX_DRIVER_NVIDIA) {
                dev_dbg(chip->card->dev, "Enable delay in RIRB handling\n");
-               chip->bus.needs_damn_long_delay = 1;
+               chip->bus.core.needs_damn_long_delay = 1;
        }
 
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
@@ -1884,7 +1897,6 @@ static int azx_first_init(struct azx *chip)
        }
 
        pci_set_master(pci);
-       synchronize_irq(bus->irq);
 
        gcap = azx_readw(chip, GCAP);
        dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap);
@@ -2043,6 +2055,7 @@ static int disable_msi_reset_irq(struct azx *chip)
 
        free_irq(bus->irq, chip);
        bus->irq = -1;
+       chip->card->sync_irq = -1;
        pci_disable_msi(chip->pci);
        chip->msi = 0;
        err = azx_acquire_irq(chip, 1);
@@ -2089,11 +2102,13 @@ static int azx_probe(struct pci_dev *pci,
        /*
         * stop probe if another Intel's DSP driver should be activated
         */
-       if (dsp_driver) {
+       if (dmic_detect) {
                err = snd_intel_dsp_driver_probe(pci);
                if (err != SND_INTEL_DSP_DRIVER_ANY &&
                    err != SND_INTEL_DSP_DRIVER_LEGACY)
                        return -ENODEV;
+       } else {
+               dev_warn(&pci->dev, "dmic_detect option is deprecated, pass snd-intel-dspcfg.dsp_driver=1 option instead\n");
        }
 
        err = snd_card_new(&pci->dev, index[dev], id[dev], THIS_MODULE,
@@ -2163,7 +2178,7 @@ out_free:
  * So we keep a list of devices where we disable powersaving as its known
  * to causes problems on these devices.
  */
-static struct snd_pci_quirk power_save_blacklist[] = {
+static const struct snd_pci_quirk power_save_blacklist[] = {
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1849, 0xc892, "Asrock B85M-ITX", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
@@ -2175,6 +2190,8 @@ static struct snd_pci_quirk power_save_blacklist[] = {
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1581607 */
        SND_PCI_QUIRK(0x1558, 0x3501, "Clevo W35xSS_370SS", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
+       SND_PCI_QUIRK(0x1558, 0x6504, "Clevo W65_67SB", 0),
+       /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        SND_PCI_QUIRK(0x1028, 0x0497, "Dell Precision T3600", 0),
        /* https://bugzilla.redhat.com/show_bug.cgi?id=1525104 */
        /* Note the P55A-UD3 and Z87-D3HP share the subsys id for the HDA dev */
@@ -2219,7 +2236,7 @@ static void set_default_power_save(struct azx *chip)
 }
 
 /* number of codec slots for each chipset: 0 = default slots (i.e. 4) */
-static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
+static const unsigned int azx_max_codecs[AZX_NUM_DRIVERS] = {
        [AZX_DRIVER_NVIDIA] = 8,
        [AZX_DRIVER_TERA] = 1,
 };
@@ -2434,6 +2451,8 @@ static const struct pci_device_id azx_ids[] = {
        /* Jasperlake */
        { PCI_DEVICE(0x8086, 0x38c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
+       { PCI_DEVICE(0x8086, 0x4dc8),
+         .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
        /* Tigerlake */
        { PCI_DEVICE(0x8086, 0xa0c8),
          .driver_data = AZX_DRIVER_SKL | AZX_DCAPS_INTEL_SKYLAKE},
index bf0255c..02cc682 100644 (file)
@@ -122,6 +122,7 @@ any_jack_tbl_get_from_nid(struct hda_codec *codec, hda_nid_t nid)
  * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
  * @codec: the HDA codec
  * @nid: pin NID to assign
+ * @dev_id: pin device entry id
  */
 static struct hda_jack_tbl *
 snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid, int dev_id)
@@ -233,6 +234,7 @@ EXPORT_SYMBOL_GPL(snd_hda_jack_set_dirty_all);
  * snd_hda_jack_pin_sense - execute pin sense measurement
  * @codec: the CODEC to sense
  * @nid: the pin NID to sense
+ * @dev_id: pin device entry id
  *
  * Execute necessary pin sense measurement and return its Presence Detect,
  * Impedance, ELD Valid etc. status bits.
index 3942e1b..3dca65d 100644 (file)
@@ -138,6 +138,8 @@ int snd_hda_codec_reset(struct hda_codec *codec);
 void snd_hda_codec_register(struct hda_codec *codec);
 void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec);
 
+#define snd_hda_regmap_sync(codec)     snd_hdac_regmap_sync(&(codec)->core)
+
 enum {
        HDA_VMUTE_OFF,
        HDA_VMUTE_ON,
index 468836c..0631f31 100644 (file)
@@ -160,7 +160,7 @@ static void print_amp_vals(struct snd_info_buffer *buffer,
 
 static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
 {
-       static unsigned int rates[] = {
+       static const unsigned int rates[] = {
                8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
                96000, 176400, 192000, 384000
        };
index fcc3441..0607ed5 100644 (file)
@@ -611,7 +611,7 @@ struct hda_patch_item {
        void (*parser)(char *buf, struct hda_bus *bus, struct hda_codec **retc);
 };
 
-static struct hda_patch_item patch_items[NUM_LINE_MODES] = {
+static const struct hda_patch_item patch_items[NUM_LINE_MODES] = {
        [LINE_MODE_CODEC] = {
                .tag = "[codec]",
                .parser = parse_codec_mode,
index 8350954..773992a 100644 (file)
@@ -166,11 +166,9 @@ static int __maybe_unused hda_tegra_runtime_suspend(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
        struct hda_tegra *hda = container_of(chip, struct hda_tegra, chip);
-       struct hdac_bus *bus = azx_bus(chip);
 
        if (chip && chip->running) {
                azx_stop_chip(chip);
-               synchronize_irq(bus->irq);
                azx_enter_link_reset(chip);
        }
        hda_tegra_disable_clocks(hda);
@@ -298,8 +296,7 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev)
                return err;
        }
        bus->irq = irq_id;
-
-       synchronize_irq(bus->irq);
+       card->sync_irq = bus->irq;
 
        gcap = azx_readw(chip, GCAP);
        dev_dbg(card->dev, "chipset global capabilities = 0x%x\n", gcap);
@@ -369,7 +366,7 @@ static int hda_tegra_create(struct snd_card *card,
                            unsigned int driver_caps,
                            struct hda_tegra *hda)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_disconnect = hda_tegra_dev_disconnect,
                .dev_free = hda_tegra_dev_free,
        };
@@ -397,7 +394,8 @@ static int hda_tegra_create(struct snd_card *card,
        if (err < 0)
                return err;
 
-       chip->bus.needs_damn_long_delay = 1;
+       chip->bus.core.needs_damn_long_delay = 1;
+       chip->bus.core.aligned_mmio = 1;
 
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
        if (err < 0) {
index bc9dd8e..2132b2a 100644 (file)
@@ -28,6 +28,7 @@ struct ad198x_spec {
        hda_nid_t eapd_nid;
 
        unsigned int beep_amp;  /* beep amp value, set via set_beep_amp() */
+       int num_smux_conns;
 };
 
 
@@ -389,7 +390,7 @@ static int patch_ad1986a(struct hda_codec *codec)
 {
        int err;
        struct ad198x_spec *spec;
-       static hda_nid_t preferred_pairs[] = {
+       static const hda_nid_t preferred_pairs[] = {
                0x1a, 0x03,
                0x1b, 0x03,
                0x1c, 0x04,
@@ -453,8 +454,7 @@ static int ad1983_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
        struct ad198x_spec *spec = codec->spec;
        static const char * const texts2[] = { "PCM", "ADC" };
        static const char * const texts3[] = { "PCM", "ADC1", "ADC2" };
-       hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
-       int num_conns = snd_hda_get_num_conns(codec, dig_out);
+       int num_conns = spec->num_smux_conns;
 
        if (num_conns == 2)
                return snd_hda_enum_helper_info(kcontrol, uinfo, 2, texts2);
@@ -481,7 +481,7 @@ static int ad1983_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
        struct ad198x_spec *spec = codec->spec;
        unsigned int val = ucontrol->value.enumerated.item[0];
        hda_nid_t dig_out = spec->gen.multiout.dig_out_nid;
-       int num_conns = snd_hda_get_num_conns(codec, dig_out);
+       int num_conns = spec->num_smux_conns;
 
        if (val >= num_conns)
                return -EINVAL;
@@ -512,6 +512,7 @@ static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
        num_conns = snd_hda_get_num_conns(codec, dig_out);
        if (num_conns != 2 && num_conns != 3)
                return 0;
+       spec->num_smux_conns = num_conns;
        if (!snd_hda_gen_add_kctl(&spec->gen, NULL, &ad1983_auto_smux_mixer))
                return -ENOMEM;
        return 0;
@@ -519,9 +520,9 @@ static int ad1983_add_spdif_mux_ctl(struct hda_codec *codec)
 
 static int patch_ad1983(struct hda_codec *codec)
 {
+       static const hda_nid_t conn_0c[] = { 0x08 };
+       static const hda_nid_t conn_0d[] = { 0x09 };
        struct ad198x_spec *spec;
-       static hda_nid_t conn_0c[] = { 0x08 };
-       static hda_nid_t conn_0d[] = { 0x09 };
        int err;
 
        err = alloc_ad_spec(codec);
@@ -730,10 +731,12 @@ static int ad1988_auto_smux_enum_info(struct snd_kcontrol *kcontrol,
                                      struct snd_ctl_elem_info *uinfo)
 {
        struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+       struct ad198x_spec *spec = codec->spec;
        static const char * const texts[] = {
                "PCM", "ADC1", "ADC2", "ADC3",
        };
-       int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
+       int num_conns = spec->num_smux_conns;
+
        if (num_conns > 4)
                num_conns = 4;
        return snd_hda_enum_helper_info(kcontrol, uinfo, num_conns, texts);
@@ -756,7 +759,7 @@ static int ad1988_auto_smux_enum_put(struct snd_kcontrol *kcontrol,
        struct ad198x_spec *spec = codec->spec;
        unsigned int val = ucontrol->value.enumerated.item[0];
        struct nid_path *path;
-       int num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
+       int num_conns = spec->num_smux_conns;
 
        if (val >= num_conns)
                return -EINVAL;
@@ -812,7 +815,7 @@ static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
        /* we create four static faked paths, since AD codecs have odd
         * widget connections regarding the SPDIF out source
         */
-       static struct nid_path fake_paths[4] = {
+       static const struct nid_path fake_paths[4] = {
                {
                        .depth = 3,
                        .path = { 0x02, 0x1d, 0x1b },
@@ -847,6 +850,7 @@ static int ad1988_add_spdif_mux_ctl(struct hda_codec *codec)
        num_conns = snd_hda_get_num_conns(codec, 0x0b) + 1;
        if (num_conns != 3 && num_conns != 4)
                return 0;
+       spec->num_smux_conns = num_conns;
 
        for (i = 0; i < num_conns; i++) {
                struct nid_path *path = snd_array_new(&spec->gen.paths);
index e780922..1818ce6 100644 (file)
@@ -53,7 +53,7 @@ static int patch_ca0110(struct hda_codec *codec)
        codec->patch_ops = ca0110_patch_ops;
 
        spec->multi_cap_vol = 1;
-       codec->bus->needs_damn_long_delay = 1;
+       codec->bus->core.needs_damn_long_delay = 1;
 
        err = ca0110_parse_auto_config(codec);
        if (err < 0)
index b7a1abb..ded8bc0 100644 (file)
@@ -1809,13 +1809,14 @@ struct scp_msg {
 
 static void dspio_clear_response_queue(struct hda_codec *codec)
 {
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        unsigned int dummy = 0;
-       int status = -1;
+       int status;
 
        /* clear all from the response queue */
        do {
                status = dspio_read(codec, &dummy);
-       } while (status == 0);
+       } while (status == 0 && time_before(jiffies, timeout));
 }
 
 static int dspio_get_response_data(struct hda_codec *codec)
@@ -1922,6 +1923,7 @@ static int dspio_send_scp_message(struct hda_codec *codec,
  * Prepare and send the SCP message to DSP
  * @codec: the HDA codec
  * @mod_id: ID of the DSP module to send the command
+ * @src_id: ID of the source
  * @req: ID of request to send to the DSP module
  * @dir: SET or GET
  * @data: pointer to the data to send with the request, request specific
@@ -3767,7 +3769,7 @@ static const unsigned int float_xbass_xover_lookup[] = {
 /* The following are for tuning of products */
 #ifdef ENABLE_TUNING_CONTROLS
 
-static unsigned int voice_focus_vals_lookup[] = {
+static const unsigned int voice_focus_vals_lookup[] = {
 0x41A00000, 0x41A80000, 0x41B00000, 0x41B80000, 0x41C00000, 0x41C80000,
 0x41D00000, 0x41D80000, 0x41E00000, 0x41E80000, 0x41F00000, 0x41F80000,
 0x42000000, 0x42040000, 0x42080000, 0x420C0000, 0x42100000, 0x42140000,
@@ -3797,7 +3799,7 @@ static unsigned int voice_focus_vals_lookup[] = {
 0x43300000, 0x43310000, 0x43320000, 0x43330000, 0x43340000
 };
 
-static unsigned int mic_svm_vals_lookup[] = {
+static const unsigned int mic_svm_vals_lookup[] = {
 0x00000000, 0x3C23D70A, 0x3CA3D70A, 0x3CF5C28F, 0x3D23D70A, 0x3D4CCCCD,
 0x3D75C28F, 0x3D8F5C29, 0x3DA3D70A, 0x3DB851EC, 0x3DCCCCCD, 0x3DE147AE,
 0x3DF5C28F, 0x3E051EB8, 0x3E0F5C29, 0x3E19999A, 0x3E23D70A, 0x3E2E147B,
@@ -3817,7 +3819,7 @@ static unsigned int mic_svm_vals_lookup[] = {
 0x3F75C28F, 0x3F7851EC, 0x3F7AE148, 0x3F7D70A4, 0x3F800000
 };
 
-static unsigned int equalizer_vals_lookup[] = {
+static const unsigned int equalizer_vals_lookup[] = {
 0xC1C00000, 0xC1B80000, 0xC1B00000, 0xC1A80000, 0xC1A00000, 0xC1980000,
 0xC1900000, 0xC1880000, 0xC1800000, 0xC1700000, 0xC1600000, 0xC1500000,
 0xC1400000, 0xC1300000, 0xC1200000, 0xC1100000, 0xC1000000, 0xC0E00000,
@@ -3830,7 +3832,7 @@ static unsigned int equalizer_vals_lookup[] = {
 };
 
 static int tuning_ctl_set(struct hda_codec *codec, hda_nid_t nid,
-                         unsigned int *lookup, int idx)
+                         const unsigned int *lookup, int idx)
 {
        int i = 0;
 
@@ -7588,12 +7590,14 @@ static void ca0132_process_dsp_response(struct hda_codec *codec,
        struct ca0132_spec *spec = codec->spec;
 
        codec_dbg(codec, "ca0132_process_dsp_response\n");
+       snd_hda_power_up_pm(codec);
        if (spec->wait_scp) {
                if (dspio_get_response_data(codec) >= 0)
                        spec->wait_scp = 0;
        }
 
        dspio_clear_response_queue(codec);
+       snd_hda_power_down_pm(codec);
 }
 
 static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
@@ -7604,11 +7608,10 @@ static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
        /* Delay enabling the HP amp, to let the mic-detection
         * state machine run.
         */
-       cancel_delayed_work(&spec->unsol_hp_work);
-       schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
        tbl = snd_hda_jack_tbl_get(codec, cb->nid);
        if (tbl)
                tbl->block_report = 1;
+       schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
 }
 
 static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
@@ -7640,14 +7643,14 @@ static void ca0132_init_unsol(struct hda_codec *codec)
  */
 
 /* Sends before DSP download. */
-static struct hda_verb ca0132_base_init_verbs[] = {
+static const struct hda_verb ca0132_base_init_verbs[] = {
        /*enable ct extension*/
        {0x15, VENDOR_CHIPIO_CT_EXTENSIONS_ENABLE, 0x1},
        {}
 };
 
 /* Send at exit. */
-static struct hda_verb ca0132_base_exit_verbs[] = {
+static const struct hda_verb ca0132_base_exit_verbs[] = {
        /*set afg to D3*/
        {0x01, AC_VERB_SET_POWER_STATE, 0x03},
        /*disable ct extension*/
@@ -7657,7 +7660,7 @@ static struct hda_verb ca0132_base_exit_verbs[] = {
 
 /* Other verbs tables. Sends after DSP download. */
 
-static struct hda_verb ca0132_init_verbs0[] = {
+static const struct hda_verb ca0132_init_verbs0[] = {
        /* chip init verbs */
        {0x15, 0x70D, 0xF0},
        {0x15, 0x70E, 0xFE},
@@ -7690,7 +7693,7 @@ static struct hda_verb ca0132_init_verbs0[] = {
 };
 
 /* Extra init verbs for desktop cards. */
-static struct hda_verb ca0132_init_verbs1[] = {
+static const struct hda_verb ca0132_init_verbs1[] = {
        {0x15, 0x70D, 0x20},
        {0x15, 0x70E, 0x19},
        {0x15, 0x707, 0x00},
@@ -7800,23 +7803,23 @@ static void sbz_region2_exit(struct hda_codec *codec)
 
 static void sbz_set_pin_ctl_default(struct hda_codec *codec)
 {
-       hda_nid_t pins[5] = {0x0B, 0x0C, 0x0E, 0x12, 0x13};
+       static const hda_nid_t pins[] = {0x0B, 0x0C, 0x0E, 0x12, 0x13};
        unsigned int i;
 
        snd_hda_codec_write(codec, 0x11, 0,
                        AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40);
 
-       for (i = 0; i < 5; i++)
+       for (i = 0; i < ARRAY_SIZE(pins); i++)
                snd_hda_codec_write(codec, pins[i], 0,
                                AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00);
 }
 
 static void ca0132_clear_unsolicited(struct hda_codec *codec)
 {
-       hda_nid_t pins[7] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
+       static const hda_nid_t pins[] = {0x0B, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13};
        unsigned int i;
 
-       for (i = 0; i < 7; i++) {
+       for (i = 0; i < ARRAY_SIZE(pins); i++) {
                snd_hda_codec_write(codec, pins[i], 0,
                                AC_VERB_SET_UNSOLICITED_ENABLE, 0x00);
        }
@@ -7840,10 +7843,10 @@ static void sbz_gpio_shutdown_commands(struct hda_codec *codec, int dir,
 
 static void zxr_dbpro_power_state_shutdown(struct hda_codec *codec)
 {
-       hda_nid_t pins[7] = {0x05, 0x0c, 0x09, 0x0e, 0x08, 0x11, 0x01};
+       static const hda_nid_t pins[] = {0x05, 0x0c, 0x09, 0x0e, 0x08, 0x11, 0x01};
        unsigned int i;
 
-       for (i = 0; i < 7; i++)
+       for (i = 0; i < ARRAY_SIZE(pins); i++)
                snd_hda_codec_write(codec, pins[i], 0,
                                AC_VERB_SET_POWER_STATE, 0x03);
 }
@@ -8454,12 +8457,25 @@ static void ca0132_reboot_notify(struct hda_codec *codec)
        codec->patch_ops.free(codec);
 }
 
+#ifdef CONFIG_PM
+static int ca0132_suspend(struct hda_codec *codec)
+{
+       struct ca0132_spec *spec = codec->spec;
+
+       cancel_delayed_work_sync(&spec->unsol_hp_work);
+       return 0;
+}
+#endif
+
 static const struct hda_codec_ops ca0132_patch_ops = {
        .build_controls = ca0132_build_controls,
        .build_pcms = ca0132_build_pcms,
        .init = ca0132_init,
        .free = ca0132_free,
        .unsol_event = snd_hda_jack_unsol_event,
+#ifdef CONFIG_PM
+       .suspend = ca0132_suspend,
+#endif
        .reboot_notify = ca0132_reboot_notify,
 };
 
@@ -8854,7 +8870,7 @@ static int patch_ca0132(struct hda_codec *codec)
 /*
  * patch entries
  */
-static struct hda_device_id snd_hda_id_ca0132[] = {
+static const struct hda_device_id snd_hda_id_ca0132[] = {
        HDA_CODEC_ENTRY(0x11020011, "CA0132", patch_ca0132),
        {} /* terminator */
 };
index 90aa0f4..396b550 100644 (file)
@@ -116,7 +116,7 @@ static void cx_auto_parse_eapd(struct hda_codec *codec)
 }
 
 static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
-                             hda_nid_t *pins, bool on)
+                             const hda_nid_t *pins, bool on)
 {
        int i;
        for (i = 0; i < num_pins; i++) {
@@ -922,6 +922,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x17aa, 0x215f, "Lenovo T510", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21ce, "Lenovo T420", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520", CXT_PINCFG_LENOVO_TP410),
+       SND_PCI_QUIRK(0x17aa, 0x21d2, "Lenovo T420s", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
        SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD),
@@ -959,10 +960,10 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
 static void add_cx5051_fake_mutes(struct hda_codec *codec)
 {
        struct conexant_spec *spec = codec->spec;
-       static hda_nid_t out_nids[] = {
+       static const hda_nid_t out_nids[] = {
                0x10, 0x11, 0
        };
-       hda_nid_t *p;
+       const hda_nid_t *p;
 
        for (p = out_nids; *p; p++)
                snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
index 78647ee..5119a9a 100644 (file)
@@ -372,7 +372,8 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
 }
 
 static const struct snd_kcontrol_new eld_bytes_ctl = {
-       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+       .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE |
+               SNDRV_CTL_ELEM_ACCESS_SKIP_CHECK,
        .iface = SNDRV_CTL_ELEM_IFACE_PCM,
        .name = "ELD",
        .info = hdmi_eld_ctl_info,
@@ -819,10 +820,12 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
                cp_ready);
 
        /* TODO */
-       if (cp_state)
+       if (cp_state) {
                ;
-       if (cp_ready)
+       }
+       if (cp_ready) {
                ;
+       }
 }
 
 
@@ -1547,6 +1550,34 @@ static bool update_eld(struct hda_codec *codec,
        return eld_changed;
 }
 
+static struct snd_jack *pin_idx_to_pcm_jack(struct hda_codec *codec,
+                                           struct hdmi_spec_per_pin *per_pin)
+{
+       struct hdmi_spec *spec = codec->spec;
+       struct snd_jack *jack = NULL;
+       struct hda_jack_tbl *jack_tbl;
+
+       /* if !dyn_pcm_assign, get jack from hda_jack_tbl
+        * in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
+        * NULL even after snd_hda_jack_tbl_clear() is called to
+        * free snd_jack. This may cause access invalid memory
+        * when calling snd_jack_report
+        */
+       if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign) {
+               jack = spec->pcm_rec[per_pin->pcm_idx].jack;
+       } else if (!spec->dyn_pcm_assign) {
+               /*
+                * jack tbl doesn't support DP MST
+                * DP MST will use dyn_pcm_assign,
+                * so DP MST will never come here
+                */
+               jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
+                                                   per_pin->dev_id);
+               if (jack_tbl)
+                       jack = jack_tbl->jack;
+       }
+       return jack;
+}
 /* update ELD and jack state via HD-audio verbs */
 static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
                                         int repoll)
@@ -1568,6 +1599,7 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
        int present;
        bool ret;
        bool do_repoll = false;
+       struct snd_jack *pcm_jack = NULL;
 
        present = snd_hda_jack_pin_sense(codec, pin_nid, dev_id);
 
@@ -1595,10 +1627,19 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
                        do_repoll = true;
        }
 
-       if (do_repoll)
+       if (do_repoll) {
                schedule_delayed_work(&per_pin->work, msecs_to_jiffies(300));
-       else
+       } else {
+               /*
+                * pcm_idx >=0 before update_eld() means it is in monitor
+                * disconnected event. Jack must be fetched before
+                * update_eld().
+                */
+               pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
                update_eld(codec, per_pin, eld);
+               if (!pcm_jack)
+                       pcm_jack = pin_idx_to_pcm_jack(codec, per_pin);
+       }
 
        ret = !repoll || !eld->monitor_present || eld->eld_valid;
 
@@ -1607,38 +1648,32 @@ static bool hdmi_present_sense_via_verbs(struct hdmi_spec_per_pin *per_pin,
                jack->block_report = !ret;
                jack->pin_sense = (eld->monitor_present && eld->eld_valid) ?
                        AC_PINSENSE_PRESENCE : 0;
-       }
-       mutex_unlock(&per_pin->lock);
-       return ret;
-}
 
-static struct snd_jack *pin_idx_to_jack(struct hda_codec *codec,
-                                struct hdmi_spec_per_pin *per_pin)
-{
-       struct hdmi_spec *spec = codec->spec;
-       struct snd_jack *jack = NULL;
-       struct hda_jack_tbl *jack_tbl;
+               if (spec->dyn_pcm_assign && pcm_jack && !do_repoll) {
+                       int state = 0;
+
+                       if (jack->pin_sense & AC_PINSENSE_PRESENCE)
+                               state = SND_JACK_AVOUT;
+                       snd_jack_report(pcm_jack, state);
+               }
 
-       /* if !dyn_pcm_assign, get jack from hda_jack_tbl
-        * in !dyn_pcm_assign case, spec->pcm_rec[].jack is not
-        * NULL even after snd_hda_jack_tbl_clear() is called to
-        * free snd_jack. This may cause access invalid memory
-        * when calling snd_jack_report
-        */
-       if (per_pin->pcm_idx >= 0 && spec->dyn_pcm_assign)
-               jack = spec->pcm_rec[per_pin->pcm_idx].jack;
-       else if (!spec->dyn_pcm_assign) {
                /*
-                * jack tbl doesn't support DP MST
-                * DP MST will use dyn_pcm_assign,
-                * so DP MST will never come here
+                * snd_hda_jack_pin_sense() call at the beginning of this
+                * function, updates jack->pins_sense and clears
+                * jack->jack_dirty, therefore snd_hda_jack_report_sync() will
+                * not override the jack->pin_sense.
+                *
+                * snd_hda_jack_report_sync() is superfluous for dyn_pcm_assign
+                * case. The jack->pin_sense update was already performed, and
+                * hda_jack->jack is NULL for dyn_pcm_assign.
+                *
+                * Don't call snd_hda_jack_report_sync() for
+                * dyn_pcm_assign.
                 */
-               jack_tbl = snd_hda_jack_tbl_get_mst(codec, per_pin->pin_nid,
-                                                   per_pin->dev_id);
-               if (jack_tbl)
-                       jack = jack_tbl->jack;
+               ret = ret && !spec->dyn_pcm_assign;
        }
-       return jack;
+       mutex_unlock(&per_pin->lock);
+       return ret;
 }
 
 /* update ELD and jack state via audio component */
@@ -1674,10 +1709,10 @@ static void sync_eld_via_acomp(struct hda_codec *codec,
        /* pcm_idx >=0 before update_eld() means it is in monitor
         * disconnected event. Jack must be fetched before update_eld()
         */
-       jack = pin_idx_to_jack(codec, per_pin);
+       jack = pin_idx_to_pcm_jack(codec, per_pin);
        changed = update_eld(codec, per_pin, eld);
        if (jack == NULL)
-               jack = pin_idx_to_jack(codec, per_pin);
+               jack = pin_idx_to_pcm_jack(codec, per_pin);
        if (changed && jack)
                snd_jack_report(jack,
                                (eld->monitor_present && eld->eld_valid) ?
@@ -2021,6 +2056,8 @@ static int hdmi_pcm_close(struct hda_pcm_stream *hinfo,
                per_cvt->assigned = 0;
                hinfo->nid = 0;
 
+               azx_stream(get_azx_dev(substream))->stripe = 0;
+
                mutex_lock(&spec->pcm_lock);
                snd_hda_spdif_ctls_unassign(codec, pcm_idx);
                clear_bit(pcm_idx, &spec->pcm_in_use);
@@ -2401,7 +2438,7 @@ static int generic_hdmi_resume(struct hda_codec *codec)
        int pin_idx;
 
        codec->patch_ops.init(codec);
-       regcache_sync(codec->core.regmap);
+       snd_hda_regmap_sync(codec);
 
        for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
                struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx);
@@ -2828,9 +2865,12 @@ static int alloc_intel_hdmi(struct hda_codec *codec)
 /* parse and post-process for Intel codecs */
 static int parse_intel_hdmi(struct hda_codec *codec)
 {
-       int err;
+       int err, retries = 3;
+
+       do {
+               err = hdmi_parse_codec(codec);
+       } while (err < 0 && retries--);
 
-       err = hdmi_parse_codec(codec);
        if (err < 0) {
                generic_spec_free(codec);
                return err;
@@ -4248,6 +4288,7 @@ HDA_CODEC_ENTRY(0x8086280c, "Cannonlake HDMI",    patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280d, "Geminilake HDMI", patch_i915_glk_hdmi),
 HDA_CODEC_ENTRY(0x8086280f, "Icelake HDMI",    patch_i915_icl_hdmi),
 HDA_CODEC_ENTRY(0x80862812, "Tigerlake HDMI",  patch_i915_tgl_hdmi),
+HDA_CODEC_ENTRY(0x8086281a, "Jasperlake HDMI", patch_i915_icl_hdmi),
 HDA_CODEC_ENTRY(0x80862880, "CedarTrail HDMI", patch_generic_hdmi),
 HDA_CODEC_ENTRY(0x80862882, "Valleyview2 HDMI",        patch_i915_byt_hdmi),
 HDA_CODEC_ENTRY(0x80862883, "Braswell HDMI",   patch_i915_byt_hdmi),
index 6d6e34b..3b38a13 100644 (file)
@@ -412,6 +412,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0672:
                alc_update_coef_idx(codec, 0xd, 0, 1<<14); /* EAPD Ctrl */
                break;
+       case 0x10ec0222:
        case 0x10ec0623:
                alc_update_coef_idx(codec, 0x19, 1<<13, 0);
                break;
@@ -430,6 +431,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
                break;
        case 0x10ec0899:
        case 0x10ec0900:
+       case 0x10ec0b00:
        case 0x10ec1168:
        case 0x10ec1220:
                alc_update_coef_idx(codec, 0x7, 1<<1, 0);
@@ -464,10 +466,10 @@ static void set_eapd(struct hda_codec *codec, hda_nid_t nid, int on)
 static void alc_auto_setup_eapd(struct hda_codec *codec, bool on)
 {
        /* We currently only handle front, HP */
-       static hda_nid_t pins[] = {
+       static const hda_nid_t pins[] = {
                0x0f, 0x10, 0x14, 0x15, 0x17, 0
        };
-       hda_nid_t *p;
+       const hda_nid_t *p;
        for (p = pins; *p; p++)
                set_eapd(codec, *p, on);
 }
@@ -501,6 +503,7 @@ static void alc_shutup_pins(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
 
        switch (codec->core.vendor_id) {
+       case 0x10ec0283:
        case 0x10ec0286:
        case 0x10ec0288:
        case 0x10ec0298:
@@ -904,7 +907,7 @@ static int alc_resume(struct hda_codec *codec)
        if (!spec->no_depop_delay)
                msleep(150); /* to avoid pop noise */
        codec->patch_ops.init(codec);
-       regcache_sync(codec->core.regmap);
+       snd_hda_regmap_sync(codec);
        hda_call_check_power_status(codec, 0x01);
        return 0;
 }
@@ -946,7 +949,7 @@ struct alc_codec_rename_pci_table {
        const char *name;
 };
 
-static struct alc_codec_rename_table rename_tbl[] = {
+static const struct alc_codec_rename_table rename_tbl[] = {
        { 0x10ec0221, 0xf00f, 0x1003, "ALC231" },
        { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
        { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
@@ -967,7 +970,7 @@ static struct alc_codec_rename_table rename_tbl[] = {
        { } /* terminator */
 };
 
-static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
+static const struct alc_codec_rename_pci_table rename_pci_tbl[] = {
        { 0x10ec0280, 0x1028, 0, "ALC3220" },
        { 0x10ec0282, 0x1028, 0, "ALC3221" },
        { 0x10ec0283, 0x1028, 0, "ALC3223" },
@@ -1935,19 +1938,19 @@ static void alc889_fixup_dac_route(struct hda_codec *codec,
 {
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
                /* fake the connections during parsing the tree */
-               hda_nid_t conn1[2] = { 0x0c, 0x0d };
-               hda_nid_t conn2[2] = { 0x0e, 0x0f };
-               snd_hda_override_conn_list(codec, 0x14, 2, conn1);
-               snd_hda_override_conn_list(codec, 0x15, 2, conn1);
-               snd_hda_override_conn_list(codec, 0x18, 2, conn2);
-               snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
+               static const hda_nid_t conn1[] = { 0x0c, 0x0d };
+               static const hda_nid_t conn2[] = { 0x0e, 0x0f };
+               snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
+               snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn1), conn1);
+               snd_hda_override_conn_list(codec, 0x18, ARRAY_SIZE(conn2), conn2);
+               snd_hda_override_conn_list(codec, 0x1a, ARRAY_SIZE(conn2), conn2);
        } else if (action == HDA_FIXUP_ACT_PROBE) {
                /* restore the connections */
-               hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
-               snd_hda_override_conn_list(codec, 0x14, 5, conn);
-               snd_hda_override_conn_list(codec, 0x15, 5, conn);
-               snd_hda_override_conn_list(codec, 0x18, 5, conn);
-               snd_hda_override_conn_list(codec, 0x1a, 5, conn);
+               static const hda_nid_t conn[] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
+               snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn), conn);
+               snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn), conn);
+               snd_hda_override_conn_list(codec, 0x18, ARRAY_SIZE(conn), conn);
+               snd_hda_override_conn_list(codec, 0x1a, ARRAY_SIZE(conn), conn);
        }
 }
 
@@ -1955,8 +1958,8 @@ static void alc889_fixup_dac_route(struct hda_codec *codec,
 static void alc889_fixup_mbp_vref(struct hda_codec *codec,
                                  const struct hda_fixup *fix, int action)
 {
+       static const hda_nid_t nids[] = { 0x14, 0x15, 0x19 };
        struct alc_spec *spec = codec->spec;
-       static hda_nid_t nids[3] = { 0x14, 0x15, 0x19 };
        int i;
 
        if (action != HDA_FIXUP_ACT_INIT)
@@ -1992,7 +1995,7 @@ static void alc889_fixup_mac_pins(struct hda_codec *codec,
 static void alc889_fixup_imac91_vref(struct hda_codec *codec,
                                     const struct hda_fixup *fix, int action)
 {
-       static hda_nid_t nids[2] = { 0x18, 0x1a };
+       static const hda_nid_t nids[] = { 0x18, 0x1a };
 
        if (action == HDA_FIXUP_ACT_INIT)
                alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
@@ -2002,7 +2005,7 @@ static void alc889_fixup_imac91_vref(struct hda_codec *codec,
 static void alc889_fixup_mba11_vref(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
-       static hda_nid_t nids[1] = { 0x18 };
+       static const hda_nid_t nids[] = { 0x18 };
 
        if (action == HDA_FIXUP_ACT_INIT)
                alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
@@ -2012,7 +2015,7 @@ static void alc889_fixup_mba11_vref(struct hda_codec *codec,
 static void alc889_fixup_mba21_vref(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
-       static hda_nid_t nids[2] = { 0x18, 0x19 };
+       static const hda_nid_t nids[] = { 0x18, 0x19 };
 
        if (action == HDA_FIXUP_ACT_INIT)
                alc889_fixup_mac_pins(codec, nids, ARRAY_SIZE(nids));
@@ -2094,7 +2097,7 @@ static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
                                     const struct hda_fixup *fix,
                                     int action)
 {
-       hda_nid_t conn1[1] = { 0x0c };
+       static const hda_nid_t conn1[] = { 0x0c };
 
        if (action != HDA_FIXUP_ACT_PRE_PROBE)
                return;
@@ -2103,8 +2106,8 @@ static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
        /* We therefore want to make sure 0x14 (front headphone) and
         * 0x1b (speakers) use the stereo DAC 0x02
         */
-       snd_hda_override_conn_list(codec, 0x14, 1, conn1);
-       snd_hda_override_conn_list(codec, 0x1b, 1, conn1);
+       snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
+       snd_hda_override_conn_list(codec, 0x1b, ARRAY_SIZE(conn1), conn1);
 }
 
 static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
@@ -2525,6 +2528,7 @@ static int patch_alc882(struct hda_codec *codec)
        case 0x10ec0882:
        case 0x10ec0885:
        case 0x10ec0900:
+       case 0x10ec0b00:
        case 0x10ec1220:
                break;
        default:
@@ -2992,7 +2996,7 @@ static void alc269_shutup(struct hda_codec *codec)
        alc_shutup_pins(codec);
 }
 
-static struct coef_fw alc282_coefs[] = {
+static const struct coef_fw alc282_coefs[] = {
        WRITE_COEF(0x03, 0x0002), /* Power Down Control */
        UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
        WRITE_COEF(0x07, 0x0200), /* DMIC control */
@@ -3104,7 +3108,7 @@ static void alc282_shutup(struct hda_codec *codec)
        alc_write_coef_idx(codec, 0x78, coef78);
 }
 
-static struct coef_fw alc283_coefs[] = {
+static const struct coef_fw alc283_coefs[] = {
        WRITE_COEF(0x03, 0x0002), /* Power Down Control */
        UPDATE_COEF(0x05, 0xff3f, 0x0700), /* FIFO and filter clock */
        WRITE_COEF(0x07, 0x0200), /* DMIC control */
@@ -3597,8 +3601,8 @@ static void alc5505_dsp_init(struct hda_codec *codec)
 }
 
 #ifdef HALT_REALTEK_ALC5505
-#define alc5505_dsp_suspend(codec)     /* NOP */
-#define alc5505_dsp_resume(codec)      /* NOP */
+#define alc5505_dsp_suspend(codec)     do { } while (0) /* NOP */
+#define alc5505_dsp_resume(codec)      do { } while (0) /* NOP */
 #else
 #define alc5505_dsp_suspend(codec)     alc5505_dsp_halt(codec)
 #define alc5505_dsp_resume(codec)      alc5505_dsp_back_from_halt(codec)
@@ -3634,7 +3638,7 @@ static int alc269_resume(struct hda_codec *codec)
                msleep(200);
        }
 
-       regcache_sync(codec->core.regmap);
+       snd_hda_regmap_sync(codec);
        hda_call_check_power_status(codec, 0x01);
 
        /* on some machine, the BIOS will clear the codec gpio data when enter
@@ -4180,7 +4184,7 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
        }
 }
 
-static struct coef_fw alc225_pre_hsmode[] = {
+static const struct coef_fw alc225_pre_hsmode[] = {
        UPDATE_COEF(0x4a, 1<<8, 0),
        UPDATE_COEFEX(0x57, 0x05, 1<<14, 0),
        UPDATE_COEF(0x63, 3<<14, 3<<14),
@@ -4193,7 +4197,7 @@ static struct coef_fw alc225_pre_hsmode[] = {
 
 static void alc_headset_mode_unplugged(struct hda_codec *codec)
 {
-       static struct coef_fw coef0255[] = {
+       static const struct coef_fw coef0255[] = {
                WRITE_COEF(0x1b, 0x0c0b), /* LDO and MISC control */
                WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
                UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
@@ -4201,7 +4205,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
                WRITE_COEFEX(0x57, 0x03, 0x8aa6), /* Direct Drive HP Amp control */
                {}
        };
-       static struct coef_fw coef0256[] = {
+       static const struct coef_fw coef0256[] = {
                WRITE_COEF(0x1b, 0x0c4b), /* LDO and MISC control */
                WRITE_COEF(0x45, 0xd089), /* UAJ function set to menual mode */
                WRITE_COEF(0x06, 0x6104), /* Set MIC2 Vref gate with HP */
@@ -4209,7 +4213,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
                UPDATE_COEFEX(0x57, 0x05, 1<<14, 0), /* Direct Drive HP Amp control(Set to verb control)*/
                {}
        };
-       static struct coef_fw coef0233[] = {
+       static const struct coef_fw coef0233[] = {
                WRITE_COEF(0x1b, 0x0c0b),
                WRITE_COEF(0x45, 0xc429),
                UPDATE_COEF(0x35, 0x4000, 0),
@@ -4219,7 +4223,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
                WRITE_COEF(0x32, 0x42a3),
                {}
        };
-       static struct coef_fw coef0288[] = {
+       static const struct coef_fw coef0288[] = {
                UPDATE_COEF(0x4f, 0xfcc0, 0xc400),
                UPDATE_COEF(0x50, 0x2000, 0x2000),
                UPDATE_COEF(0x56, 0x0006, 0x0006),
@@ -4227,18 +4231,18 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
                UPDATE_COEF(0x67, 0x2000, 0),
                {}
        };
-       static struct coef_fw coef0298[] = {
+       static const struct coef_fw coef0298[] = {
                UPDATE_COEF(0x19, 0x1300, 0x0300),
                {}
        };
-       static struct coef_fw coef0292[] = {
+       static const struct coef_fw coef0292[] = {
                WRITE_COEF(0x76, 0x000e),
                WRITE_COEF(0x6c, 0x2400),
                WRITE_COEF(0x18, 0x7308),
                WRITE_COEF(0x6b, 0xc429),
                {}
        };
-       static struct coef_fw coef0293[] = {
+       static const struct coef_fw coef0293[] = {
                UPDATE_COEF(0x10, 7<<8, 6<<8), /* SET Line1 JD to 0 */
                UPDATE_COEFEX(0x57, 0x05, 1<<15|1<<13, 0x0), /* SET charge pump by verb */
                UPDATE_COEFEX(0x57, 0x03, 1<<10, 1<<10), /* SET EN_OSW to 1 */
@@ -4247,16 +4251,16 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
                UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
                {}
        };
-       static struct coef_fw coef0668[] = {
+       static const struct coef_fw coef0668[] = {
                WRITE_COEF(0x15, 0x0d40),
                WRITE_COEF(0xb7, 0x802b),
                {}
        };
-       static struct coef_fw coef0225[] = {
+       static const struct coef_fw coef0225[] = {
                UPDATE_COEF(0x63, 3<<14, 0),
                {}
        };
-       static struct coef_fw coef0274[] = {
+       static const struct coef_fw coef0274[] = {
                UPDATE_COEF(0x4a, 0x0100, 0),
                UPDATE_COEFEX(0x57, 0x05, 0x4000, 0),
                UPDATE_COEF(0x6b, 0xf000, 0x5000),
@@ -4321,25 +4325,25 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
 static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
                                    hda_nid_t mic_pin)
 {
-       static struct coef_fw coef0255[] = {
+       static const struct coef_fw coef0255[] = {
                WRITE_COEFEX(0x57, 0x03, 0x8aa6),
                WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
                {}
        };
-       static struct coef_fw coef0256[] = {
+       static const struct coef_fw coef0256[] = {
                UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14), /* Direct Drive HP Amp control(Set to verb control)*/
                WRITE_COEFEX(0x57, 0x03, 0x09a3),
                WRITE_COEF(0x06, 0x6100), /* Set MIC2 Vref gate to normal */
                {}
        };
-       static struct coef_fw coef0233[] = {
+       static const struct coef_fw coef0233[] = {
                UPDATE_COEF(0x35, 0, 1<<14),
                WRITE_COEF(0x06, 0x2100),
                WRITE_COEF(0x1a, 0x0021),
                WRITE_COEF(0x26, 0x008c),
                {}
        };
-       static struct coef_fw coef0288[] = {
+       static const struct coef_fw coef0288[] = {
                UPDATE_COEF(0x4f, 0x00c0, 0),
                UPDATE_COEF(0x50, 0x2000, 0),
                UPDATE_COEF(0x56, 0x0006, 0),
@@ -4348,30 +4352,30 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
                UPDATE_COEF(0x67, 0x2000, 0x2000),
                {}
        };
-       static struct coef_fw coef0292[] = {
+       static const struct coef_fw coef0292[] = {
                WRITE_COEF(0x19, 0xa208),
                WRITE_COEF(0x2e, 0xacf0),
                {}
        };
-       static struct coef_fw coef0293[] = {
+       static const struct coef_fw coef0293[] = {
                UPDATE_COEFEX(0x57, 0x05, 0, 1<<15|1<<13), /* SET charge pump by verb */
                UPDATE_COEFEX(0x57, 0x03, 1<<10, 0), /* SET EN_OSW to 0 */
                UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
                {}
        };
-       static struct coef_fw coef0688[] = {
+       static const struct coef_fw coef0688[] = {
                WRITE_COEF(0xb7, 0x802b),
                WRITE_COEF(0xb5, 0x1040),
                UPDATE_COEF(0xc3, 0, 1<<12),
                {}
        };
-       static struct coef_fw coef0225[] = {
+       static const struct coef_fw coef0225[] = {
                UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14),
                UPDATE_COEF(0x4a, 3<<4, 2<<4),
                UPDATE_COEF(0x63, 3<<14, 0),
                {}
        };
-       static struct coef_fw coef0274[] = {
+       static const struct coef_fw coef0274[] = {
                UPDATE_COEFEX(0x57, 0x05, 0x4000, 0x4000),
                UPDATE_COEF(0x4a, 0x0010, 0),
                UPDATE_COEF(0x6b, 0xf000, 0),
@@ -4457,7 +4461,7 @@ 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[] = {
+       static const struct coef_fw coef0225[] = {
                UPDATE_COEF(0x45, 0x3f<<10, 0x30<<10),
                UPDATE_COEF(0x45, 0x3f<<10, 0x31<<10),
                UPDATE_COEF(0x49, 3<<8, 0<<8),
@@ -4466,14 +4470,14 @@ static void alc_headset_mode_default(struct hda_codec *codec)
                UPDATE_COEF(0x67, 0xf000, 0x3000),
                {}
        };
-       static struct coef_fw coef0255[] = {
+       static const struct coef_fw coef0255[] = {
                WRITE_COEF(0x45, 0xc089),
                WRITE_COEF(0x45, 0xc489),
                WRITE_COEFEX(0x57, 0x03, 0x8ea6),
                WRITE_COEF(0x49, 0x0049),
                {}
        };
-       static struct coef_fw coef0256[] = {
+       static const struct coef_fw coef0256[] = {
                WRITE_COEF(0x45, 0xc489),
                WRITE_COEFEX(0x57, 0x03, 0x0da3),
                WRITE_COEF(0x49, 0x0049),
@@ -4481,12 +4485,12 @@ static void alc_headset_mode_default(struct hda_codec *codec)
                WRITE_COEF(0x06, 0x6100),
                {}
        };
-       static struct coef_fw coef0233[] = {
+       static const struct coef_fw coef0233[] = {
                WRITE_COEF(0x06, 0x2100),
                WRITE_COEF(0x32, 0x4ea3),
                {}
        };
-       static struct coef_fw coef0288[] = {
+       static const struct coef_fw coef0288[] = {
                UPDATE_COEF(0x4f, 0xfcc0, 0xc400), /* Set to TRS type */
                UPDATE_COEF(0x50, 0x2000, 0x2000),
                UPDATE_COEF(0x56, 0x0006, 0x0006),
@@ -4494,26 +4498,26 @@ static void alc_headset_mode_default(struct hda_codec *codec)
                UPDATE_COEF(0x67, 0x2000, 0),
                {}
        };
-       static struct coef_fw coef0292[] = {
+       static const struct coef_fw coef0292[] = {
                WRITE_COEF(0x76, 0x000e),
                WRITE_COEF(0x6c, 0x2400),
                WRITE_COEF(0x6b, 0xc429),
                WRITE_COEF(0x18, 0x7308),
                {}
        };
-       static struct coef_fw coef0293[] = {
+       static const struct coef_fw coef0293[] = {
                UPDATE_COEF(0x4a, 0x000f, 0x000e), /* Combo Jack auto detect */
                WRITE_COEF(0x45, 0xC429), /* Set to TRS type */
                UPDATE_COEF(0x1a, 1<<3, 0), /* Combo JD gating without LINE1-VREFO */
                {}
        };
-       static struct coef_fw coef0688[] = {
+       static const struct coef_fw coef0688[] = {
                WRITE_COEF(0x11, 0x0041),
                WRITE_COEF(0x15, 0x0d40),
                WRITE_COEF(0xb7, 0x802b),
                {}
        };
-       static struct coef_fw coef0274[] = {
+       static const struct coef_fw coef0274[] = {
                WRITE_COEF(0x45, 0x4289),
                UPDATE_COEF(0x4a, 0x0010, 0x0010),
                UPDATE_COEF(0x6b, 0x0f00, 0),
@@ -4576,53 +4580,53 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
 {
        int val;
 
-       static struct coef_fw coef0255[] = {
+       static const struct coef_fw coef0255[] = {
                WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
                WRITE_COEF(0x1b, 0x0c2b),
                WRITE_COEFEX(0x57, 0x03, 0x8ea6),
                {}
        };
-       static struct coef_fw coef0256[] = {
+       static const struct coef_fw coef0256[] = {
                WRITE_COEF(0x45, 0xd489), /* Set to CTIA type */
                WRITE_COEF(0x1b, 0x0e6b),
                {}
        };
-       static struct coef_fw coef0233[] = {
+       static const struct coef_fw coef0233[] = {
                WRITE_COEF(0x45, 0xd429),
                WRITE_COEF(0x1b, 0x0c2b),
                WRITE_COEF(0x32, 0x4ea3),
                {}
        };
-       static struct coef_fw coef0288[] = {
+       static const struct coef_fw coef0288[] = {
                UPDATE_COEF(0x50, 0x2000, 0x2000),
                UPDATE_COEF(0x56, 0x0006, 0x0006),
                UPDATE_COEF(0x66, 0x0008, 0),
                UPDATE_COEF(0x67, 0x2000, 0),
                {}
        };
-       static struct coef_fw coef0292[] = {
+       static const struct coef_fw coef0292[] = {
                WRITE_COEF(0x6b, 0xd429),
                WRITE_COEF(0x76, 0x0008),
                WRITE_COEF(0x18, 0x7388),
                {}
        };
-       static struct coef_fw coef0293[] = {
+       static const struct coef_fw coef0293[] = {
                WRITE_COEF(0x45, 0xd429), /* Set to ctia type */
                UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
                {}
        };
-       static struct coef_fw coef0688[] = {
+       static const struct coef_fw coef0688[] = {
                WRITE_COEF(0x11, 0x0001),
                WRITE_COEF(0x15, 0x0d60),
                WRITE_COEF(0xc3, 0x0000),
                {}
        };
-       static struct coef_fw coef0225_1[] = {
+       static const struct coef_fw coef0225_1[] = {
                UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
                UPDATE_COEF(0x63, 3<<14, 2<<14),
                {}
        };
-       static struct coef_fw coef0225_2[] = {
+       static const struct coef_fw coef0225_2[] = {
                UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
                UPDATE_COEF(0x63, 3<<14, 1<<14),
                {}
@@ -4694,48 +4698,48 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
 /* Nokia type */
 static void alc_headset_mode_omtp(struct hda_codec *codec)
 {
-       static struct coef_fw coef0255[] = {
+       static const struct coef_fw coef0255[] = {
                WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
                WRITE_COEF(0x1b, 0x0c2b),
                WRITE_COEFEX(0x57, 0x03, 0x8ea6),
                {}
        };
-       static struct coef_fw coef0256[] = {
+       static const struct coef_fw coef0256[] = {
                WRITE_COEF(0x45, 0xe489), /* Set to OMTP Type */
                WRITE_COEF(0x1b, 0x0e6b),
                {}
        };
-       static struct coef_fw coef0233[] = {
+       static const struct coef_fw coef0233[] = {
                WRITE_COEF(0x45, 0xe429),
                WRITE_COEF(0x1b, 0x0c2b),
                WRITE_COEF(0x32, 0x4ea3),
                {}
        };
-       static struct coef_fw coef0288[] = {
+       static const struct coef_fw coef0288[] = {
                UPDATE_COEF(0x50, 0x2000, 0x2000),
                UPDATE_COEF(0x56, 0x0006, 0x0006),
                UPDATE_COEF(0x66, 0x0008, 0),
                UPDATE_COEF(0x67, 0x2000, 0),
                {}
        };
-       static struct coef_fw coef0292[] = {
+       static const struct coef_fw coef0292[] = {
                WRITE_COEF(0x6b, 0xe429),
                WRITE_COEF(0x76, 0x0008),
                WRITE_COEF(0x18, 0x7388),
                {}
        };
-       static struct coef_fw coef0293[] = {
+       static const struct coef_fw coef0293[] = {
                WRITE_COEF(0x45, 0xe429), /* Set to omtp type */
                UPDATE_COEF(0x10, 7<<8, 7<<8), /* SET Line1 JD to 1 */
                {}
        };
-       static struct coef_fw coef0688[] = {
+       static const struct coef_fw coef0688[] = {
                WRITE_COEF(0x11, 0x0001),
                WRITE_COEF(0x15, 0x0d50),
                WRITE_COEF(0xc3, 0x0000),
                {}
        };
-       static struct coef_fw coef0225[] = {
+       static const struct coef_fw coef0225[] = {
                UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10),
                UPDATE_COEF(0x63, 3<<14, 2<<14),
                {}
@@ -4795,17 +4799,17 @@ static void alc_determine_headset_type(struct hda_codec *codec)
        int val;
        bool is_ctia = false;
        struct alc_spec *spec = codec->spec;
-       static struct coef_fw coef0255[] = {
+       static const struct coef_fw coef0255[] = {
                WRITE_COEF(0x45, 0xd089), /* combo jack auto switch control(Check type)*/
                WRITE_COEF(0x49, 0x0149), /* combo jack auto switch control(Vref
  conteol) */
                {}
        };
-       static struct coef_fw coef0288[] = {
+       static const struct coef_fw coef0288[] = {
                UPDATE_COEF(0x4f, 0xfcc0, 0xd400), /* Check Type */
                {}
        };
-       static struct coef_fw coef0298[] = {
+       static const struct coef_fw coef0298[] = {
                UPDATE_COEF(0x50, 0x2000, 0x2000),
                UPDATE_COEF(0x56, 0x0006, 0x0006),
                UPDATE_COEF(0x66, 0x0008, 0),
@@ -4813,19 +4817,19 @@ static void alc_determine_headset_type(struct hda_codec *codec)
                UPDATE_COEF(0x19, 0x1300, 0x1300),
                {}
        };
-       static struct coef_fw coef0293[] = {
+       static const struct coef_fw coef0293[] = {
                UPDATE_COEF(0x4a, 0x000f, 0x0008), /* Combo Jack auto detect */
                WRITE_COEF(0x45, 0xD429), /* Set to ctia type */
                {}
        };
-       static struct coef_fw coef0688[] = {
+       static const struct coef_fw coef0688[] = {
                WRITE_COEF(0x11, 0x0001),
                WRITE_COEF(0xb7, 0x802b),
                WRITE_COEF(0x15, 0x0d60),
                WRITE_COEF(0xc3, 0x0c00),
                {}
        };
-       static struct coef_fw coef0274[] = {
+       static const struct coef_fw coef0274[] = {
                UPDATE_COEF(0x4a, 0x0010, 0),
                UPDATE_COEF(0x4a, 0x8000, 0),
                WRITE_COEF(0x45, 0xd289),
@@ -5112,7 +5116,7 @@ static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
 static void alc255_set_default_jack_type(struct hda_codec *codec)
 {
        /* Set to iphone type */
-       static struct coef_fw alc255fw[] = {
+       static const struct coef_fw alc255fw[] = {
                WRITE_COEF(0x1b, 0x880b),
                WRITE_COEF(0x45, 0xd089),
                WRITE_COEF(0x1b, 0x080b),
@@ -5120,7 +5124,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
                WRITE_COEF(0x1b, 0x0c0b),
                {}
        };
-       static struct coef_fw alc256fw[] = {
+       static const struct coef_fw alc256fw[] = {
                WRITE_COEF(0x1b, 0x884b),
                WRITE_COEF(0x45, 0xd089),
                WRITE_COEF(0x1b, 0x084b),
@@ -5243,7 +5247,7 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
         * the speaker output becomes too low by some reason on Thinkpads with
         * ALC298 codec
         */
-       static hda_nid_t preferred_pairs[] = {
+       static const hda_nid_t preferred_pairs[] = {
                0x14, 0x03, 0x17, 0x02, 0x21, 0x02,
                0
        };
@@ -5515,9 +5519,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
                /* DAC node 0x03 is giving mono output. We therefore want to
                   make sure 0x14 (front speaker) and 0x15 (headphones) use the
                   stereo DAC, while leaving 0x17 (bass speaker) for node 0x03. */
-               hda_nid_t conn1[2] = { 0x0c };
-               snd_hda_override_conn_list(codec, 0x14, 1, conn1);
-               snd_hda_override_conn_list(codec, 0x15, 1, conn1);
+               static const hda_nid_t conn1[] = { 0x0c };
+               snd_hda_override_conn_list(codec, 0x14, ARRAY_SIZE(conn1), conn1);
+               snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn1), conn1);
        }
 }
 
@@ -5532,8 +5536,8 @@ static void alc298_fixup_speaker_volume(struct hda_codec *codec,
                   Pin Complex), since Node 0x02 has Amp-out caps, we can adjust
                   speaker's volume now. */
 
-               hda_nid_t conn1[1] = { 0x0c };
-               snd_hda_override_conn_list(codec, 0x17, 1, conn1);
+               static const hda_nid_t conn1[] = { 0x0c };
+               snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn1), conn1);
        }
 }
 
@@ -5542,8 +5546,8 @@ static void alc295_fixup_disable_dac3(struct hda_codec *codec,
                                      const struct hda_fixup *fix, int action)
 {
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-               hda_nid_t conn[2] = { 0x02, 0x03 };
-               snd_hda_override_conn_list(codec, 0x17, 2, conn);
+               static const hda_nid_t conn[] = { 0x02, 0x03 };
+               snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
        }
 }
 
@@ -5552,8 +5556,8 @@ static void alc285_fixup_speaker2_to_dac1(struct hda_codec *codec,
                                          const struct hda_fixup *fix, int action)
 {
        if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-               hda_nid_t conn[1] = { 0x02 };
-               snd_hda_override_conn_list(codec, 0x17, 1, conn);
+               static const hda_nid_t conn[] = { 0x02 };
+               snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
        }
 }
 
@@ -5631,7 +5635,7 @@ static void alc274_fixup_bind_dacs(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action)
 {
        struct alc_spec *spec = codec->spec;
-       static hda_nid_t preferred_pairs[] = {
+       static const hda_nid_t preferred_pairs[] = {
                0x21, 0x03, 0x1b, 0x03, 0x16, 0x02,
                0
        };
@@ -5844,6 +5848,7 @@ enum {
        ALC288_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC288_FIXUP_DELL_XPS_13,
        ALC288_FIXUP_DISABLE_AAMIX,
+       ALC292_FIXUP_DELL_E7X_AAMIX,
        ALC292_FIXUP_DELL_E7X,
        ALC292_FIXUP_DISABLE_AAMIX,
        ALC293_FIXUP_DISABLE_AAMIX_MULTIJACK,
@@ -5904,9 +5909,12 @@ enum {
        ALC256_FIXUP_ASUS_HEADSET_MIC,
        ALC256_FIXUP_ASUS_MIC_NO_PRESENCE,
        ALC299_FIXUP_PREDATOR_SPK,
-       ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC,
        ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE,
-       ALC294_FIXUP_ASUS_INTSPK_GPIO,
+       ALC289_FIXUP_DELL_SPK2,
+       ALC289_FIXUP_DUAL_SPK,
+       ALC294_FIXUP_SPK2_TO_DAC1,
+       ALC294_FIXUP_ASUS_DUAL_SPK,
+
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -6536,12 +6544,19 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC293_FIXUP_DELL1_MIC_NO_PRESENCE
        },
-       [ALC292_FIXUP_DELL_E7X] = {
+       [ALC292_FIXUP_DELL_E7X_AAMIX] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_dell_xps13,
                .chained = true,
                .chain_id = ALC292_FIXUP_DISABLE_AAMIX
        },
+       [ALC292_FIXUP_DELL_E7X] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = snd_hda_gen_fixup_micmute_led,
+               /* micmute fixup must be applied at last */
+               .chained_before = true,
+               .chain_id = ALC292_FIXUP_DELL_E7X_AAMIX,
+       },
        [ALC298_FIXUP_ALIENWARE_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
@@ -6981,33 +6996,45 @@ static const struct hda_fixup alc269_fixups[] = {
                        { }
                }
        },
-       [ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC] = {
+       [ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
-                       { 0x14, 0x411111f0 }, /* disable confusing internal speaker */
-                       { 0x19, 0x04a11150 }, /* use as headset mic, without its own jack detect */
+                       { 0x19, 0x04a11040 },
+                       { 0x21, 0x04211020 },
                        { }
                },
                .chained = true,
-               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+               .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
        },
-       [ALC256_FIXUP_MEDION_HEADSET_NO_PRESENCE] = {
+       [ALC289_FIXUP_DELL_SPK2] = {
                .type = HDA_FIXUP_PINS,
                .v.pins = (const struct hda_pintbl[]) {
-                       { 0x19, 0x04a11040 },
-                       { 0x21, 0x04211020 },
+                       { 0x17, 0x90170130 }, /* bass spk */
                        { }
                },
                .chained = true,
-               .chain_id = ALC256_FIXUP_ASUS_HEADSET_MODE
+               .chain_id = ALC269_FIXUP_DELL4_MIC_NO_PRESENCE
+       },
+       [ALC289_FIXUP_DUAL_SPK] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_speaker2_to_dac1,
+               .chained = true,
+               .chain_id = ALC289_FIXUP_DELL_SPK2
        },
-       [ALC294_FIXUP_ASUS_INTSPK_GPIO] = {
+       [ALC294_FIXUP_SPK2_TO_DAC1] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_speaker2_to_dac1,
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_HEADSET_MIC
+       },
+       [ALC294_FIXUP_ASUS_DUAL_SPK] = {
                .type = HDA_FIXUP_FUNC,
                /* The GPIO must be pulled to initialize the AMP */
                .v.func = alc_fixup_gpio4,
                .chained = true,
-               .chain_id = ALC294_FIXUP_ASUS_INTSPK_HEADSET_MIC
+               .chain_id = ALC294_FIXUP_SPK2_TO_DAC1
        },
+
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -7080,6 +7107,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x08ad, "Dell WYSE AIO", ALC225_FIXUP_DELL_WYSE_AIO_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x08ae, "Dell WYSE NB", ALC225_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
+       SND_PCI_QUIRK(0x1028, 0x097e, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
+       SND_PCI_QUIRK(0x1028, 0x097d, "Dell Precision", ALC289_FIXUP_DUAL_SPK),
        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),
@@ -7167,7 +7196,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_ASUS_ZENBOOK),
        SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_ASUS_ZENBOOK_UX31A),
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
-       SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_INTSPK_GPIO),
+       SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
        SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
        SND_PCI_QUIRK(0x1043, 0x1a30, "ASUS X705UD", ALC256_FIXUP_ASUS_MIC),
@@ -7239,6 +7268,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x224c, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x224d, "Thinkpad", ALC298_FIXUP_TPT470_DOCK),
        SND_PCI_QUIRK(0x17aa, 0x225d, "Thinkpad T480", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x17aa, 0x2292, "Thinkpad X1 Yoga 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1),
        SND_PCI_QUIRK(0x17aa, 0x2293, "Thinkpad X1 Carbon 7th", ALC285_FIXUP_SPEAKER2_TO_DAC1),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
@@ -7643,11 +7673,6 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x1a, 0x90a70130},
                {0x1b, 0x90170110},
                {0x21, 0x03211020}),
-       SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB,
-               {0x12, 0xb7a60130},
-               {0x13, 0xb8a61140},
-               {0x16, 0x90170110},
-               {0x21, 0x04211020}),
        SND_HDA_PIN_QUIRK(0x10ec0280, 0x103c, "HP", ALC280_FIXUP_HP_GPIO4,
                {0x12, 0x90a60130},
                {0x14, 0x90170110},
@@ -7841,6 +7866,9 @@ static const struct snd_hda_pin_quirk alc269_fallback_pin_fixup_tbl[] = {
        SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
                {0x19, 0x40000000},
                {0x1a, 0x40000000}),
+       SND_HDA_PIN_QUIRK(0x10ec0274, 0x1028, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB,
+               {0x19, 0x40000000},
+               {0x1a, 0x40000000}),
        {}
 };
 
@@ -8456,7 +8484,30 @@ static void alc662_fixup_aspire_ethos_hp(struct hda_codec *codec,
        }
 }
 
-static struct coef_fw alc668_coefs[] = {
+static void alc671_fixup_hp_headset_mic2(struct hda_codec *codec,
+                                            const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       static const struct hda_pintbl pincfgs[] = {
+               { 0x19, 0x02a11040 }, /* use as headset mic, with its own jack detect */
+               { 0x1b, 0x0181304f },
+               { }
+       };
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               spec->gen.mixer_nid = 0;
+               spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
+               snd_hda_apply_pincfgs(codec, pincfgs);
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               alc_write_coef_idx(codec, 0x19, 0xa054);
+               break;
+       }
+}
+
+static const struct coef_fw alc668_coefs[] = {
        WRITE_COEF(0x01, 0xbebe), WRITE_COEF(0x02, 0xaaaa), WRITE_COEF(0x03,    0x0),
        WRITE_COEF(0x04, 0x0180), WRITE_COEF(0x06,    0x0), WRITE_COEF(0x07, 0x0f80),
        WRITE_COEF(0x08, 0x0031), WRITE_COEF(0x0a, 0x0060), WRITE_COEF(0x0b,    0x0),
@@ -8529,6 +8580,7 @@ enum {
        ALC662_FIXUP_LENOVO_MULTI_CODECS,
        ALC669_FIXUP_ACER_ASPIRE_ETHOS,
        ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET,
+       ALC671_FIXUP_HP_HEADSET_MIC2,
 };
 
 static const struct hda_fixup alc662_fixups[] = {
@@ -8870,6 +8922,10 @@ static const struct hda_fixup alc662_fixups[] = {
                .chained = true,
                .chain_id = ALC669_FIXUP_ACER_ASPIRE_ETHOS_HEADSET
        },
+       [ALC671_FIXUP_HP_HEADSET_MIC2] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc671_fixup_hp_headset_mic2,
+       },
 };
 
 static const struct snd_pci_quirk alc662_fixup_tbl[] = {
@@ -9052,6 +9108,22 @@ static const struct snd_hda_pin_quirk alc662_pin_fixup_tbl[] = {
                {0x12, 0x90a60130},
                {0x14, 0x90170110},
                {0x15, 0x0321101f}),
+       SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
+               {0x14, 0x01014010},
+               {0x17, 0x90170150},
+               {0x1b, 0x01813030},
+               {0x21, 0x02211020}),
+       SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
+               {0x14, 0x01014010},
+               {0x18, 0x01a19040},
+               {0x1b, 0x01813030},
+               {0x21, 0x02211020}),
+       SND_HDA_PIN_QUIRK(0x10ec0671, 0x103c, "HP cPC", ALC671_FIXUP_HP_HEADSET_MIC2,
+               {0x14, 0x01014020},
+               {0x17, 0x90170110},
+               {0x18, 0x01a19050},
+               {0x1b, 0x01813040},
+               {0x21, 0x02211030}),
        {}
 };
 
@@ -9239,6 +9311,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0892, "ALC892", patch_alc662),
        HDA_CODEC_ENTRY(0x10ec0899, "ALC898", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec0900, "ALC1150", patch_alc882),
+       HDA_CODEC_ENTRY(0x10ec0b00, "ALCS1200A", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec1168, "ALC1220", patch_alc882),
        HDA_CODEC_ENTRY(0x10ec1220, "ALC1220", patch_alc882),
        {} /* terminator */
index 894f3f5..a608d04 100644 (file)
@@ -795,7 +795,7 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
 static bool has_builtin_speaker(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
-       hda_nid_t *nid_pin;
+       const hda_nid_t *nid_pin;
        int nids, i;
 
        if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) {
@@ -825,11 +825,11 @@ static int stac_auto_create_beep_ctls(struct hda_codec *codec,
        struct sigmatel_spec *spec = codec->spec;
        u32 caps = query_amp_caps(codec, nid, HDA_OUTPUT);
        struct snd_kcontrol_new *knew;
-       static struct snd_kcontrol_new abeep_mute_ctl =
+       static const struct snd_kcontrol_new abeep_mute_ctl =
                HDA_CODEC_MUTE(NULL, 0, 0, 0);
-       static struct snd_kcontrol_new dbeep_mute_ctl =
+       static const struct snd_kcontrol_new dbeep_mute_ctl =
                HDA_CODEC_MUTE_BEEP(NULL, 0, 0, 0);
-       static struct snd_kcontrol_new beep_vol_ctl =
+       static const struct snd_kcontrol_new beep_vol_ctl =
                HDA_CODEC_VOLUME(NULL, 0, 0, 0);
 
        /* check for mute support for the the amp */
@@ -2182,7 +2182,7 @@ static void hp_envy_ts_fixup_dac_bind(struct hda_codec *codec,
                                            int action)
 {
        struct sigmatel_spec *spec = codec->spec;
-       static hda_nid_t preferred_pairs[] = {
+       static const hda_nid_t preferred_pairs[] = {
                0xd, 0x13,
                0
        };
@@ -4908,7 +4908,7 @@ static int patch_stac927x(struct hda_codec *codec)
         * The below flag enables the longer delay (see get_response
         * in hda_intel.c).
         */
-       codec->bus->needs_damn_long_delay = 1;
+       codec->bus->core.needs_damn_long_delay = 1;
 
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
 
index 29dcdb8..7ef8f31 100644 (file)
@@ -396,7 +396,7 @@ static int via_resume(struct hda_codec *codec)
        /* some delay here to make jack detection working (bko#98921) */
        msleep(10);
        codec->patch_ops.init(codec);
-       regcache_sync(codec->core.regmap);
+       snd_hda_regmap_sync(codec);
        return 0;
 }
 #endif
@@ -1038,8 +1038,8 @@ static const struct snd_pci_quirk vt2002p_fixups[] = {
  */
 static void fix_vt1802_connections(struct hda_codec *codec)
 {
-       static hda_nid_t conn_24[] = { 0x14, 0x1c };
-       static hda_nid_t conn_33[] = { 0x1c };
+       static const hda_nid_t conn_24[] = { 0x14, 0x1c };
+       static const hda_nid_t conn_33[] = { 0x1c };
 
        snd_hda_override_conn_list(codec, 0x24, ARRAY_SIZE(conn_24), conn_24);
        snd_hda_override_conn_list(codec, 0x33, ARRAY_SIZE(conn_33), conn_33);
index 4556ba7..9a30f6d 100644 (file)
@@ -1389,7 +1389,7 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl
  * mixers
  */
 
-static struct snd_kcontrol_new aureon_dac_controls[] = {
+static const struct snd_kcontrol_new aureon_dac_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -1504,7 +1504,7 @@ static struct snd_kcontrol_new aureon_dac_controls[] = {
        }
 };
 
-static struct snd_kcontrol_new wm_controls[] = {
+static const struct snd_kcontrol_new wm_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "PCM Playback Switch",
@@ -1570,7 +1570,7 @@ static struct snd_kcontrol_new wm_controls[] = {
        }
 };
 
-static struct snd_kcontrol_new ac97_controls[] = {
+static const struct snd_kcontrol_new ac97_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "AC97 Playback Switch",
@@ -1675,7 +1675,7 @@ static struct snd_kcontrol_new ac97_controls[] = {
        }
 };
 
-static struct snd_kcontrol_new universe_ac97_controls[] = {
+static const struct snd_kcontrol_new universe_ac97_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "AC97 Playback Switch",
@@ -1807,7 +1807,7 @@ static struct snd_kcontrol_new universe_ac97_controls[] = {
 
 };
 
-static struct snd_kcontrol_new cs8415_controls[] = {
+static const struct snd_kcontrol_new cs8415_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = SNDRV_CTL_NAME_IEC958("", CAPTURE, SWITCH),
@@ -2133,7 +2133,7 @@ static int aureon_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char aureon51_eeprom[] = {
+static const unsigned char aureon51_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x0a,  /* clock 512, spdif-in/ADC, 3DACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
@@ -2149,7 +2149,7 @@ static unsigned char aureon51_eeprom[] = {
        [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static unsigned char aureon71_eeprom[] = {
+static const unsigned char aureon71_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x0b,  /* clock 512, spdif-in/ADC, 4DACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
@@ -2166,7 +2166,7 @@ static unsigned char aureon71_eeprom[] = {
 };
 #define prodigy71_eeprom aureon71_eeprom
 
-static unsigned char aureon71_universe_eeprom[] = {
+static const unsigned char aureon71_universe_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401, spdif-in/ADC,
                                         * 4DACs
                                         */
@@ -2184,7 +2184,7 @@ static unsigned char aureon71_universe_eeprom[] = {
        [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static unsigned char prodigy71lt_eeprom[] = {
+static const unsigned char prodigy71lt_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x4b,  /* clock 384, spdif-in/ADC, 4DACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xfc,  /* vol, 96k, 24bit, 192k */
index 519c9fb..8192906 100644 (file)
@@ -753,15 +753,15 @@ static int snd_ice1712_delta_init(struct snd_ice1712 *ice)
  * additional controls for M-Audio cards
  */
 
-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select =
+static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
-static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select =
+static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0);
-static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status =
+static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
-static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select =
+static const struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
-static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status =
+static const struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status =
 ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
 
 
index fe08dd9..3794308 100644 (file)
@@ -597,7 +597,7 @@ static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct sn
        return val != nval;
 }
 
-static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] = {
+static const struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Input Sensitivity Switch",
@@ -792,7 +792,7 @@ static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct
   .private_value = xshift | (xinvert << 8),\
 }
 
-static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] = {
+static const struct snd_kcontrol_new snd_ice1712_ews88d_controls[] = {
        EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */
        EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0),
        EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0),
@@ -928,7 +928,7 @@ static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, str
   .private_value = xshift | (xinvert << 8),\
 }
 
-static struct snd_kcontrol_new snd_ice1712_6fire_controls[] = {
+static const struct snd_kcontrol_new snd_ice1712_6fire_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Analog Input Select",
index deadba4..884d0cd 100644 (file)
@@ -480,21 +480,6 @@ static irqreturn_t snd_ice1712_interrupt(int irq, void *dev_id)
 
 
 /*
- *  PCM part - misc
- */
-
-static int snd_ice1712_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_ice1712_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
-/*
  *  PCM part - consumer I/O
  */
 
@@ -836,9 +821,6 @@ static int snd_ice1712_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_ice1712_playback_ops = {
        .open =         snd_ice1712_playback_open,
        .close =        snd_ice1712_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ice1712_hw_params,
-       .hw_free =      snd_ice1712_hw_free,
        .prepare =      snd_ice1712_playback_prepare,
        .trigger =      snd_ice1712_playback_trigger,
        .pointer =      snd_ice1712_playback_pointer,
@@ -847,9 +829,6 @@ static const struct snd_pcm_ops snd_ice1712_playback_ops = {
 static const struct snd_pcm_ops snd_ice1712_playback_ds_ops = {
        .open =         snd_ice1712_playback_ds_open,
        .close =        snd_ice1712_playback_ds_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ice1712_hw_params,
-       .hw_free =      snd_ice1712_hw_free,
        .prepare =      snd_ice1712_playback_ds_prepare,
        .trigger =      snd_ice1712_playback_ds_trigger,
        .pointer =      snd_ice1712_playback_ds_pointer,
@@ -858,9 +837,6 @@ static const struct snd_pcm_ops snd_ice1712_playback_ds_ops = {
 static const struct snd_pcm_ops snd_ice1712_capture_ops = {
        .open =         snd_ice1712_capture_open,
        .close =        snd_ice1712_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_ice1712_hw_params,
-       .hw_free =      snd_ice1712_hw_free,
        .prepare =      snd_ice1712_capture_prepare,
        .trigger =      snd_ice1712_capture_trigger,
        .pointer =      snd_ice1712_capture_pointer,
@@ -883,9 +859,8 @@ static int snd_ice1712_pcm(struct snd_ice1712 *ice, int device)
        strcpy(pcm->name, "ICE1712 consumer");
        ice->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &ice->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &ice->pci->dev, 64*1024, 64*1024);
 
        dev_warn(ice->card->dev,
                 "Consumer PCM code does not work well at the moment --jk\n");
@@ -909,9 +884,8 @@ static int snd_ice1712_pcm_ds(struct snd_ice1712 *ice, int device)
        strcpy(pcm->name, "ICE1712 consumer (DS)");
        ice->pcm_ds = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &ice->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &ice->pci->dev, 64*1024, 128*1024);
 
        return 0;
 }
@@ -1063,7 +1037,7 @@ static int snd_ice1712_playback_pro_hw_params(struct snd_pcm_substream *substrea
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
        snd_ice1712_set_pro_rate(ice, params_rate(hw_params), 0);
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+       return 0;
 }
 
 static int snd_ice1712_capture_pro_prepare(struct snd_pcm_substream *substream)
@@ -1085,7 +1059,7 @@ static int snd_ice1712_capture_pro_hw_params(struct snd_pcm_substream *substream
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
 
        snd_ice1712_set_pro_rate(ice, params_rate(hw_params), 0);
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+       return 0;
 }
 
 static snd_pcm_uframes_t snd_ice1712_playback_pro_pointer(struct snd_pcm_substream *substream)
@@ -1219,9 +1193,7 @@ static int snd_ice1712_capture_pro_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_ice1712_playback_pro_ops = {
        .open =         snd_ice1712_playback_pro_open,
        .close =        snd_ice1712_playback_pro_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_ice1712_playback_pro_hw_params,
-       .hw_free =      snd_ice1712_hw_free,
        .prepare =      snd_ice1712_playback_pro_prepare,
        .trigger =      snd_ice1712_pro_trigger,
        .pointer =      snd_ice1712_playback_pro_pointer,
@@ -1230,9 +1202,7 @@ static const struct snd_pcm_ops snd_ice1712_playback_pro_ops = {
 static const struct snd_pcm_ops snd_ice1712_capture_pro_ops = {
        .open =         snd_ice1712_capture_pro_open,
        .close =        snd_ice1712_capture_pro_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_ice1712_capture_pro_hw_params,
-       .hw_free =      snd_ice1712_hw_free,
        .prepare =      snd_ice1712_capture_pro_prepare,
        .trigger =      snd_ice1712_pro_trigger,
        .pointer =      snd_ice1712_capture_pro_pointer,
@@ -1254,9 +1224,8 @@ static int snd_ice1712_pcm_profi(struct snd_ice1712 *ice, int device)
        pcm->info_flags = 0;
        strcpy(pcm->name, "ICE1712 multi");
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &ice->pci->dev,
-                                             256*1024, 256*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &ice->pci->dev, 256*1024, 256*1024);
 
        ice->pcm_pro = pcm;
 
@@ -1366,7 +1335,7 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc
 
 static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0);
 
-static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] = {
+static const struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Multi Playback Switch",
@@ -1495,11 +1464,11 @@ static int snd_ice1712_ac97_mixer(struct snd_ice1712 *ice)
        int err, bus_num = 0;
        struct snd_ac97_template ac97;
        struct snd_ac97_bus *pbus;
-       static struct snd_ac97_bus_ops con_ops = {
+       static const struct snd_ac97_bus_ops con_ops = {
                .write = snd_ice1712_ac97_write,
                .read = snd_ice1712_ac97_read,
        };
-       static struct snd_ac97_bus_ops pro_ops = {
+       static const struct snd_ac97_bus_ops pro_ops = {
                .write = snd_ice1712_pro_ac97_write,
                .read = snd_ice1712_pro_ac97_read,
        };
@@ -2249,7 +2218,7 @@ static const struct snd_kcontrol_new snd_ice1712_mixer_pro_peak = {
 /*
  * list of available boards
  */
-static struct snd_ice1712_card_info *card_tables[] = {
+static const struct snd_ice1712_card_info *card_tables[] = {
        snd_ice1712_hoontech_cards,
        snd_ice1712_delta_cards,
        snd_ice1712_ews_cards,
@@ -2273,7 +2242,7 @@ static int snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
 {
        int dev = ICE_I2C_EEPROM_ADDR;  /* I2C EEPROM device address */
        unsigned int i, size;
-       struct snd_ice1712_card_info * const *tbl, *c;
+       const struct snd_ice1712_card_info * const *tbl, *c;
 
        if (!modelname || !*modelname) {
                ice->eeprom.subvendor = 0;
@@ -2505,7 +2474,7 @@ static int snd_ice1712_create(struct snd_card *card,
 {
        struct snd_ice1712 *ice;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ice1712_dev_free,
        };
 
@@ -2559,7 +2528,6 @@ static int snd_ice1712_create(struct snd_card *card,
        pci_write_config_word(ice->pci, 0x40, 0x807f);
        pci_write_config_word(ice->pci, 0x42, 0x0006);
        snd_ice1712_proc_init(ice);
-       synchronize_irq(pci->irq);
 
        card->private_data = ice;
 
@@ -2582,6 +2550,7 @@ static int snd_ice1712_create(struct snd_card *card,
        }
 
        ice->irq = pci->irq;
+       card->sync_irq = ice->irq;
 
        if (snd_ice1712_read_eeprom(ice, modelname) < 0) {
                snd_ice1712_free(ice);
@@ -2618,7 +2587,7 @@ static int snd_ice1712_probe(struct pci_dev *pci,
        struct snd_card *card;
        struct snd_ice1712 *ice;
        int pcm_dev = 0, err;
-       struct snd_ice1712_card_info * const *tbl, *c;
+       const struct snd_ice1712_card_info * const *tbl, *c;
 
        if (dev >= SNDRV_CARDS)
                return -ENODEV;
index 8814570..cd02710 100644 (file)
@@ -316,7 +316,7 @@ struct snd_ice1712 {
        struct snd_info_entry *proc_entry;
 
        struct snd_ice1712_eeprom eeprom;
-       struct snd_ice1712_card_info *card_info;
+       const struct snd_ice1712_card_info *card_info;
 
        unsigned int pro_volumes[20];
        unsigned int omni:1;            /* Delta Omni I/O */
index c80a16e..c0fca94 100644 (file)
@@ -647,6 +647,7 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
        unsigned long flags;
        unsigned char mclk_change;
        unsigned int i, old_rate;
+       bool call_set_rate = false;
 
        if (rate > ice->hw_rates->list[ice->hw_rates->count - 1])
                return -EINVAL;
@@ -670,7 +671,7 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
                 * setting clock rate for internal clock mode */
                old_rate = ice->get_rate(ice);
                if (force || (old_rate != rate))
-                       ice->set_rate(ice, rate);
+                       call_set_rate = true;
                else if (rate == ice->cur_rate) {
                        spin_unlock_irqrestore(&ice->reg_lock, flags);
                        return 0;
@@ -678,12 +679,14 @@ static int snd_vt1724_set_pro_rate(struct snd_ice1712 *ice, unsigned int rate,
        }
 
        ice->cur_rate = rate;
+       spin_unlock_irqrestore(&ice->reg_lock, flags);
+
+       if (call_set_rate)
+               ice->set_rate(ice, rate);
 
        /* setting master clock */
        mclk_change = ice->set_mclk(ice, rate);
 
-       spin_unlock_irqrestore(&ice->reg_lock, flags);
-
        if (mclk_change && ice->gpio.i2s_mclk_changed)
                ice->gpio.i2s_mclk_changed(ice);
        if (ice->gpio.set_pro_rate)
@@ -704,7 +707,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream,
                                    struct snd_pcm_hw_params *hw_params)
 {
        struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
-       int i, chs, err;
+       int i, chs;
 
        chs = params_channels(hw_params);
        mutex_lock(&ice->open_mutex);
@@ -740,11 +743,7 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream,
        }
        mutex_unlock(&ice->open_mutex);
 
-       err = snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0);
-       if (err < 0)
-               return err;
-
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
+       return snd_vt1724_set_pro_rate(ice, params_rate(hw_params), 0);
 }
 
 static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream)
@@ -758,7 +757,7 @@ static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream)
                if (ice->pcm_reserved[i] == substream)
                        ice->pcm_reserved[i] = NULL;
        mutex_unlock(&ice->open_mutex);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int snd_vt1724_playback_pro_prepare(struct snd_pcm_substream *substream)
@@ -1100,7 +1099,6 @@ static int snd_vt1724_capture_pro_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_vt1724_playback_pro_ops = {
        .open =         snd_vt1724_playback_pro_open,
        .close =        snd_vt1724_playback_pro_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_vt1724_pcm_hw_params,
        .hw_free =      snd_vt1724_pcm_hw_free,
        .prepare =      snd_vt1724_playback_pro_prepare,
@@ -1111,7 +1109,6 @@ static const struct snd_pcm_ops snd_vt1724_playback_pro_ops = {
 static const struct snd_pcm_ops snd_vt1724_capture_pro_ops = {
        .open =         snd_vt1724_capture_pro_open,
        .close =        snd_vt1724_capture_pro_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_vt1724_pcm_hw_params,
        .hw_free =      snd_vt1724_pcm_hw_free,
        .prepare =      snd_vt1724_pcm_prepare,
@@ -1142,9 +1139,8 @@ static int snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
        pcm->info_flags = 0;
        strcpy(pcm->name, "ICE1724");
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &ice->pci->dev,
-                                             256*1024, 256*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &ice->pci->dev, 256*1024, 256*1024);
 
        ice->pcm_pro = pcm;
 
@@ -1279,7 +1275,6 @@ static int snd_vt1724_capture_spdif_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_vt1724_playback_spdif_ops = {
        .open =         snd_vt1724_playback_spdif_open,
        .close =        snd_vt1724_playback_spdif_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_vt1724_pcm_hw_params,
        .hw_free =      snd_vt1724_pcm_hw_free,
        .prepare =      snd_vt1724_playback_spdif_prepare,
@@ -1290,7 +1285,6 @@ static const struct snd_pcm_ops snd_vt1724_playback_spdif_ops = {
 static const struct snd_pcm_ops snd_vt1724_capture_spdif_ops = {
        .open =         snd_vt1724_capture_spdif_open,
        .close =        snd_vt1724_capture_spdif_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_vt1724_pcm_hw_params,
        .hw_free =      snd_vt1724_pcm_hw_free,
        .prepare =      snd_vt1724_pcm_prepare,
@@ -1340,9 +1334,8 @@ static int snd_vt1724_pcm_spdif(struct snd_ice1712 *ice, int device)
        pcm->info_flags = 0;
        strcpy(pcm->name, name);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &ice->pci->dev,
-                                             256*1024, 256*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &ice->pci->dev, 256*1024, 256*1024);
 
        ice->pcm = pcm;
 
@@ -1424,7 +1417,6 @@ static int snd_vt1724_playback_indep_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_vt1724_playback_indep_ops = {
        .open =         snd_vt1724_playback_indep_open,
        .close =        snd_vt1724_playback_indep_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_vt1724_pcm_hw_params,
        .hw_free =      snd_vt1724_pcm_hw_free,
        .prepare =      snd_vt1724_playback_indep_prepare,
@@ -1454,9 +1446,8 @@ static int snd_vt1724_pcm_indep(struct snd_ice1712 *ice, int device)
        pcm->info_flags = 0;
        strcpy(pcm->name, "ICE1724 Surround PCM");
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &ice->pci->dev,
-                                             256*1024, 256*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &ice->pci->dev, 256*1024, 256*1024);
 
        ice->pcm_ds = pcm;
 
@@ -1475,7 +1466,7 @@ static int snd_vt1724_ac97_mixer(struct snd_ice1712 *ice)
        if (!(ice->eeprom.data[ICE_EEP2_ACLINK] & VT1724_CFG_PRO_I2S)) {
                struct snd_ac97_bus *pbus;
                struct snd_ac97_template ac97;
-               static struct snd_ac97_bus_ops ops = {
+               static const struct snd_ac97_bus_ops ops = {
                        .write = snd_vt1724_ac97_write,
                        .read = snd_vt1724_ac97_read,
                };
@@ -2182,13 +2173,13 @@ static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak = {
  *
  */
 
-static struct snd_ice1712_card_info no_matched;
+static const struct snd_ice1712_card_info no_matched;
 
 
 /*
   ooAoo cards with no controls
 */
-static unsigned char ooaoo_sq210_eeprom[] = {
+static const unsigned char ooaoo_sq210_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x4c,  /* 49MHz crystal, no mpu401, no ADC,
                                           1xDACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
@@ -2208,7 +2199,7 @@ static unsigned char ooaoo_sq210_eeprom[] = {
 };
 
 
-static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] = {
+static const struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] = {
        {
                .name = "ooAoo SQ210a",
                .model = "sq210a",
@@ -2218,7 +2209,7 @@ static struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] = {
        { } /* terminator */
 };
 
-static struct snd_ice1712_card_info *card_tables[] = {
+static const struct snd_ice1712_card_info *card_tables[] = {
        snd_vt1724_revo_cards,
        snd_vt1724_amp_cards,
        snd_vt1724_aureon_cards,
@@ -2288,7 +2279,7 @@ static int snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
 {
        const int dev = 0xa0;           /* EEPROM device address */
        unsigned int i, size;
-       struct snd_ice1712_card_info * const *tbl, *c;
+       const struct snd_ice1712_card_info * const *tbl, *c;
 
        if (!modelname || !*modelname) {
                ice->eeprom.subvendor = 0;
@@ -2514,7 +2505,7 @@ static int snd_vt1724_create(struct snd_card *card,
 {
        struct snd_ice1712 *ice;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_vt1724_dev_free,
        };
 
@@ -2546,7 +2537,6 @@ static int snd_vt1724_create(struct snd_card *card,
        ice->irq = -1;
        pci_set_master(pci);
        snd_vt1724_proc_init(ice);
-       synchronize_irq(pci->irq);
 
        card->private_data = ice;
 
@@ -2567,6 +2557,7 @@ static int snd_vt1724_create(struct snd_card *card,
        }
 
        ice->irq = pci->irq;
+       card->sync_irq = ice->irq;
 
        snd_vt1724_chip_reset(ice);
        if (snd_vt1724_read_eeprom(ice, modelname) < 0) {
@@ -2602,7 +2593,7 @@ static int snd_vt1724_probe(struct pci_dev *pci,
        struct snd_card *card;
        struct snd_ice1712 *ice;
        int pcm_dev = 0, err;
-       struct snd_ice1712_card_info * const *tbl, *c;
+       const struct snd_ice1712_card_info * const *tbl, *c;
 
        if (dev >= SNDRV_CARDS)
                return -ENODEV;
index 0da7e94..7be4eb4 100644 (file)
@@ -343,7 +343,7 @@ static int juli_mute_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new juli_mute_controls[] = {
+static const struct snd_kcontrol_new juli_mute_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -397,7 +397,7 @@ static struct snd_kcontrol_new juli_mute_controls[] = {
        },
 };
 
-static char *slave_vols[] = {
+static const char * const slave_vols[] = {
        PCM_VOLUME,
        MONITOR_AN_IN_VOLUME,
        MONITOR_DIG_IN_VOLUME,
@@ -420,7 +420,7 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card,
 
 static void add_slaves(struct snd_card *card,
                       struct snd_kcontrol *master,
-                      char * const *list)
+                      const char * const *list)
 {
        for (; *list; list++) {
                struct snd_kcontrol *slave = ctl_find(card, *list);
@@ -651,7 +651,7 @@ static int juli_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char juli_eeprom[] = {
+static const unsigned char juli_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401, 1xADC, 1xDACs,
                                           SPDIF in */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
index 3af5abe..b46df18 100644 (file)
@@ -116,7 +116,7 @@ struct maya_vol_info {
        unsigned char mux_bits[2];      /* extra bits for ADC mute */
 };
 
-static struct maya_vol_info vol_info[WM_NUM_VOLS] = {
+static const struct maya_vol_info vol_info[WM_NUM_VOLS] = {
        [WM_VOL_HP] = {
                .maxval = 80,
                .regs = { WM8776_REG_HEADPHONE_L, WM8776_REG_HEADPHONE_R },
@@ -158,7 +158,7 @@ static int maya_vol_info(struct snd_kcontrol *kcontrol,
                         struct snd_ctl_elem_info *uinfo)
 {
        unsigned int idx = kcontrol->private_value;
-       struct maya_vol_info *vol = &vol_info[idx];
+       const struct maya_vol_info *vol = &vol_info[idx];
 
        uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
        uinfo->count = 2;
@@ -189,7 +189,7 @@ static int maya_vol_put(struct snd_kcontrol *kcontrol,
        struct snd_wm8776 *wm =
                &chip->wm[snd_ctl_get_ioff(kcontrol, &ucontrol->id)];
        unsigned int idx = kcontrol->private_value;
-       struct maya_vol_info *vol = &vol_info[idx];
+       const struct maya_vol_info *vol = &vol_info[idx];
        unsigned int val, data;
        int ch, changed = 0;
 
@@ -424,7 +424,7 @@ static int maya_pb_route_put(struct snd_kcontrol *kcontrol,
  * controls to be added
  */
 
-static struct snd_kcontrol_new maya_controls[] = {
+static const struct snd_kcontrol_new maya_controls[] = {
        {
                .name = "Crossmix Playback Volume",
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -662,7 +662,7 @@ static const struct snd_pcm_hw_constraint_list dac_rates = {
 /*
  * chip addresses on I2C bus
  */
-static unsigned char wm8776_addr[2] = {
+static const unsigned char wm8776_addr[2] = {
        0x34, 0x36, /* codec 0 & 1 */
 };
 
@@ -712,7 +712,7 @@ static int maya44_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char maya44_eeprom[] = {
+static const unsigned char maya44_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x45,
                /* clock xin1=49.152MHz, mpu401, 2 stereo ADCs+DACs */
        [ICE_EEP2_ACLINK]      = 0x80,
index 6990511..1e47e46 100644 (file)
@@ -157,7 +157,7 @@ static int phase22_add_controls(struct snd_ice1712 *ice)
        return 0;
 }
 
-static unsigned char phase22_eeprom[] = {
+static const unsigned char phase22_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x28,  /* clock 512, mpu 401,
                                        spdif-in/1xADC, 1xDACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
@@ -174,7 +174,7 @@ static unsigned char phase22_eeprom[] = {
        [ICE_EEP2_GPIO_STATE2] = 0x00,
 };
 
-static unsigned char phase28_eeprom[] = {
+static const unsigned char phase28_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x2b,  /* clock 512, mpu401,
                                        spdif-in/1xADC, 4xDACs */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
@@ -745,7 +745,7 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol,
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
 
-static struct snd_kcontrol_new phase28_dac_controls[] = {
+static const struct snd_kcontrol_new phase28_dac_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -860,7 +860,7 @@ static struct snd_kcontrol_new phase28_dac_controls[] = {
        }
 };
 
-static struct snd_kcontrol_new wm_controls[] = {
+static const struct snd_kcontrol_new wm_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "PCM Playback Switch",
index 56cbc96..683909c 100644 (file)
@@ -529,7 +529,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);
  * mixers
  */
 
-static struct snd_kcontrol_new pontis_controls[] = {
+static const struct snd_kcontrol_new pontis_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -778,7 +778,7 @@ static int pontis_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char pontis_eeprom[] = {
+static const unsigned char pontis_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x08,  /* clock 256, mpu401, spdif-in/ADC, 1DAC */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
        [ICE_EEP2_I2S]         = 0xf8,  /* vol, 96k, 24bit, 192k */
index 98f8ac6..8df14f6 100644 (file)
@@ -346,7 +346,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
  * mixers
  */
 
-static struct snd_kcontrol_new stac_controls[] = {
+static const struct snd_kcontrol_new stac_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -578,7 +578,7 @@ static int ak4114_input_sw_put(struct snd_kcontrol *kcontrol,
 }
 
 
-static struct snd_kcontrol_new ak4114_controls[] = {
+static const struct snd_kcontrol_new ak4114_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "MIODIO IEC958 Capture Input",
@@ -753,7 +753,7 @@ static int prodigy192_init(struct snd_ice1712 *ice)
  * hence the driver needs to sets up it properly.
  */
 
-static unsigned char prodigy71_eeprom[] = {
+static const unsigned char prodigy71_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x6a,  /* 49MHz crystal, mpu401,
                                         * spdif-in+ 1 stereo ADC,
                                         * 3 stereo DACs
index 9d71e9d..91f83ce 100644 (file)
@@ -284,7 +284,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
 static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
-static struct snd_kcontrol_new prodigy_hd2_controls[] = {
+static const struct snd_kcontrol_new prodigy_hd2_controls[] = {
     {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -741,7 +741,7 @@ static int wm_chswap_put(struct snd_kcontrol *kcontrol,
  * mixers
  */
 
-static struct snd_kcontrol_new prodigy_hifi_controls[] = {
+static const struct snd_kcontrol_new prodigy_hifi_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -930,7 +930,7 @@ static int prodigy_hd2_add_controls(struct snd_ice1712 *ice)
 
 static void wm8766_init(struct snd_ice1712 *ice)
 {
-       static unsigned short wm8766_inits[] = {
+       static const unsigned short wm8766_inits[] = {
                WM8766_RESET,      0x0000,
                WM8766_DAC_CTRL,        0x0120,
                WM8766_INT_CTRL,        0x0022, /* I2S Normal Mode, 24 bit */
@@ -953,7 +953,7 @@ static void wm8766_init(struct snd_ice1712 *ice)
 
 static void wm8776_init(struct snd_ice1712 *ice)
 {
-       static unsigned short wm8776_inits[] = {
+       static const unsigned short wm8776_inits[] = {
                /* These come first to reduce init pop noise */
                WM_ADC_MUX,     0x0003, /* ADC mute */
                /* 0x00c0 replaced by 0x0003 */
@@ -973,7 +973,7 @@ static void wm8776_init(struct snd_ice1712 *ice)
 #ifdef CONFIG_PM_SLEEP
 static int prodigy_hifi_resume(struct snd_ice1712 *ice)
 {
-       static unsigned short wm8776_reinit_registers[] = {
+       static const unsigned short wm8776_reinit_registers[] = {
                WM_MASTER_CTRL,
                WM_DAC_INT,
                WM_ADC_INT,
@@ -1033,7 +1033,7 @@ static int prodigy_hifi_resume(struct snd_ice1712 *ice)
  */
 static int prodigy_hifi_init(struct snd_ice1712 *ice)
 {
-       static unsigned short wm8776_defaults[] = {
+       static const unsigned short wm8776_defaults[] = {
                WM_MASTER_CTRL,  0x0022, /* 256fs, slave mode */
                WM_DAC_INT,     0x0022, /* I2S, normal polarity, 24bit */
                WM_ADC_INT,     0x0022, /* I2S, normal polarity, 24bit */
@@ -1108,7 +1108,7 @@ static int prodigy_hifi_init(struct snd_ice1712 *ice)
  */
 static void ak4396_init(struct snd_ice1712 *ice)
 {
-       static unsigned short ak4396_inits[] = {
+       static const unsigned short ak4396_inits[] = {
                AK4396_CTRL1,      0x87,   /* I2S Normal Mode, 24 bit */
                AK4396_CTRL2,      0x02,
                AK4396_CTRL3,      0x00, 
@@ -1180,7 +1180,7 @@ static int prodigy_hd2_init(struct snd_ice1712 *ice)
 }
 
 
-static unsigned char prodigy71hifi_eeprom[] = {
+static const unsigned char prodigy71hifi_eeprom[] = {
        0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
        0x80,   /* ACLINK: I2S */
        0xfc,   /* I2S: vol, 96k, 24bit, 192k */
@@ -1196,7 +1196,7 @@ static unsigned char prodigy71hifi_eeprom[] = {
        0x00,   /* GPIO_STATE2 */
 };
 
-static unsigned char prodigyhd2_eeprom[] = {
+static const unsigned char prodigyhd2_eeprom[] = {
        0x4b,   /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */
        0x80,   /* ACLINK: I2S */
        0xfc,   /* I2S: vol, 96k, 24bit, 192k */
@@ -1212,7 +1212,7 @@ static unsigned char prodigyhd2_eeprom[] = {
        0x00,   /* GPIO_STATE2 */
 };
 
-static unsigned char fortissimo4_eeprom[] = {
+static const unsigned char fortissimo4_eeprom[] = {
        0x43,   /* SYSCONF: clock 512, ADC, 4DACs */    
        0x80,   /* ACLINK: I2S */
        0xfc,   /* I2S: vol, 96k, 24bit, 192k */
index 7287ebe..7aa3f92 100644 (file)
@@ -420,7 +420,7 @@ static void psc724_exit(struct snd_ice1712 *ice)
 }
 
 /* PSC724 has buggy EEPROM (no 96&192kHz, all FFh GPIOs), so override it here */
-static unsigned char psc724_eeprom[] = {
+static const unsigned char psc724_eeprom[] = {
        [ICE_EEP2_SYSCONF]      = 0x42, /* 49.152MHz, 1 ADC, 3 DACs */
        [ICE_EEP2_ACLINK]       = 0x80, /* I2S */
        [ICE_EEP2_I2S]          = 0xf0, /* I2S volume, 96kHz, 24bit */
index 9e2149f..8665962 100644 (file)
@@ -657,7 +657,7 @@ static int qtet_php_put(struct snd_kcontrol *kcontrol,
        .get_register = get_##xreg,\
        .texts = {xtext1, xtext2} }
 
-static struct qtet_kcontrol_private qtet_privates[] = {
+static const struct qtet_kcontrol_private qtet_privates[] = {
        PRIV_ENUM2(IN12_SEL, CPLD_IN12_SEL, cpld, "An In 1/2", "An In 3/4"),
        PRIV_ENUM2(IN34_SEL, CPLD_IN34_SEL, cpld, "An In 3/4", "IEC958 In"),
        PRIV_ENUM2(AIN34_SEL, SCR_AIN34_SEL, scr, "Line In 3/4", "Hi-Z"),
@@ -720,7 +720,7 @@ static int qtet_sw_put(struct snd_kcontrol *kcontrol,
        .put = qtet_sw_put,\
        .private_value = xpriv }
 
-static struct snd_kcontrol_new qtet_controls[] = {
+static const struct snd_kcontrol_new qtet_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Master Playback Switch",
@@ -757,7 +757,7 @@ static struct snd_kcontrol_new qtet_controls[] = {
        QTET_CONTROL("Output 3/4 to Monitor 1/2", sw, OUT34_MON12),
 };
 
-static char *slave_vols[] = {
+static const char * const slave_vols[] = {
        PCM_12_PLAYBACK_VOLUME,
        PCM_34_PLAYBACK_VOLUME,
        NULL
@@ -777,7 +777,7 @@ static struct snd_kcontrol *ctl_find(struct snd_card *card,
 }
 
 static void add_slaves(struct snd_card *card,
-                      struct snd_kcontrol *master, char * const *list)
+                      struct snd_kcontrol *master, const char * const *list)
 {
        for (; *list; list++) {
                struct snd_kcontrol *slave = ctl_find(card, *list);
@@ -1053,7 +1053,7 @@ static int qtet_init(struct snd_ice1712 *ice)
        return 0;
 }
 
-static unsigned char qtet_eeprom[] = {
+static const unsigned char qtet_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x28,  /* clock 256(24MHz), mpu401, 1xADC,
                                           1xDACs, SPDIF in */
        [ICE_EEP2_ACLINK]      = 0x80,  /* I2S */
index fdc5027..ffa9d88 100644 (file)
@@ -245,7 +245,7 @@ static const char * const se200pci_sel[] = {
 static void se200pci_WM8776_set_input_selector(struct snd_ice1712 *ice,
                                               unsigned int sel)
 {
-       static unsigned char vals[] = {
+       static const unsigned char vals[] = {
                /* LINE, CD, MIC, ALL, GND */
                0x10, 0x04, 0x08, 0x1c, 0x03
        };
@@ -288,7 +288,7 @@ static void se200pci_WM8776_set_agc(struct snd_ice1712 *ice, unsigned int agc)
 static void se200pci_WM8776_init(struct snd_ice1712 *ice)
 {
        int i;
-       static unsigned short default_values[] = {
+       static const unsigned short default_values[] = {
                0x100, 0x100, 0x100,
                0x100, 0x100, 0x100,
                0x000, 0x090, 0x000, 0x000,
@@ -701,7 +701,7 @@ static int se_add_controls(struct snd_ice1712 *ice)
 /*  entry point                                                             */
 /****************************************************************************/
 
-static unsigned char se200pci_eeprom[] = {
+static const unsigned char se200pci_eeprom[] = {
        [ICE_EEP2_SYSCONF]      = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
        [ICE_EEP2_ACLINK]       = 0x80, /* I2S */
        [ICE_EEP2_I2S]          = 0x78, /* 96k-ok, 24bit, 192k-ok */
@@ -720,7 +720,7 @@ static unsigned char se200pci_eeprom[] = {
        [ICE_EEP2_GPIO_STATE2]  = 0x07, /* WM8766 ML/MC/MD */
 };
 
-static unsigned char se90pci_eeprom[] = {
+static const unsigned char se90pci_eeprom[] = {
        [ICE_EEP2_SYSCONF]      = 0x4b, /* 49.152Hz, spdif-in/ADC, 4DACs */
        [ICE_EEP2_ACLINK]       = 0x80, /* I2S */
        [ICE_EEP2_I2S]          = 0x78, /* 96k-ok, 24bit, 192k-ok */
index 3d24012..47470b0 100644 (file)
@@ -39,7 +39,7 @@ static int k8x800_add_controls(struct snd_ice1712 *ice)
 
 /* EEPROM image */
 
-static unsigned char k8x800_eeprom[] = {
+static const unsigned char k8x800_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x01,  /* clock 256, 1ADC, 2DACs */
        [ICE_EEP2_ACLINK]      = 0x02,  /* ACLINK, packed */
        [ICE_EEP2_I2S]         = 0x00,  /* - */
@@ -55,7 +55,7 @@ static unsigned char k8x800_eeprom[] = {
        [ICE_EEP2_GPIO_STATE2] = 0x00,  /* - */
 };
 
-static unsigned char sn25p_eeprom[] = {
+static const unsigned char sn25p_eeprom[] = {
        [ICE_EEP2_SYSCONF]     = 0x01,  /* clock 256, 1ADC, 2DACs */
        [ICE_EEP2_ACLINK]      = 0x02,  /* ACLINK, packed */
        [ICE_EEP2_I2S]         = 0x00,  /* - */
index 0943f9e..fe3e243 100644 (file)
@@ -26,7 +26,7 @@ static void snd_wm8766_write(struct snd_wm8766 *wm, u16 addr, u16 data)
 
 static const DECLARE_TLV_DB_SCALE(wm8766_tlv, -12750, 50, 1);
 
-static struct snd_wm8766_ctl snd_wm8766_default_ctl[WM8766_CTL_COUNT] = {
+static const struct snd_wm8766_ctl snd_wm8766_default_ctl[WM8766_CTL_COUNT] = {
        [WM8766_CTL_CH1_VOL] = {
                .name = "Channel 1 Playback Volume",
                .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
index d696a7c..d96008d 100644 (file)
@@ -129,7 +129,7 @@ static const DECLARE_TLV_DB_SCALE(wm8776_ngth_tlv, -7800, 600, 0);
 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_lim_tlv, -1200, 100, 0);
 static const DECLARE_TLV_DB_SCALE(wm8776_maxatten_alc_tlv, -2100, 400, 0);
 
-static struct snd_wm8776_ctl snd_wm8776_default_ctl[WM8776_CTL_COUNT] = {
+static const struct snd_wm8776_ctl snd_wm8776_default_ctl[WM8776_CTL_COUNT] = {
        [WM8776_CTL_DAC_VOL] = {
                .name = "Master Playback Volume",
                .type = SNDRV_CTL_ELEM_TYPE_INTEGER,
index 4ca96ec..f613f00 100644 (file)
@@ -477,7 +477,7 @@ static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
 /*
  * Control tabs
  */
-static struct snd_kcontrol_new stac9640_controls[] = {
+static const struct snd_kcontrol_new stac9640_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -567,12 +567,12 @@ static int wtm_add_controls(struct snd_ice1712 *ice)
 
 static int wtm_init(struct snd_ice1712 *ice)
 {
-       static unsigned short stac_inits_wtm[] = {
+       static const unsigned short stac_inits_wtm[] = {
                STAC946X_RESET, 0,
                STAC946X_MASTER_CLOCKING, 0x11,
                (unsigned short)-1
        };
-       unsigned short *p;
+       const unsigned short *p;
        struct wtm_spec *spec;
 
        /*WTM 192M*/
@@ -599,7 +599,7 @@ static int wtm_init(struct snd_ice1712 *ice)
 }
 
 
-static unsigned char wtm_eeprom[] = {
+static const unsigned char wtm_eeprom[] = {
        [ICE_EEP2_SYSCONF]      = 0x67, /*SYSCONF: clock 192KHz, mpu401,
                                                        4ADC, 8DAC */
        [ICE_EEP2_ACLINK]       = 0x80, /* ACLINK : I2S */
index 12374ba..1781a1c 100644 (file)
@@ -393,7 +393,7 @@ struct intel8x0 {
        struct snd_ac97 *ac97[3];
        unsigned int ac97_sdin[3];
        unsigned int max_codecs, ncodecs;
-       unsigned int *codec_bit;
+       const unsigned int *codec_bit;
        unsigned int codec_isr_bits;
        unsigned int codec_ready_bits;
 
@@ -843,7 +843,7 @@ static int snd_intel8x0_ali_trigger(struct snd_pcm_substream *substream, int cmd
        struct intel8x0 *chip = snd_pcm_substream_chip(substream);
        struct ichdev *ichdev = get_ichdev(substream);
        unsigned long port = ichdev->reg_offset;
-       static int fiforeg[] = {
+       static const int fiforeg[] = {
                ICHREG(ALI_FIFOCR1), ICHREG(ALI_FIFOCR2), ICHREG(ALI_FIFOCR3)
        };
        unsigned int val, fifo;
@@ -901,9 +901,6 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
        int dbl = params_rate(hw_params) > 48000;
        int err;
 
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        if (ichdev->pcm_open_flag) {
                snd_ac97_pcm_close(ichdev->pcm);
                ichdev->pcm_open_flag = 0;
@@ -929,7 +926,7 @@ static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
                snd_ac97_pcm_close(ichdev->pcm);
                ichdev->pcm_open_flag = 0;
        }
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static void snd_intel8x0_setup_pcm_out(struct intel8x0 *chip,
@@ -1314,7 +1311,6 @@ static int snd_intel8x0_ali_spdifout_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_intel8x0_playback_ops = {
        .open =         snd_intel8x0_playback_open,
        .close =        snd_intel8x0_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1325,7 +1321,6 @@ static const struct snd_pcm_ops snd_intel8x0_playback_ops = {
 static const struct snd_pcm_ops snd_intel8x0_capture_ops = {
        .open =         snd_intel8x0_capture_open,
        .close =        snd_intel8x0_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1336,7 +1331,6 @@ static const struct snd_pcm_ops snd_intel8x0_capture_ops = {
 static const struct snd_pcm_ops snd_intel8x0_capture_mic_ops = {
        .open =         snd_intel8x0_mic_open,
        .close =        snd_intel8x0_mic_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1347,7 +1341,6 @@ static const struct snd_pcm_ops snd_intel8x0_capture_mic_ops = {
 static const struct snd_pcm_ops snd_intel8x0_capture_mic2_ops = {
        .open =         snd_intel8x0_mic2_open,
        .close =        snd_intel8x0_mic2_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1358,7 +1351,6 @@ static const struct snd_pcm_ops snd_intel8x0_capture_mic2_ops = {
 static const struct snd_pcm_ops snd_intel8x0_capture2_ops = {
        .open =         snd_intel8x0_capture2_open,
        .close =        snd_intel8x0_capture2_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1369,7 +1361,6 @@ static const struct snd_pcm_ops snd_intel8x0_capture2_ops = {
 static const struct snd_pcm_ops snd_intel8x0_spdif_ops = {
        .open =         snd_intel8x0_spdif_open,
        .close =        snd_intel8x0_spdif_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1380,7 +1371,6 @@ static const struct snd_pcm_ops snd_intel8x0_spdif_ops = {
 static const struct snd_pcm_ops snd_intel8x0_ali_playback_ops = {
        .open =         snd_intel8x0_playback_open,
        .close =        snd_intel8x0_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1391,7 +1381,6 @@ static const struct snd_pcm_ops snd_intel8x0_ali_playback_ops = {
 static const struct snd_pcm_ops snd_intel8x0_ali_capture_ops = {
        .open =         snd_intel8x0_capture_open,
        .close =        snd_intel8x0_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1402,7 +1391,6 @@ static const struct snd_pcm_ops snd_intel8x0_ali_capture_ops = {
 static const struct snd_pcm_ops snd_intel8x0_ali_capture_mic_ops = {
        .open =         snd_intel8x0_mic_open,
        .close =        snd_intel8x0_mic_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1413,7 +1401,6 @@ static const struct snd_pcm_ops snd_intel8x0_ali_capture_mic_ops = {
 static const struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = {
        .open =         snd_intel8x0_ali_ac97spdifout_open,
        .close =        snd_intel8x0_ali_ac97spdifout_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1425,7 +1412,6 @@ static const struct snd_pcm_ops snd_intel8x0_ali_ac97spdifout_ops = {
 static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
        .open =         snd_intel8x0_ali_spdifin_open,
        .close =        snd_intel8x0_ali_spdifin_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1436,7 +1422,6 @@ static struct snd_pcm_ops snd_intel8x0_ali_spdifin_ops = {
 static struct snd_pcm_ops snd_intel8x0_ali_spdifout_ops = {
        .open =         snd_intel8x0_ali_spdifout_open,
        .close =        snd_intel8x0_ali_spdifout_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_intel8x0_hw_params,
        .hw_free =      snd_intel8x0_hw_free,
        .prepare =      snd_intel8x0_pcm_prepare,
@@ -1458,7 +1443,7 @@ struct ich_pcm_table {
        ((chip)->fix_nocache ? SNDRV_DMA_TYPE_DEV_UC : SNDRV_DMA_TYPE_DEV)
 
 static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
-                            struct ich_pcm_table *rec)
+                            const struct ich_pcm_table *rec)
 {
        struct snd_pcm *pcm;
        int err;
@@ -1487,9 +1472,9 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
                strcpy(pcm->name, chip->card->shortname);
        chip->pcm[device] = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, intel8x0_dma_type(chip),
-                                             &chip->pci->dev,
-                                             rec->prealloc_size, rec->prealloc_max_size);
+       snd_pcm_set_managed_buffer_all(pcm, intel8x0_dma_type(chip),
+                                      &chip->pci->dev,
+                                      rec->prealloc_size, rec->prealloc_max_size);
 
        if (rec->playback_ops &&
            rec->playback_ops->open == snd_intel8x0_playback_open) {
@@ -1513,7 +1498,7 @@ static int snd_intel8x0_pcm1(struct intel8x0 *chip, int device,
        return 0;
 }
 
-static struct ich_pcm_table intel_pcms[] = {
+static const struct ich_pcm_table intel_pcms[] = {
        {
                .playback_ops = &snd_intel8x0_playback_ops,
                .capture_ops = &snd_intel8x0_capture_ops,
@@ -1550,7 +1535,7 @@ static struct ich_pcm_table intel_pcms[] = {
        },
 };
 
-static struct ich_pcm_table nforce_pcms[] = {
+static const struct ich_pcm_table nforce_pcms[] = {
        {
                .playback_ops = &snd_intel8x0_playback_ops,
                .capture_ops = &snd_intel8x0_capture_ops,
@@ -1573,7 +1558,7 @@ static struct ich_pcm_table nforce_pcms[] = {
        },
 };
 
-static struct ich_pcm_table ali_pcms[] = {
+static const struct ich_pcm_table ali_pcms[] = {
        {
                .playback_ops = &snd_intel8x0_ali_playback_ops,
                .capture_ops = &snd_intel8x0_ali_capture_ops,
@@ -1608,7 +1593,7 @@ static struct ich_pcm_table ali_pcms[] = {
 static int snd_intel8x0_pcm(struct intel8x0 *chip)
 {
        int i, tblsize, device, err;
-       struct ich_pcm_table *tbl, *rec;
+       const struct ich_pcm_table *tbl, *rec;
 
        switch (chip->device_type) {
        case DEVICE_INTEL_ICH4:
@@ -2153,12 +2138,12 @@ static int snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
        int err;
        unsigned int i, codecs;
        unsigned int glob_sta = 0;
-       struct snd_ac97_bus_ops *ops;
-       static struct snd_ac97_bus_ops standard_bus_ops = {
+       const struct snd_ac97_bus_ops *ops;
+       static const struct snd_ac97_bus_ops standard_bus_ops = {
                .write = snd_intel8x0_codec_write,
                .read = snd_intel8x0_codec_read,
        };
-       static struct snd_ac97_bus_ops ali_bus_ops = {
+       static const struct snd_ac97_bus_ops ali_bus_ops = {
                .write = snd_intel8x0_ali_codec_write,
                .read = snd_intel8x0_ali_codec_read,
        };
@@ -2343,7 +2328,7 @@ static void do_ali_reset(struct intel8x0 *chip)
 }
 
 #ifdef CONFIG_SND_AC97_POWER_SAVE
-static struct snd_pci_quirk ich_chip_reset_mode[] = {
+static const struct snd_pci_quirk ich_chip_reset_mode[] = {
        SND_PCI_QUIRK(0x1014, 0x051f, "Thinkpad R32", 1),
        { } /* end */
 };
@@ -2607,6 +2592,7 @@ static int intel8x0_suspend(struct device *dev)
        if (chip->irq >= 0) {
                free_irq(chip->irq, chip);
                chip->irq = -1;
+               card->sync_irq = -1;
        }
        return 0;
 }
@@ -2627,7 +2613,7 @@ static int intel8x0_resume(struct device *dev)
                return -EIO;
        }
        chip->irq = pci->irq;
-       synchronize_irq(chip->irq);
+       card->sync_irq = chip->irq;
 
        /* re-initialize mixer stuff */
        if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
@@ -2788,7 +2774,7 @@ static void intel8x0_measure_ac97_clock(struct intel8x0 *chip)
        snd_ac97_update_power(chip->ac97[0], AC97_PCM_FRONT_DAC_RATE, 0);
 }
 
-static struct snd_pci_quirk intel8x0_clock_list[] = {
+static const struct snd_pci_quirk intel8x0_clock_list[] = {
        SND_PCI_QUIRK(0x0e11, 0x008a, "AD1885", 41000),
        SND_PCI_QUIRK(0x1014, 0x0581, "AD1981B", 48000),
        SND_PCI_QUIRK(0x1028, 0x00be, "AD1885", 44100),
@@ -2863,10 +2849,10 @@ struct ich_reg_info {
        unsigned int offset;
 };
 
-static unsigned int ich_codec_bits[3] = {
+static const unsigned int ich_codec_bits[3] = {
        ICH_PCR, ICH_SCR, ICH_TCR
 };
-static unsigned int sis_codec_bits[3] = {
+static const unsigned int sis_codec_bits[3] = {
        ICH_PCR, ICH_SCR, ICH_SIS_TCR
 };
 
@@ -2911,18 +2897,18 @@ static int snd_intel8x0_create(struct snd_card *card,
        unsigned int i;
        unsigned int int_sta_masks;
        struct ichdev *ichdev;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_intel8x0_dev_free,
        };
 
-       static unsigned int bdbars[] = {
+       static const unsigned int bdbars[] = {
                3, /* DEVICE_INTEL */
                6, /* DEVICE_INTEL_ICH4 */
                3, /* DEVICE_SIS */
                6, /* DEVICE_ALI */
                4, /* DEVICE_NFORCE */
        };
-       static struct ich_reg_info intel_regs[6] = {
+       static const struct ich_reg_info intel_regs[6] = {
                { ICH_PIINT, 0 },
                { ICH_POINT, 0x10 },
                { ICH_MCINT, 0x20 },
@@ -2930,13 +2916,13 @@ static int snd_intel8x0_create(struct snd_card *card,
                { ICH_P2INT, 0x50 },
                { ICH_SPINT, 0x60 },
        };
-       static struct ich_reg_info nforce_regs[4] = {
+       static const struct ich_reg_info nforce_regs[4] = {
                { ICH_PIINT, 0 },
                { ICH_POINT, 0x10 },
                { ICH_MCINT, 0x20 },
                { ICH_NVSPINT, 0x70 },
        };
-       static struct ich_reg_info ali_regs[6] = {
+       static const struct ich_reg_info ali_regs[6] = {
                { ALI_INT_PCMIN, 0x40 },
                { ALI_INT_PCMOUT, 0x50 },
                { ALI_INT_MICIN, 0x60 },
@@ -2944,7 +2930,7 @@ static int snd_intel8x0_create(struct snd_card *card,
                { ALI_INT_SPDIFIN, 0xa0 },
                { ALI_INT_SPDIFOUT, 0xb0 },
        };
-       struct ich_reg_info *tbl;
+       const struct ich_reg_info *tbl;
 
        *r_intel8x0 = NULL;
 
@@ -3107,6 +3093,7 @@ static int snd_intel8x0_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
                snd_intel8x0_free(chip);
@@ -3146,7 +3133,7 @@ static struct shortname_table {
        { 0, NULL },
 };
 
-static struct snd_pci_quirk spdif_aclink_defaults[] = {
+static const struct snd_pci_quirk spdif_aclink_defaults[] = {
        SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1),
        { } /* end */
 };
index a9add5f..1b7df0c 100644 (file)
@@ -288,7 +288,7 @@ static inline void iaputword(struct intel8x0m *chip, u32 offset, u16 val)
 /* return the GLOB_STA bit for the corresponding codec */
 static unsigned int get_ich_codec_bit(struct intel8x0m *chip, unsigned int codec)
 {
-       static unsigned int codec_bit[3] = {
+       static const unsigned int codec_bit[3] = {
                ICH_PCR, ICH_SCR, ICH_TCR
        };
        if (snd_BUG_ON(codec >= 3))
@@ -553,17 +553,6 @@ static int snd_intel8x0m_pcm_trigger(struct snd_pcm_substream *substream, int cm
        return 0;
 }
 
-static int snd_intel8x0m_hw_params(struct snd_pcm_substream *substream,
-                                 struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_intel8x0m_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static snd_pcm_uframes_t snd_intel8x0m_pcm_pointer(struct snd_pcm_substream *substream)
 {
        struct intel8x0m *chip = snd_pcm_substream_chip(substream);
@@ -673,9 +662,6 @@ static int snd_intel8x0m_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_intel8x0m_playback_ops = {
        .open =         snd_intel8x0m_playback_open,
        .close =        snd_intel8x0m_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_intel8x0m_hw_params,
-       .hw_free =      snd_intel8x0m_hw_free,
        .prepare =      snd_intel8x0m_pcm_prepare,
        .trigger =      snd_intel8x0m_pcm_trigger,
        .pointer =      snd_intel8x0m_pcm_pointer,
@@ -684,9 +670,6 @@ static const struct snd_pcm_ops snd_intel8x0m_playback_ops = {
 static const struct snd_pcm_ops snd_intel8x0m_capture_ops = {
        .open =         snd_intel8x0m_capture_open,
        .close =        snd_intel8x0m_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_intel8x0m_hw_params,
-       .hw_free =      snd_intel8x0m_hw_free,
        .prepare =      snd_intel8x0m_pcm_prepare,
        .trigger =      snd_intel8x0m_pcm_trigger,
        .pointer =      snd_intel8x0m_pcm_pointer,
@@ -703,7 +686,7 @@ struct ich_pcm_table {
 };
 
 static int snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
-                             struct ich_pcm_table *rec)
+                             const struct ich_pcm_table *rec)
 {
        struct snd_pcm *pcm;
        int err;
@@ -733,15 +716,15 @@ static int snd_intel8x0m_pcm1(struct intel8x0m *chip, int device,
                strcpy(pcm->name, chip->card->shortname);
        chip->pcm[device] = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             rec->prealloc_size,
-                                             rec->prealloc_max_size);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev,
+                                      rec->prealloc_size,
+                                      rec->prealloc_max_size);
 
        return 0;
 }
 
-static struct ich_pcm_table intel_pcms[] = {
+static const struct ich_pcm_table intel_pcms[] = {
        {
                .suffix = "Modem",
                .playback_ops = &snd_intel8x0m_playback_ops,
@@ -754,7 +737,7 @@ static struct ich_pcm_table intel_pcms[] = {
 static int snd_intel8x0m_pcm(struct intel8x0m *chip)
 {
        int i, tblsize, device, err;
-       struct ich_pcm_table *tbl, *rec;
+       const struct ich_pcm_table *tbl, *rec;
 
 #if 1
        tbl = intel_pcms;
@@ -818,7 +801,7 @@ static int snd_intel8x0m_mixer(struct intel8x0m *chip, int ac97_clock)
        struct snd_ac97 *x97;
        int err;
        unsigned int glob_sta = 0;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_intel8x0m_codec_write,
                .read = snd_intel8x0m_codec_read,
        };
@@ -1016,6 +999,7 @@ static int intel8x0m_suspend(struct device *dev)
        if (chip->irq >= 0) {
                free_irq(chip->irq, chip);
                chip->irq = -1;
+               card->sync_irq = -1;
        }
        return 0;
 }
@@ -1034,6 +1018,7 @@ static int intel8x0m_resume(struct device *dev)
                return -EIO;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        snd_intel8x0m_chip_init(chip, 0);
        snd_ac97_resume(chip->ac97);
 
@@ -1094,14 +1079,14 @@ static int snd_intel8x0m_create(struct snd_card *card,
        unsigned int i;
        unsigned int int_sta_masks;
        struct ichdev *ichdev;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_intel8x0m_dev_free,
        };
-       static struct ich_reg_info intel_regs[2] = {
+       static const struct ich_reg_info intel_regs[2] = {
                { ICH_MIINT, 0 },
                { ICH_MOINT, 0x10 },
        };
-       struct ich_reg_info *tbl;
+       const struct ich_reg_info *tbl;
 
        *r_intel8x0m = NULL;
 
@@ -1208,6 +1193,7 @@ static int snd_intel8x0m_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
                snd_intel8x0m_free(chip);
index 2b8204a..21ab9cc 100644 (file)
@@ -415,7 +415,7 @@ static const struct pci_device_id snd_korg1212_ids[] = {
 
 MODULE_DEVICE_TABLE(pci, snd_korg1212_ids);
 
-static char *stateName[] = {
+static const char * const stateName[] = {
        "Non-existent",
        "Uninitialized",
        "DSP download in process",
@@ -455,7 +455,7 @@ static const char * const channelName[] = {
        "SPDIF-R",
 };
 
-static u16 ClockSourceSelector[] = {
+static const u16 ClockSourceSelector[] = {
        0x8000,   // selects source as ADAT at 44.1 kHz
        0x0000,   // selects source as ADAT at 48 kHz
        0x8001,   // selects source as S/PDIF at 44.1 kHz
@@ -813,12 +813,12 @@ static inline int snd_korg1212_use_is_exclusive(struct snd_korg1212 *korg1212)
 
 static int snd_korg1212_SetRate(struct snd_korg1212 *korg1212, int rate)
 {
-        static enum ClockSourceIndex s44[] = {
+       static const enum ClockSourceIndex s44[] = {
                K1212_CLKIDX_AdatAt44_1K,
                K1212_CLKIDX_WordAt44_1K,
                K1212_CLKIDX_LocalAt44_1K
        };
-        static enum ClockSourceIndex s48[] = {
+       static const enum ClockSourceIndex s48[] = {
                K1212_CLKIDX_AdatAt48K,
                K1212_CLKIDX_WordAt48K,
                K1212_CLKIDX_LocalAt48K
@@ -2019,7 +2019,7 @@ static int snd_korg1212_control_sync_put(struct snd_kcontrol *kcontrol,
                .private_value = ord,                                                           \
         }
 
-static struct snd_kcontrol_new snd_korg1212_controls[] = {
+static const struct snd_kcontrol_new snd_korg1212_controls[] = {
         MON_MIXER(8, "Analog"),
        MON_MIXER(10, "SPDIF"), 
         MON_MIXER(0, "ADAT-1"), MON_MIXER(1, "ADAT-2"), MON_MIXER(2, "ADAT-3"), MON_MIXER(3, "ADAT-4"),
@@ -2153,7 +2153,7 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
         struct snd_korg1212 * korg1212;
        const struct firmware *dsp_code;
 
-        static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                 .dev_free = snd_korg1212_dev_free,
         };
 
@@ -2237,6 +2237,7 @@ static int snd_korg1212_create(struct snd_card *card, struct pci_dev *pci,
         }
 
         korg1212->irq = pci->irq;
+       card->sync_irq = korg1212->irq;
 
        pci_set_master(korg1212->pci);
 
index 21ac9d0..cdd8db7 100644 (file)
@@ -559,7 +559,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
        struct lola *chip;
        int err;
        unsigned int dever;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = lola_dev_free,
        };
 
@@ -638,7 +638,7 @@ static int lola_create(struct snd_card *card, struct pci_dev *pci,
                goto errout;
        }
        chip->irq = pci->irq;
-       synchronize_irq(chip->irq);
+       card->sync_irq = chip->irq;
 
        dever = lola_readl(chip, BAR1, DEVER);
        chip->pcm[CAPT].num_streams = (dever >> 0) & 0x3ff;
index 856bcca..f647c7e 100644 (file)
@@ -282,8 +282,7 @@ static int lola_pcm_hw_params(struct snd_pcm_substream *substream,
        str->bufsize = 0;
        str->period_bytes = 0;
        str->format_verb = 0;
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
+       return 0;
 }
 
 static int lola_pcm_hw_free(struct snd_pcm_substream *substream)
@@ -296,7 +295,7 @@ static int lola_pcm_hw_free(struct snd_pcm_substream *substream)
        lola_stream_reset(chip, str);
        lola_cleanup_slave_streams(pcm, str);
        mutex_unlock(&chip->open_mutex);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 /*
@@ -576,7 +575,6 @@ void lola_pcm_update(struct lola *chip, struct lola_pcm *pcm, unsigned int bits)
 static const struct snd_pcm_ops lola_pcm_ops = {
        .open = lola_pcm_open,
        .close = lola_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = lola_pcm_hw_params,
        .hw_free = lola_pcm_hw_free,
        .prepare = lola_pcm_prepare,
@@ -610,9 +608,9 @@ int lola_create_pcm(struct lola *chip)
                        snd_pcm_set_ops(pcm, i, &lola_pcm_ops);
        }
        /* buffer pre-allocation */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             1024 * 64, 32 * 1024 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev,
+                                      1024 * 64, 32 * 1024 * 1024);
        return 0;
 }
 
index d0f63fa..b92ea07 100644 (file)
@@ -342,23 +342,18 @@ static int lx_pcm_hw_params(struct snd_pcm_substream *substream,
                            struct snd_pcm_hw_params *hw_params, int is_capture)
 {
        struct lx6464es *chip = snd_pcm_substream_chip(substream);
-       int err = 0;
 
        dev_dbg(chip->card->dev, "->lx_pcm_hw_params\n");
 
        mutex_lock(&chip->setup_mutex);
 
-       /* set dma buffer */
-       err = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-
        if (is_capture)
                chip->capture_stream.stream = substream;
        else
                chip->playback_stream.stream = substream;
 
        mutex_unlock(&chip->setup_mutex);
-       return err;
+       return 0;
 }
 
 static int lx_pcm_hw_params_playback(struct snd_pcm_substream *substream,
@@ -400,8 +395,6 @@ static int lx_pcm_hw_free(struct snd_pcm_substream *substream)
                chip->hardware_running[is_capture] = 0;
        }
 
-       err = snd_pcm_lib_free_pages(substream);
-
        if (is_capture)
                chip->capture_stream.stream = NULL;
        else
@@ -798,7 +791,6 @@ mac_ready:
 static const struct snd_pcm_ops lx_ops_playback = {
        .open      = lx_pcm_open,
        .close     = lx_pcm_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .prepare   = lx_pcm_prepare,
        .hw_params = lx_pcm_hw_params_playback,
        .hw_free   = lx_pcm_hw_free,
@@ -809,7 +801,6 @@ static const struct snd_pcm_ops lx_ops_playback = {
 static const struct snd_pcm_ops lx_ops_capture = {
        .open      = lx_pcm_open,
        .close     = lx_pcm_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .prepare   = lx_pcm_prepare,
        .hw_params = lx_pcm_hw_params_capture,
        .hw_free   = lx_pcm_hw_free,
@@ -845,9 +836,8 @@ static int lx_pcm_create(struct lx6464es *chip)
        pcm->nonatomic = true;
        strcpy(pcm->name, card_name);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             size, size);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, size, size);
 
        chip->pcm = pcm;
        chip->capture_stream.is_capture = 1;
@@ -948,7 +938,7 @@ static int snd_lx6464es_create(struct snd_card *card,
        struct lx6464es *chip;
        int err;
 
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_lx6464es_dev_free,
        };
 
@@ -1012,6 +1002,7 @@ static int snd_lx6464es_create(struct snd_card *card,
                goto request_irq_failed;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
        if (err < 0)
index dd3a873..f884f5a 100644 (file)
@@ -161,7 +161,7 @@ struct dsp_cmd_info {
     the number of status words (in addition to the return value)
 */
 
-static struct dsp_cmd_info dsp_commands[] =
+static const struct dsp_cmd_info dsp_commands[] =
 {
        { (CMD_00_INFO_DEBUG << OPCODE_OFFSET)                  , 1 /*custom*/
          , 1   , 0 /**/                    , CMD_NAME("INFO_DEBUG") },
@@ -858,7 +858,7 @@ int lx_level_unmute(struct lx6464es *chip, int is_capture, int unmute)
        return err;
 }
 
-static u32 peak_map[] = {
+static const u32 peak_map[] = {
        0x00000109, /* -90.308dB */
        0x0000083B, /* -72.247dB */
        0x000020C4, /* -60.205dB */
index cc8594d..40232a2 100644 (file)
@@ -807,7 +807,7 @@ static const struct pci_device_id snd_m3_ids[] = {
 
 MODULE_DEVICE_TABLE(pci, snd_m3_ids);
 
-static struct snd_pci_quirk m3_amp_quirk_list[] = {
+static const struct snd_pci_quirk m3_amp_quirk_list[] = {
        SND_PCI_QUIRK(0x0E11, 0x0094, "Compaq Evo N600c", 0x0c),
        SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d),
        SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d),
@@ -816,7 +816,7 @@ static struct snd_pci_quirk m3_amp_quirk_list[] = {
        { } /* END */
 };
 
-static struct snd_pci_quirk m3_irda_quirk_list[] = {
+static const struct snd_pci_quirk m3_irda_quirk_list[] = {
        SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1),
        SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1),
        SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1),
@@ -824,7 +824,7 @@ static struct snd_pci_quirk m3_irda_quirk_list[] = {
 };
 
 /* hardware volume quirks */
-static struct snd_pci_quirk m3_hv_quirk_list[] = {
+static const struct snd_pci_quirk m3_hv_quirk_list[] = {
        /* Allegro chips */
        SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
        SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
@@ -902,7 +902,7 @@ static struct snd_pci_quirk m3_hv_quirk_list[] = {
 };
 
 /* HP Omnibook quirks */
-static struct snd_pci_quirk m3_omnibook_quirk_list[] = {
+static const struct snd_pci_quirk m3_omnibook_quirk_list[] = {
        SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */
        SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */
        { } /* END */
@@ -1381,10 +1381,7 @@ static int snd_m3_pcm_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *hw_params)
 {
        struct m3_dma *s = substream->runtime->private_data;
-       int err;
 
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
        /* set buffer address */
        s->buffer_addr = substream->runtime->dma_addr;
        if (s->buffer_addr & 0x3) {
@@ -1401,7 +1398,6 @@ static int snd_m3_pcm_hw_free(struct snd_pcm_substream *substream)
        if (substream->runtime->private_data == NULL)
                return 0;
        s = substream->runtime->private_data;
-       snd_pcm_lib_free_pages(substream);
        s->buffer_addr = 0;
        return 0;
 }
@@ -1822,7 +1818,6 @@ snd_m3_capture_close(struct snd_pcm_substream *subs)
 static const struct snd_pcm_ops snd_m3_playback_ops = {
        .open =         snd_m3_playback_open,
        .close =        snd_m3_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_m3_pcm_hw_params,
        .hw_free =      snd_m3_pcm_hw_free,
        .prepare =      snd_m3_pcm_prepare,
@@ -1833,7 +1828,6 @@ static const struct snd_pcm_ops snd_m3_playback_ops = {
 static const struct snd_pcm_ops snd_m3_capture_ops = {
        .open =         snd_m3_capture_open,
        .close =        snd_m3_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_m3_pcm_hw_params,
        .hw_free =      snd_m3_pcm_hw_free,
        .prepare =      snd_m3_pcm_prepare,
@@ -1860,9 +1854,8 @@ snd_m3_pcm(struct snd_m3 * chip, int device)
        strcpy(pcm->name, chip->card->driver);
        chip->pcm = pcm;
        
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 64*1024);
 
        return 0;
 }
@@ -2043,7 +2036,7 @@ static int snd_m3_mixer(struct snd_m3 *chip)
        struct snd_ctl_elem_id elem_id;
 #endif
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_m3_ac97_write,
                .read = snd_m3_ac97_read,
        };
@@ -2529,7 +2522,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
        struct snd_m3 *chip;
        int i, err;
        const struct snd_pci_quirk *quirk;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_m3_dev_free,
        };
 
@@ -2640,6 +2633,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
                goto free_chip;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
 #ifdef CONFIG_PM_SLEEP
        chip->suspend_mem =
index 674d37e..7ba4874 100644 (file)
@@ -624,10 +624,7 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs,
                return err;
        }
 
-       /* allocate buffer */
-       err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));
-
-       if (err > 0) {
+       if (subs->runtime->buffer_changed) {
                struct mixart_bufferinfo *bufferinfo;
                int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number;
                if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) {
@@ -647,13 +644,12 @@ static int snd_mixart_hw_params(struct snd_pcm_substream *subs,
        }
        mutex_unlock(&mgr->setup_mutex);
 
-       return err;
+       return 0;
 }
 
 static int snd_mixart_hw_free(struct snd_pcm_substream *subs)
 {
        struct snd_mixart *chip = snd_pcm_substream_chip(subs);
-       snd_pcm_lib_free_pages(subs);
        mixart_sync_nonblock_events(chip->mgr);
        return 0;
 }
@@ -913,7 +909,6 @@ static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *sub
 static const struct snd_pcm_ops snd_mixart_playback_ops = {
        .open      = snd_mixart_playback_open,
        .close     = snd_mixart_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .prepare   = snd_mixart_prepare,
        .hw_params = snd_mixart_hw_params,
        .hw_free   = snd_mixart_hw_free,
@@ -924,7 +919,6 @@ static const struct snd_pcm_ops snd_mixart_playback_ops = {
 static const struct snd_pcm_ops snd_mixart_capture_ops = {
        .open      = snd_mixart_capture_open,
        .close     = snd_mixart_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .prepare   = snd_mixart_prepare,
        .hw_params = snd_mixart_hw_params,
        .hw_free   = snd_mixart_hw_free,
@@ -947,9 +941,9 @@ static void preallocate_buffers(struct snd_mixart *chip, struct snd_pcm *pcm)
                                (chip->chip_idx + 1) << 24;
        }
 #endif
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->mgr->pci->dev,
-                                             32*1024, 32*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->mgr->pci->dev,
+                                      32*1024, 32*1024);
 }
 
 /*
@@ -1036,7 +1030,7 @@ static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int
 {
        int err;
        struct snd_mixart *chip;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_mixart_chip_dev_free,
        };
 
@@ -1047,6 +1041,7 @@ static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int
        chip->card = card;
        chip->chip_idx = idx;
        chip->mgr = mgr;
+       card->sync_irq = mgr->irq;
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
                snd_mixart_chip_free(chip);
@@ -1158,11 +1153,11 @@ static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry,
        return count;
 }
 
-static struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
+static const struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
        .read   = snd_mixart_BA0_read,
 };
 
-static struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
+static const struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
        .read   = snd_mixart_BA1_read,
 };
 
index 92b051c..13dcb2f 100644 (file)
@@ -548,7 +548,7 @@ static int mixart_dsp_load(struct mixart_mgr* mgr, int index, const struct firmw
 
 int snd_mixart_setup_firmware(struct mixart_mgr *mgr)
 {
-       static char *fw_files[3] = {
+       static const char * const fw_files[3] = {
                "miXart8.xlx", "miXart8.elf", "miXart8AES.xlx"
        };
        char path[32];
index 1378f9e..d2e7c33 100644 (file)
@@ -20,7 +20,7 @@
 #include <sound/tlv.h>
 #include "mixart_mixer.h"
 
-static u32 mixart_analog_level[256] = {
+static const u32 mixart_analog_level[256] = {
        0xc2c00000,             /* [000] -96.0 dB */
        0xc2bf0000,             /* [001] -95.5 dB */
        0xc2be0000,             /* [002] -95.0 dB */
@@ -443,7 +443,7 @@ static const struct snd_kcontrol_new mixart_control_output_switch = {
        .put =          mixart_audio_sw_put
 };
 
-static u32 mixart_digital_level[256] = {
+static const u32 mixart_digital_level[256] = {
        0x00000000,             /* [000] = 0.00e+000 = mute if <= -109.5dB */
        0x366e1c7a,             /* [001] = 3.55e-006 = pow(10.0, 0.05 * -109.0dB) */
        0x367c3860,             /* [002] = 3.76e-006 = pow(10.0, 0.05 * -108.5dB) */
index 1201c9c..1726f29 100644 (file)
@@ -299,7 +299,7 @@ snd_nm256_writel(struct nm256 *chip, int offset, u32 val)
 }
 
 static inline void
-snd_nm256_write_buffer(struct nm256 *chip, void *src, int offset, int size)
+snd_nm256_write_buffer(struct nm256 *chip, const void *src, int offset, int size)
 {
        offset -= chip->buffer_start;
 #ifdef CONFIG_SND_DEBUG
@@ -460,6 +460,7 @@ static int snd_nm256_acquire_irq(struct nm256 *chip)
                        return -EBUSY;
                }
                chip->irq = chip->pci->irq;
+               chip->card->sync_irq = chip->irq;
        }
        chip->irq_acks++;
        mutex_unlock(&chip->irq_mutex);
@@ -475,6 +476,7 @@ static void snd_nm256_release_irq(struct nm256 *chip)
        if (chip->irq_acks == 0 && chip->irq >= 0) {
                free_irq(chip->irq, chip);
                chip->irq = -1;
+               chip->card->sync_irq = -1;
        }
        mutex_unlock(&chip->irq_mutex);
 }
@@ -783,7 +785,7 @@ snd_nm256_capture_update(struct nm256 *chip)
 /*
  * hardware info
  */
-static struct snd_pcm_hardware snd_nm256_playback =
+static const struct snd_pcm_hardware snd_nm256_playback =
 {
        .info =                 SNDRV_PCM_INFO_MMAP_IOMEM |SNDRV_PCM_INFO_MMAP_VALID |
                                SNDRV_PCM_INFO_INTERLEAVED |
@@ -802,7 +804,7 @@ static struct snd_pcm_hardware snd_nm256_playback =
        .period_bytes_max =     128 * 1024,
 };
 
-static struct snd_pcm_hardware snd_nm256_capture =
+static const struct snd_pcm_hardware snd_nm256_capture =
 {
        .info =                 SNDRV_PCM_INFO_MMAP_IOMEM | SNDRV_PCM_INFO_MMAP_VALID |
                                SNDRV_PCM_INFO_INTERLEAVED |
@@ -836,7 +838,7 @@ static int snd_nm256_pcm_hw_params(struct snd_pcm_substream *substream,
  */
 static void snd_nm256_setup_stream(struct nm256 *chip, struct nm256_stream *s,
                                   struct snd_pcm_substream *substream,
-                                  struct snd_pcm_hardware *hw_ptr)
+                                  const struct snd_pcm_hardware *hw_ptr)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
 
@@ -906,7 +908,6 @@ snd_nm256_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_nm256_playback_ops = {
        .open =         snd_nm256_playback_open,
        .close =        snd_nm256_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_nm256_pcm_hw_params,
        .prepare =      snd_nm256_pcm_prepare,
        .trigger =      snd_nm256_playback_trigger,
@@ -922,7 +923,6 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = {
 static const struct snd_pcm_ops snd_nm256_capture_ops = {
        .open =         snd_nm256_capture_open,
        .close =        snd_nm256_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_nm256_pcm_hw_params,
        .prepare =      snd_nm256_pcm_prepare,
        .trigger =      snd_nm256_capture_trigger,
@@ -1179,7 +1179,7 @@ struct initialValues {
        unsigned short value;
 };
 
-static struct initialValues nm256_ac97_init_val[] =
+static const struct initialValues nm256_ac97_init_val[] =
 {
        { AC97_MASTER,          0x8000 },
        { AC97_HEADPHONE,       0x8000 },
@@ -1309,7 +1309,7 @@ snd_nm256_mixer(struct nm256 *chip)
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .reset = snd_nm256_ac97_reset,
                .write = snd_nm256_ac97_write,
                .read = snd_nm256_ac97_read,
@@ -1471,7 +1471,7 @@ snd_nm256_create(struct snd_card *card, struct pci_dev *pci,
 {
        struct nm256 *chip;
        int err, pval;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_nm256_dev_free,
        };
        u32 addr;
@@ -1634,7 +1634,7 @@ __error:
 
 enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 };
 
-static struct snd_pci_quirk nm256_quirks[] = {
+static const struct snd_pci_quirk nm256_quirks[] = {
        /* HP omnibook 4150 has cs4232 codec internally */
        SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_BLACKLISTED),
        /* Reset workarounds to avoid lock-ups */
index c757252..f0599db 100644 (file)
@@ -1,7 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #define NM_TOTAL_COEFF_COUNT 0x3158
 
-static char coefficients[NM_TOTAL_COEFF_COUNT * 4] = { 
+static const char coefficients[NM_TOTAL_COEFF_COUNT * 4] = {
        0xFF, 0xFF, 0x2F, 0x00, 0x4B, 0xFF, 0xA5, 0x01, 0xEF, 0xFC, 0x21,
        0x05, 0x87, 0xF7, 0x62, 0x11, 0xE9, 0x45, 0x5E, 0xF9, 0xB5, 0x01,
        0xDE, 0xFF, 0xA4, 0xFF, 0x60, 0x00, 0xCA, 0xFF, 0x0D, 0x00, 0xFD,
@@ -4598,7 +4598,7 @@ static char coefficients[NM_TOTAL_COEFF_COUNT * 4] = {
        0x01, 0x8D, 0xFF, 0x0F, 0x00 
 };
 
-static u16
+static const u16
 coefficient_sizes[8 * 2] = {
        /* Playback */
        0x00C0, 0x5000, 0x0060, 0x2800, 0x0040, 0x0060, 0x1400, 0x0000,
index ed65d9f..afc6dd3 100644 (file)
@@ -661,6 +661,7 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
                goto err_card;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        strcpy(card->driver, chip->model.chip);
        strcpy(card->shortname, chip->model.shortname);
@@ -743,7 +744,6 @@ static int oxygen_pci_suspend(struct device *dev)
        oxygen_write16(chip, OXYGEN_INTERRUPT_MASK, 0);
        spin_unlock_irq(&chip->reg_lock);
 
-       synchronize_irq(chip->irq);
        flush_work(&chip->spdif_input_bits_work);
        flush_work(&chip->gpio_work);
        chip->interrupt_mask = saved_interrupt_mask;
index 203c8fe..75b25ec 100644 (file)
@@ -304,12 +304,6 @@ static int oxygen_hw_params(struct snd_pcm_substream *substream,
 {
        struct oxygen *chip = snd_pcm_substream_chip(substream);
        unsigned int channel = oxygen_substream_channel(substream);
-       int err;
-
-       err = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
 
        oxygen_write32(chip, channel_base_registers[channel],
                       (u32)substream->runtime->dma_addr);
@@ -529,7 +523,7 @@ static int oxygen_hw_free(struct snd_pcm_substream *substream)
        oxygen_clear_bits8(chip, OXYGEN_DMA_FLUSH, channel_mask);
        spin_unlock_irq(&chip->reg_lock);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int oxygen_spdif_hw_free(struct snd_pcm_substream *substream)
@@ -622,7 +616,6 @@ static snd_pcm_uframes_t oxygen_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops oxygen_rec_a_ops = {
        .open      = oxygen_rec_a_open,
        .close     = oxygen_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .hw_params = oxygen_rec_a_hw_params,
        .hw_free   = oxygen_hw_free,
        .prepare   = oxygen_prepare,
@@ -633,7 +626,6 @@ static const struct snd_pcm_ops oxygen_rec_a_ops = {
 static const struct snd_pcm_ops oxygen_rec_b_ops = {
        .open      = oxygen_rec_b_open,
        .close     = oxygen_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .hw_params = oxygen_rec_b_hw_params,
        .hw_free   = oxygen_hw_free,
        .prepare   = oxygen_prepare,
@@ -644,7 +636,6 @@ static const struct snd_pcm_ops oxygen_rec_b_ops = {
 static const struct snd_pcm_ops oxygen_rec_c_ops = {
        .open      = oxygen_rec_c_open,
        .close     = oxygen_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .hw_params = oxygen_rec_c_hw_params,
        .hw_free   = oxygen_hw_free,
        .prepare   = oxygen_prepare,
@@ -655,7 +646,6 @@ static const struct snd_pcm_ops oxygen_rec_c_ops = {
 static const struct snd_pcm_ops oxygen_spdif_ops = {
        .open      = oxygen_spdif_open,
        .close     = oxygen_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .hw_params = oxygen_spdif_hw_params,
        .hw_free   = oxygen_spdif_hw_free,
        .prepare   = oxygen_prepare,
@@ -666,7 +656,6 @@ static const struct snd_pcm_ops oxygen_spdif_ops = {
 static const struct snd_pcm_ops oxygen_multich_ops = {
        .open      = oxygen_multich_open,
        .close     = oxygen_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .hw_params = oxygen_multich_hw_params,
        .hw_free   = oxygen_hw_free,
        .prepare   = oxygen_prepare,
@@ -677,7 +666,6 @@ static const struct snd_pcm_ops oxygen_multich_ops = {
 static const struct snd_pcm_ops oxygen_ac97_ops = {
        .open      = oxygen_ac97_open,
        .close     = oxygen_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .hw_params = oxygen_hw_params,
        .hw_free   = oxygen_hw_free,
        .prepare   = oxygen_prepare,
@@ -711,17 +699,17 @@ int oxygen_pcm_init(struct oxygen *chip)
                pcm->private_data = chip;
                strcpy(pcm->name, "Multichannel");
                if (outs)
-                       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
-                                                     SNDRV_DMA_TYPE_DEV,
-                                                     &chip->pci->dev,
-                                                     DEFAULT_BUFFER_BYTES_MULTICH,
-                                                     BUFFER_BYTES_MAX_MULTICH);
+                       snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+                                                  SNDRV_DMA_TYPE_DEV,
+                                                  &chip->pci->dev,
+                                                  DEFAULT_BUFFER_BYTES_MULTICH,
+                                                  BUFFER_BYTES_MAX_MULTICH);
                if (ins)
-                       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
-                                                     SNDRV_DMA_TYPE_DEV,
-                                                     &chip->pci->dev,
-                                                     DEFAULT_BUFFER_BYTES,
-                                                     BUFFER_BYTES_MAX);
+                       snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+                                                  SNDRV_DMA_TYPE_DEV,
+                                                  &chip->pci->dev,
+                                                  DEFAULT_BUFFER_BYTES,
+                                                  BUFFER_BYTES_MAX);
        }
 
        outs = !!(chip->model.device_config & PLAYBACK_1_TO_SPDIF);
@@ -738,10 +726,10 @@ int oxygen_pcm_init(struct oxygen *chip)
                                        &oxygen_rec_c_ops);
                pcm->private_data = chip;
                strcpy(pcm->name, "Digital");
-               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                     &chip->pci->dev,
-                                                     DEFAULT_BUFFER_BYTES,
-                                                     BUFFER_BYTES_MAX);
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                              &chip->pci->dev,
+                                              DEFAULT_BUFFER_BYTES,
+                                              BUFFER_BYTES_MAX);
        }
 
        if (chip->has_ac97_1) {
@@ -768,10 +756,10 @@ int oxygen_pcm_init(struct oxygen *chip)
                                        &oxygen_rec_b_ops);
                pcm->private_data = chip;
                strcpy(pcm->name, outs ? "Front Panel" : "Analog 2");
-               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                     &chip->pci->dev,
-                                                     DEFAULT_BUFFER_BYTES,
-                                                     BUFFER_BYTES_MAX);
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                              &chip->pci->dev,
+                                              DEFAULT_BUFFER_BYTES,
+                                              BUFFER_BYTES_MAX);
        }
 
        ins = !!(chip->model.device_config & CAPTURE_3_FROM_I2S_3);
@@ -786,10 +774,10 @@ int oxygen_pcm_init(struct oxygen *chip)
                                     OXYGEN_REC_C_ROUTE_MASK);
                pcm->private_data = chip;
                strcpy(pcm->name, "Analog 3");
-               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                     &chip->pci->dev,
-                                                     DEFAULT_BUFFER_BYTES,
-                                                     BUFFER_BYTES_MAX);
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                              &chip->pci->dev,
+                                              DEFAULT_BUFFER_BYTES,
+                                              BUFFER_BYTES_MAX);
        }
        return 0;
 }
index 4af34d6..c2e4831 100644 (file)
@@ -136,7 +136,7 @@ struct board_parameters {
        short fw_file_set;
        short firmware_num;
 };
-static struct board_parameters pcxhr_board_params[] = {
+static const struct board_parameters pcxhr_board_params[] = {
 [PCI_ID_VX882HR] =      { "VX882HR",      4, 4, 0, 41 },
 [PCI_ID_PCX882HR] =     { "PCX882HR",     4, 4, 0, 41 },
 [PCI_ID_VX881HR] =      { "VX881HR",      4, 4, 0, 41 },
@@ -940,32 +940,16 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs,
        struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
        struct pcxhr_mgr *mgr = chip->mgr;
        struct pcxhr_stream *stream = subs->runtime->private_data;
-       snd_pcm_format_t format;
-       int err;
-       int channels;
-
-       /* set up channels */
-       channels = params_channels(hw);
-
-       /*  set up format for the stream */
-       format = params_format(hw);
 
        mutex_lock(&mgr->setup_mutex);
 
-       stream->channels = channels;
-       stream->format = format;
-
-       /* allocate buffer */
-       err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));
+       /* set up channels */
+       stream->channels = params_channels(hw);
+       /* set up format for the stream */
+       stream->format = params_format(hw);
 
        mutex_unlock(&mgr->setup_mutex);
 
-       return err;
-}
-
-static int pcxhr_hw_free(struct snd_pcm_substream *subs)
-{
-       snd_pcm_lib_free_pages(subs);
        return 0;
 }
 
@@ -1136,10 +1120,8 @@ static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs)
 static const struct snd_pcm_ops pcxhr_ops = {
        .open      = pcxhr_open,
        .close     = pcxhr_close,
-       .ioctl     = snd_pcm_lib_ioctl,
        .prepare   = pcxhr_prepare,
        .hw_params = pcxhr_hw_params,
-       .hw_free   = pcxhr_hw_free,
        .trigger   = pcxhr_trigger,
        .pointer   = pcxhr_stream_pointer,
 };
@@ -1170,9 +1152,9 @@ int pcxhr_create_pcm(struct snd_pcxhr *chip)
        pcm->nonatomic = true;
        strcpy(pcm->name, name);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->mgr->pci->dev,
-                                             32*1024, 32*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->mgr->pci->dev,
+                                      32*1024, 32*1024);
        chip->pcm = pcm;
        return 0;
 }
@@ -1197,7 +1179,7 @@ static int pcxhr_create(struct pcxhr_mgr *mgr,
 {
        int err;
        struct snd_pcxhr *chip;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = pcxhr_chip_dev_free,
        };
 
@@ -1208,6 +1190,7 @@ static int pcxhr_create(struct pcxhr_mgr *mgr,
        chip->card = card;
        chip->chip_idx = idx;
        chip->mgr = mgr;
+       card->sync_irq = mgr->irq;
 
        if (idx < mgr->playback_chips)
                /* stereo or mono streams */
index 495be27..87d2422 100644 (file)
@@ -466,7 +466,7 @@ enum {
 /*
  * Array of DSP commands
  */
-static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {
+static const struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {
 [CMD_VERSION] =                                { 0x010000, 1, RMH_SSIZE_FIXED },
 [CMD_SUPPORTED] =                      { 0x020000, 4, RMH_SSIZE_FIXED },
 [CMD_TEST_IT] =                                { 0x040000, 1, RMH_SSIZE_FIXED },
@@ -497,7 +497,7 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {
 };
 
 #ifdef CONFIG_SND_DEBUG_VERBOSE
-static char* cmd_names[] = {
+static const char * const cmd_names[] = {
 [CMD_VERSION] =                                "CMD_VERSION",
 [CMD_SUPPORTED] =                      "CMD_SUPPORTED",
 [CMD_TEST_IT] =                                "CMD_TEST_IT",
@@ -1006,7 +1006,7 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
                                  enum pcxhr_async_err_src err_src, int pipe,
                                  int is_capture)
 {
-       static char* err_src_name[] = {
+       static const char * const err_src_name[] = {
                [PCXHR_ERR_PIPE]        = "Pipe",
                [PCXHR_ERR_STREAM]      = "Stream",
                [PCXHR_ERR_AUDIO]       = "Audio"
index 12a6bdb..2258bd6 100644 (file)
@@ -348,7 +348,7 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
  */
 int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
 {
-       static char *fw_files[][5] = {
+       static const char * const fw_files[][5] = {
        [0] = { "xlxint.dat", "xlxc882hr.dat",
                "dspe882.e56", "dspb882hr.b56", "dspd882.d56" },
        [1] = { "xlxint.dat", "xlxc882e.dat",
index abcea86..b4f3002 100644 (file)
@@ -361,9 +361,9 @@ enum RT_CHANNEL_IDS {
 enum { SB_CMD = 0, MODEM_CMD, I2S_CMD0, I2S_CMD1, FM_CMD, MAX_CMD };
 
 struct lbuspath {
-       unsigned char *noconv;
-       unsigned char *stereo;
-       unsigned char *mono;
+       const unsigned char *noconv;
+       const unsigned char *stereo;
+       const unsigned char *mono;
 };
 
 struct cmdport {
@@ -464,7 +464,7 @@ struct sgd {                        /* scatter gather desriptor */
 
 struct pcmhw {                 /* pcm descriptor */
        struct lbuspath paths;
-       unsigned char *lbuspath;
+       const unsigned char *lbuspath;
        unsigned char source;
        unsigned char intdec[2];
        unsigned char mixer;
@@ -517,7 +517,7 @@ MODULE_DEVICE_TABLE(pci, snd_riptide_ids);
 /*
  */
 
-static unsigned char lbusin2out[E2SINK_MAX + 1][2] = {
+static const unsigned char lbusin2out[E2SINK_MAX + 1][2] = {
        {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
                                                                     LS_NONE2},
        {NO_OUT, LS_NONE1}, {NO_OUT, LS_NONE2}, {NO_OUT, LS_NONE1}, {NO_OUT,
@@ -557,63 +557,63 @@ static unsigned char lbusin2out[E2SINK_MAX + 1][2] = {
                                                                     LS_NONE2},
 };
 
-static unsigned char lbus_play_opl3[] = {
+static const unsigned char lbus_play_opl3[] = {
        DIGITAL_MIXER_IN0 + FM_MIXER, 0xff
 };
-static unsigned char lbus_play_modem[] = {
+static const unsigned char lbus_play_modem[] = {
        DIGITAL_MIXER_IN0 + MODEM_MIXER, 0xff
 };
-static unsigned char lbus_play_i2s[] = {
+static const unsigned char lbus_play_i2s[] = {
        INTER0_IN + I2S_INTDEC, DIGITAL_MIXER_IN0 + I2S_MIXER, 0xff
 };
-static unsigned char lbus_play_out[] = {
+static const unsigned char lbus_play_out[] = {
        PDAC2ACLNK, 0xff
 };
-static unsigned char lbus_play_outhp[] = {
+static const unsigned char lbus_play_outhp[] = {
        HNDSPK2ACLNK, 0xff
 };
-static unsigned char lbus_play_noconv1[] = {
+static const unsigned char lbus_play_noconv1[] = {
        DIGITAL_MIXER_IN0, 0xff
 };
-static unsigned char lbus_play_stereo1[] = {
+static const unsigned char lbus_play_stereo1[] = {
        INTER0_IN, DIGITAL_MIXER_IN0, 0xff
 };
-static unsigned char lbus_play_mono1[] = {
+static const unsigned char lbus_play_mono1[] = {
        INTERM0_IN, DIGITAL_MIXER_IN0, 0xff
 };
-static unsigned char lbus_play_noconv2[] = {
+static const unsigned char lbus_play_noconv2[] = {
        DIGITAL_MIXER_IN1, 0xff
 };
-static unsigned char lbus_play_stereo2[] = {
+static const unsigned char lbus_play_stereo2[] = {
        INTER1_IN, DIGITAL_MIXER_IN1, 0xff
 };
-static unsigned char lbus_play_mono2[] = {
+static const unsigned char lbus_play_mono2[] = {
        INTERM1_IN, DIGITAL_MIXER_IN1, 0xff
 };
-static unsigned char lbus_play_noconv3[] = {
+static const unsigned char lbus_play_noconv3[] = {
        DIGITAL_MIXER_IN2, 0xff
 };
-static unsigned char lbus_play_stereo3[] = {
+static const unsigned char lbus_play_stereo3[] = {
        INTER2_IN, DIGITAL_MIXER_IN2, 0xff
 };
-static unsigned char lbus_play_mono3[] = {
+static const unsigned char lbus_play_mono3[] = {
        INTERM2_IN, DIGITAL_MIXER_IN2, 0xff
 };
-static unsigned char lbus_rec_noconv1[] = {
+static const unsigned char lbus_rec_noconv1[] = {
        LBUS2ARM_FIFO5, 0xff
 };
-static unsigned char lbus_rec_stereo1[] = {
+static const unsigned char lbus_rec_stereo1[] = {
        DECIM0_IN, LBUS2ARM_FIFO5, 0xff
 };
-static unsigned char lbus_rec_mono1[] = {
+static const unsigned char lbus_rec_mono1[] = {
        DECIMM3_IN, LBUS2ARM_FIFO5, 0xff
 };
 
-static unsigned char play_ids[] = { 4, 1, 2, };
-static unsigned char play_sources[] = {
+static const unsigned char play_ids[] = { 4, 1, 2, };
+static const unsigned char play_sources[] = {
        ARM2LBUS_FIFO4, ARM2LBUS_FIFO1, ARM2LBUS_FIFO2,
 };
-static struct lbuspath lbus_play_paths[] = {
+static const struct lbuspath lbus_play_paths[] = {
        {
         .noconv = lbus_play_noconv1,
         .stereo = lbus_play_stereo1,
@@ -737,7 +737,7 @@ static int loadfirmware(struct cmdif *cif, const unsigned char *img,
 
 static void
 alloclbuspath(struct cmdif *cif, unsigned char source,
-             unsigned char *path, unsigned char *mixer, unsigned char *s)
+             const unsigned char *path, unsigned char *mixer, unsigned char *s)
 {
        while (*path != 0xff) {
                unsigned char sink, type;
@@ -765,7 +765,7 @@ alloclbuspath(struct cmdif *cif, unsigned char source,
                        }
                }
                if (*path++ & SPLIT_PATH) {
-                       unsigned char *npath = path;
+                       const unsigned char *npath = path;
 
                        while (*npath != 0xff)
                                npath++;
@@ -775,7 +775,7 @@ alloclbuspath(struct cmdif *cif, unsigned char source,
 }
 
 static void
-freelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path)
+freelbuspath(struct cmdif *cif, unsigned char source, const unsigned char *path)
 {
        while (*path != 0xff) {
                unsigned char sink;
@@ -787,7 +787,7 @@ freelbuspath(struct cmdif *cif, unsigned char source, unsigned char *path)
                        source = lbusin2out[sink][0];
                }
                if (*path++ & SPLIT_PATH) {
-                       unsigned char *npath = path;
+                       const unsigned char *npath = path;
 
                        while (*npath != 0xff)
                                npath++;
@@ -1441,7 +1441,7 @@ static int snd_riptide_prepare(struct snd_pcm_substream *substream)
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct pcmhw *data = get_pcmhwdev(substream);
        struct cmdif *cif = chip->cif;
-       unsigned char *lbuspath = NULL;
+       const unsigned char *lbuspath = NULL;
        unsigned int rate, channels;
        int err = 0;
        snd_pcm_format_t format;
@@ -1558,8 +1558,7 @@ snd_riptide_hw_params(struct snd_pcm_substream *substream,
                return err;
        }
        data->sgdbuf = (struct sgd *)sgdlist->area;
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
+       return 0;
 }
 
 static int snd_riptide_hw_free(struct snd_pcm_substream *substream)
@@ -1581,7 +1580,7 @@ static int snd_riptide_hw_free(struct snd_pcm_substream *substream)
                        data->sgdlist.area = NULL;
                }
        }
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int snd_riptide_playback_open(struct snd_pcm_substream *substream)
@@ -1657,7 +1656,6 @@ static int snd_riptide_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_riptide_playback_ops = {
        .open = snd_riptide_playback_open,
        .close = snd_riptide_playback_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_riptide_hw_params,
        .hw_free = snd_riptide_hw_free,
        .prepare = snd_riptide_prepare,
@@ -1667,7 +1665,6 @@ static const struct snd_pcm_ops snd_riptide_playback_ops = {
 static const struct snd_pcm_ops snd_riptide_capture_ops = {
        .open = snd_riptide_capture_open,
        .close = snd_riptide_capture_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_riptide_hw_params,
        .hw_free = snd_riptide_hw_free,
        .prepare = snd_riptide_prepare,
@@ -1692,9 +1689,8 @@ static int snd_riptide_pcm(struct snd_riptide *chip, int device)
        pcm->info_flags = 0;
        strcpy(pcm->name, "RIPTIDE");
        chip->pcm = pcm;
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             64 * 1024, 128 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev, 64 * 1024, 128 * 1024);
        return 0;
 }
 
@@ -1828,7 +1824,7 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
        struct snd_riptide *chip;
        struct riptideport *hwport;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = snd_riptide_dev_free,
        };
 
@@ -1868,6 +1864,7 @@ snd_riptide_create(struct snd_card *card, struct pci_dev *pci,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        chip->device_id = pci->device;
        pci_set_master(pci);
        if ((err = snd_riptide_initialize(chip)) < 0) {
@@ -1966,7 +1963,7 @@ static int snd_riptide_mixer(struct snd_riptide *chip)
        struct snd_ac97_bus *pbus;
        struct snd_ac97_template ac97;
        int err = 0;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_riptide_codec_write,
                .read = snd_riptide_codec_read,
        };
index 58a4b8d..16d726d 100644 (file)
@@ -662,11 +662,7 @@ snd_rme32_playback_hw_params(struct snd_pcm_substream *substream,
        struct rme32 *rme32 = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
 
-       if (rme32->fullduplex_mode) {
-               err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-               if (err < 0)
-                       return err;
-       } else {
+       if (!rme32->fullduplex_mode) {
                runtime->dma_area = (void __force *)(rme32->iobase +
                                                     RME32_IO_DATA_BUFFER);
                runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
@@ -717,11 +713,7 @@ snd_rme32_capture_hw_params(struct snd_pcm_substream *substream,
        struct rme32 *rme32 = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
 
-       if (rme32->fullduplex_mode) {
-               err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
-               if (err < 0)
-                       return err;
-       } else {
+       if (!rme32->fullduplex_mode) {
                runtime->dma_area = (void __force *)rme32->iobase +
                                        RME32_IO_DATA_BUFFER;
                runtime->dma_addr = rme32->port + RME32_IO_DATA_BUFFER;
@@ -771,14 +763,6 @@ snd_rme32_capture_hw_params(struct snd_pcm_substream *substream,
        return 0;
 }
 
-static int snd_rme32_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-       if (! rme32->fullduplex_mode)
-               return 0;
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static void snd_rme32_pcm_start(struct rme32 * rme32, int from_pause)
 {
        if (!from_pause) {
@@ -1193,9 +1177,7 @@ snd_rme32_capture_fd_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = {
        .open =         snd_rme32_playback_spdif_open,
        .close =        snd_rme32_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme32_playback_hw_params,
-       .hw_free =      snd_rme32_pcm_hw_free,
        .prepare =      snd_rme32_playback_prepare,
        .trigger =      snd_rme32_pcm_trigger,
        .pointer =      snd_rme32_playback_pointer,
@@ -1208,9 +1190,7 @@ static const struct snd_pcm_ops snd_rme32_playback_spdif_ops = {
 static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = {
        .open =         snd_rme32_capture_spdif_open,
        .close =        snd_rme32_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme32_capture_hw_params,
-       .hw_free =      snd_rme32_pcm_hw_free,
        .prepare =      snd_rme32_capture_prepare,
        .trigger =      snd_rme32_pcm_trigger,
        .pointer =      snd_rme32_capture_pointer,
@@ -1222,7 +1202,6 @@ static const struct snd_pcm_ops snd_rme32_capture_spdif_ops = {
 static const struct snd_pcm_ops snd_rme32_playback_adat_ops = {
        .open =         snd_rme32_playback_adat_open,
        .close =        snd_rme32_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme32_playback_hw_params,
        .prepare =      snd_rme32_playback_prepare,
        .trigger =      snd_rme32_pcm_trigger,
@@ -1236,7 +1215,6 @@ static const struct snd_pcm_ops snd_rme32_playback_adat_ops = {
 static const struct snd_pcm_ops snd_rme32_capture_adat_ops = {
        .open =         snd_rme32_capture_adat_open,
        .close =        snd_rme32_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme32_capture_hw_params,
        .prepare =      snd_rme32_capture_prepare,
        .trigger =      snd_rme32_pcm_trigger,
@@ -1250,9 +1228,7 @@ static const struct snd_pcm_ops snd_rme32_capture_adat_ops = {
 static const struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = {
        .open =         snd_rme32_playback_spdif_open,
        .close =        snd_rme32_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme32_playback_hw_params,
-       .hw_free =      snd_rme32_pcm_hw_free,
        .prepare =      snd_rme32_playback_prepare,
        .trigger =      snd_rme32_pcm_trigger,
        .pointer =      snd_rme32_playback_fd_pointer,
@@ -1262,9 +1238,7 @@ static const struct snd_pcm_ops snd_rme32_playback_spdif_fd_ops = {
 static const struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = {
        .open =         snd_rme32_capture_spdif_open,
        .close =        snd_rme32_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme32_capture_hw_params,
-       .hw_free =      snd_rme32_pcm_hw_free,
        .prepare =      snd_rme32_capture_prepare,
        .trigger =      snd_rme32_pcm_trigger,
        .pointer =      snd_rme32_capture_fd_pointer,
@@ -1274,7 +1248,6 @@ static const struct snd_pcm_ops snd_rme32_capture_spdif_fd_ops = {
 static const struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = {
        .open =         snd_rme32_playback_adat_open,
        .close =        snd_rme32_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme32_playback_hw_params,
        .prepare =      snd_rme32_playback_prepare,
        .trigger =      snd_rme32_pcm_trigger,
@@ -1285,7 +1258,6 @@ static const struct snd_pcm_ops snd_rme32_playback_adat_fd_ops = {
 static const struct snd_pcm_ops snd_rme32_capture_adat_fd_ops = {
        .open =         snd_rme32_capture_adat_open,
        .close =        snd_rme32_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme32_capture_hw_params,
        .prepare =      snd_rme32_capture_prepare,
        .trigger =      snd_rme32_pcm_trigger,
@@ -1358,6 +1330,7 @@ static int snd_rme32_create(struct rme32 *rme32)
                return -EBUSY;
        }
        rme32->irq = pci->irq;
+       rme32->card->sync_irq = rme32->irq;
 
        /* read the card's revision number */
        pci_read_config_byte(pci, 8, &rme32->rev);
@@ -1374,9 +1347,8 @@ static int snd_rme32_create(struct rme32 *rme32)
                                &snd_rme32_playback_spdif_fd_ops);
                snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_CAPTURE,
                                &snd_rme32_capture_spdif_fd_ops);
-               snd_pcm_lib_preallocate_pages_for_all(rme32->spdif_pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                                     NULL,
-                                                     0, RME32_MID_BUFFER_SIZE);
+               snd_pcm_set_managed_buffer_all(rme32->spdif_pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                              NULL, 0, RME32_MID_BUFFER_SIZE);
                rme32->spdif_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
        } else {
                snd_pcm_set_ops(rme32->spdif_pcm, SNDRV_PCM_STREAM_PLAYBACK,
@@ -1406,9 +1378,9 @@ static int snd_rme32_create(struct rme32 *rme32)
                                        &snd_rme32_playback_adat_fd_ops);
                        snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_CAPTURE, 
                                        &snd_rme32_capture_adat_fd_ops);
-                       snd_pcm_lib_preallocate_pages_for_all(rme32->adat_pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                                             NULL,
-                                                             0, RME32_MID_BUFFER_SIZE);
+                       snd_pcm_set_managed_buffer_all(rme32->adat_pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                                      NULL,
+                                                      0, RME32_MID_BUFFER_SIZE);
                        rme32->adat_pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
                } else {
                        snd_pcm_set_ops(rme32->adat_pcm, SNDRV_PCM_STREAM_PLAYBACK, 
@@ -1824,7 +1796,7 @@ static int snd_rme32_control_spdif_mask_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new snd_rme32_controls[] = {
+static const struct snd_kcontrol_new snd_rme32_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
                .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
index 64ab557..db576b7 100644 (file)
@@ -1508,7 +1508,6 @@ snd_rme96_capture_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = {
        .open =         snd_rme96_playback_spdif_open,
        .close =        snd_rme96_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme96_playback_hw_params,
        .prepare =      snd_rme96_playback_prepare,
        .trigger =      snd_rme96_playback_trigger,
@@ -1522,7 +1521,6 @@ static const struct snd_pcm_ops snd_rme96_playback_spdif_ops = {
 static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = {
        .open =         snd_rme96_capture_spdif_open,
        .close =        snd_rme96_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme96_capture_hw_params,
        .prepare =      snd_rme96_capture_prepare,
        .trigger =      snd_rme96_capture_trigger,
@@ -1535,7 +1533,6 @@ static const struct snd_pcm_ops snd_rme96_capture_spdif_ops = {
 static const struct snd_pcm_ops snd_rme96_playback_adat_ops = {
        .open =         snd_rme96_playback_adat_open,
        .close =        snd_rme96_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme96_playback_hw_params,
        .prepare =      snd_rme96_playback_prepare,
        .trigger =      snd_rme96_playback_trigger,
@@ -1549,7 +1546,6 @@ static const struct snd_pcm_ops snd_rme96_playback_adat_ops = {
 static const struct snd_pcm_ops snd_rme96_capture_adat_ops = {
        .open =         snd_rme96_capture_adat_open,
        .close =        snd_rme96_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_rme96_capture_hw_params,
        .prepare =      snd_rme96_capture_prepare,
        .trigger =      snd_rme96_capture_trigger,
@@ -1633,6 +1629,7 @@ snd_rme96_create(struct rme96 *rme96)
                return -EBUSY;
        }
        rme96->irq = pci->irq;
+       rme96->card->sync_irq = rme96->irq;
 
        /* read the card's revision number */
        pci_read_config_byte(pci, 8, &rme96->rev);      
@@ -2256,7 +2253,7 @@ snd_rme96_dac_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_valu
         return change;
 }
 
-static struct snd_kcontrol_new snd_rme96_controls[] = {
+static const struct snd_kcontrol_new snd_rme96_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
index cd20af4..25b3c56 100644 (file)
@@ -479,7 +479,7 @@ struct hdsp {
        pid_t                 playback_pid;
        int                   running;
        int                   system_sample_rate;
-       char                 *channel_map;
+       const char           *channel_map;
        int                   dev;
        int                   irq;
        unsigned long         port;
@@ -501,12 +501,12 @@ struct hdsp {
    where the data for that channel can be read/written from/to.
 */
 
-static char channel_map_df_ss[HDSP_MAX_CHANNELS] = {
+static const char channel_map_df_ss[HDSP_MAX_CHANNELS] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19, 20, 21, 22, 23, 24, 25
 };
 
-static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
+static const char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
        /* Analog */
        0, 1, 2, 3, 4, 5, 6, 7,
        /* ADAT 2 */
@@ -516,7 +516,7 @@ static char channel_map_mf_ss[HDSP_MAX_CHANNELS] = { /* Multiface */
        -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_ds[HDSP_MAX_CHANNELS] = {
+static const char channel_map_ds[HDSP_MAX_CHANNELS] = {
        /* ADAT channels are remapped */
        1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,
        /* channels 12 and 13 are S/PDIF */
@@ -525,7 +525,7 @@ static char channel_map_ds[HDSP_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
+static const char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
        /* ADAT channels */
        0, 1, 2, 3, 4, 5, 6, 7,
        /* SPDIF */
@@ -539,7 +539,7 @@ static char channel_map_H9632_ss[HDSP_MAX_CHANNELS] = {
        -1, -1
 };
 
-static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
+static const char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
        /* ADAT */
        1, 3, 5, 7,
        /* SPDIF */
@@ -553,7 +553,7 @@ static char channel_map_H9632_ds[HDSP_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
+static const char channel_map_H9632_qs[HDSP_MAX_CHANNELS] = {
        /* ADAT is disabled in this mode */
        /* SPDIF */
        8, 9,
@@ -2879,7 +2879,7 @@ static int snd_hdsp_put_dds_offset(struct snd_kcontrol *kcontrol, struct snd_ctl
        return change;
 }
 
-static struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
+static const struct snd_kcontrol_new snd_hdsp_9632_controls[] = {
 HDSP_DA_GAIN("DA Gain", 0),
 HDSP_AD_GAIN("AD Gain", 0),
 HDSP_PHONE_GAIN("Phones Gain", 0),
@@ -2887,7 +2887,7 @@ HDSP_TOGGLE_SETTING("XLR Breakout Cable", HDSP_XLRBreakoutCable),
 HDSP_DDS_OFFSET("DDS Sample Rate Offset", 0)
 };
 
-static struct snd_kcontrol_new snd_hdsp_controls[] = {
+static const struct snd_kcontrol_new snd_hdsp_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -3216,7 +3216,7 @@ static int snd_hdsp_info_rpm_disconnect(struct snd_kcontrol *kcontrol, struct sn
        return snd_ctl_enum_info(uinfo, 1, 2, texts);
 }
 
-static struct snd_kcontrol_new snd_hdsp_rpm_controls[] = {
+static const struct snd_kcontrol_new snd_hdsp_rpm_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "RPM Bypass",
@@ -3249,7 +3249,7 @@ static struct snd_kcontrol_new snd_hdsp_rpm_controls[] = {
        HDSP_MIXER("Mixer", 0)
 };
 
-static struct snd_kcontrol_new snd_hdsp_96xx_aeb =
+static const struct snd_kcontrol_new snd_hdsp_96xx_aeb =
        HDSP_TOGGLE_SETTING("Analog Extension Board",
                        HDSP_AnalogExtensionBoard);
 static struct snd_kcontrol_new snd_hdsp_adat_sync_check = HDSP_ADAT_SYNC_CHECK;
@@ -4802,7 +4802,7 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
                break;
        }
        case SNDRV_HDSP_IOCTL_UPLOAD_FIRMWARE: {
-               struct hdsp_firmware __user *firmware;
+               struct hdsp_firmware firmware;
                u32 __user *firmware_data;
                int err;
 
@@ -4815,10 +4815,9 @@ static int snd_hdsp_hwdep_ioctl(struct snd_hwdep *hw, struct file *file, unsigne
 
                dev_info(hdsp->card->dev,
                         "initializing firmware upload\n");
-               firmware = (struct hdsp_firmware __user *)argp;
-
-               if (get_user(firmware_data, &firmware->firmware_data))
+               if (copy_from_user(&firmware, argp, sizeof(firmware)))
                        return -EFAULT;
+               firmware_data = (u32 __user *)firmware.firmware_data;
 
                if (hdsp_check_for_iobox (hdsp))
                        return -EIO;
@@ -5233,6 +5232,7 @@ static int snd_hdsp_create(struct snd_card *card,
        }
 
        hdsp->irq = pci->irq;
+       card->sync_irq = hdsp->irq;
        hdsp->precise_ptr = 0;
        hdsp->use_midi_tasklet = 1;
        hdsp->dds_value = 0;
index 75c06a7..2212d57 100644 (file)
@@ -637,7 +637,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
 #define HDSPM_SPEED_QUAD   2
 
 /* names for speed modes */
-static char *hdspm_speed_names[] = { "single", "double", "quad" };
+static const char * const hdspm_speed_names[] = { "single", "double", "quad" };
 
 static const char *const texts_autosync_aes_tco[] = { "Word Clock",
                                          "AES1", "AES2", "AES3", "AES4",
@@ -684,7 +684,7 @@ static const char *const texts_freq[] = {
        "192 kHz"
 };
 
-static char *texts_ports_madi[] = {
+static const char * const texts_ports_madi[] = {
        "MADI.1", "MADI.2", "MADI.3", "MADI.4", "MADI.5", "MADI.6",
        "MADI.7", "MADI.8", "MADI.9", "MADI.10", "MADI.11", "MADI.12",
        "MADI.13", "MADI.14", "MADI.15", "MADI.16", "MADI.17", "MADI.18",
@@ -699,7 +699,7 @@ static char *texts_ports_madi[] = {
 };
 
 
-static char *texts_ports_raydat_ss[] = {
+static const char * const texts_ports_raydat_ss[] = {
        "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4", "ADAT1.5", "ADAT1.6",
        "ADAT1.7", "ADAT1.8", "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
        "ADAT2.5", "ADAT2.6", "ADAT2.7", "ADAT2.8", "ADAT3.1", "ADAT3.2",
@@ -710,7 +710,7 @@ static char *texts_ports_raydat_ss[] = {
        "SPDIF.L", "SPDIF.R"
 };
 
-static char *texts_ports_raydat_ds[] = {
+static const char * const texts_ports_raydat_ds[] = {
        "ADAT1.1", "ADAT1.2", "ADAT1.3", "ADAT1.4",
        "ADAT2.1", "ADAT2.2", "ADAT2.3", "ADAT2.4",
        "ADAT3.1", "ADAT3.2", "ADAT3.3", "ADAT3.4",
@@ -719,7 +719,7 @@ static char *texts_ports_raydat_ds[] = {
        "SPDIF.L", "SPDIF.R"
 };
 
-static char *texts_ports_raydat_qs[] = {
+static const char * const texts_ports_raydat_qs[] = {
        "ADAT1.1", "ADAT1.2",
        "ADAT2.1", "ADAT2.2",
        "ADAT3.1", "ADAT3.2",
@@ -729,7 +729,7 @@ static char *texts_ports_raydat_qs[] = {
 };
 
 
-static char *texts_ports_aio_in_ss[] = {
+static const char * const texts_ports_aio_in_ss[] = {
        "Analogue.L", "Analogue.R",
        "AES.L", "AES.R",
        "SPDIF.L", "SPDIF.R",
@@ -738,7 +738,7 @@ static char *texts_ports_aio_in_ss[] = {
        "AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
-static char *texts_ports_aio_out_ss[] = {
+static const char * const texts_ports_aio_out_ss[] = {
        "Analogue.L", "Analogue.R",
        "AES.L", "AES.R",
        "SPDIF.L", "SPDIF.R",
@@ -748,7 +748,7 @@ static char *texts_ports_aio_out_ss[] = {
        "AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
-static char *texts_ports_aio_in_ds[] = {
+static const char * const texts_ports_aio_in_ds[] = {
        "Analogue.L", "Analogue.R",
        "AES.L", "AES.R",
        "SPDIF.L", "SPDIF.R",
@@ -756,7 +756,7 @@ static char *texts_ports_aio_in_ds[] = {
        "AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
-static char *texts_ports_aio_out_ds[] = {
+static const char * const texts_ports_aio_out_ds[] = {
        "Analogue.L", "Analogue.R",
        "AES.L", "AES.R",
        "SPDIF.L", "SPDIF.R",
@@ -765,7 +765,7 @@ static char *texts_ports_aio_out_ds[] = {
        "AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
-static char *texts_ports_aio_in_qs[] = {
+static const char * const texts_ports_aio_in_qs[] = {
        "Analogue.L", "Analogue.R",
        "AES.L", "AES.R",
        "SPDIF.L", "SPDIF.R",
@@ -773,7 +773,7 @@ static char *texts_ports_aio_in_qs[] = {
        "AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
-static char *texts_ports_aio_out_qs[] = {
+static const char * const texts_ports_aio_out_qs[] = {
        "Analogue.L", "Analogue.R",
        "AES.L", "AES.R",
        "SPDIF.L", "SPDIF.R",
@@ -782,7 +782,7 @@ static char *texts_ports_aio_out_qs[] = {
        "AEB.1", "AEB.2", "AEB.3", "AEB.4"
 };
 
-static char *texts_ports_aes32[] = {
+static const char * const texts_ports_aes32[] = {
        "AES.1", "AES.2", "AES.3", "AES.4", "AES.5", "AES.6", "AES.7",
        "AES.8", "AES.9.", "AES.10", "AES.11", "AES.12", "AES.13", "AES.14",
        "AES.15", "AES.16"
@@ -796,7 +796,7 @@ static char *texts_ports_aes32[] = {
    where the data for that channel can be read/written from/to.
 */
 
-static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
        0, 1, 2, 3, 4, 5, 6, 7,
        8, 9, 10, 11, 12, 13, 14, 15,
        16, 17, 18, 19, 20, 21, 22, 23,
@@ -807,7 +807,7 @@ static char channel_map_unity_ss[HDSPM_MAX_CHANNELS] = {
        56, 57, 58, 59, 60, 61, 62, 63
 };
 
-static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
        4, 5, 6, 7, 8, 9, 10, 11,       /* ADAT 1 */
        12, 13, 14, 15, 16, 17, 18, 19, /* ADAT 2 */
        20, 21, 22, 23, 24, 25, 26, 27, /* ADAT 3 */
@@ -820,7 +820,7 @@ static char channel_map_raydat_ss[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1,
 };
 
-static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
        4, 5, 6, 7,             /* ADAT 1 */
        8, 9, 10, 11,           /* ADAT 2 */
        12, 13, 14, 15,         /* ADAT 3 */
@@ -835,7 +835,7 @@ static char channel_map_raydat_ds[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1,
 };
 
-static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
        4, 5,                   /* ADAT 1 */
        6, 7,                   /* ADAT 2 */
        8, 9,                   /* ADAT 3 */
@@ -851,7 +851,7 @@ static char channel_map_raydat_qs[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1,
 };
 
-static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
        0, 1,                   /* line in */
        8, 9,                   /* aes in, */
        10, 11,                 /* spdif in */
@@ -865,7 +865,7 @@ static char channel_map_aio_in_ss[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1,
 };
 
-static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
        0, 1,                   /* line out */
        8, 9,                   /* aes out */
        10, 11,                 /* spdif out */
@@ -880,7 +880,7 @@ static char channel_map_aio_out_ss[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1,
 };
 
-static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
        0, 1,                   /* line in */
        8, 9,                   /* aes in */
        10, 11,                 /* spdif in */
@@ -895,7 +895,7 @@ static char channel_map_aio_in_ds[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
        0, 1,                   /* line out */
        8, 9,                   /* aes out */
        10, 11,                 /* spdif out */
@@ -910,7 +910,7 @@ static char channel_map_aio_out_ds[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
        0, 1,                   /* line in */
        8, 9,                   /* aes in */
        10, 11,                 /* spdif in */
@@ -925,7 +925,7 @@ static char channel_map_aio_in_qs[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
        0, 1,                   /* line out */
        8, 9,                   /* aes out */
        10, 11,                 /* spdif out */
@@ -941,7 +941,7 @@ static char channel_map_aio_out_qs[HDSPM_MAX_CHANNELS] = {
        -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
+static const char channel_map_aes32[HDSPM_MAX_CHANNELS] = {
        0, 1, 2, 3, 4, 5, 6, 7,
        8, 9, 10, 11, 12, 13, 14, 15,
        -1, -1, -1, -1, -1, -1, -1, -1,
@@ -1010,17 +1010,21 @@ struct hdspm {
        unsigned char max_channels_in;
        unsigned char max_channels_out;
 
-       signed char *channel_map_in;
-       signed char *channel_map_out;
+       const signed char *channel_map_in;
+       const signed char *channel_map_out;
 
-       signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
-       signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
+       const signed char *channel_map_in_ss, *channel_map_in_ds, *channel_map_in_qs;
+       const signed char *channel_map_out_ss, *channel_map_out_ds, *channel_map_out_qs;
 
-       char **port_names_in;
-       char **port_names_out;
+       const char * const *port_names_in;
+       const char * const *port_names_out;
 
-       char **port_names_in_ss, **port_names_in_ds, **port_names_in_qs;
-       char **port_names_out_ss, **port_names_out_ds, **port_names_out_qs;
+       const char * const *port_names_in_ss;
+       const char * const *port_names_in_ds;
+       const char * const *port_names_in_qs;
+       const char * const *port_names_out_ss;
+       const char * const *port_names_out_ds;
+       const char * const *port_names_out_qs;
 
        unsigned char *playback_buffer; /* suitably aligned address */
        unsigned char *capture_buffer;  /* suitably aligned address */
@@ -4478,7 +4482,7 @@ static int snd_hdspm_put_tco_word_term(struct snd_kcontrol *kcontrol,
 
 
 
-static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
+static const struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
        HDSPM_MIXER("Mixer", 0),
        HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
        HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
@@ -4500,7 +4504,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
 };
 
 
-static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
+static const struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
        HDSPM_MIXER("Mixer", 0),
        HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
        HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
@@ -4513,7 +4517,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_madiface[] = {
        HDSPM_MADI_SPEEDMODE("MADI Speed Mode", 0)
 };
 
-static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
+static const struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
        HDSPM_MIXER("Mixer", 0),
        HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
        HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
@@ -4554,7 +4558,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_aio[] = {
                   */
 };
 
-static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
+static const struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
        HDSPM_MIXER("Mixer", 0),
        HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
        HDSPM_SYSTEM_CLOCK_MODE("Clock Mode", 0),
@@ -4582,7 +4586,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_raydat[] = {
        HDSPM_TOGGLE_SETTING("Single Speed WordClock Out", HDSPM_c0_Wck48)
 };
 
-static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
+static const struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
        HDSPM_MIXER("Mixer", 0),
        HDSPM_INTERNAL_CLOCK("Internal Clock", 0),
        HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
@@ -4624,7 +4628,7 @@ static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
 
 
 /* Control elements for the optional TCO module */
-static struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
+static const struct snd_kcontrol_new snd_hdspm_controls_tco[] = {
        HDSPM_TCO_SAMPLE_RATE("TCO Sample Rate", 0),
        HDSPM_TCO_PULL("TCO Pull", 0),
        HDSPM_TCO_WCK_CONVERSION("TCO WCK Conversion", 0),
@@ -4671,7 +4675,7 @@ static int snd_hdspm_create_controls(struct snd_card *card,
        unsigned int idx, limit;
        int err;
        struct snd_kcontrol *kctl;
-       struct snd_kcontrol_new *list = NULL;
+       const struct snd_kcontrol_new *list = NULL;
 
        switch (hdspm->io_type) {
        case MADI:
@@ -5820,7 +5824,7 @@ static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
+static const struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
        .info = (SNDRV_PCM_INFO_MMAP |
                 SNDRV_PCM_INFO_MMAP_VALID |
                 SNDRV_PCM_INFO_NONINTERLEAVED |
@@ -5845,7 +5849,7 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
        .fifo_size = 0
 };
 
-static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
+static const struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
        .info = (SNDRV_PCM_INFO_MMAP |
                 SNDRV_PCM_INFO_MMAP_VALID |
                 SNDRV_PCM_INFO_NONINTERLEAVED |
@@ -6613,6 +6617,7 @@ static int snd_hdspm_create(struct snd_card *card,
        dev_dbg(card->dev, "use IRQ %d\n", pci->irq);
 
        hdspm->irq = pci->irq;
+       card->sync_irq = hdspm->irq;
 
        dev_dbg(card->dev, "kmalloc Mixer memory of %zd Bytes\n",
                sizeof(*hdspm->mixer));
index ef5c2f8..c20e590 100644 (file)
@@ -229,7 +229,7 @@ struct snd_rme9652 {
        int last_spdif_sample_rate;     /* so that we can catch externally ... */
        int last_adat_sample_rate;      /* ... induced rate changes            */
 
-        char *channel_map;
+       const char *channel_map;
 
        struct snd_card *card;
        struct snd_pcm *pcm;
@@ -246,12 +246,12 @@ struct snd_rme9652 {
    where the data for that channel can be read/written from/to.
 */
 
-static char channel_map_9652_ss[26] = {
+static const char channel_map_9652_ss[26] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
        18, 19, 20, 21, 22, 23, 24, 25
 };
 
-static char channel_map_9636_ss[26] = {
+static const char channel_map_9636_ss[26] = {
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
        /* channels 16 and 17 are S/PDIF */
        24, 25,
@@ -259,7 +259,7 @@ static char channel_map_9636_ss[26] = {
        -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_9652_ds[26] = {
+static const char channel_map_9652_ds[26] = {
        /* ADAT channels are remapped */
        1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23,
        /* channels 12 and 13 are S/PDIF */
@@ -268,7 +268,7 @@ static char channel_map_9652_ds[26] = {
        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
 };
 
-static char channel_map_9636_ds[26] = {
+static const char channel_map_9636_ds[26] = {
        /* ADAT channels are remapped */
        1, 3, 5, 7, 9, 11, 13, 15,
        /* channels 8 and 9 are S/PDIF */
@@ -1454,7 +1454,7 @@ static int snd_rme9652_get_tc_value(void *private_data,
 
 #endif                         /* ALSA_HAS_STANDARD_WAY_OF_RETURNING_TIMECODE */
 
-static struct snd_kcontrol_new snd_rme9652_controls[] = {
+static const struct snd_kcontrol_new snd_rme9652_controls[] = {
 {
        .iface =        SNDRV_CTL_ELEM_IFACE_PCM,
        .name =         SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1509,10 +1509,10 @@ RME9652_TC_VALID("Timecode Valid", 0),
 RME9652_PASSTHRU("Passthru", 0)
 };
 
-static struct snd_kcontrol_new snd_rme9652_adat3_check =
+static const struct snd_kcontrol_new snd_rme9652_adat3_check =
 RME9652_ADAT_SYNC("ADAT3 Sync Check", 0, 2);
 
-static struct snd_kcontrol_new snd_rme9652_adat1_input =
+static const struct snd_kcontrol_new snd_rme9652_adat1_input =
 RME9652_ADAT1_IN("ADAT1 Input Source", 0);
 
 static int snd_rme9652_create_controls(struct snd_card *card, struct snd_rme9652 *rme9652)
@@ -2479,6 +2479,7 @@ static int snd_rme9652_create(struct snd_card *card,
                return -EBUSY;
        }
        rme9652->irq = pci->irq;
+       card->sync_irq = rme9652->irq;
        rme9652->precise_ptr = precise_ptr;
 
        /* Determine the h/w rev level of the card. This seems like
index ef7dd29..4977ab0 100644 (file)
@@ -499,18 +499,6 @@ static int sis_substream_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int sis_playback_hw_params(struct snd_pcm_substream *substream,
-                                       struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-static int sis_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int sis_pcm_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_pcm_runtime *runtime = substream->runtime;
@@ -701,11 +689,6 @@ static int sis_capture_hw_params(struct snd_pcm_substream *substream,
        if (rc)
                goto out;
 
-       rc = snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-       if (rc < 0)
-               goto out;
-
        rc = sis_alloc_timing_voice(substream, hw_params);
 
 out:
@@ -863,9 +846,6 @@ static int sis_pcm_capture_prepare(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops sis_playback_ops = {
        .open = sis_playback_open,
        .close = sis_substream_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = sis_playback_hw_params,
-       .hw_free = sis_hw_free,
        .prepare = sis_pcm_playback_prepare,
        .trigger = sis_pcm_trigger,
        .pointer = sis_pcm_pointer,
@@ -874,9 +854,7 @@ static const struct snd_pcm_ops sis_playback_ops = {
 static const struct snd_pcm_ops sis_capture_ops = {
        .open = sis_capture_open,
        .close = sis_substream_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = sis_capture_hw_params,
-       .hw_free = sis_hw_free,
        .prepare = sis_pcm_capture_prepare,
        .trigger = sis_pcm_trigger,
        .pointer = sis_pcm_pointer,
@@ -904,9 +882,8 @@ static int sis_pcm_create(struct sis7019 *sis)
        /* Try to preallocate some memory, but it's not the end of the
         * world if this fails.
         */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &sis->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &sis->pci->dev, 64*1024, 128*1024);
 
        return 0;
 }
@@ -1006,7 +983,7 @@ static int sis_mixer_create(struct sis7019 *sis)
 {
        struct snd_ac97_bus *bus;
        struct snd_ac97_template ac97;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = sis_ac97_write,
                .read = sis_ac97_read,
        };
@@ -1303,7 +1280,7 @@ static int sis_chip_create(struct snd_card *card,
 {
        struct sis7019 *sis = card->private_data;
        struct voice *voice;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free = sis_dev_free,
        };
        int rc;
@@ -1358,6 +1335,7 @@ static int sis_chip_create(struct snd_card *card,
        }
 
        sis->irq = pci->irq;
+       card->sync_irq = sis->irq;
        pci_set_master(pci);
 
        for (i = 0; i < 64; i++) {
index 31cbc81..ecdd54d 100644 (file)
@@ -681,17 +681,6 @@ static int snd_sonicvibes_capture_trigger(struct snd_pcm_substream *substream,
        return snd_sonicvibes_trigger(sonic, 2, cmd);
 }
 
-static int snd_sonicvibes_hw_params(struct snd_pcm_substream *substream,
-                                   struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_sonicvibes_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_sonicvibes_playback_prepare(struct snd_pcm_substream *substream)
 {
        struct sonicvibes *sonic = snd_pcm_substream_chip(substream);
@@ -846,9 +835,6 @@ static int snd_sonicvibes_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_sonicvibes_playback_ops = {
        .open =         snd_sonicvibes_playback_open,
        .close =        snd_sonicvibes_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_sonicvibes_hw_params,
-       .hw_free =      snd_sonicvibes_hw_free,
        .prepare =      snd_sonicvibes_playback_prepare,
        .trigger =      snd_sonicvibes_playback_trigger,
        .pointer =      snd_sonicvibes_playback_pointer,
@@ -857,9 +843,6 @@ static const struct snd_pcm_ops snd_sonicvibes_playback_ops = {
 static const struct snd_pcm_ops snd_sonicvibes_capture_ops = {
        .open =         snd_sonicvibes_capture_open,
        .close =        snd_sonicvibes_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_sonicvibes_hw_params,
-       .hw_free =      snd_sonicvibes_hw_free,
        .prepare =      snd_sonicvibes_capture_prepare,
        .trigger =      snd_sonicvibes_capture_trigger,
        .pointer =      snd_sonicvibes_capture_pointer,
@@ -883,9 +866,8 @@ static int snd_sonicvibes_pcm(struct sonicvibes *sonic, int device)
        strcpy(pcm->name, "S3 SonicVibes");
        sonic->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &sonic->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &sonic->pci->dev, 64*1024, 128*1024);
 
        return 0;
 }
@@ -1068,7 +1050,7 @@ static int snd_sonicvibes_put_double(struct snd_kcontrol *kcontrol, struct snd_c
        return change;
 }
 
-static struct snd_kcontrol_new snd_sonicvibes_controls[] = {
+static const struct snd_kcontrol_new snd_sonicvibes_controls[] = {
 SONICVIBES_DOUBLE("Capture Volume", 0, SV_IREG_LEFT_ADC, SV_IREG_RIGHT_ADC, 0, 0, 15, 0),
 SONICVIBES_DOUBLE("Aux Playback Switch", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 7, 7, 1, 1),
 SONICVIBES_DOUBLE("Aux Playback Volume", 0, SV_IREG_LEFT_AUX1, SV_IREG_RIGHT_AUX1, 0, 0, 31, 1),
@@ -1167,7 +1149,7 @@ static void snd_sonicvibes_proc_init(struct sonicvibes *sonic)
  */
 
 #ifdef SUPPORT_JOYSTICK
-static struct snd_kcontrol_new snd_sonicvibes_game_control =
+static const struct snd_kcontrol_new snd_sonicvibes_game_control =
 SONICVIBES_SINGLE("Joystick Speed", 0, SV_IREG_GAME_PORT, 1, 15, 0);
 
 static int snd_sonicvibes_create_gameport(struct sonicvibes *sonic)
@@ -1239,7 +1221,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
        struct sonicvibes *sonic;
        unsigned int dmaa, dmac;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_sonicvibes_dev_free,
        };
 
@@ -1285,6 +1267,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
                return -EBUSY;
        }
        sonic->irq = pci->irq;
+       card->sync_irq = sonic->irq;
 
        pci_read_config_dword(pci, 0x40, &dmaa);
        pci_read_config_dword(pci, 0x48, &dmac);
@@ -1392,7 +1375,7 @@ static int snd_sonicvibes_create(struct snd_card *card,
  *  MIDI section
  */
 
-static struct snd_kcontrol_new snd_sonicvibes_midi_controls[] = {
+static const struct snd_kcontrol_new snd_sonicvibes_midi_controls[] = {
 SONICVIBES_SINGLE("SonicVibes Wave Source RAM", 0, SV_IREG_WAVE_SOURCE, 0, 1, 0),
 SONICVIBES_SINGLE("SonicVibes Wave Source RAM+ROM", 0, SV_IREG_WAVE_SOURCE, 1, 1, 0),
 SONICVIBES_SINGLE("SonicVibes Onboard Synth", 0, SV_IREG_MPU401, 0, 1, 0),
index 07022c0..6e50376 100644 (file)
@@ -768,29 +768,6 @@ static unsigned int snd_trident_control_mode(struct snd_pcm_substream *substream
  */
 
 /*---------------------------------------------------------------------------
-   snd_trident_ioctl
-  
-   Description: Device I/O control handler for playback/capture parameters.
-  
-   Parameters:   substream  - PCM substream class
-                cmd     - what ioctl message to process
-                arg     - additional message infoarg     
-  
-   Returns:     Error status
-  
-  ---------------------------------------------------------------------------*/
-
-static int snd_trident_ioctl(struct snd_pcm_substream *substream,
-                            unsigned int cmd,
-                            void *arg)
-{
-       /* FIXME: it seems that with small periods the behaviour of
-                 trident hardware is unpredictable and interrupt generator
-                 is broken */
-       return snd_pcm_lib_ioctl(substream, cmd, arg);
-}
-
-/*---------------------------------------------------------------------------
    snd_trident_allocate_pcm_mem
   
    Description: Allocate PCM ring buffer for given substream
@@ -808,12 +785,9 @@ static int snd_trident_allocate_pcm_mem(struct snd_pcm_substream *substream,
        struct snd_trident *trident = snd_pcm_substream_chip(substream);
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct snd_trident_voice *voice = runtime->private_data;
-       int err;
 
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
        if (trident->tlb.entries) {
-               if (err > 0) { /* change */
+               if (runtime->buffer_changed) {
                        if (voice->memblk)
                                snd_trident_free_pages(trident, voice->memblk);
                        voice->memblk = snd_trident_alloc_pages(trident, substream);
@@ -911,7 +885,6 @@ static int snd_trident_hw_free(struct snd_pcm_substream *substream)
                        voice->memblk = NULL;
                }
        }
-       snd_pcm_lib_free_pages(substream);
        if (evoice != NULL) {
                snd_trident_free_voice(trident, evoice);
                voice->extra = NULL;
@@ -1128,11 +1101,6 @@ static int snd_trident_capture_prepare(struct snd_pcm_substream *substream)
 static int snd_trident_si7018_capture_hw_params(struct snd_pcm_substream *substream,
                                                struct snd_pcm_hw_params *hw_params)
 {
-       int err;
-
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
-
        return snd_trident_allocate_evoice(substream, hw_params);
 }
 
@@ -1154,7 +1122,6 @@ static int snd_trident_si7018_capture_hw_free(struct snd_pcm_substream *substrea
        struct snd_trident_voice *voice = runtime->private_data;
        struct snd_trident_voice *evoice = voice ? voice->extra : NULL;
 
-       snd_pcm_lib_free_pages(substream);
        if (evoice != NULL) {
                snd_trident_free_voice(trident, evoice);
                voice->extra = NULL;
@@ -2059,7 +2026,6 @@ static int snd_trident_foldback_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_trident_playback_ops = {
        .open =         snd_trident_playback_open,
        .close =        snd_trident_playback_close,
-       .ioctl =        snd_trident_ioctl,
        .hw_params =    snd_trident_hw_params,
        .hw_free =      snd_trident_hw_free,
        .prepare =      snd_trident_playback_prepare,
@@ -2070,7 +2036,6 @@ static const struct snd_pcm_ops snd_trident_playback_ops = {
 static const struct snd_pcm_ops snd_trident_nx_playback_ops = {
        .open =         snd_trident_playback_open,
        .close =        snd_trident_playback_close,
-       .ioctl =        snd_trident_ioctl,
        .hw_params =    snd_trident_hw_params,
        .hw_free =      snd_trident_hw_free,
        .prepare =      snd_trident_playback_prepare,
@@ -2081,7 +2046,6 @@ static const struct snd_pcm_ops snd_trident_nx_playback_ops = {
 static const struct snd_pcm_ops snd_trident_capture_ops = {
        .open =         snd_trident_capture_open,
        .close =        snd_trident_capture_close,
-       .ioctl =        snd_trident_ioctl,
        .hw_params =    snd_trident_capture_hw_params,
        .hw_free =      snd_trident_hw_free,
        .prepare =      snd_trident_capture_prepare,
@@ -2092,7 +2056,6 @@ static const struct snd_pcm_ops snd_trident_capture_ops = {
 static const struct snd_pcm_ops snd_trident_si7018_capture_ops = {
        .open =         snd_trident_capture_open,
        .close =        snd_trident_capture_close,
-       .ioctl =        snd_trident_ioctl,
        .hw_params =    snd_trident_si7018_capture_hw_params,
        .hw_free =      snd_trident_si7018_capture_hw_free,
        .prepare =      snd_trident_si7018_capture_prepare,
@@ -2103,7 +2066,6 @@ static const struct snd_pcm_ops snd_trident_si7018_capture_ops = {
 static const struct snd_pcm_ops snd_trident_foldback_ops = {
        .open =         snd_trident_foldback_open,
        .close =        snd_trident_foldback_close,
-       .ioctl =        snd_trident_ioctl,
        .hw_params =    snd_trident_hw_params,
        .hw_free =      snd_trident_hw_free,
        .prepare =      snd_trident_foldback_prepare,
@@ -2114,7 +2076,6 @@ static const struct snd_pcm_ops snd_trident_foldback_ops = {
 static const struct snd_pcm_ops snd_trident_nx_foldback_ops = {
        .open =         snd_trident_foldback_open,
        .close =        snd_trident_foldback_close,
-       .ioctl =        snd_trident_ioctl,
        .hw_params =    snd_trident_hw_params,
        .hw_free =      snd_trident_hw_free,
        .prepare =      snd_trident_foldback_prepare,
@@ -2125,7 +2086,6 @@ static const struct snd_pcm_ops snd_trident_nx_foldback_ops = {
 static const struct snd_pcm_ops snd_trident_spdif_ops = {
        .open =         snd_trident_spdif_open,
        .close =        snd_trident_spdif_close,
-       .ioctl =        snd_trident_ioctl,
        .hw_params =    snd_trident_spdif_hw_params,
        .hw_free =      snd_trident_hw_free,
        .prepare =      snd_trident_spdif_prepare,
@@ -2136,7 +2096,6 @@ static const struct snd_pcm_ops snd_trident_spdif_ops = {
 static const struct snd_pcm_ops snd_trident_spdif_7018_ops = {
        .open =         snd_trident_spdif_open,
        .close =        snd_trident_spdif_close,
-       .ioctl =        snd_trident_ioctl,
        .hw_params =    snd_trident_spdif_hw_params,
        .hw_free =      snd_trident_hw_free,
        .prepare =      snd_trident_spdif_prepare,
@@ -2183,17 +2142,17 @@ int snd_trident_pcm(struct snd_trident *trident, int device)
        if (trident->tlb.entries) {
                struct snd_pcm_substream *substream;
                for (substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; substream; substream = substream->next)
-                       snd_pcm_lib_preallocate_pages(substream, SNDRV_DMA_TYPE_DEV_SG,
-                                                     &trident->pci->dev,
-                                                     64*1024, 128*1024);
-               snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
-                                             SNDRV_DMA_TYPE_DEV,
-                                             &trident->pci->dev,
-                                             64*1024, 128*1024);
+                       snd_pcm_set_managed_buffer(substream, SNDRV_DMA_TYPE_DEV_SG,
+                                                  &trident->pci->dev,
+                                                  64*1024, 128*1024);
+               snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+                                          SNDRV_DMA_TYPE_DEV,
+                                          &trident->pci->dev,
+                                          64*1024, 128*1024);
        } else {
-               snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                                     &trident->pci->dev,
-                                                     64*1024, 128*1024);
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                              &trident->pci->dev,
+                                              64*1024, 128*1024);
        }
 
        return 0;
@@ -2242,13 +2201,13 @@ int snd_trident_foldback_pcm(struct snd_trident *trident, int device)
        trident->foldback = foldback;
 
        if (trident->tlb.entries)
-               snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV_SG,
-                                                     &trident->pci->dev,
-                                                     0, 128*1024);
+               snd_pcm_set_managed_buffer_all(foldback, SNDRV_DMA_TYPE_DEV_SG,
+                                              &trident->pci->dev,
+                                              0, 128*1024);
        else
-               snd_pcm_lib_preallocate_pages_for_all(foldback, SNDRV_DMA_TYPE_DEV,
-                                                     &trident->pci->dev,
-                                                     64*1024, 128*1024);
+               snd_pcm_set_managed_buffer_all(foldback, SNDRV_DMA_TYPE_DEV,
+                                              &trident->pci->dev,
+                                              64*1024, 128*1024);
 
        return 0;
 }
@@ -2282,9 +2241,8 @@ int snd_trident_spdif_pcm(struct snd_trident *trident, int device)
        strcpy(spdif->name, "Trident 4DWave IEC958");
        trident->spdif = spdif;
 
-       snd_pcm_lib_preallocate_pages_for_all(spdif, SNDRV_DMA_TYPE_DEV,
-                                             &trident->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(spdif, SNDRV_DMA_TYPE_DEV,
+                                      &trident->pci->dev, 64*1024, 128*1024);
 
        return 0;
 }
@@ -2954,7 +2912,7 @@ static int snd_trident_mixer(struct snd_trident *trident, int pcm_spdif_device)
        struct snd_kcontrol *kctl;
        struct snd_ctl_elem_value *uctl;
        int idx, err, retries = 2;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_trident_codec_write,
                .read = snd_trident_codec_read,
        };
@@ -3529,7 +3487,7 @@ int snd_trident_create(struct snd_card *card,
        int i, err;
        struct snd_trident_voice *voice;
        struct snd_trident_pcm_mixer *tmix;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_trident_dev_free,
        };
 
@@ -3585,6 +3543,7 @@ int snd_trident_create(struct snd_card *card,
                return -EBUSY;
        }
        trident->irq = pci->irq;
+       card->sync_irq = trident->irq;
 
        /* allocate 16k-aligned TLB for NX cards */
        trident->tlb.entries = NULL;
index 30c817b..799789c 100644 (file)
@@ -919,18 +919,10 @@ static int snd_via82xx_hw_params(struct snd_pcm_substream *substream,
 {
        struct via82xx *chip = snd_pcm_substream_chip(substream);
        struct viadev *viadev = substream->runtime->private_data;
-       int err;
 
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
-       err = build_via_table(viadev, substream, chip->pci,
-                             params_periods(hw_params),
-                             params_period_bytes(hw_params));
-       if (err < 0)
-               return err;
-
-       return 0;
+       return build_via_table(viadev, substream, chip->pci,
+                              params_periods(hw_params),
+                              params_period_bytes(hw_params));
 }
 
 /*
@@ -943,7 +935,6 @@ static int snd_via82xx_hw_free(struct snd_pcm_substream *substream)
        struct viadev *viadev = substream->runtime->private_data;
 
        clean_via_table(viadev, substream, chip->pci);
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -1357,7 +1348,6 @@ static int snd_via8233_playback_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_via686_playback_ops = {
        .open =         snd_via686_playback_open,
        .close =        snd_via82xx_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via686_playback_prepare,
@@ -1369,7 +1359,6 @@ static const struct snd_pcm_ops snd_via686_playback_ops = {
 static const struct snd_pcm_ops snd_via686_capture_ops = {
        .open =         snd_via82xx_capture_open,
        .close =        snd_via82xx_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via686_capture_prepare,
@@ -1381,7 +1370,6 @@ static const struct snd_pcm_ops snd_via686_capture_ops = {
 static const struct snd_pcm_ops snd_via8233_playback_ops = {
        .open =         snd_via8233_playback_open,
        .close =        snd_via8233_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via8233_playback_prepare,
@@ -1393,7 +1381,6 @@ static const struct snd_pcm_ops snd_via8233_playback_ops = {
 static const struct snd_pcm_ops snd_via8233_multi_ops = {
        .open =         snd_via8233_multi_open,
        .close =        snd_via82xx_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via8233_multi_prepare,
@@ -1405,7 +1392,6 @@ static const struct snd_pcm_ops snd_via8233_multi_ops = {
 static const struct snd_pcm_ops snd_via8233_capture_ops = {
        .open =         snd_via82xx_capture_open,
        .close =        snd_via82xx_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via8233_capture_prepare,
@@ -1453,9 +1439,9 @@ static int snd_via8233_pcm_new(struct via82xx *chip)
        /* capture */
        init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             64*1024, VIA_MAX_BUFSIZE);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev,
+                                      64*1024, VIA_MAX_BUFSIZE);
 
        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                     snd_pcm_std_chmaps, 2, 0,
@@ -1477,9 +1463,9 @@ static int snd_via8233_pcm_new(struct via82xx *chip)
        /* set up capture */
        init_viadev(chip, chip->capture_devno + 1, VIA_REG_CAPTURE_8233_STATUS + 0x10, 7, 1);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             64*1024, VIA_MAX_BUFSIZE);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev,
+                                      64*1024, VIA_MAX_BUFSIZE);
 
        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                     snd_pcm_alt_chmaps, 6, 0,
@@ -1520,9 +1506,9 @@ static int snd_via8233a_pcm_new(struct via82xx *chip)
        /* capture */
        init_viadev(chip, chip->capture_devno, VIA_REG_CAPTURE_8233_STATUS, 6, 1);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             64*1024, VIA_MAX_BUFSIZE);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev,
+                                      64*1024, VIA_MAX_BUFSIZE);
 
        err = snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                     snd_pcm_alt_chmaps, 6, 0,
@@ -1546,9 +1532,9 @@ static int snd_via8233a_pcm_new(struct via82xx *chip)
        /* set up playback */
        init_viadev(chip, chip->playback_devno, 0x30, 3, 0);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             64*1024, VIA_MAX_BUFSIZE);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev,
+                                      64*1024, VIA_MAX_BUFSIZE);
        return 0;
 }
 
@@ -1576,9 +1562,9 @@ static int snd_via686_pcm_new(struct via82xx *chip)
        init_viadev(chip, 0, VIA_REG_PLAYBACK_STATUS, 0, 0);
        init_viadev(chip, 1, VIA_REG_CAPTURE_STATUS, 0, 1);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             64*1024, VIA_MAX_BUFSIZE);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev,
+                                      64*1024, VIA_MAX_BUFSIZE);
        return 0;
 }
 
@@ -1882,7 +1868,7 @@ static int snd_via82xx_mixer_new(struct via82xx *chip, const char *quirk_overrid
 {
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_via82xx_codec_write,
                .read = snd_via82xx_codec_read,
                .wait = snd_via82xx_codec_wait,
@@ -2259,7 +2245,6 @@ static int snd_via82xx_suspend(struct device *dev)
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
        for (i = 0; i < chip->num_devs; i++)
                snd_via82xx_channel_reset(chip, &chip->devs[i]);
-       synchronize_irq(chip->irq);
        snd_ac97_suspend(chip->ac97);
 
        /* save misc values */
@@ -2347,7 +2332,7 @@ static int snd_via82xx_create(struct snd_card *card,
 {
        struct via82xx *chip;
        int err;
-        static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_via82xx_dev_free,
         };
 
@@ -2390,9 +2375,9 @@ static int snd_via82xx_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        if (ac97_clock >= 8000 && ac97_clock <= 48000)
                chip->ac97_clock = ac97_clock;
-       synchronize_irq(chip->irq);
 
        if ((err = snd_via82xx_chip_init(chip)) < 0) {
                snd_via82xx_free(chip);
@@ -2418,7 +2403,7 @@ struct via823x_info {
        char *name;
        int type;
 };
-static struct via823x_info via823x_cards[] = {
+static const struct via823x_info via823x_cards[] = {
        { VIA_REV_PRE_8233, "VIA 8233-Pre", TYPE_VIA8233 },
        { VIA_REV_8233C, "VIA 8233C", TYPE_VIA8233 },
        { VIA_REV_8233, "VIA 8233", TYPE_VIA8233 },
@@ -2432,7 +2417,7 @@ static struct via823x_info via823x_cards[] = {
  * auto detection of DXS channel supports.
  */
 
-static struct snd_pci_quirk dxs_whitelist[] = {
+static const struct snd_pci_quirk dxs_whitelist[] = {
        SND_PCI_QUIRK(0x1005, 0x4710, "Avance Logic Mobo", VIA_DXS_ENABLE),
        SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K),
        SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA),
index 0edb9ea..84e5898 100644 (file)
@@ -642,9 +642,6 @@ static int snd_via82xx_hw_params(struct snd_pcm_substream *substream,
        struct viadev *viadev = substream->runtime->private_data;
        int err;
 
-       err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        err = build_via_table(viadev, substream, chip->pci,
                              params_periods(hw_params),
                              params_period_bytes(hw_params));
@@ -667,7 +664,6 @@ static int snd_via82xx_hw_free(struct snd_pcm_substream *substream)
        struct viadev *viadev = substream->runtime->private_data;
 
        clean_via_table(viadev, substream, chip->pci);
-       snd_pcm_lib_free_pages(substream);
        return 0;
 }
 
@@ -795,7 +791,6 @@ static int snd_via82xx_pcm_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_via686_playback_ops = {
        .open =         snd_via82xx_playback_open,
        .close =        snd_via82xx_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via82xx_pcm_prepare,
@@ -807,7 +802,6 @@ static const struct snd_pcm_ops snd_via686_playback_ops = {
 static const struct snd_pcm_ops snd_via686_capture_ops = {
        .open =         snd_via82xx_capture_open,
        .close =        snd_via82xx_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_via82xx_hw_params,
        .hw_free =      snd_via82xx_hw_free,
        .prepare =      snd_via82xx_pcm_prepare,
@@ -849,9 +843,8 @@ static int snd_via686_pcm_new(struct via82xx_modem *chip)
        init_viadev(chip, 0, VIA_REG_MO_STATUS, 0);
        init_viadev(chip, 1, VIA_REG_MI_STATUS, 1);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
-                                             &chip->pci->dev,
-                                             64*1024, 128*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
+                                      &chip->pci->dev, 64*1024, 128*1024);
        return 0;
 }
 
@@ -878,7 +871,7 @@ static int snd_via82xx_mixer_new(struct via82xx_modem *chip)
 {
        struct snd_ac97_template ac97;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_via82xx_codec_write,
                .read = snd_via82xx_codec_read,
                .wait = snd_via82xx_codec_wait,
@@ -1020,7 +1013,6 @@ static int snd_via82xx_suspend(struct device *dev)
        snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
        for (i = 0; i < chip->num_devs; i++)
                snd_via82xx_channel_reset(chip, &chip->devs[i]);
-       synchronize_irq(chip->irq);
        snd_ac97_suspend(chip->ac97);
        return 0;
 }
@@ -1082,7 +1074,7 @@ static int snd_via82xx_create(struct snd_card *card,
 {
        struct via82xx_modem *chip;
        int err;
-        static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_via82xx_dev_free,
         };
 
@@ -1112,9 +1104,9 @@ static int snd_via82xx_create(struct snd_card *card,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
        if (ac97_clock >= 8000 && ac97_clock <= 48000)
                chip->ac97_clock = ac97_clock;
-       synchronize_irq(chip->irq);
 
        if ((err = snd_via82xx_chip_init(chip)) < 0) {
                snd_via82xx_free(chip);
index b502c24..f7800ed 100644 (file)
@@ -62,7 +62,7 @@ MODULE_DEVICE_TABLE(pci, snd_vx222_ids);
 static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
 static const DECLARE_TLV_DB_SCALE(db_scale_akm, -7350, 50, 0);
 
-static struct snd_vx_hardware vx222_old_hw = {
+static const struct snd_vx_hardware vx222_old_hw = {
 
        .name = "VX222/Old",
        .type = VX_TYPE_BOARD,
@@ -74,7 +74,7 @@ static struct snd_vx_hardware vx222_old_hw = {
        .output_level_db_scale = db_scale_old_vol,
 };
 
-static struct snd_vx_hardware vx222_v2_hw = {
+static const struct snd_vx_hardware vx222_v2_hw = {
 
        .name = "VX222/v2",
        .type = VX_TYPE_V2,
@@ -86,7 +86,7 @@ static struct snd_vx_hardware vx222_v2_hw = {
        .output_level_db_scale = db_scale_akm,
 };
 
-static struct snd_vx_hardware vx222_mic_hw = {
+static const struct snd_vx_hardware vx222_mic_hw = {
 
        .name = "VX222/Mic",
        .type = VX_TYPE_MIC,
@@ -122,16 +122,16 @@ static int snd_vx222_dev_free(struct snd_device *device)
 
 
 static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
-                           struct snd_vx_hardware *hw,
+                           const struct snd_vx_hardware *hw,
                            struct snd_vx222 **rchip)
 {
        struct vx_core *chip;
        struct snd_vx222 *vx;
        int i, err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_vx222_dev_free,
        };
-       struct snd_vx_ops *vx_ops;
+       const struct snd_vx_ops *vx_ops;
 
        /* enable PCI device */
        if ((err = pci_enable_device(pci)) < 0)
@@ -163,6 +163,7 @@ static int snd_vx222_create(struct snd_card *card, struct pci_dev *pci,
                return -EBUSY;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
                snd_vx222_free(chip);
@@ -179,7 +180,7 @@ static int snd_vx222_probe(struct pci_dev *pci,
 {
        static int dev;
        struct snd_card *card;
-       struct snd_vx_hardware *hw;
+       const struct snd_vx_hardware *hw;
        struct snd_vx222 *vx;
        int err;
 
index d27af63..46ddc68 100644 (file)
@@ -31,8 +31,8 @@ struct snd_vx222 {
 /* we use a lookup table with 148 values, see vx_mixer.c */
 #define VX2_AKM_LEVEL_MAX      0x93
 
-extern struct snd_vx_ops vx222_ops;
-extern struct snd_vx_ops vx222_old_ops;
+extern const struct snd_vx_ops vx222_ops;
+extern const struct snd_vx_ops vx222_old_ops;
 
 /* Offset of registers with base equal to portDSP. */
 #define VX_RESET_DMA_REGISTER_OFFSET    0x00000008
index c145951..23d4338 100644 (file)
@@ -19,7 +19,7 @@
 #include "vx222.h"
 
 
-static int vx2_reg_offset[VX_REG_MAX] = {
+static const int vx2_reg_offset[VX_REG_MAX] = {
        [VX_ICR]    = 0x00,
        [VX_CVR]    = 0x04,
        [VX_ISR]    = 0x08,
@@ -45,7 +45,7 @@ static int vx2_reg_offset[VX_REG_MAX] = {
        [VX_GPIOC]  = 0x54,             // VX_GPIOC (new with PLX9030)
 };
 
-static int vx2_reg_index[VX_REG_MAX] = {
+static const int vx2_reg_index[VX_REG_MAX] = {
        [VX_ICR]        = 1,
        [VX_CVR]        = 1,
        [VX_ISR]        = 1,
@@ -984,7 +984,7 @@ static int vx2_add_mic_controls(struct vx_core *_chip)
 /*
  * callbacks
  */
-struct snd_vx_ops vx222_ops = {
+const struct snd_vx_ops vx222_ops = {
        .in8 = vx2_inb,
        .in32 = vx2_inl,
        .out8 = vx2_outb,
@@ -1004,7 +1004,7 @@ struct snd_vx_ops vx222_ops = {
 };
 
 /* for old VX222 board */
-struct snd_vx_ops vx222_old_ops = {
+const struct snd_vx_ops vx222_old_ops = {
        .in8 = vx2_inb,
        .in32 = vx2_inl,
        .out8 = vx2_outb,
index 125c11e..e07d703 100644 (file)
@@ -122,14 +122,14 @@ static u32 snd_ymfpci_calc_delta(u32 rate)
        }
 }
 
-static u32 def_rate[8] = {
+static const u32 def_rate[8] = {
        100, 2000, 8000, 11025, 16000, 22050, 32000, 48000
 };
 
 static u32 snd_ymfpci_calc_lpfK(u32 rate)
 {
        u32 i;
-       static u32 val[8] = {
+       static const u32 val[8] = {
                0x00570000, 0x06AA0000, 0x18B20000, 0x20930000,
                0x2B9A0000, 0x35A10000, 0x3EAA0000, 0x40000000
        };
@@ -145,7 +145,7 @@ static u32 snd_ymfpci_calc_lpfK(u32 rate)
 static u32 snd_ymfpci_calc_lpfQ(u32 rate)
 {
        u32 i;
-       static u32 val[8] = {
+       static const u32 val[8] = {
                0x35280000, 0x34A70000, 0x32020000, 0x31770000,
                0x31390000, 0x31C90000, 0x33D00000, 0x40000000
        };
@@ -628,8 +628,6 @@ static int snd_ymfpci_playback_hw_params(struct snd_pcm_substream *substream,
        struct snd_ymfpci_pcm *ypcm = runtime->private_data;
        int err;
 
-       if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
-               return err;
        if ((err = snd_ymfpci_pcm_voice_alloc(ypcm, params_channels(hw_params))) < 0)
                return err;
        return 0;
@@ -647,7 +645,6 @@ static int snd_ymfpci_playback_hw_free(struct snd_pcm_substream *substream)
 
        /* wait, until the PCI operations are not finished */
        snd_ymfpci_irq_wait(chip);
-       snd_pcm_lib_free_pages(substream);
        if (ypcm->voices[1]) {
                snd_ymfpci_voice_free(chip, ypcm->voices[1]);
                ypcm->voices[1] = NULL;
@@ -683,19 +680,13 @@ static int snd_ymfpci_playback_prepare(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int snd_ymfpci_capture_hw_params(struct snd_pcm_substream *substream,
-                                       struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
 static int snd_ymfpci_capture_hw_free(struct snd_pcm_substream *substream)
 {
        struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
 
        /* wait, until the PCI operations are not finished */
        snd_ymfpci_irq_wait(chip);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int snd_ymfpci_capture_prepare(struct snd_pcm_substream *substream)
@@ -1112,7 +1103,6 @@ static int snd_ymfpci_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_ymfpci_playback_ops = {
        .open =                 snd_ymfpci_playback_open,
        .close =                snd_ymfpci_playback_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_ymfpci_playback_hw_params,
        .hw_free =              snd_ymfpci_playback_hw_free,
        .prepare =              snd_ymfpci_playback_prepare,
@@ -1123,8 +1113,6 @@ static const struct snd_pcm_ops snd_ymfpci_playback_ops = {
 static const struct snd_pcm_ops snd_ymfpci_capture_rec_ops = {
        .open =                 snd_ymfpci_capture_rec_open,
        .close =                snd_ymfpci_capture_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_ymfpci_capture_hw_params,
        .hw_free =              snd_ymfpci_capture_hw_free,
        .prepare =              snd_ymfpci_capture_prepare,
        .trigger =              snd_ymfpci_capture_trigger,
@@ -1148,9 +1136,8 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device)
        strcpy(pcm->name, "YMFPCI");
        chip->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 256*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 256*1024);
 
        return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                     snd_pcm_std_chmaps, 2, 0, NULL);
@@ -1159,8 +1146,6 @@ int snd_ymfpci_pcm(struct snd_ymfpci *chip, int device)
 static const struct snd_pcm_ops snd_ymfpci_capture_ac97_ops = {
        .open =                 snd_ymfpci_capture_ac97_open,
        .close =                snd_ymfpci_capture_close,
-       .ioctl =                snd_pcm_lib_ioctl,
-       .hw_params =            snd_ymfpci_capture_hw_params,
        .hw_free =              snd_ymfpci_capture_hw_free,
        .prepare =              snd_ymfpci_capture_prepare,
        .trigger =              snd_ymfpci_capture_trigger,
@@ -1184,9 +1169,8 @@ int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device)
                chip->device_id == PCI_DEVICE_ID_YAMAHA_754 ? "Direct Recording" : "AC'97");
        chip->pcm2 = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 256*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 256*1024);
 
        return 0;
 }
@@ -1194,7 +1178,6 @@ int snd_ymfpci_pcm2(struct snd_ymfpci *chip, int device)
 static const struct snd_pcm_ops snd_ymfpci_playback_spdif_ops = {
        .open =                 snd_ymfpci_playback_spdif_open,
        .close =                snd_ymfpci_playback_spdif_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_ymfpci_playback_hw_params,
        .hw_free =              snd_ymfpci_playback_hw_free,
        .prepare =              snd_ymfpci_playback_prepare,
@@ -1218,9 +1201,8 @@ int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device)
        strcpy(pcm->name, "YMFPCI - IEC958");
        chip->pcm_spdif = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 256*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 256*1024);
 
        return 0;
 }
@@ -1228,7 +1210,6 @@ int snd_ymfpci_pcm_spdif(struct snd_ymfpci *chip, int device)
 static const struct snd_pcm_ops snd_ymfpci_playback_4ch_ops = {
        .open =                 snd_ymfpci_playback_4ch_open,
        .close =                snd_ymfpci_playback_4ch_close,
-       .ioctl =                snd_pcm_lib_ioctl,
        .hw_params =            snd_ymfpci_playback_hw_params,
        .hw_free =              snd_ymfpci_playback_hw_free,
        .prepare =              snd_ymfpci_playback_prepare,
@@ -1260,9 +1241,8 @@ int snd_ymfpci_pcm_4ch(struct snd_ymfpci *chip, int device)
        strcpy(pcm->name, "YMFPCI - Rear PCM");
        chip->pcm_4ch = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pci->dev,
-                                             64*1024, 256*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pci->dev, 64*1024, 256*1024);
 
        return snd_pcm_add_chmap_ctls(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                                     surround_map, 2, 0, NULL);
@@ -1608,7 +1588,7 @@ static const struct snd_kcontrol_new snd_ymfpci_dup4ch = {
        .put = snd_ymfpci_put_dup4ch,
 };
 
-static struct snd_kcontrol_new snd_ymfpci_controls[] = {
+static const struct snd_kcontrol_new snd_ymfpci_controls[] = {
 {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Wave Playback Volume",
@@ -1800,7 +1780,7 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
        struct snd_pcm_substream *substream;
        unsigned int idx;
        int err;
-       static struct snd_ac97_bus_ops ops = {
+       static const struct snd_ac97_bus_ops ops = {
                .write = snd_ymfpci_codec_write,
                .read = snd_ymfpci_codec_read,
        };
@@ -1928,7 +1908,7 @@ static int snd_ymfpci_timer_precise_resolution(struct snd_timer *timer,
        return 0;
 }
 
-static struct snd_timer_hardware snd_ymfpci_timer_hw = {
+static const struct snd_timer_hardware snd_ymfpci_timer_hw = {
        .flags = SNDRV_TIMER_HW_AUTO,
        .resolution = 10417, /* 1 / 96 kHz = 10.41666...us */
        .ticks = 0x10000,
@@ -2254,7 +2234,7 @@ static int snd_ymfpci_dev_free(struct snd_device *device)
 }
 
 #ifdef CONFIG_PM_SLEEP
-static int saved_regs_index[] = {
+static const int saved_regs_index[] = {
        /* spdif */
        YDSXGR_SPDIFOUTCTRL,
        YDSXGR_SPDIFOUTSTATUS,
@@ -2347,7 +2327,7 @@ int snd_ymfpci_create(struct snd_card *card,
 {
        struct snd_ymfpci *chip;
        int err;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_ymfpci_dev_free,
        };
        
@@ -2391,6 +2371,7 @@ int snd_ymfpci_create(struct snd_card *card,
                goto free_chip;
        }
        chip->irq = pci->irq;
+       card->sync_irq = chip->irq;
 
        snd_ymfpci_aclink_reset(pci);
        if (snd_ymfpci_codec_ready(chip, 0) < 0) {
index 022db04..6c33ea9 100644 (file)
@@ -82,7 +82,7 @@ static int snd_pdacf_probe(struct pcmcia_device *link)
        int i, err;
        struct snd_pdacf *pdacf;
        struct snd_card *card;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_pdacf_dev_free,
        };
 
@@ -224,6 +224,7 @@ static int pdacf_config(struct pcmcia_device *link)
                                        link->irq) < 0)
                goto failed;
 
+       pdacf->card->sync_irq = link->irq;
        return 0;
 
  failed:
index db3cd45..5537c08 100644 (file)
@@ -179,7 +179,7 @@ int snd_pdacf_ak4117_create(struct snd_pdacf *chip)
        /* from AK4117 then INT1 pin from AK4117 will be high all time, because PCMCIA interrupts are */
        /* egde based and FPGA does logical OR for all interrupt sources, we cannot use these */
        /* high-rate sources */
-       static unsigned char pgm[5] = {
+       static const unsigned char pgm[5] = {
                AK4117_XTL_24_576M | AK4117_EXCT,                               /* AK4117_REG_PWRDN */
                AK4117_CM_PLL_XTAL | AK4117_PKCS_128fs | AK4117_XCKS_128fs,     /* AK4117_REQ_CLOCK */
                AK4117_EFH_1024LRCLK | AK4117_DIF_24R | AK4117_IPS,             /* AK4117_REG_IO */
index 067b1c3..6cbe5cb 100644 (file)
@@ -84,23 +84,6 @@ static int pdacf_pcm_trigger(struct snd_pcm_substream *subs, int cmd)
 }
 
 /*
- * pdacf_pcm_hw_params - hw_params callback for playback and capture
- */
-static int pdacf_pcm_hw_params(struct snd_pcm_substream *subs,
-                                    struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw_params));
-}
-
-/*
- * pdacf_pcm_hw_free - hw_free callback for playback and capture
- */
-static int pdacf_pcm_hw_free(struct snd_pcm_substream *subs)
-{
-       return snd_pcm_lib_free_pages(subs);
-}
-
-/*
  * pdacf_pcm_prepare - prepare callback for playback and capture
  */
 static int pdacf_pcm_prepare(struct snd_pcm_substream *subs)
@@ -255,9 +238,6 @@ static snd_pcm_uframes_t pdacf_pcm_capture_pointer(struct snd_pcm_substream *sub
 static const struct snd_pcm_ops pdacf_pcm_capture_ops = {
        .open =         pdacf_pcm_capture_open,
        .close =        pdacf_pcm_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    pdacf_pcm_hw_params,
-       .hw_free =      pdacf_pcm_hw_free,
        .prepare =      pdacf_pcm_prepare,
        .trigger =      pdacf_pcm_trigger,
        .pointer =      pdacf_pcm_capture_pointer,
@@ -277,9 +257,9 @@ int snd_pdacf_pcm_new(struct snd_pdacf *chip)
                return err;
                
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pdacf_pcm_capture_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32),
-                                             0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
+                                      snd_dma_continuous_data(GFP_KERNEL | GFP_DMA32),
+                                      0, 0);
 
        pcm->private_data = chip;
        pcm->info_flags = 0;
index 447c634..45eeb0f 100644 (file)
@@ -15,7 +15,7 @@
 #include "vxpocket.h"
 
 
-static int vxp_reg_offset[VX_REG_MAX] = {
+static const int vxp_reg_offset[VX_REG_MAX] = {
        [VX_ICR]        = 0x00,         // ICR
        [VX_CVR]        = 0x01,         // CVR
        [VX_ISR]        = 0x02,         // ISR
@@ -581,7 +581,7 @@ static void vxp_reset_board(struct vx_core *_chip, int cold_reset)
  * callbacks
  */
 /* exported */
-struct snd_vx_ops snd_vxpocket_ops = {
+const struct snd_vx_ops snd_vxpocket_ops = {
        .in8 = vxp_inb,
        .out8 = vxp_outb,
        .test_and_ack = vxp_test_and_ack,
index 4e08863..afd30a9 100644 (file)
@@ -82,7 +82,7 @@ static int snd_vxpocket_dev_free(struct snd_device *device)
 
 static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
 
-static struct snd_vx_hardware vxpocket_hw = {
+static const struct snd_vx_hardware vxpocket_hw = {
        .name = "VXPocket",
        .type = VX_TYPE_VXPOCKET,
 
@@ -104,7 +104,7 @@ static struct snd_vx_hardware vxpocket_hw = {
  * UER, but only for the first two inputs and outputs.
  */
 
-static struct snd_vx_hardware vxp440_hw = {
+static const struct snd_vx_hardware vxp440_hw = {
        .name = "VXPocket440",
        .type = VX_TYPE_VXP440,
 
@@ -126,7 +126,7 @@ static int snd_vxpocket_new(struct snd_card *card, int ibl,
 {
        struct vx_core *chip;
        struct snd_vxpocket *vxp;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_vxpocket_dev_free,
        };
        int err;
@@ -185,6 +185,7 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq
                card->shortname, port, irq);
 
        chip->irq = irq;
+       card->sync_irq = chip->irq;
 
        if ((err = snd_vx_setup_firmware(chip)) < 0)
                return err;
index 6dbd9f6..bce616c 100644 (file)
@@ -32,7 +32,7 @@ struct snd_vxpocket {
 
 #define to_vxpocket(x) container_of(x, struct snd_vxpocket, core)
 
-extern struct snd_vx_ops snd_vxpocket_ops;
+extern const struct snd_vx_ops snd_vxpocket_ops;
 
 void vx_set_mic_boost(struct vx_core *chip, int boost);
 void vx_set_mic_level(struct vx_core *chip, int level);
index 359d22a..73c0fd7 100644 (file)
@@ -464,7 +464,7 @@ static int snd_pmac_awacs_put_master_amp(struct snd_kcontrol *kcontrol,
 #define AMP_CH_SPK     0
 #define AMP_CH_HD      1
 
-static struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_amp_vol[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Speaker Playback Volume",
          .info = snd_pmac_awacs_info_volume_amp,
@@ -582,46 +582,46 @@ static int snd_pmac_screamer_mic_boost_put(struct snd_kcontrol *kcontrol,
 /*
  * lists of mixer elements
  */
-static struct snd_kcontrol_new snd_pmac_awacs_mixers[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_mixers[] = {
        AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0),
        AWACS_VOLUME("Master Capture Volume", 0, 4, 0),
 /*     AWACS_SWITCH("Unknown Playback Switch", 6, SHIFT_PAROUT0, 0), */
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] = {
+static const struct snd_kcontrol_new snd_pmac_screamer_mixers_beige[] = {
        AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
        AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_LINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] = {
+static const struct snd_kcontrol_new snd_pmac_screamer_mixers_lo[] = {
        AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] = {
+static const struct snd_kcontrol_new snd_pmac_screamer_mixers_imac[] = {
        AWACS_VOLUME("Play-through Playback Volume", 5, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] = {
+static const struct snd_kcontrol_new snd_pmac_screamer_mixers_g4agp[] = {
        AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
        AWACS_VOLUME("Master Playback Volume", 5, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac7500[] = {
        AWACS_VOLUME("Line out Playback Volume", 2, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac5500[] = {
        AWACS_VOLUME("Headphone Playback Volume", 2, 6, 1),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] = {
        AWACS_VOLUME("Master Playback Volume", 2, 6, 1),
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
@@ -629,34 +629,34 @@ static struct snd_kcontrol_new snd_pmac_awacs_mixers_pmac[] = {
 /* FIXME: is this correct order?
  * screamer (powerbook G3 pismo) seems to have different bits...
  */
-static struct snd_kcontrol_new snd_pmac_awacs_mixers2[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_mixers2[] = {
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0),
        AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mixers2[] = {
+static const struct snd_kcontrol_new snd_pmac_screamer_mixers2[] = {
        AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0),
        AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_mixers2_pmac5500[] = {
        AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw =
+static const struct snd_kcontrol_new snd_pmac_awacs_master_sw =
 AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac =
+static const struct snd_kcontrol_new snd_pmac_awacs_master_sw_imac =
 AWACS_SWITCH("Line out Playback Switch", 1, SHIFT_HDMUTE, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 =
+static const struct snd_kcontrol_new snd_pmac_awacs_master_sw_pmac5500 =
 AWACS_SWITCH("Headphone Playback Switch", 1, SHIFT_HDMUTE, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_mic_boost[] = {
        AWACS_SWITCH("Mic Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] = {
+static const struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Mic Boost Capture Volume",
          .info = snd_pmac_screamer_mic_boost_info,
@@ -665,34 +665,34 @@ static struct snd_kcontrol_new snd_pmac_screamer_mic_boost[] = {
        },
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] =
+static const struct snd_kcontrol_new snd_pmac_awacs_mic_boost_pmac7500[] =
 {
        AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] =
+static const struct snd_kcontrol_new snd_pmac_screamer_mic_boost_beige[] =
 {
        AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
        AWACS_SWITCH("CD Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] =
+static const struct snd_kcontrol_new snd_pmac_screamer_mic_boost_imac[] =
 {
        AWACS_SWITCH("Line Boost Capture Switch", 0, SHIFT_GAINLINE, 0),
        AWACS_SWITCH("Mic Boost Capture Switch", 6, SHIFT_MIC_BOOST, 0),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] = {
+static const struct snd_kcontrol_new snd_pmac_awacs_speaker_vol[] = {
        AWACS_VOLUME("Speaker Playback Volume", 4, 6, 1),
 };
 
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw =
+static const struct snd_kcontrol_new snd_pmac_awacs_speaker_sw =
 AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 =
+static const struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac1 =
 AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 1);
 
-static struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 =
+static const struct snd_kcontrol_new snd_pmac_awacs_speaker_sw_imac2 =
 AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
 
 
@@ -700,7 +700,7 @@ AWACS_SWITCH("Speaker Playback Switch", 1, SHIFT_PAROUT1, 0);
  * add new mixer elements to the card
  */
 static int build_mixers(struct snd_pmac *chip, int nums,
-                       struct snd_kcontrol_new *mixers)
+                       const struct snd_kcontrol_new *mixers)
 {
        int i, err;
 
index e2806b8..6bc586a 100644 (file)
@@ -44,7 +44,7 @@ void snd_pmac_beep_stop(struct snd_pmac *chip)
  * so we can multiply by an amplitude in the range 0..100 to get a
  * signed short value to put in the output buffer.
  */
-static short beep_wform[256] = {
+static const short beep_wform[256] = {
        0,      40,     79,     117,    153,    187,    218,    245,
        269,    288,    304,    316,    323,    327,    327,    324,
        318,    310,    299,    288,    275,    262,    249,    236,
index a2a41e5..4fb990a 100644 (file)
@@ -454,7 +454,7 @@ static int snd_pmac_burgundy_put_switch_b(struct snd_kcontrol *kcontrol,
 /*
  * Burgundy mixers
  */
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] = {
+static const struct snd_kcontrol_new snd_pmac_burgundy_mixers[] = {
        BURGUNDY_VOLUME_W("Master Playback Volume", 0,
                        MASK_ADDR_BURGUNDY_MASTER_VOLUME, 8),
        BURGUNDY_VOLUME_W("CD Capture Volume", 0,
@@ -482,7 +482,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers[] = {
  */    BURGUNDY_SWITCH_B("PCM Capture Switch", 0,
                        MASK_ADDR_BURGUNDY_HOSTIFEH, 0x01, 0, 0)
 };
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] = {
+static const struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] = {
        BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
                        MASK_ADDR_BURGUNDY_VOLLINE, 16),
        BURGUNDY_VOLUME_W("Mic Capture Volume", 0,
@@ -508,7 +508,7 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_imac[] = {
        BURGUNDY_SWITCH_B("Mic Boost Capture Switch", 0,
                        MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1)
 };
-static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] = {
+static const struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] = {
        BURGUNDY_VOLUME_W("Line in Capture Volume", 0,
                        MASK_ADDR_BURGUNDY_VOLMIC, 16),
        BURGUNDY_VOLUME_B("Line in Gain Capture Volume", 0,
@@ -524,33 +524,33 @@ static struct snd_kcontrol_new snd_pmac_burgundy_mixers_pmac[] = {
 /*     BURGUNDY_SWITCH_B("Line in Boost Capture Switch", 0,
  *             MASK_ADDR_BURGUNDY_INPBOOST, 0x40, 0x80, 1) */
 };
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac =
+static const struct snd_kcontrol_new snd_pmac_burgundy_master_sw_imac =
 BURGUNDY_SWITCH_B("Master Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_LEFT | BURGUNDY_LINEOUT_LEFT | BURGUNDY_HP_LEFT,
        BURGUNDY_OUTPUT_RIGHT | BURGUNDY_LINEOUT_RIGHT | BURGUNDY_HP_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac =
+static const struct snd_kcontrol_new snd_pmac_burgundy_master_sw_pmac =
 BURGUNDY_SWITCH_B("Master Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_INTERN
        | BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac =
+static const struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_imac =
 BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac =
+static const struct snd_kcontrol_new snd_pmac_burgundy_speaker_sw_pmac =
 BURGUNDY_SWITCH_B("Speaker Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_INTERN, 0, 0);
-static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac =
+static const struct snd_kcontrol_new snd_pmac_burgundy_line_sw_imac =
 BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_LINEOUT_LEFT, BURGUNDY_LINEOUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac =
+static const struct snd_kcontrol_new snd_pmac_burgundy_line_sw_pmac =
 BURGUNDY_SWITCH_B("Line out Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_OUTPUT_LEFT, BURGUNDY_OUTPUT_RIGHT, 1);
-static struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac =
+static const struct snd_kcontrol_new snd_pmac_burgundy_hp_sw_imac =
 BURGUNDY_SWITCH_B("Headphone Playback Switch", 0,
        MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
        BURGUNDY_HP_LEFT, BURGUNDY_HP_RIGHT, 1);
index f2b4478..1eb698d 100644 (file)
@@ -186,7 +186,7 @@ static int daca_put_amp(struct snd_kcontrol *kcontrol,
        return change;
 }
 
-static struct snd_kcontrol_new daca_mixers[] = {
+static const struct snd_kcontrol_new daca_mixers[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Deemphasis Switch",
          .info = daca_info_deemphasis,
index 1b11e53..592532c 100644 (file)
 
 
 /* fixed frequency table for awacs, screamer, burgundy, DACA (44100 max) */
-static int awacs_freqs[8] = {
+static const int awacs_freqs[8] = {
        44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350
 };
 /* fixed frequency table for tumbler */
-static int tumbler_freqs[1] = {
+static const int tumbler_freqs[1] = {
        44100
 };
 
@@ -108,24 +108,6 @@ static inline int another_stream(int stream)
 }
 
 /*
- * allocate buffers
- */
-static int snd_pmac_pcm_hw_params(struct snd_pcm_substream *subs,
-                                 struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw_params));
-}
-
-/*
- * release buffers
- */
-static int snd_pmac_pcm_hw_free(struct snd_pcm_substream *subs)
-{
-       snd_pcm_lib_free_pages(subs);
-       return 0;
-}
-
-/*
  * get a stream of the opposite direction
  */
 static struct pmac_stream *snd_pmac_get_stream(struct snd_pmac *chip, int stream)
@@ -671,9 +653,6 @@ static int snd_pmac_capture_close(struct snd_pcm_substream *subs)
 static const struct snd_pcm_ops snd_pmac_playback_ops = {
        .open =         snd_pmac_playback_open,
        .close =        snd_pmac_playback_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_pmac_pcm_hw_params,
-       .hw_free =      snd_pmac_pcm_hw_free,
        .prepare =      snd_pmac_playback_prepare,
        .trigger =      snd_pmac_playback_trigger,
        .pointer =      snd_pmac_playback_pointer,
@@ -682,9 +661,6 @@ static const struct snd_pcm_ops snd_pmac_playback_ops = {
 static const struct snd_pcm_ops snd_pmac_capture_ops = {
        .open =         snd_pmac_capture_open,
        .close =        snd_pmac_capture_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_pmac_pcm_hw_params,
-       .hw_free =      snd_pmac_pcm_hw_free,
        .prepare =      snd_pmac_capture_prepare,
        .trigger =      snd_pmac_capture_trigger,
        .pointer =      snd_pmac_capture_pointer,
@@ -721,9 +697,9 @@ int snd_pmac_pcm_new(struct snd_pmac *chip)
        chip->capture.cur_freqs = chip->freqs_ok;
 
        /* preallocate 64k buffer */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->pdev->dev,
-                                             64 * 1024, 64 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->pdev->dev,
+                                      64 * 1024, 64 * 1024);
 
        return 0;
 }
@@ -1128,7 +1104,7 @@ static int pmac_hp_detect_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new auto_mute_controls[] = {
+static const struct snd_kcontrol_new auto_mute_controls[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Auto Mute Switch",
          .info = snd_pmac_boolean_mono_info,
@@ -1167,7 +1143,7 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
        int i, err;
        unsigned int irq;
        unsigned long ctrl_addr, txdma_addr, rxdma_addr;
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free =     snd_pmac_dev_free,
        };
 
@@ -1198,7 +1174,7 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
        np = chip->node;
        chip->requested = 0;
        if (chip->is_k2) {
-               static char *rnames[] = {
+               static const char * const rnames[] = {
                        "Sound Control", "Sound DMA" };
                for (i = 0; i < 2; i ++) {
                        if (of_address_to_resource(np->parent, i,
@@ -1223,7 +1199,7 @@ int snd_pmac_new(struct snd_card *card, struct snd_pmac **chip_return)
                txdma_addr = chip->rsrc[1].start;
                rxdma_addr = txdma_addr + 0x100;
        } else {
-               static char *rnames[] = {
+               static const char * const rnames[] = {
                        "Sound Control", "Sound Tx DMA", "Sound Rx DMA" };
                for (i = 0; i < 3; i ++) {
                        if (of_address_to_resource(np, i,
index 529f5a9..a758caf 100644 (file)
@@ -104,7 +104,7 @@ struct snd_pmac {
        struct resource rsrc[3];
 
        int num_freqs;
-       int *freq_table;
+       const int *freq_table;
        unsigned int freqs_ok;          /* bit flags */
        unsigned int formats_ok;        /* pcm hwinfo */
        int active;
index c213eb7..6d2a33b 100644 (file)
@@ -535,22 +535,6 @@ static int snd_ps3_pcm_close(struct snd_pcm_substream *substream)
        return 0;
 };
 
-static int snd_ps3_pcm_hw_params(struct snd_pcm_substream *substream,
-                                struct snd_pcm_hw_params *hw_params)
-{
-       size_t size;
-
-       /* alloc transport buffer */
-       size = params_buffer_bytes(hw_params);
-       snd_pcm_lib_malloc_pages(substream, size);
-       return 0;
-};
-
-static int snd_ps3_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-};
-
 static int snd_ps3_delay_to_bytes(struct snd_pcm_substream *substream,
                                  unsigned int delay_ms)
 {
@@ -731,7 +715,7 @@ static int snd_ps3_spdif_default_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new spdif_ctls[] = {
+static const struct snd_kcontrol_new spdif_ctls[] = {
        {
                .access = SNDRV_CTL_ELEM_ACCESS_READ,
                .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -758,9 +742,6 @@ static struct snd_kcontrol_new spdif_ctls[] = {
 static const struct snd_pcm_ops snd_ps3_pcm_spdif_ops = {
        .open = snd_ps3_pcm_open,
        .close = snd_ps3_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_ps3_pcm_hw_params,
-       .hw_free = snd_ps3_pcm_hw_free,
        .prepare = snd_ps3_pcm_prepare,
        .trigger = snd_ps3_pcm_trigger,
        .pointer = snd_ps3_pcm_pointer,
@@ -1007,11 +988,11 @@ static int snd_ps3_driver_probe(struct ps3_system_bus_device *dev)
 
        the_card.pcm->info_flags = SNDRV_PCM_INFO_NONINTERLEAVED;
        /* pre-alloc PCM DMA buffer*/
-       snd_pcm_lib_preallocate_pages_for_all(the_card.pcm,
-                                       SNDRV_DMA_TYPE_DEV,
-                                       &dev->core,
-                                       SND_PS3_PCM_PREALLOC_SIZE,
-                                       SND_PS3_PCM_PREALLOC_SIZE);
+       snd_pcm_set_managed_buffer_all(the_card.pcm,
+                                      SNDRV_DMA_TYPE_DEV,
+                                      &dev->core,
+                                      SND_PS3_PCM_PREALLOC_SIZE,
+                                      SND_PS3_PCM_PREALLOC_SIZE);
 
        /*
         * allocate null buffer
index 31bab6a..6e5bdaa 100644 (file)
@@ -106,7 +106,7 @@ struct pmac_tumbler {
 /*
  */
 
-static int send_init_client(struct pmac_keywest *i2c, unsigned int *regs)
+static int send_init_client(struct pmac_keywest *i2c, const unsigned int *regs)
 {
        while (*regs > 0) {
                int err, count = 10;
@@ -128,7 +128,7 @@ static int send_init_client(struct pmac_keywest *i2c, unsigned int *regs)
 
 static int tumbler_init_client(struct pmac_keywest *i2c)
 {
-       static unsigned int regs[] = {
+       static const unsigned int regs[] = {
                /* normal operation, SCLK=64fps, i2s output, i2s input, 16bit width */
                TAS_REG_MCS, (1<<6)|(2<<4)|(2<<2)|0,
                0, /* terminator */
@@ -139,7 +139,7 @@ static int tumbler_init_client(struct pmac_keywest *i2c)
 
 static int snapper_init_client(struct pmac_keywest *i2c)
 {
-       static unsigned int regs[] = {
+       static const unsigned int regs[] = {
                /* normal operation, SCLK=64fps, i2s output, 16bit width */
                TAS_REG_MCS, (1<<6)|(2<<4)|0,
                /* normal operation, all-pass mode */
@@ -478,11 +478,11 @@ struct tumbler_mono_vol {
        int reg;
        int bytes;
        unsigned int max;
-       unsigned int *table;
+       const unsigned int *table;
 };
 
 static int tumbler_set_mono_volume(struct pmac_tumbler *mix,
-                                  struct tumbler_mono_vol *info)
+                                  const struct tumbler_mono_vol *info)
 {
        unsigned char block[4];
        unsigned int vol;
@@ -553,7 +553,7 @@ static int tumbler_put_mono(struct snd_kcontrol *kcontrol,
 }
 
 /* TAS3001c mono volumes */
-static struct tumbler_mono_vol tumbler_pcm_vol_info = {
+static const struct tumbler_mono_vol tumbler_pcm_vol_info = {
        .index = VOL_IDX_PCM_MONO,
        .reg = TAS_REG_PCM,
        .bytes = 3,
@@ -561,7 +561,7 @@ static struct tumbler_mono_vol tumbler_pcm_vol_info = {
        .table = mixer_volume_table,
 };
 
-static struct tumbler_mono_vol tumbler_bass_vol_info = {
+static const struct tumbler_mono_vol tumbler_bass_vol_info = {
        .index = VOL_IDX_BASS,
        .reg = TAS_REG_BASS,
        .bytes = 1,
@@ -569,7 +569,7 @@ static struct tumbler_mono_vol tumbler_bass_vol_info = {
        .table = bass_volume_table,
 };
 
-static struct tumbler_mono_vol tumbler_treble_vol_info = {
+static const struct tumbler_mono_vol tumbler_treble_vol_info = {
        .index = VOL_IDX_TREBLE,
        .reg = TAS_REG_TREBLE,
        .bytes = 1,
@@ -578,7 +578,7 @@ static struct tumbler_mono_vol tumbler_treble_vol_info = {
 };
 
 /* TAS3004 mono volumes */
-static struct tumbler_mono_vol snapper_bass_vol_info = {
+static const struct tumbler_mono_vol snapper_bass_vol_info = {
        .index = VOL_IDX_BASS,
        .reg = TAS_REG_BASS,
        .bytes = 1,
@@ -586,7 +586,7 @@ static struct tumbler_mono_vol snapper_bass_vol_info = {
        .table = snapper_bass_volume_table,
 };
 
-static struct tumbler_mono_vol snapper_treble_vol_info = {
+static const struct tumbler_mono_vol snapper_treble_vol_info = {
        .index = VOL_IDX_TREBLE,
        .reg = TAS_REG_TREBLE,
        .bytes = 1,
@@ -826,7 +826,7 @@ static int snapper_put_capture_source(struct snd_kcontrol *kcontrol,
 
 /*
  */
-static struct snd_kcontrol_new tumbler_mixers[] = {
+static const struct snd_kcontrol_new tumbler_mixers[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Master Playback Volume",
          .info = tumbler_info_master_volume,
@@ -850,7 +850,7 @@ static struct snd_kcontrol_new tumbler_mixers[] = {
        },
 };
 
-static struct snd_kcontrol_new snapper_mixers[] = {
+static const struct snd_kcontrol_new snapper_mixers[] = {
        { .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
          .name = "Master Playback Volume",
          .info = tumbler_info_master_volume,
index 549ec6a..16d5480 100644 (file)
@@ -2,7 +2,7 @@
 /* volume tables, taken from TAS3001c data manual */
 /* volume gain values */
 /* 0 = -70 dB, 175 = 18.0 dB in 0.5 dB step */
-static unsigned int master_volume_table[] = {
+static const unsigned int master_volume_table[] = {
        0x00000015, 0x00000016, 0x00000017,
        0x00000019, 0x0000001a, 0x0000001c,
        0x0000001d, 0x0000001f, 0x00000021,
@@ -66,7 +66,7 @@ static unsigned int master_volume_table[] = {
 
 /* treble table for TAS3001c */
 /* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */
-static unsigned int treble_volume_table[] = {
+static const unsigned int treble_volume_table[] = {
        0x96, 0x95, 0x94,
        0x93, 0x92, 0x91,
        0x90, 0x8f, 0x8e,
@@ -96,7 +96,7 @@ static unsigned int treble_volume_table[] = {
 
 /* bass table for TAS3001c */
 /* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */
-static unsigned int bass_volume_table[] = {
+static const unsigned int bass_volume_table[] = {
        0x86, 0x82, 0x7f,
        0x7d, 0x7a, 0x78,
        0x76, 0x74, 0x72,
@@ -126,7 +126,7 @@ static unsigned int bass_volume_table[] = {
 
 /* mixer (pcm) volume table */
 /* 0 = -70 dB, 175 = 18.0 dB in 0.5 dB step */
-static unsigned int mixer_volume_table[] = {
+static const unsigned int mixer_volume_table[] = {
        0x00014b, 0x00015f, 0x000174,
        0x00018a, 0x0001a1, 0x0001ba,
        0x0001d4, 0x0001f0, 0x00020d,
@@ -191,7 +191,7 @@ static unsigned int mixer_volume_table[] = {
 
 /* treble table for TAS3004 */
 /* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */
-static unsigned int snapper_treble_volume_table[] = {
+static const unsigned int snapper_treble_volume_table[] = {
        0x96, 0x95, 0x94,
        0x93, 0x92, 0x91,
        0x90, 0x8f, 0x8e,
@@ -221,7 +221,7 @@ static unsigned int snapper_treble_volume_table[] = {
 
 /* bass table for TAS3004 */
 /* 0 = -18 dB, 72 = 18 dB in 0.5 dB step */
-static unsigned int snapper_bass_volume_table[] = {
+static const unsigned int snapper_bass_volume_table[] = {
        0x96, 0x95, 0x94,
        0x93, 0x92, 0x91,
        0x90, 0x8f, 0x8e,
index bf1fb0d..8fa6843 100644 (file)
@@ -101,10 +101,10 @@ static void spu_memset(u32 toi, u32 what, int length)
 }
 
 /* spu_memload - write to SPU address space */
-static void spu_memload(u32 toi, void *from, int length)
+static void spu_memload(u32 toi, const void *from, int length)
 {
        unsigned long flags;
-       u32 *froml = from;
+       const u32 *froml = from;
        u32 __iomem *to = (u32 __iomem *) (SPU_MEMORY_BASE + toi);
        int i;
        u32 val;
@@ -363,23 +363,6 @@ static int snd_aicapcm_pcm_close(struct snd_pcm_substream
        return 0;
 }
 
-static int snd_aicapcm_pcm_hw_free(struct snd_pcm_substream
-                                  *substream)
-{
-       /* Free the DMA buffer */
-       return snd_pcm_lib_free_pages(substream);
-}
-
-static int snd_aicapcm_pcm_hw_params(struct snd_pcm_substream
-                                    *substream, struct snd_pcm_hw_params
-                                    *hw_params)
-{
-       /* Allocate a DMA buffer using ALSA built-ins */
-       return
-           snd_pcm_lib_malloc_pages(substream,
-                                    params_buffer_bytes(hw_params));
-}
-
 static int snd_aicapcm_pcm_prepare(struct snd_pcm_substream
                                   *substream)
 {
@@ -416,9 +399,6 @@ static unsigned long snd_aicapcm_pcm_pointer(struct snd_pcm_substream
 static const struct snd_pcm_ops snd_aicapcm_playback_ops = {
        .open = snd_aicapcm_pcm_open,
        .close = snd_aicapcm_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = snd_aicapcm_pcm_hw_params,
-       .hw_free = snd_aicapcm_pcm_hw_free,
        .prepare = snd_aicapcm_pcm_prepare,
        .trigger = snd_aicapcm_pcm_trigger,
        .pointer = snd_aicapcm_pcm_pointer,
@@ -441,11 +421,11 @@ static int __init snd_aicapcmchip(struct snd_card_aica
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
                        &snd_aicapcm_playback_ops);
        /* Allocate the DMA buffers */
-       snd_pcm_lib_preallocate_pages_for_all(pcm,
-                                             SNDRV_DMA_TYPE_CONTINUOUS,
-                                             NULL,
-                                             AICA_BUFFER_SIZE,
-                                             AICA_BUFFER_SIZE);
+       snd_pcm_set_managed_buffer_all(pcm,
+                                      SNDRV_DMA_TYPE_CONTINUOUS,
+                                      NULL,
+                                      AICA_BUFFER_SIZE,
+                                      AICA_BUFFER_SIZE);
        return 0;
 }
 
index f9e36ab..feb2850 100644 (file)
@@ -125,18 +125,6 @@ static int snd_sh_dac_pcm_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int snd_sh_dac_pcm_hw_params(struct snd_pcm_substream *substream,
-                               struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream,
-                       params_buffer_bytes(hw_params));
-}
-
-static int snd_sh_dac_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static int snd_sh_dac_pcm_prepare(struct snd_pcm_substream *substream)
 {
        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
@@ -175,7 +163,6 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream,
 {
        /* channel is not used (interleaved data) */
        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
 
        if (copy_from_user_toio(chip->data_buffer + pos, src, count))
                return -EFAULT;
@@ -195,7 +182,6 @@ static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream,
 {
        /* channel is not used (interleaved data) */
        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
 
        memcpy_toio(chip->data_buffer + pos, src, count);
        chip->buffer_end = chip->data_buffer + pos + count;
@@ -214,7 +200,6 @@ static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
 {
        /* channel is not used (interleaved data) */
        struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
-       struct snd_pcm_runtime *runtime = substream->runtime;
 
        memset_io(chip->data_buffer + pos, 0, count);
        chip->buffer_end = chip->data_buffer + pos + count;
@@ -240,9 +225,6 @@ snd_pcm_uframes_t snd_sh_dac_pcm_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_sh_dac_pcm_ops = {
        .open           = snd_sh_dac_pcm_open,
        .close          = snd_sh_dac_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
-       .hw_params      = snd_sh_dac_pcm_hw_params,
-       .hw_free        = snd_sh_dac_pcm_hw_free,
        .prepare        = snd_sh_dac_pcm_prepare,
        .trigger        = snd_sh_dac_pcm_trigger,
        .pointer        = snd_sh_dac_pcm_pointer,
@@ -267,10 +249,8 @@ static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sh_dac_pcm_ops);
 
        /* buffer size=48K */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                             NULL,
-                                                       48 * 1024,
-                                                       48 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                      NULL, 48 * 1024, 48 * 1024);
 
        return 0;
 }
@@ -342,7 +322,7 @@ static int snd_sh_dac_create(struct snd_card *card,
        struct snd_sh_dac *chip;
        int err;
 
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                   .dev_free = snd_sh_dac_dev_free,
        };
 
index 513e287..e8840dc 100644 (file)
@@ -531,6 +531,7 @@ SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
 SND_SOC_DAPM_OUTPUT("DSP Trigger Out"),
 
 SND_SOC_DAPM_DEMUX("HPOUT1 Demux", SND_SOC_NOPM, 0, 0, &cs47l15_outdemux),
+SND_SOC_DAPM_MUX("HPOUT1 Mono Mux", SND_SOC_NOPM, 0, 0, &cs47l15_outdemux),
 
 SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT,
                 0, NULL, 0),
@@ -1086,6 +1087,9 @@ static const struct snd_soc_dapm_route cs47l15_dapm_routes[] = {
        { "AEC2 Loopback", "HPOUT1R", "OUT1R" },
        { "HPOUT1 Demux", NULL, "OUT1L" },
        { "HPOUT1 Demux", NULL, "OUT1R" },
+
+       { "OUT1R", NULL, "HPOUT1 Mono Mux" },
+
        { "HPOUTL", "HPOUT", "HPOUT1 Demux" },
        { "HPOUTR", "HPOUT", "HPOUT1 Demux" },
        { "EPOUTP", "EPOUT", "HPOUT1 Demux" },
@@ -1263,6 +1267,11 @@ static irqreturn_t cs47l15_adsp2_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static const struct snd_soc_dapm_route cs47l15_mono_routes[] = {
+       { "HPOUT1 Mono Mux", "HPOUT", "OUT1L" },
+       { "HPOUT1 Mono Mux", "EPOUT", "OUT1L" },
+};
+
 static int cs47l15_component_probe(struct snd_soc_component *component)
 {
        struct cs47l15 *cs47l15 = snd_soc_component_get_drvdata(component);
@@ -1279,7 +1288,9 @@ static int cs47l15_component_probe(struct snd_soc_component *component)
        if (ret)
                return ret;
 
-       ret = madera_init_outputs(component, CS47L15_MONO_OUTPUTS);
+       ret = madera_init_outputs(component, cs47l15_mono_routes,
+                                 ARRAY_SIZE(cs47l15_mono_routes),
+                                 CS47L15_MONO_OUTPUTS);
        if (ret)
                return ret;
 
index ba7aa6b..3d48a0d 100644 (file)
@@ -633,6 +633,7 @@ SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
 SND_SOC_DAPM_OUTPUT("DSP Trigger Out"),
 
 SND_SOC_DAPM_DEMUX("HPOUT1 Demux", SND_SOC_NOPM, 0, 0, &cs47l35_outdemux),
+SND_SOC_DAPM_MUX("HPOUT1 Mono Mux", SND_SOC_NOPM, 0, 0, &cs47l35_outdemux),
 
 SND_SOC_DAPM_PGA("PWM1 Driver", MADERA_PWM_DRIVE_1, MADERA_PWM1_ENA_SHIFT,
                 0, NULL, 0),
@@ -1311,6 +1312,8 @@ static const struct snd_soc_dapm_route cs47l35_dapm_routes[] = {
        { "SPKOUTN", NULL, "OUT4L" },
        { "SPKOUTP", NULL, "OUT4L" },
 
+       { "OUT1R", NULL, "HPOUT1 Mono Mux" },
+
        { "HPOUTL", "HPOUT", "HPOUT1 Demux" },
        { "HPOUTR", "HPOUT", "HPOUT1 Demux" },
        { "EPOUTP", "EPOUT", "HPOUT1 Demux" },
@@ -1554,6 +1557,11 @@ static irqreturn_t cs47l35_adsp2_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static const struct snd_soc_dapm_route cs47l35_mono_routes[] = {
+       { "HPOUT1 Mono Mux", "HPOUT", "OUT1L" },
+       { "HPOUT1 Mono Mux", "EPOUT", "OUT1L" },
+};
+
 static int cs47l35_component_probe(struct snd_soc_component *component)
 {
        struct cs47l35 *cs47l35 = snd_soc_component_get_drvdata(component);
@@ -1570,7 +1578,9 @@ static int cs47l35_component_probe(struct snd_soc_component *component)
        if (ret)
                return ret;
 
-       ret = madera_init_outputs(component, CS47L35_MONO_OUTPUTS);
+       ret = madera_init_outputs(component, cs47l35_mono_routes,
+                                 ARRAY_SIZE(cs47l35_mono_routes),
+                                 CS47L35_MONO_OUTPUTS);
        if (ret)
                return ret;
 
index f85581a..bef3471 100644 (file)
@@ -2008,12 +2008,18 @@ static const struct snd_soc_dapm_route cs47l85_dapm_routes[] = {
        { "IN3R", NULL, "IN3R Mode" },
 
        { "IN4L", NULL, "DMICCLK4" },
+       { "IN4L", NULL, "DMICDAT4" },
+       { "IN4R", NULL, "DMICCLK4" },
        { "IN4R", NULL, "DMICDAT4" },
 
        { "IN5L", NULL, "DMICCLK5" },
+       { "IN5L", NULL, "DMICDAT5" },
+       { "IN5R", NULL, "DMICCLK5" },
        { "IN5R", NULL, "DMICDAT5" },
 
        { "IN6L", NULL, "DMICCLK6" },
+       { "IN6L", NULL, "DMICDAT6" },
+       { "IN6R", NULL, "DMICCLK6" },
        { "IN6R", NULL, "DMICDAT6" },
 
        MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
@@ -2510,7 +2516,8 @@ static int cs47l85_component_probe(struct snd_soc_component *component)
        if (ret)
                return ret;
 
-       ret = madera_init_outputs(component, CS47L85_MONO_OUTPUTS);
+       ret = madera_init_outputs(component, NULL, CS47L85_MONO_OUTPUTS,
+                                 CS47L85_MONO_OUTPUTS);
        if (ret)
                return ret;
 
index c3b6f4d..266eade 100644 (file)
@@ -1938,12 +1938,18 @@ static const struct snd_soc_dapm_route cs47l90_dapm_routes[] = {
        { "IN2R", NULL, "IN2R Mode" },
 
        { "IN3L", NULL, "DMICCLK3" },
+       { "IN3L", NULL, "DMICDAT3" },
+       { "IN3R", NULL, "DMICCLK3" },
        { "IN3R", NULL, "DMICDAT3" },
 
        { "IN4L", NULL, "DMICCLK4" },
+       { "IN4L", NULL, "DMICDAT4" },
+       { "IN4R", NULL, "DMICCLK4" },
        { "IN4R", NULL, "DMICDAT4" },
 
        { "IN5L", NULL, "DMICCLK5" },
+       { "IN5L", NULL, "DMICDAT5" },
+       { "IN5R", NULL, "DMICCLK5" },
        { "IN5R", NULL, "DMICDAT5" },
 
        MADERA_MIXER_ROUTES("OUT1L", "HPOUT1L"),
@@ -2421,7 +2427,8 @@ static int cs47l90_component_probe(struct snd_soc_component *component)
        if (ret)
                return ret;
 
-       ret = madera_init_outputs(component, CS47L90_MONO_OUTPUTS);
+       ret = madera_init_outputs(component, NULL, CS47L90_MONO_OUTPUTS,
+                                 CS47L90_MONO_OUTPUTS);
        if (ret)
                return ret;
 
index cbffcd8..942040f 100644 (file)
@@ -778,6 +778,7 @@ SND_SOC_DAPM_MUX("IN2L Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]),
 SND_SOC_DAPM_MUX("IN2R Mode", SND_SOC_NOPM, 0, 0, &madera_inmode[1]),
 
 SND_SOC_DAPM_DEMUX("OUT3 Demux", SND_SOC_NOPM, 0, 0, &cs47l92_outdemux),
+SND_SOC_DAPM_MUX("OUT3 Mono Mux", SND_SOC_NOPM, 0, 0, &cs47l92_outdemux),
 
 SND_SOC_DAPM_OUTPUT("DRC1 Signal Activity"),
 SND_SOC_DAPM_OUTPUT("DRC2 Signal Activity"),
@@ -1632,6 +1633,8 @@ static const struct snd_soc_dapm_route cs47l92_dapm_routes[] = {
        { "OUT3 Demux", NULL, "OUT3L" },
        { "OUT3 Demux", NULL, "OUT3R" },
 
+       { "OUT3R", NULL, "OUT3 Mono Mux" },
+
        { "HPOUT3L", "HPOUT3", "OUT3 Demux" },
        { "HPOUT3R", "HPOUT3", "OUT3 Demux" },
        { "HPOUT4L", "HPOUT4", "OUT3 Demux" },
@@ -1865,6 +1868,13 @@ static irqreturn_t cs47l92_adsp2_irq(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static const struct snd_soc_dapm_route cs47l92_mono_routes[] = {
+       { "OUT1R", NULL, "OUT1L" },
+       { "OUT2R", NULL, "OUT2L" },
+       { "OUT3 Mono Mux", "HPOUT3", "OUT3L" },
+       { "OUT3 Mono Mux", "HPOUT4", "OUT3L" },
+};
+
 static int cs47l92_component_probe(struct snd_soc_component *component)
 {
        struct cs47l92 *cs47l92 = snd_soc_component_get_drvdata(component);
@@ -1881,7 +1891,9 @@ static int cs47l92_component_probe(struct snd_soc_component *component)
        if (ret)
                return ret;
 
-       ret = madera_init_outputs(component, CS47L92_MONO_OUTPUTS);
+       ret = madera_init_outputs(component, cs47l92_mono_routes,
+                                 ARRAY_SIZE(cs47l92_mono_routes),
+                                 CS47L92_MONO_OUTPUTS);
        if (ret)
                return ret;
 
index 5433631..444cc4e 100644 (file)
@@ -293,7 +293,7 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
                             struct snd_ctl_elem_info *uinfo)
 {
        uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
-       uinfo->count = FIELD_SIZEOF(struct hdmi_codec_priv, eld);
+       uinfo->count = sizeof_field(struct hdmi_codec_priv, eld);
 
        return 0;
 }
index 7eccff6..40de9d7 100644 (file)
@@ -1212,7 +1212,9 @@ static const struct snd_soc_dapm_route madera_mono_routes[] = {
        { "OUT6R", NULL, "OUT6L" },
 };
 
-int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes)
+int madera_init_outputs(struct snd_soc_component *component,
+                       const struct snd_soc_dapm_route *routes,
+                       int n_mono_routes, int n_real)
 {
        struct snd_soc_dapm_context *dapm =
                snd_soc_component_get_dapm(component);
@@ -1229,16 +1231,21 @@ int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes)
                n_mono_routes = MADERA_MAX_OUTPUT;
        }
 
+       if (!routes)
+               routes = madera_mono_routes;
+
        for (i = 0; i < n_mono_routes; i++) {
                /* Default is 0 so noop with defaults */
                if (pdata->out_mono[i]) {
                        val = MADERA_OUT1_MONO;
-                       snd_soc_dapm_add_routes(dapm,
-                                               &madera_mono_routes[i], 1);
+                       snd_soc_dapm_add_routes(dapm, &routes[i], 1);
                } else {
                        val = 0;
                }
 
+               if (i >= n_real)
+                       continue;
+
                regmap_update_bits(madera->regmap,
                                   MADERA_OUTPUT_PATH_CONFIG_1L + (i * 8),
                                   MADERA_OUT1_MONO, val);
index 49a8f68..e0c0be5 100644 (file)
@@ -423,7 +423,9 @@ int madera_core_free(struct madera_priv *priv);
 int madera_init_overheat(struct madera_priv *priv);
 int madera_free_overheat(struct madera_priv *priv);
 int madera_init_inputs(struct snd_soc_component *component);
-int madera_init_outputs(struct snd_soc_component *component, int n_mono_routes);
+int madera_init_outputs(struct snd_soc_component *component,
+                       const struct snd_soc_dapm_route *routes,
+                       int n_mono_routes, int n_real);
 int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num,
                              irq_handler_t handler);
 void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num);
index 2a9b610..d3d32b5 100644 (file)
@@ -1030,8 +1030,8 @@ static int wm_coeff_write_acked_control(struct wm_coeff_ctl *ctl,
        return -ETIMEDOUT;
 }
 
-static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
-                                 const void *buf, size_t len)
+static int wm_coeff_write_ctrl_raw(struct wm_coeff_ctl *ctl,
+                                  const void *buf, size_t len)
 {
        struct wm_adsp *dsp = ctl->dsp;
        void *scratch;
@@ -1061,6 +1061,23 @@ static int wm_coeff_write_control(struct wm_coeff_ctl *ctl,
        return 0;
 }
 
+static int wm_coeff_write_ctrl(struct wm_coeff_ctl *ctl,
+                              const void *buf, size_t len)
+{
+       int ret = 0;
+
+       if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
+               ret = -EPERM;
+       else if (buf != ctl->cache)
+               memcpy(ctl->cache, buf, len);
+
+       ctl->set = 1;
+       if (ctl->enabled && ctl->dsp->running)
+               ret = wm_coeff_write_ctrl_raw(ctl, buf, len);
+
+       return ret;
+}
+
 static int wm_coeff_put(struct snd_kcontrol *kctl,
                        struct snd_ctl_elem_value *ucontrol)
 {
@@ -1071,16 +1088,7 @@ static int wm_coeff_put(struct snd_kcontrol *kctl,
        int ret = 0;
 
        mutex_lock(&ctl->dsp->pwr_lock);
-
-       if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
-               ret = -EPERM;
-       else
-               memcpy(ctl->cache, p, ctl->len);
-
-       ctl->set = 1;
-       if (ctl->enabled && ctl->dsp->running)
-               ret = wm_coeff_write_control(ctl, p, ctl->len);
-
+       ret = wm_coeff_write_ctrl(ctl, p, ctl->len);
        mutex_unlock(&ctl->dsp->pwr_lock);
 
        return ret;
@@ -1096,15 +1104,10 @@ static int wm_coeff_tlv_put(struct snd_kcontrol *kctl,
 
        mutex_lock(&ctl->dsp->pwr_lock);
 
-       if (copy_from_user(ctl->cache, bytes, size)) {
+       if (copy_from_user(ctl->cache, bytes, size))
                ret = -EFAULT;
-       } else {
-               ctl->set = 1;
-               if (ctl->enabled && ctl->dsp->running)
-                       ret = wm_coeff_write_control(ctl, ctl->cache, size);
-               else if (ctl->flags & WMFW_CTL_FLAG_VOLATILE)
-                       ret = -EPERM;
-       }
+       else
+               ret = wm_coeff_write_ctrl(ctl, ctl->cache, size);
 
        mutex_unlock(&ctl->dsp->pwr_lock);
 
@@ -1135,8 +1138,8 @@ static int wm_coeff_put_acked(struct snd_kcontrol *kctl,
        return ret;
 }
 
-static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
-                                void *buf, size_t len)
+static int wm_coeff_read_ctrl_raw(struct wm_coeff_ctl *ctl,
+                                 void *buf, size_t len)
 {
        struct wm_adsp *dsp = ctl->dsp;
        void *scratch;
@@ -1166,29 +1169,37 @@ static int wm_coeff_read_control(struct wm_coeff_ctl *ctl,
        return 0;
 }
 
-static int wm_coeff_get(struct snd_kcontrol *kctl,
-                       struct snd_ctl_elem_value *ucontrol)
+static int wm_coeff_read_ctrl(struct wm_coeff_ctl *ctl, void *buf, size_t len)
 {
-       struct soc_bytes_ext *bytes_ext =
-               (struct soc_bytes_ext *)kctl->private_value;
-       struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
-       char *p = ucontrol->value.bytes.data;
        int ret = 0;
 
-       mutex_lock(&ctl->dsp->pwr_lock);
-
        if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
                if (ctl->enabled && ctl->dsp->running)
-                       ret = wm_coeff_read_control(ctl, p, ctl->len);
+                       return wm_coeff_read_ctrl_raw(ctl, buf, len);
                else
-                       ret = -EPERM;
+                       return -EPERM;
        } else {
                if (!ctl->flags && ctl->enabled && ctl->dsp->running)
-                       ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
+                       ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
 
-               memcpy(p, ctl->cache, ctl->len);
+               if (buf != ctl->cache)
+                       memcpy(buf, ctl->cache, len);
        }
 
+       return ret;
+}
+
+static int wm_coeff_get(struct snd_kcontrol *kctl,
+                       struct snd_ctl_elem_value *ucontrol)
+{
+       struct soc_bytes_ext *bytes_ext =
+               (struct soc_bytes_ext *)kctl->private_value;
+       struct wm_coeff_ctl *ctl = bytes_ext_to_ctl(bytes_ext);
+       char *p = ucontrol->value.bytes.data;
+       int ret;
+
+       mutex_lock(&ctl->dsp->pwr_lock);
+       ret = wm_coeff_read_ctrl(ctl, p, ctl->len);
        mutex_unlock(&ctl->dsp->pwr_lock);
 
        return ret;
@@ -1204,15 +1215,7 @@ static int wm_coeff_tlv_get(struct snd_kcontrol *kctl,
 
        mutex_lock(&ctl->dsp->pwr_lock);
 
-       if (ctl->flags & WMFW_CTL_FLAG_VOLATILE) {
-               if (ctl->enabled && ctl->dsp->running)
-                       ret = wm_coeff_read_control(ctl, ctl->cache, size);
-               else
-                       ret = -EPERM;
-       } else {
-               if (!ctl->flags && ctl->enabled && ctl->dsp->running)
-                       ret = wm_coeff_read_control(ctl, ctl->cache, size);
-       }
+       ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, size);
 
        if (!ret && copy_to_user(bytes, ctl->cache, size))
                ret = -EFAULT;
@@ -1340,7 +1343,7 @@ static int wm_coeff_init_control_caches(struct wm_adsp *dsp)
                 * created so we don't need to do anything.
                 */
                if (!ctl->flags || (ctl->flags & WMFW_CTL_FLAG_READABLE)) {
-                       ret = wm_coeff_read_control(ctl, ctl->cache, ctl->len);
+                       ret = wm_coeff_read_ctrl_raw(ctl, ctl->cache, ctl->len);
                        if (ret < 0)
                                return ret;
                }
@@ -1358,7 +1361,8 @@ 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_ctrl_raw(ctl, ctl->cache,
+                                                     ctl->len);
                        if (ret < 0)
                                return ret;
                }
@@ -2048,7 +2052,7 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type,
        if (len > ctl->len)
                return -EINVAL;
 
-       ret = wm_coeff_write_control(ctl, buf, len);
+       ret = wm_coeff_write_ctrl(ctl, buf, len);
 
        kcontrol = snd_soc_card_get_kcontrol(dsp->component->card, ctl->name);
        snd_ctl_notify(dsp->component->card->snd_card,
@@ -2070,7 +2074,7 @@ int wm_adsp_read_ctl(struct wm_adsp *dsp, const char *name, int type,
        if (len > ctl->len)
                return -EINVAL;
 
-       return wm_coeff_read_control(ctl, buf, len);
+       return wm_coeff_read_ctrl(ctl, buf, len);
 }
 EXPORT_SYMBOL_GPL(wm_adsp_read_ctl);
 
index eb419e1..78ff5f2 100644 (file)
@@ -41,16 +41,19 @@ int skl_hda_hdmi_add_pcm(struct snd_soc_card *card, int device)
        return 0;
 }
 
-SND_SOC_DAILINK_DEFS(idisp1,
-       DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")),
+SND_SOC_DAILINK_DEF(idisp1_cpu,
+       DAILINK_COMP_ARRAY(COMP_CPU("iDisp1 Pin")));
+SND_SOC_DAILINK_DEF(idisp1_codec,
        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi1")));
 
-SND_SOC_DAILINK_DEFS(idisp2,
-       DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")),
+SND_SOC_DAILINK_DEF(idisp2_cpu,
+       DAILINK_COMP_ARRAY(COMP_CPU("iDisp2 Pin")));
+SND_SOC_DAILINK_DEF(idisp2_codec,
        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi2")));
 
-SND_SOC_DAILINK_DEFS(idisp3,
-       DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")),
+SND_SOC_DAILINK_DEF(idisp3_cpu,
+       DAILINK_COMP_ARRAY(COMP_CPU("iDisp3 Pin")));
+SND_SOC_DAILINK_DEF(idisp3_codec,
        DAILINK_COMP_ARRAY(COMP_CODEC("ehdaudio0D2", "intel-hdmi-hifi3")));
 
 SND_SOC_DAILINK_DEF(analog_cpu,
@@ -83,21 +86,21 @@ struct snd_soc_dai_link skl_hda_be_dai_links[HDA_DSP_MAX_BE_DAI_LINKS] = {
                .id = 1,
                .dpcm_playback = 1,
                .no_pcm = 1,
-               SND_SOC_DAILINK_REG(idisp1),
+               SND_SOC_DAILINK_REG(idisp1_cpu, idisp1_codec, platform),
        },
        {
                .name = "iDisp2",
                .id = 2,
                .dpcm_playback = 1,
                .no_pcm = 1,
-               SND_SOC_DAILINK_REG(idisp2),
+               SND_SOC_DAILINK_REG(idisp2_cpu, idisp2_codec, platform),
        },
        {
                .name = "iDisp3",
                .id = 3,
                .dpcm_playback = 1,
                .no_pcm = 1,
-               SND_SOC_DAILINK_REG(idisp3),
+               SND_SOC_DAILINK_REG(idisp3_cpu, idisp3_codec, platform),
        },
        {
                .name = "Analog Playback and Capture",
index 355165f..b995096 100644 (file)
@@ -1251,7 +1251,7 @@ static u64 skl_adjust_codec_delay(struct snd_pcm_substream *substream,
 static int skl_platform_soc_get_time_info(
                        struct snd_soc_component *component,
                        struct snd_pcm_substream *substream,
-                       struct timespec *system_ts, struct timespec *audio_ts,
+                       struct timespec64 *system_ts, struct timespec64 *audio_ts,
                        struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
                        struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
 {
@@ -1269,7 +1269,7 @@ static int skl_platform_soc_get_time_info(
                if (audio_tstamp_config->report_delay)
                        nsec = skl_adjust_codec_delay(substream, nsec);
 
-               *audio_ts = ns_to_timespec(nsec);
+               *audio_ts = ns_to_timespec64(nsec);
 
                audio_tstamp_report->actual_type = SNDRV_PCM_AUDIO_TSTAMP_TYPE_LINK;
                audio_tstamp_report->accuracy_report = 1; /* rest of struct is valid */
index df57ec4..2cc2565 100644 (file)
@@ -117,7 +117,6 @@ dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component,
        struct dma_chan *chan = pcm->chan[substream->stream];
        struct snd_dmaengine_dai_dma_data *dma_data;
        struct snd_pcm_hardware hw;
-       int ret;
 
        if (pcm->config && pcm->config->pcm_hardware)
                return snd_soc_set_runtime_hwparams(substream,
@@ -138,12 +137,15 @@ dmaengine_pcm_set_runtime_hwparams(struct snd_soc_component *component,
        if (pcm->flags & SND_DMAENGINE_PCM_FLAG_NO_RESIDUE)
                hw.info |= SNDRV_PCM_INFO_BATCH;
 
-       ret = snd_dmaengine_pcm_refine_runtime_hwparams(substream,
-                                                       dma_data,
-                                                       &hw,
-                                                       chan);
-       if (ret)
-               return ret;
+       /**
+        * FIXME: Remove the return value check to align with the code
+        * before adding snd_dmaengine_pcm_refine_runtime_hwparams
+        * function.
+        */
+       snd_dmaengine_pcm_refine_runtime_hwparams(substream,
+                                                 dma_data,
+                                                 &hw,
+                                                 chan);
 
        return snd_soc_set_runtime_hwparams(substream, &hw);
 }
index e66ac9c..ff1b7c7 100644 (file)
@@ -2895,10 +2895,10 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
 
                for_each_rtd_codec_dai(rtd, i, codec_dai) {
                        if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_PLAYBACK) &&
-                           snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
+                           snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
                                playback = 1;
                        if (snd_soc_dai_stream_valid(codec_dai, SNDRV_PCM_STREAM_CAPTURE) &&
-                           snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_CAPTURE))
+                           snd_soc_dai_stream_valid(cpu_dai,   SNDRV_PCM_STREAM_PLAYBACK))
                                capture = 1;
                }
 
index 107ba3e..d2ee6ad 100644 (file)
@@ -1909,6 +1909,10 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
        link->num_codecs = 1;
        link->num_platforms = 1;
 
+       link->dobj.index = tplg->index;
+       link->dobj.ops = tplg->ops;
+       link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
+
        if (strlen(pcm->pcm_name)) {
                link->name = kstrdup(pcm->pcm_name, GFP_KERNEL);
                link->stream_name = kstrdup(pcm->pcm_name, GFP_KERNEL);
@@ -1945,9 +1949,6 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
                goto err;
        }
 
-       link->dobj.index = tplg->index;
-       link->dobj.ops = tplg->ops;
-       link->dobj.type = SND_SOC_DOBJ_DAI_LINK;
        list_add(&link->dobj.list, &tplg->comp->dobj_list);
 
        return 0;
index d1f87a1..6191d91 100644 (file)
 
 /* Number of DAIs */
 #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA)
-#define SOF_SKL_NUM_DAIS               14
+#define SOF_SKL_NUM_DAIS               15
 #else
 #define SOF_SKL_NUM_DAIS               8
 #endif
index d4b8ccc..9d0da5f 100644 (file)
@@ -723,23 +723,9 @@ static int snd_amd7930_capture_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int snd_amd7930_hw_params(struct snd_pcm_substream *substream,
-                                   struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
-}
-
-static int snd_amd7930_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
-}
-
 static const struct snd_pcm_ops snd_amd7930_playback_ops = {
        .open           =       snd_amd7930_playback_open,
        .close          =       snd_amd7930_playback_close,
-       .ioctl          =       snd_pcm_lib_ioctl,
-       .hw_params      =       snd_amd7930_hw_params,
-       .hw_free        =       snd_amd7930_hw_free,
        .prepare        =       snd_amd7930_playback_prepare,
        .trigger        =       snd_amd7930_playback_trigger,
        .pointer        =       snd_amd7930_playback_pointer,
@@ -748,9 +734,6 @@ static const struct snd_pcm_ops snd_amd7930_playback_ops = {
 static const struct snd_pcm_ops snd_amd7930_capture_ops = {
        .open           =       snd_amd7930_capture_open,
        .close          =       snd_amd7930_capture_close,
-       .ioctl          =       snd_pcm_lib_ioctl,
-       .hw_params      =       snd_amd7930_hw_params,
-       .hw_free        =       snd_amd7930_hw_free,
        .prepare        =       snd_amd7930_capture_prepare,
        .trigger        =       snd_amd7930_capture_trigger,
        .pointer        =       snd_amd7930_capture_pointer,
@@ -776,9 +759,8 @@ static int snd_amd7930_pcm(struct snd_amd7930 *amd)
        strcpy(pcm->name, amd->card->shortname);
        amd->pcm = pcm;
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                             NULL,
-                                             64*1024, 64*1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                      NULL, 64*1024, 64*1024);
 
        return 0;
 }
@@ -855,7 +837,7 @@ static int snd_amd7930_put_volume(struct snd_kcontrol *kctl, struct snd_ctl_elem
        return change;
 }
 
-static struct snd_kcontrol_new amd7930_controls[] = {
+static const struct snd_kcontrol_new amd7930_controls[] = {
        {
                .iface          =       SNDRV_CTL_ELEM_IFACE_MIXER,
                .name           =       "Monitor Volume",
@@ -930,7 +912,7 @@ static int snd_amd7930_dev_free(struct snd_device *device)
        return snd_amd7930_free(amd);
 }
 
-static struct snd_device_ops snd_amd7930_dev_ops = {
+static const struct snd_device_ops snd_amd7930_dev_ops = {
        .dev_free       =       snd_amd7930_dev_free,
 };
 
index 138841e..0eed5f7 100644 (file)
@@ -184,7 +184,7 @@ struct snd_cs4231 {
  *  Some variables
  */
 
-static unsigned char freq_bits[14] = {
+static const unsigned char freq_bits[14] = {
        /* 5510 */      0x00 | CS4231_XTAL2,
        /* 6620 */      0x0E | CS4231_XTAL2,
        /* 8000 */      0x00 | CS4231_XTAL1,
@@ -218,7 +218,7 @@ static int snd_cs4231_xrate(struct snd_pcm_runtime *runtime)
                                          &hw_constraints_rates);
 }
 
-static unsigned char snd_cs4231_original_image[32] =
+static const unsigned char snd_cs4231_original_image[32] =
 {
        0x00,                   /* 00/00 - lic */
        0x00,                   /* 01/01 - ric */
@@ -869,7 +869,7 @@ static int snd_cs4231_timer_close(struct snd_timer *timer)
        return 0;
 }
 
-static struct snd_timer_hardware snd_cs4231_timer_table = {
+static const struct snd_timer_hardware snd_cs4231_timer_table = {
        .flags          =       SNDRV_TIMER_HW_AUTO,
        .resolution     =       9945,
        .ticks          =       65535,
@@ -889,12 +889,7 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
        unsigned char new_pdfr;
-       int err;
 
-       err = snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params),
                                         params_channels(hw_params)) |
                snd_cs4231_get_rate(params_rate(hw_params));
@@ -933,12 +928,7 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream,
 {
        struct snd_cs4231 *chip = snd_pcm_substream_chip(substream);
        unsigned char new_cdfr;
-       int err;
 
-       err = snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-       if (err < 0)
-               return err;
        new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params),
                                         params_channels(hw_params)) |
                snd_cs4231_get_rate(params_rate(hw_params));
@@ -1203,9 +1193,7 @@ static int snd_cs4231_capture_close(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_cs4231_playback_ops = {
        .open           =       snd_cs4231_playback_open,
        .close          =       snd_cs4231_playback_close,
-       .ioctl          =       snd_pcm_lib_ioctl,
        .hw_params      =       snd_cs4231_playback_hw_params,
-       .hw_free        =       snd_pcm_lib_free_pages,
        .prepare        =       snd_cs4231_playback_prepare,
        .trigger        =       snd_cs4231_trigger,
        .pointer        =       snd_cs4231_playback_pointer,
@@ -1214,9 +1202,7 @@ static const struct snd_pcm_ops snd_cs4231_playback_ops = {
 static const struct snd_pcm_ops snd_cs4231_capture_ops = {
        .open           =       snd_cs4231_capture_open,
        .close          =       snd_cs4231_capture_close,
-       .ioctl          =       snd_pcm_lib_ioctl,
        .hw_params      =       snd_cs4231_capture_hw_params,
-       .hw_free        =       snd_pcm_lib_free_pages,
        .prepare        =       snd_cs4231_capture_prepare,
        .trigger        =       snd_cs4231_trigger,
        .pointer        =       snd_cs4231_capture_pointer,
@@ -1242,9 +1228,8 @@ static int snd_cs4231_pcm(struct snd_card *card)
        pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
        strcpy(pcm->name, "CS4231");
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
-                                             &chip->op->dev,
-                                             64 * 1024, 128 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
+                                      &chip->op->dev, 64 * 1024, 128 * 1024);
 
        chip->pcm = pcm;
 
@@ -1494,7 +1479,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol,
   .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \
                   ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) }
 
-static struct snd_kcontrol_new snd_cs4231_controls[] = {
+static const struct snd_kcontrol_new snd_cs4231_controls[] = {
 CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT,
                CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
 CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT,
@@ -1786,7 +1771,7 @@ static int snd_cs4231_sbus_dev_free(struct snd_device *device)
        return snd_cs4231_sbus_free(cp);
 }
 
-static struct snd_device_ops snd_cs4231_sbus_dev_ops = {
+static const struct snd_device_ops snd_cs4231_sbus_dev_ops = {
        .dev_free       =       snd_cs4231_sbus_dev_free,
 };
 
@@ -1952,7 +1937,7 @@ static int snd_cs4231_ebus_dev_free(struct snd_device *device)
        return snd_cs4231_ebus_free(cp);
 }
 
-static struct snd_device_ops snd_cs4231_ebus_dev_ops = {
+static const struct snd_device_ops snd_cs4231_ebus_dev_ops = {
        .dev_free       =       snd_cs4231_ebus_dev_free,
 };
 
index 4911103..cf70499 100644 (file)
@@ -104,7 +104,7 @@ module_param(dbri_debug, int, 0644);
 MODULE_PARM_DESC(dbri_debug, "Debug value for Sun DBRI soundcard.");
 
 #ifdef DBRI_DEBUG
-static char *cmds[] = {
+static const char * const cmds[] = {
        "WAIT", "PAUSE", "JUMP", "IIQ", "REX", "SDP", "CDP", "DTS",
        "SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV"
 };
@@ -2099,12 +2099,6 @@ static int snd_dbri_hw_params(struct snd_pcm_substream *substream,
        if (ret != 0)
                return ret;
 
-       if ((ret = snd_pcm_lib_malloc_pages(substream,
-                               params_buffer_bytes(hw_params))) < 0) {
-               printk(KERN_ERR "malloc_pages failed with %d\n", ret);
-               return ret;
-       }
-
        /* hw_params can get called multiple times. Only map the DMA once.
         */
        if (info->dvma_buffer == 0) {
@@ -2151,7 +2145,7 @@ static int snd_dbri_hw_free(struct snd_pcm_substream *substream)
                info->pipe = -1;
        }
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int snd_dbri_prepare(struct snd_pcm_substream *substream)
@@ -2221,7 +2215,6 @@ static snd_pcm_uframes_t snd_dbri_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops snd_dbri_ops = {
        .open = snd_dbri_open,
        .close = snd_dbri_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_dbri_hw_params,
        .hw_free = snd_dbri_hw_free,
        .prepare = snd_dbri_prepare,
@@ -2248,9 +2241,8 @@ static int snd_dbri_pcm(struct snd_card *card)
        pcm->info_flags = 0;
        strcpy(pcm->name, card->shortname);
 
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                             NULL,
-                                             64 * 1024, 64 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                      NULL, 64 * 1024, 64 * 1024);
        return 0;
 }
 
@@ -2418,7 +2410,7 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol,
   .private_value = (entry) | ((shift) << 8) | ((mask) << 16) | \
                        ((invert) << 24) },
 
-static struct snd_kcontrol_new dbri_controls[] = {
+static const struct snd_kcontrol_new dbri_controls[] = {
        {
         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
         .name  = "Playback Volume",
index 4de1ba9..76c0e37 100644 (file)
@@ -36,7 +36,7 @@
 #define BITRATE_MAX    50000 /* Hardware limit. */
 
 /* Initial (hardware reset) AT73C213 register values. */
-static u8 snd_at73c213_original_image[18] =
+static const u8 snd_at73c213_original_image[18] =
 {
        0x00,   /* 00 - CTRL    */
        0x05,   /* 01 - LLIG    */
@@ -242,13 +242,7 @@ static int snd_at73c213_pcm_hw_params(struct snd_pcm_substream *substream,
        val = SSC_BFINS(TFMR_DATNB, channels - 1, val);
        ssc_writel(chip->ssc->regs, TFMR, val);
 
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-static int snd_at73c213_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static int snd_at73c213_pcm_prepare(struct snd_pcm_substream *substream)
@@ -322,9 +316,7 @@ snd_at73c213_pcm_pointer(struct snd_pcm_substream *substream)
 static const struct snd_pcm_ops at73c213_playback_ops = {
        .open           = snd_at73c213_pcm_open,
        .close          = snd_at73c213_pcm_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = snd_at73c213_pcm_hw_params,
-       .hw_free        = snd_at73c213_pcm_hw_free,
        .prepare        = snd_at73c213_pcm_prepare,
        .trigger        = snd_at73c213_pcm_trigger,
        .pointer        = snd_at73c213_pcm_pointer,
@@ -347,7 +339,7 @@ static int snd_at73c213_pcm_new(struct snd_at73c213 *chip, int device)
 
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &at73c213_playback_ops);
 
-       snd_pcm_lib_preallocate_pages_for_all(chip->pcm,
+       snd_pcm_set_managed_buffer_all(chip->pcm,
                        SNDRV_DMA_TYPE_DEV, &chip->ssc->pdev->dev,
                        64 * 1024, 64 * 1024);
 out:
@@ -665,7 +657,7 @@ static int snd_at73c213_aux_capture_volume_info(
                        | (mask << 24) | (invert << 22))                \
 }
 
-static struct snd_kcontrol_new snd_at73c213_controls[] = {
+static const struct snd_kcontrol_new snd_at73c213_controls[] = {
 AT73C213_STEREO("Master Playback Volume", 0, DAC_LMPG, DAC_RMPG, 0, 0, 0x1f, 1),
 AT73C213_STEREO("Master Playback Switch", 0, DAC_LMPG, DAC_RMPG, 5, 5, 1, 1),
 AT73C213_STEREO("PCM Playback Volume", 0, DAC_LLOG, DAC_RLOG, 0, 0, 0x1f, 1),
@@ -882,7 +874,7 @@ static int snd_at73c213_dev_free(struct snd_device *device)
 static int snd_at73c213_dev_init(struct snd_card *card,
                                 struct spi_device *spi)
 {
-       static struct snd_device_ops ops = {
+       static const struct snd_device_ops ops = {
                .dev_free       = snd_at73c213_dev_free,
        };
        struct snd_at73c213 *chip = get_chip(card);
index 1ac2267..7eed579 100644 (file)
@@ -63,7 +63,7 @@ static int send_converted_effect(const struct nrpn_conv_table *table,
 /* effect sensitivities for GS NRPN:
  *  adjusted for chaos 8MB soundfonts
  */
-static int gs_sense[] = 
+static const int gs_sense[] =
 {
        DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
        DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
@@ -72,7 +72,7 @@ static int gs_sense[] =
 /* effect sensitivies for XG controls:
  * adjusted for chaos 8MB soundfonts
  */
-static int xg_sense[] = 
+static const int xg_sense[] =
 {
        DEF_FX_CUTOFF, DEF_FX_RESONANCE, DEF_FX_ATTACK, DEF_FX_RELEASE,
        DEF_FX_VIBRATE, DEF_FX_VIBDEPTH, DEF_FX_VIBDELAY
index a14fc65..d8d3267 100644 (file)
@@ -34,7 +34,7 @@ static void fake_event(struct snd_emux *emu, struct snd_emux_port *port,
                       int ch, int param, int val, int atomic, int hop);
 
 /* operators */
-static struct snd_seq_oss_callback oss_callback = {
+static const struct snd_seq_oss_callback oss_callback = {
        .owner = THIS_MODULE,
        .open = snd_emux_open_seq_oss,
        .close = snd_emux_close_seq_oss,
index 9d8a69f..b227c7e 100644 (file)
@@ -19,7 +19,7 @@ static int snd_emux_unuse(void *private_data, struct snd_seq_port_subscribe *inf
 /*
  * MIDI emulation operators
  */
-static struct snd_midi_op emux_ops = {
+static const struct snd_midi_op emux_ops = {
        .note_on = snd_emux_note_on,
        .note_off = snd_emux_note_off,
        .key_press = snd_emux_key_press,
index 7c9eecd..a5385ef 100644 (file)
@@ -529,7 +529,7 @@ update_voice(struct snd_emux *emu, struct snd_emux_voice *vp, int update)
 
 #if 0 // not used
 /* table for volume target calculation */
-static unsigned short voltarget[16] = { 
+static const unsigned short voltarget[16] = {
        0xEAC0, 0xE0C8, 0xD740, 0xCE20, 0xC560, 0xBD08, 0xB500, 0xAD58,
        0xA5F8, 0x9EF0, 0x9830, 0x91C0, 0x8B90, 0x85A8, 0x8000, 0x7A90
 };
@@ -616,7 +616,7 @@ setup_voice(struct snd_emux_voice *vp)
 /*
  * calculate pitch parameter
  */
-static unsigned char pan_volumes[256] = {
+static const unsigned char pan_volumes[256] = {
 0x00,0x03,0x06,0x09,0x0c,0x0f,0x12,0x14,0x17,0x1a,0x1d,0x20,0x22,0x25,0x28,0x2a,
 0x2d,0x30,0x32,0x35,0x37,0x3a,0x3c,0x3f,0x41,0x44,0x46,0x49,0x4b,0x4d,0x50,0x52,
 0x54,0x57,0x59,0x5b,0x5d,0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6f,0x71,0x73,0x75,
@@ -684,7 +684,7 @@ calc_pan(struct snd_emux_voice *vp)
  */
 
 /* tables for volume->attenuation calculation */
-static unsigned char voltab1[128] = {
+static const unsigned char voltab1[128] = {
    0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
    0x63, 0x2b, 0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22,
    0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
@@ -700,7 +700,7 @@ static unsigned char voltab1[128] = {
    0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char voltab2[128] = {
+static const unsigned char voltab2[128] = {
    0x32, 0x31, 0x30, 0x2f, 0x2e, 0x2d, 0x2c, 0x2b, 0x2a, 0x2a,
    0x29, 0x28, 0x27, 0x26, 0x25, 0x24, 0x24, 0x23, 0x22, 0x21,
    0x21, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1c, 0x1c, 0x1b, 0x1a,
@@ -716,7 +716,7 @@ static unsigned char voltab2[128] = {
    0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static unsigned char expressiontab[128] = {
+static const unsigned char expressiontab[128] = {
    0x7f, 0x6c, 0x62, 0x5a, 0x54, 0x50, 0x4b, 0x48, 0x45, 0x42,
    0x40, 0x3d, 0x3b, 0x39, 0x38, 0x36, 0x34, 0x33, 0x31, 0x30,
    0x2f, 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, 0x25,
index dcc6a92..9ebc711 100644 (file)
@@ -751,7 +751,7 @@ load_data(struct snd_sf_list *sflist, const void __user *data, long count)
 
 
 /* log2_tbl[i] = log2(i+128) * 0x10000 */
-static int log_tbl[129] = {
+static const int log_tbl[129] = {
        0x70000, 0x702df, 0x705b9, 0x7088e, 0x70b5d, 0x70e26, 0x710eb, 0x713aa,
        0x71663, 0x71918, 0x71bc8, 0x71e72, 0x72118, 0x723b9, 0x72655, 0x728ed,
        0x72b80, 0x72e0e, 0x73098, 0x7331d, 0x7359e, 0x7381b, 0x73a93, 0x73d08,
@@ -857,7 +857,7 @@ calc_gus_envelope_time(int rate, int start, int end)
 /* convert envelope time parameter to soundfont parameters */
 
 /* attack & decay/release time table (msec) */
-static short attack_time_tbl[128] = {
+static const short attack_time_tbl[128] = {
 32767, 32767, 5989, 4235, 2994, 2518, 2117, 1780, 1497, 1373, 1259, 1154, 1058, 970, 890, 816,
 707, 691, 662, 634, 607, 581, 557, 533, 510, 489, 468, 448, 429, 411, 393, 377,
 361, 345, 331, 317, 303, 290, 278, 266, 255, 244, 234, 224, 214, 205, 196, 188,
@@ -868,7 +868,7 @@ static short attack_time_tbl[128] = {
 11, 11, 10, 10, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 6, 0,
 };
 
-static short decay_time_tbl[128] = {
+static const short decay_time_tbl[128] = {
 32767, 32767, 22614, 15990, 11307, 9508, 7995, 6723, 5653, 5184, 4754, 4359, 3997, 3665, 3361, 3082,
 2828, 2765, 2648, 2535, 2428, 2325, 2226, 2132, 2042, 1955, 1872, 1793, 1717, 1644, 1574, 1507,
 1443, 1382, 1324, 1267, 1214, 1162, 1113, 1066, 978, 936, 897, 859, 822, 787, 754, 722,
@@ -891,7 +891,7 @@ snd_sf_calc_parm_hold(int msec)
 
 /* search an index for specified time from given time table */
 static int
-calc_parm_search(int msec, short *table)
+calc_parm_search(int msec, const short *table)
 {
        int left = 1, right = 127, mid;
        while (left < right) {
index de1f030..20f34d2 100644 (file)
@@ -397,7 +397,7 @@ static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static struct snd_kcontrol_new vol_elements[] = {
+static const struct snd_kcontrol_new vol_elements[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Analog Playback Volume",
@@ -437,7 +437,7 @@ static struct snd_kcontrol_new vol_elements[] = {
        {}
 };
 
-static struct snd_kcontrol_new mute_elements[] = {
+static const struct snd_kcontrol_new mute_elements[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Analog Playback Switch",
@@ -471,7 +471,7 @@ static struct snd_kcontrol_new mute_elements[] = {
        {}
 };
 
-static struct snd_kcontrol_new elements[] = {
+static const struct snd_kcontrol_new elements[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "Line/Phono Capture Route",
@@ -517,7 +517,7 @@ static int usb6fire_control_add_virtual(
        struct control_runtime *rt,
        struct snd_card *card,
        char *name,
-       struct snd_kcontrol_new *elems)
+       const struct snd_kcontrol_new *elems)
 {
        int ret;
        int i;
index cdc5dd7..7168f1c 100644 (file)
@@ -446,18 +446,6 @@ static int usb6fire_pcm_close(struct snd_pcm_substream *alsa_sub)
        return 0;
 }
 
-static int usb6fire_pcm_hw_params(struct snd_pcm_substream *alsa_sub,
-               struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(alsa_sub,
-                                       params_buffer_bytes(hw_params));
-}
-
-static int usb6fire_pcm_hw_free(struct snd_pcm_substream *alsa_sub)
-{
-       return snd_pcm_lib_free_pages(alsa_sub);
-}
-
 static int usb6fire_pcm_prepare(struct snd_pcm_substream *alsa_sub)
 {
        struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
@@ -554,9 +542,6 @@ static snd_pcm_uframes_t usb6fire_pcm_pointer(
 static const struct snd_pcm_ops pcm_ops = {
        .open = usb6fire_pcm_open,
        .close = usb6fire_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = usb6fire_pcm_hw_params,
-       .hw_free = usb6fire_pcm_hw_free,
        .prepare = usb6fire_pcm_prepare,
        .trigger = usb6fire_pcm_trigger,
        .pointer = usb6fire_pcm_pointer,
@@ -658,8 +643,7 @@ int usb6fire_pcm_init(struct sfire_chip *chip)
        strcpy(pcm->name, "DMX 6Fire USB");
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC, NULL, 0, 0);
 
        rt->instance = pcm;
 
index 6e31758..010976d 100644 (file)
@@ -25,9 +25,9 @@ static const struct usb_device_id id_table[] = {
        { },
 };
 
-static unsigned char device_cmd_prefix[] = {0x03, 0x00};
+static const unsigned char device_cmd_prefix[] = {0x03, 0x00};
 
-static unsigned char bcd2000_init_sequence[] = {
+static const unsigned char bcd2000_init_sequence[] = {
        0x07, 0x00, 0x00, 0x00, 0x78, 0x48, 0x1c, 0x81,
        0xc4, 0x00, 0x00, 0x00, 0x5e, 0x53, 0x4a, 0xf7,
        0x18, 0xfa, 0x11, 0xff, 0x6c, 0xf3, 0x90, 0xff,
index 970eb08..e9243d5 100644 (file)
@@ -30,7 +30,7 @@
 #define MAKE_CHECKBYTE(cdev,stream,i) \
        (stream << 1) | (~(i / (cdev->n_streams * BYTES_PER_SAMPLE_USB)) & 1)
 
-static struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = {
+static const struct snd_pcm_hardware snd_usb_caiaq_pcm_hardware = {
        .info           = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                           SNDRV_PCM_INFO_BLOCK_TRANSFER),
        .formats        = SNDRV_PCM_FMTBIT_S24_3BE,
@@ -167,17 +167,11 @@ static int snd_usb_caiaq_substream_close(struct snd_pcm_substream *substream)
        return 0;
 }
 
-static int snd_usb_caiaq_pcm_hw_params(struct snd_pcm_substream *sub,
-                                      struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(sub, params_buffer_bytes(hw_params));
-}
-
 static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
 {
        struct snd_usb_caiaqdev *cdev = snd_pcm_substream_chip(sub);
        deactivate_substream(cdev, sub);
-       return snd_pcm_lib_free_pages(sub);
+       return 0;
 }
 
 /* this should probably go upstream */
@@ -185,7 +179,7 @@ static int snd_usb_caiaq_pcm_hw_free(struct snd_pcm_substream *sub)
 #error "Change this table"
 #endif
 
-static unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
+static const unsigned int rates[] = { 5512, 8000, 11025, 16000, 22050, 32000, 44100,
                                48000, 64000, 88200, 96000, 176400, 192000 };
 
 static int snd_usb_caiaq_pcm_prepare(struct snd_pcm_substream *substream)
@@ -327,8 +321,6 @@ unlock:
 static const struct snd_pcm_ops snd_usb_caiaq_ops = {
        .open =         snd_usb_caiaq_substream_open,
        .close =        snd_usb_caiaq_substream_close,
-       .ioctl =        snd_pcm_lib_ioctl,
-       .hw_params =    snd_usb_caiaq_pcm_hw_params,
        .hw_free =      snd_usb_caiaq_pcm_hw_free,
        .prepare =      snd_usb_caiaq_pcm_prepare,
        .trigger =      snd_usb_caiaq_pcm_trigger,
@@ -841,8 +833,8 @@ int snd_usb_caiaq_audio_init(struct snd_usb_caiaqdev *cdev)
                                &snd_usb_caiaq_ops);
        snd_pcm_set_ops(cdev->pcm, SNDRV_PCM_STREAM_CAPTURE,
                                &snd_usb_caiaq_ops);
-       snd_pcm_lib_preallocate_pages_for_all(cdev->pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(cdev->pcm, SNDRV_DMA_TYPE_VMALLOC,
+                                      NULL, 0, 0);
 
        cdev->data_cb_info =
                kmalloc_array(N_URBS, sizeof(struct snd_usb_caiaq_cb_info),
index 532e354..af459c4 100644 (file)
@@ -163,14 +163,14 @@ struct caiaq_controller {
        int index;
 };
 
-static struct caiaq_controller ak1_controller[] = {
+static const struct caiaq_controller ak1_controller[] = {
        { "LED left",   2 },
        { "LED middle", 1 },
        { "LED right",  0 },
        { "LED ring",   3 }
 };
 
-static struct caiaq_controller rk2_controller[] = {
+static const struct caiaq_controller rk2_controller[] = {
        { "LED 1",              5  },
        { "LED 2",              4  },
        { "LED 3",              3  },
@@ -196,7 +196,7 @@ static struct caiaq_controller rk2_controller[] = {
        { "LED 7seg_3g",        23 }
 };
 
-static struct caiaq_controller rk3_controller[] = {
+static const struct caiaq_controller rk3_controller[] = {
        { "LED 7seg_1a",        0 + 0 },
        { "LED 7seg_1b",        0 + 1 },
        { "LED 7seg_1c",        0 + 2 },
@@ -244,7 +244,7 @@ static struct caiaq_controller rk3_controller[] = {
        { "LED pedal",          32 + 8 }
 };
 
-static struct caiaq_controller kore_controller[] = {
+static const struct caiaq_controller kore_controller[] = {
        { "LED F1",             8   | CNT_INTVAL },
        { "LED F2",             12  | CNT_INTVAL },
        { "LED F3",             0   | CNT_INTVAL },
@@ -278,7 +278,7 @@ static struct caiaq_controller kore_controller[] = {
        { "LED control",        26  | CNT_INTVAL }
 };
 
-static struct caiaq_controller a8dj_controller[] = {
+static const struct caiaq_controller a8dj_controller[] = {
        { "Current input mode",                 0 | CNT_INTVAL  },
        { "GND lift for TC Vinyl mode",         24 + 0          },
        { "GND lift for TC CD/Line mode",       24 + 1          },
@@ -286,11 +286,11 @@ static struct caiaq_controller a8dj_controller[] = {
        { "Software lock",                      40              }
 };
 
-static struct caiaq_controller a4dj_controller[] = {
+static const struct caiaq_controller a4dj_controller[] = {
        { "Current input mode", 0 | CNT_INTVAL  }
 };
 
-static struct caiaq_controller kontrolx1_controller[] = {
+static const struct caiaq_controller kontrolx1_controller[] = {
        { "LED FX A: ON",               7 | CNT_INTVAL  },
        { "LED FX A: 1",                6 | CNT_INTVAL  },
        { "LED FX A: 2",                5 | CNT_INTVAL  },
@@ -327,7 +327,7 @@ static struct caiaq_controller kontrolx1_controller[] = {
        { "LED Deck B: SYNC",           8  | CNT_INTVAL },
 };
 
-static struct caiaq_controller kontrols4_controller[] = {
+static const struct caiaq_controller kontrols4_controller[] = {
        { "LED: Master: Quant",                 10  | CNT_INTVAL },
        { "LED: Master: Headphone",             11  | CNT_INTVAL },
        { "LED: Master: Master",                12  | CNT_INTVAL },
@@ -500,7 +500,7 @@ static struct caiaq_controller kontrols4_controller[] = {
        { "LED: FX2: Mode",                     133 | CNT_INTVAL },
 };
 
-static struct caiaq_controller maschine_controller[] = {
+static const struct caiaq_controller maschine_controller[] = {
        { "LED: Pad 1",                         3  | CNT_INTVAL },
        { "LED: Pad 2",                         2  | CNT_INTVAL },
        { "LED: Pad 3",                         1  | CNT_INTVAL },
@@ -568,7 +568,7 @@ static struct caiaq_controller maschine_controller[] = {
        { "Backlight Display",                  59 | CNT_INTVAL }
 };
 
-static int add_controls(struct caiaq_controller *c, int num,
+static int add_controls(const struct caiaq_controller *c, int num,
                        struct snd_usb_caiaqdev *cdev)
 {
        int i, ret;
index 533eb69..1e2cf2f 100644 (file)
 #include "device.h"
 #include "input.h"
 
-static unsigned short keycode_ak1[] =  { KEY_C, KEY_B, KEY_A };
-static unsigned short keycode_rk2[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
+static const unsigned short keycode_ak1[] =  { KEY_C, KEY_B, KEY_A };
+static const unsigned short keycode_rk2[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
                                         KEY_5, KEY_6, KEY_7 };
-static unsigned short keycode_rk3[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
+static const unsigned short keycode_rk3[] =  { KEY_1, KEY_2, KEY_3, KEY_4,
                                         KEY_5, KEY_6, KEY_7, KEY_8, KEY_9 };
 
-static unsigned short keycode_kore[] = {
+static const unsigned short keycode_kore[] = {
        KEY_FN_F1,      /* "menu"               */
        KEY_FN_F7,      /* "lcd backlight       */
        KEY_FN_F2,      /* "control"            */
@@ -60,7 +60,7 @@ static unsigned short keycode_kore[] = {
 #define MASCHINE_PADS      (16)
 #define MASCHINE_PAD(X)    ((X) + ABS_PRESSURE)
 
-static unsigned short keycode_maschine[] = {
+static const unsigned short keycode_maschine[] = {
        MASCHINE_BUTTON(40), /* mute       */
        MASCHINE_BUTTON(39), /* solo       */
        MASCHINE_BUTTON(38), /* select     */
index 9f743eb..827fb0b 100644 (file)
@@ -600,6 +600,10 @@ static int usb_audio_probe(struct usb_interface *intf,
                }
        }
        if (! chip) {
+               err = snd_usb_apply_boot_quirk_once(dev, intf, quirk, id);
+               if (err < 0)
+                       goto __error;
+
                /* it's a fresh one.
                 * now look for an empty slot and create a new card instance
                 */
index 2991b99..395403a 100644 (file)
@@ -145,6 +145,7 @@ struct snd_usb_substream {
        struct snd_usb_endpoint *sync_endpoint;
        unsigned long flags;
        bool need_setup_ep;             /* (re)configure EP at prepare? */
+       bool need_setup_fmt;            /* (re)configure fmt after resume? */
        unsigned int speed;             /* USB_SPEED_XXX */
 
        u64 formats;                    /* format bitmasks (all or'ed) */
index d79db71..9260136 100644 (file)
@@ -292,10 +292,13 @@ static int line6_parse_audio_format_rates_quirk(struct snd_usb_audio *chip,
                                                struct audioformat *fp)
 {
        switch (chip->usb_id) {
-       case USB_ID(0x0E41, 0x4241): /* Line6 Helix */
-       case USB_ID(0x0E41, 0x4242): /* Line6 Helix Rack */
-       case USB_ID(0x0E41, 0x4244): /* Line6 Helix LT */
-       case USB_ID(0x0E41, 0x4246): /* Line6 HX-Stomp */
+       case USB_ID(0x0e41, 0x4241): /* Line6 Helix */
+       case USB_ID(0x0e41, 0x4242): /* Line6 Helix Rack */
+       case USB_ID(0x0e41, 0x4244): /* Line6 Helix LT */
+       case USB_ID(0x0e41, 0x4246): /* Line6 HX-Stomp */
+       case USB_ID(0x0e41, 0x4248): /* Line6 Helix >= fw 2.82 */
+       case USB_ID(0x0e41, 0x4249): /* Line6 Helix Rack >= fw 2.82 */
+       case USB_ID(0x0e41, 0x424a): /* Line6 Helix LT >= fw 2.82 */
                /* supported rates: 48Khz */
                kfree(fp->rate_table);
                fp->rate_table = kmalloc(sizeof(int), GFP_KERNEL);
index e0de719..a148caa 100644 (file)
@@ -415,18 +415,6 @@ static int hiface_pcm_close(struct snd_pcm_substream *alsa_sub)
        return 0;
 }
 
-static int hiface_pcm_hw_params(struct snd_pcm_substream *alsa_sub,
-                               struct snd_pcm_hw_params *hw_params)
-{
-       return snd_pcm_lib_malloc_pages(alsa_sub,
-                                       params_buffer_bytes(hw_params));
-}
-
-static int hiface_pcm_hw_free(struct snd_pcm_substream *alsa_sub)
-{
-       return snd_pcm_lib_free_pages(alsa_sub);
-}
-
 static int hiface_pcm_prepare(struct snd_pcm_substream *alsa_sub)
 {
        struct pcm_runtime *rt = snd_pcm_substream_chip(alsa_sub);
@@ -512,9 +500,6 @@ static snd_pcm_uframes_t hiface_pcm_pointer(struct snd_pcm_substream *alsa_sub)
 static const struct snd_pcm_ops pcm_ops = {
        .open = hiface_pcm_open,
        .close = hiface_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
-       .hw_params = hiface_pcm_hw_params,
-       .hw_free = hiface_pcm_hw_free,
        .prepare = hiface_pcm_prepare,
        .trigger = hiface_pcm_trigger,
        .pointer = hiface_pcm_pointer,
@@ -613,8 +598,8 @@ int hiface_pcm_init(struct hiface_chip *chip, u8 extra_freq)
 
        strlcpy(pcm->name, "USB-SPDIF Audio", sizeof(pcm->name));
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcm_ops);
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_VMALLOC,
+                                      NULL, 0, 0);
 
        rt->instance = pcm;
 
index 82abef3..663d608 100644 (file)
@@ -247,7 +247,6 @@ static int snd_line6_capture_close(struct snd_pcm_substream *substream)
 const struct snd_pcm_ops snd_line6_capture_ops = {
        .open = snd_line6_capture_open,
        .close = snd_line6_capture_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_line6_hw_params,
        .hw_free = snd_line6_hw_free,
        .prepare = snd_line6_prepare,
index 9c437c7..fdbdfb7 100644 (file)
@@ -359,13 +359,6 @@ int snd_line6_hw_params(struct snd_pcm_substream *substream,
        if (ret < 0)
                goto error;
 
-       ret = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-       if (ret < 0) {
-               line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
-               goto error;
-       }
-
        pstr->period = params_period_bytes(hw_params);
  error:
        mutex_unlock(&line6pcm->state_mutex);
@@ -381,7 +374,7 @@ int snd_line6_hw_free(struct snd_pcm_substream *substream)
        mutex_lock(&line6pcm->state_mutex);
        line6_buffer_release(line6pcm, pstr, LINE6_STREAM_PCM);
        mutex_unlock(&line6pcm->state_mutex);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 
@@ -501,8 +494,8 @@ static int snd_line6_new_pcm(struct usb_line6 *line6, struct snd_pcm **pcm_ret)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_line6_capture_ops);
 
        /* pre-allocation of buffers */
-       snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
-                                             NULL, 64 * 1024, 128 * 1024);
+       snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+                                      NULL, 64 * 1024, 128 * 1024);
        return 0;
 }
 
index 2e8ead3..01930ce 100644 (file)
@@ -392,7 +392,6 @@ static int snd_line6_playback_close(struct snd_pcm_substream *substream)
 const struct snd_pcm_ops snd_line6_playback_ops = {
        .open = snd_line6_playback_open,
        .close = snd_line6_playback_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = snd_line6_hw_params,
        .hw_free = snd_line6_hw_free,
        .prepare = snd_line6_prepare,
index ee4c9d2..cd44cb5 100644 (file)
@@ -110,7 +110,7 @@ enum {
        POD_BUSY_MIDISEND
 };
 
-static struct snd_ratden pod_ratden = {
+static const struct snd_ratden pod_ratden = {
        .num_min = 78125,
        .num_max = 78125,
        .num_step = 1,
index 27bf61c..d37db32 100644 (file)
@@ -42,7 +42,7 @@ struct usb_line6_podhd {
 
 #define line6_to_podhd(x)      container_of(x, struct usb_line6_podhd, line6)
 
-static struct snd_ratden podhd_ratden = {
+static const struct snd_ratden podhd_ratden = {
        .num_min = 48000,
        .num_max = 48000,
        .num_step = 1,
index d0a555d..94dd5e7 100644 (file)
@@ -63,7 +63,7 @@ static int toneport_send_cmd(struct usb_device *usbdev, int cmd1, int cmd2);
 
 #define TONEPORT_PCM_DELAY 1
 
-static struct snd_ratden toneport_ratden = {
+static const struct snd_ratden toneport_ratden = {
        .num_min = 44100,
        .num_max = 44100,
        .num_step = 1,
index b737f0e..392e5fd 100644 (file)
@@ -1408,8 +1408,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
                /*
                 * Some devices only work with 9 bytes packet size:
                 */
-       case USB_ID(0x0644, 0x800E): /* Tascam US-122L */
-       case USB_ID(0x0644, 0x800F): /* Tascam US-144 */
+       case USB_ID(0x0644, 0x800e): /* Tascam US-122L */
+       case USB_ID(0x0644, 0x800f): /* Tascam US-144 */
                ep->max_transfer = 9;
                break;
        }
index 566a4a3..884e740 100644 (file)
@@ -730,11 +730,7 @@ static int capture_pcm_hw_params(struct snd_pcm_substream *substream,
        mutex_lock(&ua->mutex);
        err = start_usb_capture(ua);
        mutex_unlock(&ua->mutex);
-       if (err < 0)
-               return err;
-
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
+       return err;
 }
 
 static int playback_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -748,16 +744,7 @@ static int playback_pcm_hw_params(struct snd_pcm_substream *substream,
        if (err >= 0)
                err = start_usb_playback(ua);
        mutex_unlock(&ua->mutex);
-       if (err < 0)
-               return err;
-
-       return snd_pcm_lib_malloc_pages(substream,
-                                       params_buffer_bytes(hw_params));
-}
-
-static int ua101_pcm_hw_free(struct snd_pcm_substream *substream)
-{
-       return snd_pcm_lib_free_pages(substream);
+       return err;
 }
 
 static int capture_pcm_prepare(struct snd_pcm_substream *substream)
@@ -883,9 +870,7 @@ static snd_pcm_uframes_t playback_pcm_pointer(struct snd_pcm_substream *subs)
 static const struct snd_pcm_ops capture_pcm_ops = {
        .open = capture_pcm_open,
        .close = capture_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = capture_pcm_hw_params,
-       .hw_free = ua101_pcm_hw_free,
        .prepare = capture_pcm_prepare,
        .trigger = capture_pcm_trigger,
        .pointer = capture_pcm_pointer,
@@ -894,9 +879,7 @@ static const struct snd_pcm_ops capture_pcm_ops = {
 static const struct snd_pcm_ops playback_pcm_ops = {
        .open = playback_pcm_open,
        .close = playback_pcm_close,
-       .ioctl = snd_pcm_lib_ioctl,
        .hw_params = playback_pcm_hw_params,
-       .hw_free = ua101_pcm_hw_free,
        .prepare = playback_pcm_prepare,
        .trigger = playback_pcm_trigger,
        .pointer = playback_pcm_pointer,
@@ -1294,8 +1277,8 @@ static int ua101_probe(struct usb_interface *interface,
        strcpy(ua->pcm->name, name);
        snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_PLAYBACK, &playback_pcm_ops);
        snd_pcm_set_ops(ua->pcm, SNDRV_PCM_STREAM_CAPTURE, &capture_pcm_ops);
-       snd_pcm_lib_preallocate_pages_for_all(ua->pcm, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+       snd_pcm_set_managed_buffer_all(ua->pcm, SNDRV_DMA_TYPE_VMALLOC,
+                                      NULL, 0, 0);
 
        err = snd_usbmidi_create(card, ua->intf[INTF_MIDI],
                                 &ua->midi_list, &midi_quirk);
index 6cd4ff0..d659fdb 100644 (file)
@@ -1020,7 +1020,7 @@ struct usb_feature_control_info {
        int type_uac2;  /* data type for uac2 if different from uac1, else -1 */
 };
 
-static struct usb_feature_control_info audio_feature_info[] = {
+static const struct usb_feature_control_info audio_feature_info[] = {
        { UAC_FU_MUTE,                  "Mute",                 USB_MIXER_INV_BOOLEAN, -1 },
        { UAC_FU_VOLUME,                "Volume",               USB_MIXER_S16, -1 },
        { UAC_FU_BASS,                  "Tone Control - Bass",  USB_MIXER_S8, -1 },
@@ -1445,7 +1445,7 @@ error:
        return 0;
 }
 
-static struct snd_kcontrol_new usb_feature_unit_ctl = {
+static const struct snd_kcontrol_new usb_feature_unit_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "", /* will be filled later manually */
        .info = mixer_ctl_feature_info,
@@ -1466,7 +1466,7 @@ static const struct snd_kcontrol_new usb_feature_unit_ctl_ro = {
  * A control which shows the boolean value from reading a UAC control on
  * the master channel.
  */
-static struct snd_kcontrol_new usb_bool_master_control_ctl_ro = {
+static const struct snd_kcontrol_new usb_bool_master_control_ctl_ro = {
        .iface = SNDRV_CTL_ELEM_IFACE_CARD,
        .name = "", /* will be filled later manually */
        .access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1488,7 +1488,7 @@ static const struct snd_kcontrol_new usb_connector_ctl_ro = {
  * This symbol is exported in order to allow the mixer quirks to
  * hook up to the standard feature unit control mechanism
  */
-struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
+const struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
 
 /*
  * build a feature control
@@ -1526,7 +1526,7 @@ static void check_no_speaker_on_headset(struct snd_kcontrol *kctl,
        strlcpy(kctl->id.name, "Headphone", sizeof(kctl->id.name));
 }
 
-static struct usb_feature_control_info *get_feature_control_info(int control)
+static const struct usb_feature_control_info *get_feature_control_info(int control)
 {
        int i;
 
@@ -1544,7 +1544,7 @@ static void __build_feature_ctl(struct usb_mixer_interface *mixer,
                                struct usb_audio_term *oterm,
                                int unitid, int nameid, int readonly_mask)
 {
-       struct usb_feature_control_info *ctl_info;
+       const struct usb_feature_control_info *ctl_info;
        unsigned int len = 0;
        int mapped_name = 0;
        struct snd_kcontrol *kctl;
@@ -2198,7 +2198,7 @@ static const struct snd_kcontrol_new mixer_procunit_ctl = {
  */
 struct procunit_value_info {
        int control;
-       char *suffix;
+       const char *suffix;
        int val_type;
        int min_value;
 };
@@ -2206,44 +2206,44 @@ struct procunit_value_info {
 struct procunit_info {
        int type;
        char *name;
-       struct procunit_value_info *values;
+       const struct procunit_value_info *values;
 };
 
-static struct procunit_value_info undefined_proc_info[] = {
+static const struct procunit_value_info undefined_proc_info[] = {
        { 0x00, "Control Undefined", 0 },
        { 0 }
 };
 
-static struct procunit_value_info updown_proc_info[] = {
+static const struct procunit_value_info updown_proc_info[] = {
        { UAC_UD_ENABLE, "Switch", USB_MIXER_BOOLEAN },
        { UAC_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
        { 0 }
 };
-static struct procunit_value_info prologic_proc_info[] = {
+static const struct procunit_value_info prologic_proc_info[] = {
        { UAC_DP_ENABLE, "Switch", USB_MIXER_BOOLEAN },
        { UAC_DP_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
        { 0 }
 };
-static struct procunit_value_info threed_enh_proc_info[] = {
+static const struct procunit_value_info threed_enh_proc_info[] = {
        { UAC_3D_ENABLE, "Switch", USB_MIXER_BOOLEAN },
        { UAC_3D_SPACE, "Spaciousness", USB_MIXER_U8 },
        { 0 }
 };
-static struct procunit_value_info reverb_proc_info[] = {
+static const struct procunit_value_info reverb_proc_info[] = {
        { UAC_REVERB_ENABLE, "Switch", USB_MIXER_BOOLEAN },
        { UAC_REVERB_LEVEL, "Level", USB_MIXER_U8 },
        { UAC_REVERB_TIME, "Time", USB_MIXER_U16 },
        { UAC_REVERB_FEEDBACK, "Feedback", USB_MIXER_U8 },
        { 0 }
 };
-static struct procunit_value_info chorus_proc_info[] = {
+static const struct procunit_value_info chorus_proc_info[] = {
        { UAC_CHORUS_ENABLE, "Switch", USB_MIXER_BOOLEAN },
        { UAC_CHORUS_LEVEL, "Level", USB_MIXER_U8 },
        { UAC_CHORUS_RATE, "Rate", USB_MIXER_U16 },
        { UAC_CHORUS_DEPTH, "Depth", USB_MIXER_U16 },
        { 0 }
 };
-static struct procunit_value_info dcr_proc_info[] = {
+static const struct procunit_value_info dcr_proc_info[] = {
        { UAC_DCR_ENABLE, "Switch", USB_MIXER_BOOLEAN },
        { UAC_DCR_RATE, "Ratio", USB_MIXER_U16 },
        { UAC_DCR_MAXAMPL, "Max Amp", USB_MIXER_S16 },
@@ -2253,7 +2253,7 @@ static struct procunit_value_info dcr_proc_info[] = {
        { 0 }
 };
 
-static struct procunit_info procunits[] = {
+static const struct procunit_info procunits[] = {
        { UAC_PROCESS_UP_DOWNMIX, "Up Down", updown_proc_info },
        { UAC_PROCESS_DOLBY_PROLOGIC, "Dolby Prologic", prologic_proc_info },
        { UAC_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", threed_enh_proc_info },
@@ -2263,16 +2263,16 @@ static struct procunit_info procunits[] = {
        { 0 },
 };
 
-static struct procunit_value_info uac3_updown_proc_info[] = {
+static const struct procunit_value_info uac3_updown_proc_info[] = {
        { UAC3_UD_MODE_SELECT, "Mode Select", USB_MIXER_U8, 1 },
        { 0 }
 };
-static struct procunit_value_info uac3_stereo_ext_proc_info[] = {
+static const struct procunit_value_info uac3_stereo_ext_proc_info[] = {
        { UAC3_EXT_WIDTH_CONTROL, "Width Control", USB_MIXER_U8 },
        { 0 }
 };
 
-static struct procunit_info uac3_procunits[] = {
+static const struct procunit_info uac3_procunits[] = {
        { UAC3_PROCESS_UP_DOWNMIX, "Up Down", uac3_updown_proc_info },
        { UAC3_PROCESS_STEREO_EXTENDER, "3D Stereo Extender", uac3_stereo_ext_proc_info },
        { UAC3_PROCESS_MULTI_FUNCTION, "Multi-Function", undefined_proc_info },
@@ -2282,23 +2282,23 @@ static struct procunit_info uac3_procunits[] = {
 /*
  * predefined data for extension units
  */
-static struct procunit_value_info clock_rate_xu_info[] = {
+static const struct procunit_value_info clock_rate_xu_info[] = {
        { USB_XU_CLOCK_RATE_SELECTOR, "Selector", USB_MIXER_U8, 0 },
        { 0 }
 };
-static struct procunit_value_info clock_source_xu_info[] = {
+static const struct procunit_value_info clock_source_xu_info[] = {
        { USB_XU_CLOCK_SOURCE_SELECTOR, "External", USB_MIXER_BOOLEAN },
        { 0 }
 };
-static struct procunit_value_info spdif_format_xu_info[] = {
+static const struct procunit_value_info spdif_format_xu_info[] = {
        { USB_XU_DIGITAL_FORMAT_SELECTOR, "SPDIF/AC3", USB_MIXER_BOOLEAN },
        { 0 }
 };
-static struct procunit_value_info soft_limit_xu_info[] = {
+static const struct procunit_value_info soft_limit_xu_info[] = {
        { USB_XU_SOFT_LIMIT_SELECTOR, " ", USB_MIXER_BOOLEAN },
        { 0 }
 };
-static struct procunit_info extunits[] = {
+static const struct procunit_info extunits[] = {
        { USB_XU_CLOCK_RATE, "Clock rate", clock_rate_xu_info },
        { USB_XU_CLOCK_SOURCE, "DigitalIn CLK source", clock_source_xu_info },
        { USB_XU_DIGITAL_IO_STATUS, "DigitalOut format:", spdif_format_xu_info },
@@ -2310,7 +2310,7 @@ static struct procunit_info extunits[] = {
  * build a processing/extension unit
  */
 static int build_audio_procunit(struct mixer_build *state, int unitid,
-                               void *raw_desc, struct procunit_info *list,
+                               void *raw_desc, const struct procunit_info *list,
                                bool extension_unit)
 {
        struct uac_processing_unit_descriptor *desc = raw_desc;
@@ -2318,14 +2318,14 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
        struct usb_mixer_elem_info *cval;
        struct snd_kcontrol *kctl;
        int i, err, nameid, type, len;
-       struct procunit_info *info;
-       struct procunit_value_info *valinfo;
+       const struct procunit_info *info;
+       const struct procunit_value_info *valinfo;
        const struct usbmix_name_map *map;
-       static struct procunit_value_info default_value_info[] = {
+       static const struct procunit_value_info default_value_info[] = {
                { 0x01, "Switch", USB_MIXER_BOOLEAN },
                { 0 }
        };
-       static struct procunit_info default_info = {
+       static const struct procunit_info default_info = {
                0, NULL, default_value_info
        };
        const char *name = extension_unit ?
@@ -2803,7 +2803,7 @@ struct uac3_badd_profile {
        int st_chmask;  /* side tone mixing channel mask */
 };
 
-static struct uac3_badd_profile uac3_badd_profiles[] = {
+static const struct uac3_badd_profile uac3_badd_profiles[] = {
        {
                /*
                 * BAIF, BAOF or combination of both
@@ -2864,7 +2864,7 @@ static struct uac3_badd_profile uac3_badd_profiles[] = {
 };
 
 static bool uac3_badd_func_has_valid_channels(struct usb_mixer_interface *mixer,
-                                             struct uac3_badd_profile *f,
+                                             const struct uac3_badd_profile *f,
                                              int c_chmask, int p_chmask)
 {
        /*
@@ -2908,7 +2908,7 @@ static int snd_usb_mixer_controls_badd(struct usb_mixer_interface *mixer,
        struct usb_device *dev = mixer->chip->dev;
        struct usb_interface_assoc_descriptor *assoc;
        int badd_profile = mixer->chip->badd_profile;
-       struct uac3_badd_profile *f;
+       const struct uac3_badd_profile *f;
        const struct usbmix_ctl_map *map;
        int p_chmask = 0, c_chmask = 0, st_chmask = 0;
        int i;
@@ -3174,7 +3174,7 @@ static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer,
                                    struct usb_mixer_elem_list *list)
 {
        struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
-       static char *val_types[] = {"BOOLEAN", "INV_BOOLEAN",
+       static const char * const val_types[] = {"BOOLEAN", "INV_BOOLEAN",
                                    "S8", "U8", "S16", "U16"};
        snd_iprintf(buffer, "    Info: id=%i, control=%i, cmask=0x%x, "
                            "channels=%i, type=\"%s\"\n", cval->head.id,
@@ -3407,7 +3407,7 @@ static int create_keep_iface_ctl(struct usb_mixer_interface *mixer)
 int snd_usb_create_mixer(struct snd_usb_audio *chip, int ctrlif,
                         int ignore_error)
 {
-       static struct snd_device_ops dev_ops = {
+       static const struct snd_device_ops dev_ops = {
                .dev_free = snd_usb_mixer_dev_free
        };
        struct usb_mixer_interface *mixer;
index 37e1b23..65d6d08 100644 (file)
@@ -116,6 +116,6 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
 
 extern void snd_usb_mixer_elem_free(struct snd_kcontrol *kctl);
 
-extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+extern const struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
 
 #endif /* __USBMIXER_H */
index 73baf39..5ebca80 100644 (file)
@@ -14,7 +14,7 @@ struct usbmix_name_map {
        int id;
        const char *name;
        int control;
-       struct usbmix_dB_map *dB;
+       const struct usbmix_dB_map *dB;
 };
 
 struct usbmix_selector_map {
@@ -52,7 +52,7 @@ Mic-IN[9] --+->FU[10]----------------------------+                  |
            ++--+->SU[11]-->FU[12] --------------------------------------------------------------------------------------> USB_OUT[13]
 */
 
-static struct usbmix_name_map extigy_map[] = {
+static const struct usbmix_name_map extigy_map[] = {
        /* 1: IT pcm */
        { 2, "PCM Playback" }, /* FU */
        /* 3: IT pcm */
@@ -93,12 +93,12 @@ static struct usbmix_name_map extigy_map[] = {
  * e.g. no Master and fake PCM volume
  *                     Pavel Mihaylov <bin@bash.info>
  */
-static struct usbmix_dB_map mp3plus_dB_1 = {.min = -4781, .max = 0};
+static const struct usbmix_dB_map mp3plus_dB_1 = {.min = -4781, .max = 0};
                                                /* just guess */
-static struct usbmix_dB_map mp3plus_dB_2 = {.min = -1781, .max = 618};
+static const struct usbmix_dB_map mp3plus_dB_2 = {.min = -1781, .max = 618};
                                                /* just guess */
 
-static struct usbmix_name_map mp3plus_map[] = {
+static const struct usbmix_name_map mp3plus_map[] = {
        /* 1: IT pcm */
        /* 2: IT mic */
        /* 3: IT line */
@@ -139,7 +139,7 @@ Lin_IN[7]-+--->FU[8]---+              +->EU[23]->FU[28]------------->Spk_OUT[19]
             |                                              ^
             +->FU[13]--------------------------------------+
 */
-static struct usbmix_name_map audigy2nx_map[] = {
+static const struct usbmix_name_map audigy2nx_map[] = {
        /* 1: IT pcm playback */
        /* 4: IT digital in */
        { 6, "Digital In Playback" }, /* FU */
@@ -167,12 +167,12 @@ static struct usbmix_name_map audigy2nx_map[] = {
        { 0 } /* terminator */
 };
 
-static struct usbmix_name_map mbox1_map[] = {
+static const struct usbmix_name_map mbox1_map[] = {
        { 1, "Clock" },
        { 0 } /* terminator */
 };
 
-static struct usbmix_selector_map c400_selectors[] = {
+static const struct usbmix_selector_map c400_selectors[] = {
        {
                .id = 0x80,
                .count = 2,
@@ -181,7 +181,7 @@ static struct usbmix_selector_map c400_selectors[] = {
        { 0 } /* terminator */
 };
 
-static struct usbmix_selector_map audigy2nx_selectors[] = {
+static const struct usbmix_selector_map audigy2nx_selectors[] = {
        {
                .id = 14, /* Capture Source */
                .count = 3,
@@ -201,21 +201,21 @@ static struct usbmix_selector_map audigy2nx_selectors[] = {
 };
 
 /* Creative SoundBlaster Live! 24-bit External */
-static struct usbmix_name_map live24ext_map[] = {
+static const struct usbmix_name_map live24ext_map[] = {
        /* 2: PCM Playback Volume */
        { 5, "Mic Capture" }, /* FU, default PCM Capture Volume */
        { 0 } /* terminator */
 };
 
 /* LineX FM Transmitter entry - needed to bypass controls bug */
-static struct usbmix_name_map linex_map[] = {
+static const struct usbmix_name_map linex_map[] = {
        /* 1: IT pcm */
        /* 2: OT Speaker */ 
        { 3, "Master" }, /* FU: master volume - left / right / mute */
        { 0 } /* terminator */
 };
 
-static struct usbmix_name_map maya44_map[] = {
+static const struct usbmix_name_map maya44_map[] = {
        /* 1: IT line */
        { 2, "Line Playback" }, /* FU */
        /* 3: IT line */
@@ -238,7 +238,7 @@ static struct usbmix_name_map maya44_map[] = {
  * so this map removes all unwanted sliders from alsamixer
  */
 
-static struct usbmix_name_map justlink_map[] = {
+static const struct usbmix_name_map justlink_map[] = {
        /* 1: IT pcm playback */
        /* 2: Not present */
        { 3, NULL}, /* IT mic (No mic input on device) */
@@ -255,7 +255,7 @@ static struct usbmix_name_map justlink_map[] = {
 };
 
 /* TerraTec Aureon 5.1 MkII USB */
-static struct usbmix_name_map aureon_51_2_map[] = {
+static const struct usbmix_name_map aureon_51_2_map[] = {
        /* 1: IT USB */
        /* 2: IT Mic */
        /* 3: IT Line */
@@ -274,7 +274,7 @@ static struct usbmix_name_map aureon_51_2_map[] = {
        {} /* terminator */
 };
 
-static struct usbmix_name_map scratch_live_map[] = {
+static const struct usbmix_name_map scratch_live_map[] = {
        /* 1: IT Line 1 (USB streaming) */
        /* 2: OT Line 1 (Speaker) */
        /* 3: IT Line 1 (Line connector) */
@@ -290,7 +290,7 @@ static struct usbmix_name_map scratch_live_map[] = {
        { 0 } /* terminator */
 };
 
-static struct usbmix_name_map ebox44_map[] = {
+static const struct usbmix_name_map ebox44_map[] = {
        { 4, NULL }, /* FU */
        { 6, NULL }, /* MU */
        { 7, NULL }, /* FU */
@@ -305,7 +305,7 @@ static struct usbmix_name_map ebox44_map[] = {
  *  FIXME: or mp3plus_map should use "Capture Source" too,
  *  so this maps can be merget
  */
-static struct usbmix_name_map hercules_usb51_map[] = {
+static const struct usbmix_name_map hercules_usb51_map[] = {
        { 8, "Capture Source" },        /* SU, default "PCM Capture Source" */
        { 9, "Master Playback" },       /* FU, default "Speaker Playback" */
        { 10, "Mic Boost", 7 },         /* FU, default "Auto Gain Input" */
@@ -316,7 +316,7 @@ static struct usbmix_name_map hercules_usb51_map[] = {
 };
 
 /* Plantronics Gamecom 780 has a broken volume control, better to disable it */
-static struct usbmix_name_map gamecom780_map[] = {
+static const struct usbmix_name_map gamecom780_map[] = {
        { 9, NULL }, /* FU, speaker out */
        {}
 };
@@ -330,8 +330,8 @@ static const struct usbmix_name_map scms_usb3318_map[] = {
 };
 
 /* Bose companion 5, the dB conversion factor is 16 instead of 256 */
-static struct usbmix_dB_map bose_companion5_dB = {-5006, -6};
-static struct usbmix_name_map bose_companion5_map[] = {
+static const struct usbmix_dB_map bose_companion5_dB = {-5006, -6};
+static const struct usbmix_name_map bose_companion5_map[] = {
        { 3, NULL, .dB = &bose_companion5_dB },
        { 0 }   /* terminator */
 };
@@ -350,10 +350,20 @@ static const struct usbmix_name_map dell_alc4020_map[] = {
 };
 
 /*
+ * Corsair Virtuoso calls everything "Headset" without this, leading to
+ * applications moving the sidetone control instead of the main one.
+ */
+static const struct usbmix_name_map corsair_virtuoso_map[] = {
+       { 3, "Mic Capture" },
+       { 6, "Sidetone Playback" },
+       { 0 }
+};
+
+/*
  * Control map entries
  */
 
-static struct usbmix_ctl_map usbmix_ctl_maps[] = {
+static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
        {
                .id = USB_ID(0x041e, 0x3000),
                .map = extigy_map,
@@ -468,6 +478,16 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x05a7, 0x1020),
                .map = bose_companion5_map,
        },
+       {
+               /* Corsair Virtuoso (wired mode) */
+               .id = USB_ID(0x1b1c, 0x0a41),
+               .map = corsair_virtuoso_map,
+       },
+       {
+               /* Corsair Virtuoso (wireless mode) */
+               .id = USB_ID(0x1b1c, 0x0a42),
+               .map = corsair_virtuoso_map,
+       },
        { 0 } /* terminator */
 };
 
@@ -475,37 +495,37 @@ static struct usbmix_ctl_map usbmix_ctl_maps[] = {
  * Control map entries for UAC3 BADD profiles
  */
 
-static struct usbmix_name_map uac3_badd_generic_io_map[] = {
+static const struct usbmix_name_map uac3_badd_generic_io_map[] = {
        { UAC3_BADD_FU_ID2, "Generic Out Playback" },
        { UAC3_BADD_FU_ID5, "Generic In Capture" },
        { 0 }                                   /* terminator */
 };
-static struct usbmix_name_map uac3_badd_headphone_map[] = {
+static const struct usbmix_name_map uac3_badd_headphone_map[] = {
        { UAC3_BADD_FU_ID2, "Headphone Playback" },
        { 0 }                                   /* terminator */
 };
-static struct usbmix_name_map uac3_badd_speaker_map[] = {
+static const struct usbmix_name_map uac3_badd_speaker_map[] = {
        { UAC3_BADD_FU_ID2, "Speaker Playback" },
        { 0 }                                   /* terminator */
 };
-static struct usbmix_name_map uac3_badd_microphone_map[] = {
+static const struct usbmix_name_map uac3_badd_microphone_map[] = {
        { UAC3_BADD_FU_ID5, "Mic Capture" },
        { 0 }                                   /* terminator */
 };
 /* Covers also 'headset adapter' profile */
-static struct usbmix_name_map uac3_badd_headset_map[] = {
+static const struct usbmix_name_map uac3_badd_headset_map[] = {
        { UAC3_BADD_FU_ID2, "Headset Playback" },
        { UAC3_BADD_FU_ID5, "Headset Capture" },
        { UAC3_BADD_FU_ID7, "Sidetone Mixing" },
        { 0 }                                   /* terminator */
 };
-static struct usbmix_name_map uac3_badd_speakerphone_map[] = {
+static const struct usbmix_name_map uac3_badd_speakerphone_map[] = {
        { UAC3_BADD_FU_ID2, "Speaker Playback" },
        { UAC3_BADD_FU_ID5, "Mic Capture" },
        { 0 }                                   /* terminator */
 };
 
-static struct usbmix_ctl_map uac3_badd_usbmix_ctl_maps[] = {
+static const struct usbmix_ctl_map uac3_badd_usbmix_ctl_maps[] = {
        {
                .id = UAC3_FUNCTION_SUBCLASS_GENERIC_IO,
                .map = uac3_badd_generic_io_map,
index 39e27ae..c237e24 100644 (file)
@@ -119,7 +119,7 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer,
  * Create a set of standard UAC controls from a table
  */
 static int snd_create_std_mono_table(struct usb_mixer_interface *mixer,
-                               struct std_mono_table *t)
+                                    const struct std_mono_table *t)
 {
        int err;
 
@@ -507,7 +507,7 @@ static int snd_emu0204_ch_switch_resume(struct usb_mixer_elem_list *list)
                                            list->kctl->private_value);
 }
 
-static struct snd_kcontrol_new snd_emu0204_control = {
+static const struct snd_kcontrol_new snd_emu0204_control = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Front Jack Channels",
        .info = snd_emu0204_ch_switch_info,
@@ -575,7 +575,7 @@ static int snd_xonar_u1_switch_resume(struct usb_mixer_elem_list *list)
                                          list->kctl->private_value);
 }
 
-static struct snd_kcontrol_new snd_xonar_u1_output_switch = {
+static const struct snd_kcontrol_new snd_xonar_u1_output_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Digital Playback Switch",
        .info = snd_ctl_boolean_mono_info,
@@ -702,7 +702,7 @@ static int snd_mbox1_switch_resume(struct usb_mixer_elem_list *list)
        return snd_mbox1_switch_update(list->mixer, list->kctl->private_value);
 }
 
-static struct snd_kcontrol_new snd_mbox1_switch = {
+static const struct snd_kcontrol_new snd_mbox1_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Clock Source",
        .index = 0,
@@ -787,7 +787,7 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
        return err < 0 ? err : 1;
 }
 
-static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
+static const struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
        {
                .name = "Direct Thru Channel A",
                .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
@@ -806,7 +806,7 @@ static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
        },
 };
 
-static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = {
+static const struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = {
        {
                .name = "Direct Thru Channel A",
                .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
@@ -1386,7 +1386,7 @@ static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
  * are valid they presents mono controls as L and R channels of
  * stereo. So we provide a good mixer here.
  */
-static struct std_mono_table ebox44_table[] = {
+static const struct std_mono_table ebox44_table[] = {
        {
                .unitid = 4,
                .control = 1,
@@ -1662,7 +1662,7 @@ static int snd_microii_spdif_switch_put(struct snd_kcontrol *kcontrol,
        return err < 0 ? err : 1;
 }
 
-static struct snd_kcontrol_new snd_microii_mixer_spdif[] = {
+static const struct snd_kcontrol_new snd_microii_mixer_spdif[] = {
        {
                .iface =    SNDRV_CTL_ELEM_IFACE_PCM,
                .name =     SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),
@@ -1691,7 +1691,7 @@ static struct snd_kcontrol_new snd_microii_mixer_spdif[] = {
 static int snd_microii_controls_create(struct usb_mixer_interface *mixer)
 {
        int err, i;
-       static usb_mixer_elem_resume_func_t resume_funcs[] = {
+       static const usb_mixer_elem_resume_func_t resume_funcs[] = {
                snd_microii_spdif_default_update,
                NULL,
                snd_microii_spdif_switch_update
@@ -1769,7 +1769,7 @@ static int snd_soundblaster_e1_switch_info(struct snd_kcontrol *kcontrol,
        return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
 }
 
-static struct snd_kcontrol_new snd_soundblaster_e1_input_switch = {
+static const struct snd_kcontrol_new snd_soundblaster_e1_input_switch = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .name = "Input Source",
        .info = snd_soundblaster_e1_switch_info,
@@ -2093,7 +2093,7 @@ static int snd_rme_sync_source_info(struct snd_kcontrol *kcontrol,
                                 ARRAY_SIZE(sync_sources), sync_sources);
 }
 
-static struct snd_kcontrol_new snd_rme_controls[] = {
+static const struct snd_kcontrol_new snd_rme_controls[] = {
        {
                .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
                .name = "AES Rate",
index 9d10cbf..49fcd25 100644 (file)
@@ -633,7 +633,7 @@ static int add_output_ctls(struct usb_mixer_interface *mixer,
 /********************** device-specific config *************************/
 
 /*  untested...  */
-static struct scarlett_device_info s6i6_info = {
+static const struct scarlett_device_info s6i6_info = {
        .matrix_in = 18,
        .matrix_out = 8,
        .input_len = 6,
@@ -675,7 +675,7 @@ static struct scarlett_device_info s6i6_info = {
 };
 
 /*  untested...  */
-static struct scarlett_device_info s8i6_info = {
+static const struct scarlett_device_info s8i6_info = {
        .matrix_in = 18,
        .matrix_out = 6,
        .input_len = 8,
@@ -714,7 +714,7 @@ static struct scarlett_device_info s8i6_info = {
        }
 };
 
-static struct scarlett_device_info s18i6_info = {
+static const struct scarlett_device_info s18i6_info = {
        .matrix_in = 18,
        .matrix_out = 6,
        .input_len = 18,
@@ -751,7 +751,7 @@ static struct scarlett_device_info s18i6_info = {
        }
 };
 
-static struct scarlett_device_info s18i8_info = {
+static const struct scarlett_device_info s18i8_info = {
        .matrix_in = 18,
        .matrix_out = 8,
        .input_len = 18,
@@ -793,7 +793,7 @@ static struct scarlett_device_info s18i8_info = {
        }
 };
 
-static struct scarlett_device_info s18i20_info = {
+static const struct scarlett_device_info s18i20_info = {
        .matrix_in = 18,
        .matrix_out = 8,
        .input_len = 18,
@@ -843,7 +843,7 @@ static struct scarlett_device_info s18i20_info = {
 
 
 static int scarlett_controls_create_generic(struct usb_mixer_interface *mixer,
-       struct scarlett_device_info *info)
+       const struct scarlett_device_info *info)
 {
        int i, err;
        char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
@@ -915,7 +915,7 @@ int snd_scarlett_controls_create(struct usb_mixer_interface *mixer)
 {
        int err, i, o;
        char mx[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
-       struct scarlett_device_info *info;
+       const struct scarlett_device_info *info;
        struct usb_mixer_elem_info *elem;
        static char sample_rate_buffer[4] = { '\x80', '\xbb', '\x00', '\x00' };
 
index 94b903d..74c00c9 100644 (file)
@@ -558,11 +558,11 @@ static const struct scarlett2_config
 
 /* proprietary request/response format */
 struct scarlett2_usb_packet {
-       u32 cmd;
-       u16 size;
-       u16 seq;
-       u32 error;
-       u32 pad;
+       __le32 cmd;
+       __le16 size;
+       __le16 seq;
+       __le32 error;
+       __le32 pad;
        u8 data[];
 };
 
@@ -664,11 +664,11 @@ static int scarlett2_usb(
                        "Scarlett Gen 2 USB invalid response; "
                           "cmd tx/rx %d/%d seq %d/%d size %d/%d "
                           "error %d pad %d\n",
-                       le16_to_cpu(req->cmd), le16_to_cpu(resp->cmd),
+                       le32_to_cpu(req->cmd), le32_to_cpu(resp->cmd),
                        le16_to_cpu(req->seq), le16_to_cpu(resp->seq),
                        resp_size, le16_to_cpu(resp->size),
-                       le16_to_cpu(resp->error),
-                       le16_to_cpu(resp->pad));
+                       le32_to_cpu(resp->error),
+                       le32_to_cpu(resp->pad));
                err = -EINVAL;
                goto unlock;
        }
@@ -687,7 +687,7 @@ error:
 /* Send SCARLETT2_USB_DATA_CMD SCARLETT2_USB_CONFIG_SAVE */
 static void scarlett2_config_save(struct usb_mixer_interface *mixer)
 {
-       u32 req = cpu_to_le32(SCARLETT2_USB_CONFIG_SAVE);
+       __le32 req = cpu_to_le32(SCARLETT2_USB_CONFIG_SAVE);
 
        scarlett2_usb(mixer, SCARLETT2_USB_DATA_CMD,
                      &req, sizeof(u32),
@@ -713,11 +713,11 @@ static int scarlett2_usb_set_config(
        const struct scarlett2_config config_item =
               scarlett2_config_items[config_item_num];
        struct {
-               u32 offset;
-               u32 bytes;
-               s32 value;
+               __le32 offset;
+               __le32 bytes;
+               __le32 value;
        } __packed req;
-       u32 req2;
+       __le32 req2;
        int err;
        struct scarlett2_mixer_data *private = mixer->private_data;
 
@@ -753,8 +753,8 @@ static int scarlett2_usb_get(
        int offset, void *buf, int size)
 {
        struct {
-               u32 offset;
-               u32 size;
+               __le32 offset;
+               __le32 size;
        } __packed req;
 
        req.offset = cpu_to_le32(offset);
@@ -794,8 +794,8 @@ static int scarlett2_usb_set_mix(struct usb_mixer_interface *mixer,
        const struct scarlett2_device_info *info = private->info;
 
        struct {
-               u16 mix_num;
-               u16 data[SCARLETT2_INPUT_MIX_MAX];
+               __le16 mix_num;
+               __le16 data[SCARLETT2_INPUT_MIX_MAX];
        } __packed req;
 
        int i, j;
@@ -850,9 +850,9 @@ static int scarlett2_usb_set_mux(struct usb_mixer_interface *mixer)
        };
 
        struct {
-               u16 pad;
-               u16 num;
-               u32 data[SCARLETT2_MUX_MAX];
+               __le16 pad;
+               __le16 num;
+               __le32 data[SCARLETT2_MUX_MAX];
        } __packed req;
 
        req.pad = 0;
@@ -911,9 +911,9 @@ static int scarlett2_usb_get_meter_levels(struct usb_mixer_interface *mixer,
                                          u16 *levels)
 {
        struct {
-               u16 pad;
-               u16 num_meters;
-               u32 magic;
+               __le16 pad;
+               __le16 num_meters;
+               __le32 magic;
        } __packed req;
        u32 resp[SCARLETT2_NUM_METERS];
        int i, err;
index f0e8e15..986145f 100644 (file)
@@ -760,7 +760,7 @@ static int snd_us16x08_meter_put(struct snd_kcontrol *kcontrol,
        return 1;
 }
 
-static struct snd_kcontrol_new snd_us16x08_ch_boolean_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_ch_boolean_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -770,7 +770,7 @@ static struct snd_kcontrol_new snd_us16x08_ch_boolean_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
 };
 
-static struct snd_kcontrol_new snd_us16x08_ch_int_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_ch_int_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -780,7 +780,7 @@ static struct snd_kcontrol_new snd_us16x08_ch_int_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
 };
 
-static struct snd_kcontrol_new snd_us16x08_pan_int_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_pan_int_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -790,7 +790,7 @@ static struct snd_kcontrol_new snd_us16x08_pan_int_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 255)
 };
 
-static struct snd_kcontrol_new snd_us16x08_master_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_master_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 1,
@@ -800,7 +800,7 @@ static struct snd_kcontrol_new snd_us16x08_master_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_FADER_BIAS, 1, 0, 133)
 };
 
-static struct snd_kcontrol_new snd_us16x08_route_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_route_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 8,
@@ -810,7 +810,7 @@ static struct snd_kcontrol_new snd_us16x08_route_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 9)
 };
 
-static struct snd_kcontrol_new snd_us16x08_bus_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_bus_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 1,
@@ -820,7 +820,7 @@ static struct snd_kcontrol_new snd_us16x08_bus_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
 };
 
-static struct snd_kcontrol_new snd_us16x08_compswitch_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_compswitch_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -830,7 +830,7 @@ static struct snd_kcontrol_new snd_us16x08_compswitch_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
 };
 
-static struct snd_kcontrol_new snd_us16x08_comp_threshold_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_comp_threshold_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -841,7 +841,7 @@ static struct snd_kcontrol_new snd_us16x08_comp_threshold_ctl = {
        0, 0x20)
 };
 
-static struct snd_kcontrol_new snd_us16x08_comp_ratio_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_comp_ratio_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -852,7 +852,7 @@ static struct snd_kcontrol_new snd_us16x08_comp_ratio_ctl = {
        sizeof(ratio_map) - 1), /*max*/
 };
 
-static struct snd_kcontrol_new snd_us16x08_comp_gain_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_comp_gain_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -862,7 +862,7 @@ static struct snd_kcontrol_new snd_us16x08_comp_gain_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x14)
 };
 
-static struct snd_kcontrol_new snd_us16x08_comp_attack_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_comp_attack_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -873,7 +873,7 @@ static struct snd_kcontrol_new snd_us16x08_comp_attack_ctl = {
        SND_US16X08_KCSET(SND_US16X08_COMP_ATTACK_BIAS, 1, 0, 0xc6),
 };
 
-static struct snd_kcontrol_new snd_us16x08_comp_release_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_comp_release_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -884,7 +884,7 @@ static struct snd_kcontrol_new snd_us16x08_comp_release_ctl = {
        SND_US16X08_KCSET(SND_US16X08_COMP_RELEASE_BIAS, 1, 0, 0x63),
 };
 
-static struct snd_kcontrol_new snd_us16x08_eq_gain_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_eq_gain_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -894,7 +894,7 @@ static struct snd_kcontrol_new snd_us16x08_eq_gain_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 24),
 };
 
-static struct snd_kcontrol_new snd_us16x08_eq_low_freq_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_eq_low_freq_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -904,7 +904,7 @@ static struct snd_kcontrol_new snd_us16x08_eq_low_freq_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x1F),
 };
 
-static struct snd_kcontrol_new snd_us16x08_eq_mid_freq_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_eq_mid_freq_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -914,7 +914,7 @@ static struct snd_kcontrol_new snd_us16x08_eq_mid_freq_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x3F)
 };
 
-static struct snd_kcontrol_new snd_us16x08_eq_mid_width_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_eq_mid_width_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -924,7 +924,7 @@ static struct snd_kcontrol_new snd_us16x08_eq_mid_width_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 0x06)
 };
 
-static struct snd_kcontrol_new snd_us16x08_eq_high_freq_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_eq_high_freq_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -935,7 +935,7 @@ static struct snd_kcontrol_new snd_us16x08_eq_high_freq_ctl = {
        SND_US16X08_KCSET(SND_US16X08_EQ_HIGHFREQ_BIAS, 1, 0, 0x1F)
 };
 
-static struct snd_kcontrol_new snd_us16x08_eq_switch_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_eq_switch_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 16,
@@ -945,7 +945,7 @@ static struct snd_kcontrol_new snd_us16x08_eq_switch_ctl = {
        .private_value = SND_US16X08_KCSET(SND_US16X08_NO_BIAS, 1, 0, 1)
 };
 
-static struct snd_kcontrol_new snd_us16x08_meter_ctl = {
+static const struct snd_kcontrol_new snd_us16x08_meter_ctl = {
        .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
        .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
        .count = 1,
index 56ff16c..7b8583d 100644 (file)
@@ -108,7 +108,7 @@ struct snd_us16x08_meter_store {
 };
 
 struct snd_us16x08_control_params {
-       struct snd_kcontrol_new *kcontrol_new;
+       const struct snd_kcontrol_new *kcontrol_new;
        int control_id;
        int type;
        int num_channels;
index 9c8930b..bd258f1 100644 (file)
@@ -260,18 +260,31 @@ static int start_endpoints(struct snd_usb_substream *subs)
        return 0;
 }
 
-static void stop_endpoints(struct snd_usb_substream *subs, bool wait)
+static void sync_pending_stops(struct snd_usb_substream *subs)
+{
+       snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
+       snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
+}
+
+static void stop_endpoints(struct snd_usb_substream *subs)
 {
        if (test_and_clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags))
                snd_usb_endpoint_stop(subs->sync_endpoint);
 
        if (test_and_clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags))
                snd_usb_endpoint_stop(subs->data_endpoint);
+}
 
-       if (wait) {
-               snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
-               snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
+/* PCM sync_stop callback */
+static int snd_usb_pcm_sync_stop(struct snd_pcm_substream *substream)
+{
+       struct snd_usb_substream *subs = substream->runtime->private_data;
+
+       if (!snd_usb_lock_shutdown(subs->stream->chip)) {
+               sync_pending_stops(subs);
+               snd_usb_unlock_shutdown(subs->stream->chip);
        }
+       return 0;
 }
 
 static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
@@ -348,6 +361,10 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                ep = 0x84;
                ifnum = 0;
                goto add_sync_ep_from_ifnum;
+       case USB_ID(0x07fd, 0x0008): /* MOTU M Series */
+               ep = 0x81;
+               ifnum = 2;
+               goto add_sync_ep_from_ifnum;
        case USB_ID(0x0582, 0x01d8): /* BOSS Katana */
                /* BOSS Katana amplifiers do not need quirks */
                return 0;
@@ -370,7 +387,7 @@ static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
 add_sync_ep_from_ifnum:
        iface = usb_ifnum_to_if(dev, ifnum);
 
-       if (!iface || iface->num_altsetting == 0)
+       if (!iface || iface->num_altsetting < 2)
                return -EINVAL;
 
        alts = &iface->altsetting[1];
@@ -506,15 +523,15 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
        if (WARN_ON(!iface))
                return -EINVAL;
        alts = usb_altnum_to_altsetting(iface, fmt->altsetting);
-       altsd = get_iface_desc(alts);
-       if (WARN_ON(altsd->bAlternateSetting != fmt->altsetting))
+       if (WARN_ON(!alts))
                return -EINVAL;
+       altsd = get_iface_desc(alts);
 
-       if (fmt == subs->cur_audiofmt)
+       if (fmt == subs->cur_audiofmt && !subs->need_setup_fmt)
                return 0;
 
        /* close the old interface */
-       if (subs->interface >= 0 && subs->interface != fmt->iface) {
+       if (subs->interface >= 0 && (subs->interface != fmt->iface || subs->need_setup_fmt)) {
                if (!subs->stream->chip->keep_iface) {
                        err = usb_set_interface(subs->dev, subs->interface, 0);
                        if (err < 0) {
@@ -528,6 +545,9 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
                subs->altset_idx = 0;
        }
 
+       if (subs->need_setup_fmt)
+               subs->need_setup_fmt = false;
+
        /* set interface */
        if (iface->cur_altsetting != alts) {
                err = snd_usb_select_mode_quirk(subs, fmt);
@@ -697,7 +717,8 @@ static int configure_endpoint(struct snd_usb_substream *subs)
        int ret;
 
        /* format changed */
-       stop_endpoints(subs, true);
+       stop_endpoints(subs);
+       sync_pending_stops(subs);
        ret = snd_usb_endpoint_set_params(subs->data_endpoint,
                                          subs->pcm_format,
                                          subs->channels,
@@ -785,11 +806,6 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
        if (ret)
                return ret;
 
-       ret = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-       if (ret < 0)
-               goto stop_pipeline;
-
        subs->pcm_format = params_format(hw_params);
        subs->period_bytes = params_period_bytes(hw_params);
        subs->period_frames = params_period_size(hw_params);
@@ -847,13 +863,14 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)
        subs->cur_rate = 0;
        subs->period_bytes = 0;
        if (!snd_usb_lock_shutdown(subs->stream->chip)) {
-               stop_endpoints(subs, true);
+               stop_endpoints(subs);
+               sync_pending_stops(subs);
                snd_usb_endpoint_deactivate(subs->sync_endpoint);
                snd_usb_endpoint_deactivate(subs->data_endpoint);
                snd_usb_unlock_shutdown(subs->stream->chip);
        }
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 /*
@@ -882,9 +899,6 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
                goto unlock;
        }
 
-       snd_usb_endpoint_sync_pending_stop(subs->sync_endpoint);
-       snd_usb_endpoint_sync_pending_stop(subs->data_endpoint);
-
        ret = snd_usb_pcm_change_state(subs, UAC3_PD_STATE_D0);
        if (ret < 0)
                goto unlock;
@@ -1342,7 +1356,6 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream)
        struct snd_usb_substream *subs = &as->substream[direction];
        int ret;
 
-       stop_endpoints(subs, true);
        snd_media_stop_pipeline(subs);
 
        if (!as->chip->keep_iface &&
@@ -1719,7 +1732,7 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
                subs->running = 1;
                return 0;
        case SNDRV_PCM_TRIGGER_STOP:
-               stop_endpoints(subs, false);
+               stop_endpoints(subs);
                subs->running = 0;
                return 0;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -1728,6 +1741,13 @@ static int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substrea
                subs->data_endpoint->retire_data_urb = retire_playback_urb;
                subs->running = 0;
                return 0;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               if (subs->stream->chip->setup_fmt_after_resume_quirk) {
+                       stop_endpoints(subs);
+                       subs->need_setup_fmt = true;
+                       return 0;
+               }
+               break;
        }
 
        return -EINVAL;
@@ -1749,7 +1769,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
                subs->running = 1;
                return 0;
        case SNDRV_PCM_TRIGGER_STOP:
-               stop_endpoints(subs, false);
+               stop_endpoints(subs);
                subs->running = 0;
                return 0;
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -1760,6 +1780,13 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
                subs->data_endpoint->retire_data_urb = retire_capture_urb;
                subs->running = 1;
                return 0;
+       case SNDRV_PCM_TRIGGER_SUSPEND:
+               if (subs->stream->chip->setup_fmt_after_resume_quirk) {
+                       stop_endpoints(subs);
+                       subs->need_setup_fmt = true;
+                       return 0;
+               }
+               break;
        }
 
        return -EINVAL;
@@ -1768,22 +1795,22 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 static const struct snd_pcm_ops snd_usb_playback_ops = {
        .open =         snd_usb_pcm_open,
        .close =        snd_usb_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_usb_hw_params,
        .hw_free =      snd_usb_hw_free,
        .prepare =      snd_usb_pcm_prepare,
        .trigger =      snd_usb_substream_playback_trigger,
+       .sync_stop =    snd_usb_pcm_sync_stop,
        .pointer =      snd_usb_pcm_pointer,
 };
 
 static const struct snd_pcm_ops snd_usb_capture_ops = {
        .open =         snd_usb_pcm_open,
        .close =        snd_usb_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_usb_hw_params,
        .hw_free =      snd_usb_hw_free,
        .prepare =      snd_usb_pcm_prepare,
        .trigger =      snd_usb_substream_capture_trigger,
+       .sync_stop =    snd_usb_pcm_sync_stop,
        .pointer =      snd_usb_pcm_pointer,
 };
 
@@ -1803,9 +1830,9 @@ void snd_usb_preallocate_buffer(struct snd_usb_substream *subs)
        struct device *dev = subs->dev->bus->controller;
 
        if (snd_usb_use_vmalloc)
-               snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_VMALLOC,
-                                             NULL, 0, 0);
+               snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_VMALLOC,
+                                          NULL, 0, 0);
        else
-               snd_pcm_lib_preallocate_pages(s, SNDRV_DMA_TYPE_DEV_SG,
-                                             dev, 64*1024, 512*1024);
+               snd_pcm_set_managed_buffer(s, SNDRV_DMA_TYPE_DEV_SG,
+                                          dev, 64*1024, 512*1024);
 }
index 49e3f17..ffbf4bd 100644 (file)
@@ -60,7 +60,7 @@ void snd_usb_audio_create_proc(struct snd_usb_audio *chip)
 static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct snd_info_buffer *buffer)
 {
        struct audioformat *fp;
-       static char *sync_types[4] = {
+       static const char * const sync_types[4] = {
                "NONE", "ASYNC", "ADAPTIVE", "SYNC"
        };
 
index 70c338f..d187aa6 100644 (file)
@@ -3466,7 +3466,8 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                .vendor_name = "Dell",
                .product_name = "WD19 Dock",
                .profile_name = "Dell-WD15-Dock",
-               .ifnum = QUIRK_NO_INTERFACE
+               .ifnum = QUIRK_ANY_INTERFACE,
+               .type = QUIRK_SETUP_FMT_AFTER_RESUME
        }
 },
 /* MOTU Microbook II */
index 349e1e5..3a5242e 100644 (file)
@@ -508,6 +508,16 @@ static int create_standard_mixer_quirk(struct snd_usb_audio *chip,
        return snd_usb_create_mixer(chip, quirk->ifnum, 0);
 }
 
+
+static int setup_fmt_after_resume_quirk(struct snd_usb_audio *chip,
+                                      struct usb_interface *iface,
+                                      struct usb_driver *driver,
+                                      const struct snd_usb_audio_quirk *quirk)
+{
+       chip->setup_fmt_after_resume_quirk = 1;
+       return 1;       /* Continue with creating streams and mixer */
+}
+
 /*
  * audio-interface quirks
  *
@@ -546,6 +556,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
                [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
                [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
                [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
+               [QUIRK_SETUP_FMT_AFTER_RESUME] = setup_fmt_after_resume_quirk,
        };
 
        if (quirk->type < QUIRK_TYPE_COUNT) {
@@ -1102,6 +1113,31 @@ free_buf:
        return err;
 }
 
+static int snd_usb_motu_m_series_boot_quirk(struct usb_device *dev)
+{
+       int ret;
+
+       if (snd_usb_pipe_sanity_check(dev, usb_sndctrlpipe(dev, 0)))
+               return -EINVAL;
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                             1, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0x0, 0, NULL, 0, 1000);
+
+       if (ret < 0)
+               return ret;
+
+       msleep(2000);
+
+       ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+                             1, USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                             0x20, 0, NULL, 0, 1000);
+
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
 /*
  * Setup quirks
  */
@@ -1286,6 +1322,19 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
        return 0;
 }
 
+int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
+                                 struct usb_interface *intf,
+                                 const struct snd_usb_audio_quirk *quirk,
+                                 unsigned int id)
+{
+       switch (id) {
+       case USB_ID(0x07fd, 0x0008): /* MOTU M Series */
+               return snd_usb_motu_m_series_boot_quirk(dev);
+       }
+
+       return 0;
+}
+
 /*
  * check if the device uses big-endian samples
  */
@@ -1382,21 +1431,22 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
 {
        /* devices which do not support reading the sample rate. */
        switch (chip->usb_id) {
-       case USB_ID(0x041E, 0x4080): /* Creative Live Cam VF0610 */
-       case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
+       case USB_ID(0x041e, 0x4080): /* Creative Live Cam VF0610 */
+       case USB_ID(0x04d8, 0xfeea): /* Benchmark DAC1 Pre */
        case USB_ID(0x0556, 0x0014): /* Phoenix Audio TMX320VC */
-       case USB_ID(0x05A3, 0x9420): /* ELP HD USB Camera */
-       case USB_ID(0x074D, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
+       case USB_ID(0x05a3, 0x9420): /* ELP HD USB Camera */
+       case USB_ID(0x05a7, 0x1020): /* Bose Companion 5 */
+       case USB_ID(0x074d, 0x3553): /* Outlaw RR2150 (Micronas UAC3553B) */
        case USB_ID(0x1395, 0x740a): /* Sennheiser DECT */
        case USB_ID(0x1901, 0x0191): /* GE B850V3 CP2114 audio interface */
-       case USB_ID(0x21B4, 0x0081): /* AudioQuest DragonFly */
+       case USB_ID(0x21b4, 0x0081): /* AudioQuest DragonFly */
                return true;
        }
 
        /* devices of these vendors don't support reading rate, either */
        switch (USB_ID_VENDOR(chip->usb_id)) {
-       case 0x045E: /* MS Lifecam */
-       case 0x047F: /* Plantronics */
+       case 0x045e: /* MS Lifecam */
+       case 0x047f: /* Plantronics */
        case 0x1de7: /* Phoenix Audio */
                return true;
        }
index a80e0dd..df03558 100644 (file)
@@ -20,6 +20,11 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
                             const struct snd_usb_audio_quirk *quirk,
                             unsigned int usb_id);
 
+int snd_usb_apply_boot_quirk_once(struct usb_device *dev,
+                                 struct usb_interface *intf,
+                                 const struct snd_usb_audio_quirk *quirk,
+                                 unsigned int usb_id);
+
 void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
                              struct audioformat *fmt);
 
index 11785f9..afd5aa5 100644 (file)
@@ -239,7 +239,7 @@ static int add_chmap(struct snd_pcm *pcm, int stream,
 static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
                                                int protocol)
 {
-       static unsigned int uac1_maps[] = {
+       static const unsigned int uac1_maps[] = {
                SNDRV_CHMAP_FL,         /* left front */
                SNDRV_CHMAP_FR,         /* right front */
                SNDRV_CHMAP_FC,         /* center front */
@@ -254,7 +254,7 @@ static struct snd_pcm_chmap_elem *convert_chmap(int channels, unsigned int bits,
                SNDRV_CHMAP_TC,         /* top */
                0 /* terminator */
        };
-       static unsigned int uac2_maps[] = {
+       static const unsigned int uac2_maps[] = {
                SNDRV_CHMAP_FL,         /* front left */
                SNDRV_CHMAP_FR,         /* front right */
                SNDRV_CHMAP_FC,         /* front center */
index ff3cbf6..6fe3ab5 100644 (file)
@@ -33,7 +33,7 @@ struct snd_usb_audio {
        wait_queue_head_t shutdown_wait;
        unsigned int txfr_quirk:1; /* Subframe boundaries on transfers */
        unsigned int tx_length_quirk:1; /* Put length specifier in transfers */
-       
+       unsigned int setup_fmt_after_resume_quirk:1; /* setup the format to interface after resume */
        int num_interfaces;
        int num_suspended_intf;
        int sample_rate_read_error;
@@ -98,6 +98,7 @@ enum quirk_type {
        QUIRK_AUDIO_EDIROL_UAXX,
        QUIRK_AUDIO_ALIGN_TRANSFER,
        QUIRK_AUDIO_STANDARD_MIXER,
+       QUIRK_SETUP_FMT_AFTER_RESUME,
 
        QUIRK_TYPE_COUNT
 };
index e82c523..f86f7a6 100644 (file)
@@ -40,13 +40,13 @@ static int snd_us122l_card_used[SNDRV_CARDS];
 
 static int us122l_create_usbmidi(struct snd_card *card)
 {
-       static struct snd_usb_midi_endpoint_info quirk_data = {
+       static const struct snd_usb_midi_endpoint_info quirk_data = {
                .out_ep = 4,
                .in_ep = 3,
                .out_cables =   0x001,
                .in_cables =    0x001
        };
-       static struct snd_usb_audio_quirk quirk = {
+       static const struct snd_usb_audio_quirk quirk = {
                .vendor_name =  "US122L",
                .product_name = NAME_ALLCAPS,
                .ifnum =        1,
@@ -62,13 +62,13 @@ static int us122l_create_usbmidi(struct snd_card *card)
 
 static int us144_create_usbmidi(struct snd_card *card)
 {
-       static struct snd_usb_midi_endpoint_info quirk_data = {
+       static const struct snd_usb_midi_endpoint_info quirk_data = {
                .out_ep = 4,
                .in_ep = 3,
                .out_cables =   0x001,
                .in_cables =    0x001
        };
-       static struct snd_usb_audio_quirk quirk = {
+       static const struct snd_usb_audio_quirk quirk = {
                .vendor_name =  "US144",
                .product_name = NAME_ALLCAPS,
                .ifnum =        0,
index d1caa8e..22412cd 100644 (file)
@@ -94,7 +94,7 @@ static __poll_t snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file, poll
 static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw,
                                      struct snd_hwdep_dsp_status *info)
 {
-       static char *type_ids[USX2Y_TYPE_NUMS] = {
+       static const char * const type_ids[USX2Y_TYPE_NUMS] = {
                [USX2Y_TYPE_122] = "us122",
                [USX2Y_TYPE_224] = "us224",
                [USX2Y_TYPE_428] = "us428",
@@ -119,33 +119,33 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw,
        info->num_dsps = 2;             // 0: Prepad Data, 1: FPGA Code
        if (us428->chip_status & USX2Y_STAT_CHIP_INIT)
                info->chip_ready = 1;
-       info->version = USX2Y_DRIVER_VERSION; 
+       info->version = USX2Y_DRIVER_VERSION;
        return 0;
 }
 
 
 static int usX2Y_create_usbmidi(struct snd_card *card)
 {
-       static struct snd_usb_midi_endpoint_info quirk_data_1 = {
+       static const struct snd_usb_midi_endpoint_info quirk_data_1 = {
                .out_ep = 0x06,
                .in_ep = 0x06,
                .out_cables =   0x001,
                .in_cables =    0x001
        };
-       static struct snd_usb_audio_quirk quirk_1 = {
+       static const struct snd_usb_audio_quirk quirk_1 = {
                .vendor_name =  "TASCAM",
                .product_name = NAME_ALLCAPS,
                .ifnum =        0,
                        .type = QUIRK_MIDI_FIXED_ENDPOINT,
                .data = &quirk_data_1
        };
-       static struct snd_usb_midi_endpoint_info quirk_data_2 = {
+       static const struct snd_usb_midi_endpoint_info quirk_data_2 = {
                .out_ep = 0x06,
                .in_ep = 0x06,
                .out_cables =   0x003,
                .in_cables =    0x003
        };
-       static struct snd_usb_audio_quirk quirk_2 = {
+       static const struct snd_usb_audio_quirk quirk_2 = {
                .vendor_name =  "TASCAM",
                .product_name = "US428",
                .ifnum =        0,
@@ -154,7 +154,7 @@ static int usX2Y_create_usbmidi(struct snd_card *card)
        };
        struct usb_device *dev = usX2Y(card)->dev;
        struct usb_interface *iface = usb_ifnum_to_if(dev, 0);
-       struct snd_usb_audio_quirk *quirk =
+       const struct snd_usb_audio_quirk *quirk =
                le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ?
                &quirk_2 : &quirk_1;
 
index 25a0939..772f6f3 100644 (file)
@@ -549,7 +549,7 @@ static int snd_usX2Y_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
  * if sg buffer is supported on the later version of alsa, we'll follow
  * that.
  */
-static struct s_c2
+static const struct s_c2
 {
        char c1, c2;
 }
@@ -589,7 +589,7 @@ static struct s_c2
        { 0x18, 0x7C},
        { 0x18, 0x7E}
 };
-static struct s_c2 SetRate48000[] =
+static const struct s_c2 SetRate48000[] =
 {
        { 0x14, 0x09},  // this line sets 48000, well actually a little less
        { 0x18, 0x40},  // only tascam / frontier design knows the further lines .......
@@ -642,7 +642,7 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate)
        int                     err = 0, i;
        struct snd_usX2Y_urbSeq *us = NULL;
        int                     *usbdata = NULL;
-       struct s_c2             *ra = rate == 48000 ? SetRate48000 : SetRate44100;
+       const struct s_c2       *ra = rate == 48000 ? SetRate48000 : SetRate44100;
 
        if (usX2Y->rate != rate) {
                us = kzalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL);
@@ -764,14 +764,6 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream,
                }
        }
 
-       err = snd_pcm_lib_malloc_pages(substream,
-                                      params_buffer_bytes(hw_params));
-       if (err < 0) {
-               snd_printk(KERN_ERR "snd_pcm_lib_malloc_pages(%p, %i) returned %i\n",
-                          substream, params_buffer_bytes(hw_params), err);
-               goto error;
-       }
-
  error:
        mutex_unlock(&usX2Y(card)->pcm_mutex);
        return err;
@@ -806,7 +798,7 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream)
                }
        }
        mutex_unlock(&subs->usX2Y->pcm_mutex);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 /*
  * prepare callback
@@ -846,7 +838,7 @@ static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream)
        return err;
 }
 
-static struct snd_pcm_hardware snd_usX2Y_2c =
+static const struct snd_pcm_hardware snd_usX2Y_2c =
 {
        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -901,7 +893,6 @@ static const struct snd_pcm_ops snd_usX2Y_pcm_ops =
 {
        .open =         snd_usX2Y_pcm_open,
        .close =        snd_usX2Y_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_usX2Y_pcm_hw_params,
        .hw_free =      snd_usX2Y_pcm_hw_free,
        .prepare =      snd_usX2Y_pcm_prepare,
@@ -968,16 +959,16 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint,
        sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->pcm_devs);
 
        if (playback_endpoint) {
-               snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
-                                             SNDRV_DMA_TYPE_CONTINUOUS,
-                                             NULL,
-                                             64*1024, 128*1024);
+               snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+                                          SNDRV_DMA_TYPE_CONTINUOUS,
+                                          NULL,
+                                          64*1024, 128*1024);
        }
 
-       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
-                                     SNDRV_DMA_TYPE_CONTINUOUS,
-                                     NULL,
-                                     64*1024, 128*1024);
+       snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+                                  SNDRV_DMA_TYPE_CONTINUOUS,
+                                  NULL,
+                                  64*1024, 128*1024);
        usX2Y(card)->pcm_devs++;
 
        return 0;
index 997493e..8253669 100644 (file)
@@ -376,7 +376,7 @@ static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream)
                }
        }
        mutex_unlock(&subs->usX2Y->pcm_mutex);
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs)
@@ -528,7 +528,7 @@ static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream)
        return err;
 }
 
-static struct snd_pcm_hardware snd_usX2Y_4c =
+static const struct snd_pcm_hardware snd_usX2Y_4c =
 {
        .info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
                                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -581,7 +581,6 @@ static const struct snd_pcm_ops snd_usX2Y_usbpcm_ops =
 {
        .open =         snd_usX2Y_usbpcm_open,
        .close =        snd_usX2Y_usbpcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    snd_usX2Y_pcm_hw_params,
        .hw_free =      snd_usX2Y_usbpcm_hw_free,
        .prepare =      snd_usX2Y_usbpcm_prepare,
@@ -726,14 +725,14 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card)
        pcm->info_flags = 0;
 
        sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio");
-       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
-                                     SNDRV_DMA_TYPE_CONTINUOUS,
-                                     NULL,
-                                     64*1024, 128*1024);
-       snd_pcm_lib_preallocate_pages(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
-                                     SNDRV_DMA_TYPE_CONTINUOUS,
-                                     NULL,
-                                     64*1024, 128*1024);
+       snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream,
+                                  SNDRV_DMA_TYPE_CONTINUOUS,
+                                  NULL,
+                                  64*1024, 128*1024);
+       snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream,
+                                  SNDRV_DMA_TYPE_CONTINUOUS,
+                                  NULL,
+                                  64*1024, 128*1024);
 
        return 0;
 }
index 36ae78c..6fe206f 100644 (file)
@@ -110,7 +110,7 @@ static bool validate_processing_unit(const void *p,
        default:
                if (v->type == UAC1_EXTENSION_UNIT)
                        return true; /* OK */
-               switch (d->wProcessType) {
+               switch (le16_to_cpu(d->wProcessType)) {
                case UAC_PROCESS_UP_DOWNMIX:
                case UAC_PROCESS_DOLBY_PROLOGIC:
                        if (d->bLength < len + 1) /* bNrModes */
@@ -125,7 +125,7 @@ static bool validate_processing_unit(const void *p,
        case UAC_VERSION_2:
                if (v->type == UAC2_EXTENSION_UNIT_V2)
                        return true; /* OK */
-               switch (d->wProcessType) {
+               switch (le16_to_cpu(d->wProcessType)) {
                case UAC2_PROCESS_UP_DOWNMIX:
                case UAC2_PROCESS_DOLBY_PROLOCIC: /* SiC! */
                        if (d->bLength < len + 1) /* bNrModes */
@@ -142,7 +142,7 @@ static bool validate_processing_unit(const void *p,
                        len += 2; /* wClusterDescrID */
                        break;
                }
-               switch (d->wProcessType) {
+               switch (le16_to_cpu(d->wProcessType)) {
                case UAC3_PROCESS_UP_DOWNMIX:
                        if (d->bLength < len + 1) /* bNrModes */
                                return false;
@@ -233,7 +233,7 @@ static bool validate_midi_out_jack(const void *p,
 #define FIXED(p, t, s) { .protocol = (p), .type = (t), .size = sizeof(s) }
 #define FUNC(p, t, f) { .protocol = (p), .type = (t), .func = (f) }
 
-static struct usb_desc_validator audio_validators[] = {
+static const struct usb_desc_validator audio_validators[] = {
        /* UAC1 */
        FUNC(UAC_VERSION_1, UAC_HEADER, validate_uac1_header),
        FIXED(UAC_VERSION_1, UAC_INPUT_TERMINAL,
@@ -288,7 +288,7 @@ static struct usb_desc_validator audio_validators[] = {
        { } /* terminator */
 };
 
-static struct usb_desc_validator midi_validators[] = {
+static const struct usb_desc_validator midi_validators[] = {
        FIXED(UAC_VERSION_ALL, USB_MS_HEADER,
              struct usb_ms_header_descriptor),
        FIXED(UAC_VERSION_ALL, USB_MS_MIDI_IN_JACK,
index cd389d2..741cf61 100644 (file)
@@ -1132,16 +1132,13 @@ static int had_pcm_hw_params(struct snd_pcm_substream *substream,
                             struct snd_pcm_hw_params *hw_params)
 {
        struct snd_intelhad *intelhaddata;
-       int buf_size, retval;
+       int buf_size;
 
        intelhaddata = snd_pcm_substream_chip(substream);
        buf_size = params_buffer_bytes(hw_params);
-       retval = snd_pcm_lib_malloc_pages(substream, buf_size);
-       if (retval < 0)
-               return retval;
        dev_dbg(intelhaddata->dev, "%s:allocated memory = %d\n",
                __func__, buf_size);
-       return retval;
+       return 0;
 }
 
 /*
@@ -1154,7 +1151,7 @@ static int had_pcm_hw_free(struct snd_pcm_substream *substream)
        intelhaddata = snd_pcm_substream_chip(substream);
        had_do_reset(intelhaddata);
 
-       return snd_pcm_lib_free_pages(substream);
+       return 0;
 }
 
 /*
@@ -1289,7 +1286,6 @@ static int had_pcm_mmap(struct snd_pcm_substream *substream,
 static const struct snd_pcm_ops had_pcm_ops = {
        .open =         had_pcm_open,
        .close =        had_pcm_close,
-       .ioctl =        snd_pcm_lib_ioctl,
        .hw_params =    had_pcm_hw_params,
        .hw_free =      had_pcm_hw_free,
        .prepare =      had_pcm_prepare,
@@ -1801,10 +1797,9 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev)
                /* allocate dma pages;
                 * try to allocate 600k buffer as default which is large enough
                 */
-               snd_pcm_lib_preallocate_pages_for_all(pcm,
-                                                     SNDRV_DMA_TYPE_DEV_UC,
-                                                     card->dev,
-                                                     HAD_DEFAULT_BUFFER, HAD_MAX_BUFFER);
+               snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_UC,
+                                              card->dev, HAD_DEFAULT_BUFFER,
+                                              HAD_MAX_BUFFER);
 
                /* create controls */
                for (i = 0; i < ARRAY_SIZE(had_controls); i++) {
index e016319..db91745 100644 (file)
@@ -692,7 +692,6 @@ static int alsa_pb_fill_silence(struct snd_pcm_substream *substream,
 static const struct snd_pcm_ops snd_drv_alsa_playback_ops = {
        .open           = alsa_open,
        .close          = alsa_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = alsa_hw_params,
        .hw_free        = alsa_hw_free,
        .prepare        = alsa_prepare,
@@ -706,7 +705,6 @@ static const struct snd_pcm_ops snd_drv_alsa_playback_ops = {
 static const struct snd_pcm_ops snd_drv_alsa_capture_ops = {
        .open           = alsa_open,
        .close          = alsa_close,
-       .ioctl          = snd_pcm_lib_ioctl,
        .hw_params      = alsa_hw_params,
        .hw_free        = alsa_hw_free,
        .prepare        = alsa_prepare,
index 2769360..03cd7c1 100644 (file)
@@ -131,8 +131,9 @@ struct kvm_vcpu_events {
        struct {
                __u8 serror_pending;
                __u8 serror_has_esr;
+               __u8 ext_dabt_pending;
                /* Align it to 8 bytes */
-               __u8 pad[6];
+               __u8 pad[5];
                __u64 serror_esr;
        } exception;
        __u32 reserved[12];
index 67c21f9..820e575 100644 (file)
@@ -164,8 +164,9 @@ struct kvm_vcpu_events {
        struct {
                __u8 serror_pending;
                __u8 serror_has_esr;
+               __u8 ext_dabt_pending;
                /* Align it to 8 bytes */
-               __u8 pad[6];
+               __u8 pad[5];
                __u64 serror_esr;
        } exception;
        __u32 reserved[12];
@@ -323,6 +324,8 @@ struct kvm_vcpu_events {
 #define KVM_ARM_VCPU_TIMER_CTRL                1
 #define   KVM_ARM_VCPU_TIMER_IRQ_VTIMER                0
 #define   KVM_ARM_VCPU_TIMER_IRQ_PTIMER                1
+#define KVM_ARM_VCPU_PVTIME_CTRL       2
+#define   KVM_ARM_VCPU_PVTIME_IPA      0
 
 /* KVM_IRQ_LINE irq field index values */
 #define KVM_ARM_IRQ_VCPU2_SHIFT                28
index b0f72de..264e266 100644 (file)
@@ -667,6 +667,8 @@ struct kvm_ppc_cpu_char {
 
 /* PPC64 eXternal Interrupt Controller Specification */
 #define KVM_DEV_XICS_GRP_SOURCES       1       /* 64-bit source attributes */
+#define KVM_DEV_XICS_GRP_CTRL          2
+#define   KVM_DEV_XICS_NR_SERVERS      1
 
 /* Layout of 64-bit source attribute values */
 #define  KVM_XICS_DESTINATION_SHIFT    0
@@ -683,6 +685,7 @@ struct kvm_ppc_cpu_char {
 #define KVM_DEV_XIVE_GRP_CTRL          1
 #define   KVM_DEV_XIVE_RESET           1
 #define   KVM_DEV_XIVE_EQ_SYNC         2
+#define   KVM_DEV_XIVE_NR_SERVERS      3
 #define KVM_DEV_XIVE_GRP_SOURCE                2       /* 64-bit source identifier */
 #define KVM_DEV_XIVE_GRP_SOURCE_CONFIG 3       /* 64-bit source identifier */
 #define KVM_DEV_XIVE_GRP_EQ_CONFIG     4       /* 64-bit EQ identifier */
index 0652d3e..e9b6249 100644 (file)
 #define X86_FEATURE_CLZERO             (13*32+ 0) /* CLZERO instruction */
 #define X86_FEATURE_IRPERF             (13*32+ 1) /* Instructions Retired Count */
 #define X86_FEATURE_XSAVEERPTR         (13*32+ 2) /* Always save/restore FP error pointers */
+#define X86_FEATURE_RDPRU              (13*32+ 4) /* Read processor register at user level */
 #define X86_FEATURE_WBNOINVD           (13*32+ 9) /* WBNOINVD instruction */
 #define X86_FEATURE_AMD_IBPB           (13*32+12) /* "" Indirect Branch Prediction Barrier */
 #define X86_FEATURE_AMD_IBRS           (13*32+14) /* "" Indirect Branch Restricted Speculation */
 #define X86_BUG_MDS                    X86_BUG(19) /* CPU is affected by Microarchitectural data sampling */
 #define X86_BUG_MSBDS_ONLY             X86_BUG(20) /* CPU is only affected by the  MSDBS variant of BUG_MDS */
 #define X86_BUG_SWAPGS                 X86_BUG(21) /* CPU is affected by speculation through SWAPGS */
+#define X86_BUG_TAA                    X86_BUG(22) /* CPU is affected by TSX Async Abort(TAA) */
+#define X86_BUG_ITLB_MULTIHIT          X86_BUG(23) /* CPU may incur MCE during certain page attribute changes */
 
 #endif /* _ASM_X86_CPUFEATURES_H */
index 20ce682..084e98d 100644 (file)
                                                  * Microarchitectural Data
                                                  * Sampling (MDS) vulnerabilities.
                                                  */
+#define ARCH_CAP_PSCHANGE_MC_NO                BIT(6)   /*
+                                                 * The processor is not susceptible to a
+                                                 * machine check error due to modifying the
+                                                 * code page size along with either the
+                                                 * physical address or cache type
+                                                 * without TLB invalidation.
+                                                 */
+#define ARCH_CAP_TSX_CTRL_MSR          BIT(7)  /* MSR for TSX control is available. */
+#define ARCH_CAP_TAA_NO                        BIT(8)  /*
+                                                * Not susceptible to
+                                                * TSX Async Abort (TAA) vulnerabilities.
+                                                */
 
 #define MSR_IA32_FLUSH_CMD             0x0000010b
 #define L1D_FLUSH                      BIT(0)  /*
 #define MSR_IA32_BBL_CR_CTL            0x00000119
 #define MSR_IA32_BBL_CR_CTL3           0x0000011e
 
+#define MSR_IA32_TSX_CTRL              0x00000122
+#define TSX_CTRL_RTM_DISABLE           BIT(0)  /* Disable RTM feature */
+#define TSX_CTRL_CPUID_CLEAR           BIT(1)  /* Disable TSX enumeration */
+
 #define MSR_IA32_SYSENTER_CS           0x00000174
 #define MSR_IA32_SYSENTER_ESP          0x00000175
 #define MSR_IA32_SYSENTER_EIP          0x00000176
 #define MSR_AMD_PSTATE_DEF_BASE                0xc0010064
 #define MSR_AMD64_OSVW_ID_LENGTH       0xc0010140
 #define MSR_AMD64_OSVW_STATUS          0xc0010141
+#define MSR_AMD_PPIN_CTL               0xc00102f0
+#define MSR_AMD_PPIN                   0xc00102f1
 #define MSR_AMD64_LS_CFG               0xc0011020
 #define MSR_AMD64_DC_CFG               0xc0011022
 #define MSR_AMD64_BU_CFG2              0xc001102a
index 9274866..df767af 100644 (file)
@@ -28,8 +28,8 @@
  * Output:
  * rax original destination
  */
-ENTRY(__memcpy)
-ENTRY(memcpy)
+SYM_FUNC_START_ALIAS(__memcpy)
+SYM_FUNC_START_LOCAL(memcpy)
        ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
                      "jmp memcpy_erms", X86_FEATURE_ERMS
 
@@ -41,8 +41,8 @@ ENTRY(memcpy)
        movl %edx, %ecx
        rep movsb
        ret
-ENDPROC(memcpy)
-ENDPROC(__memcpy)
+SYM_FUNC_END(memcpy)
+SYM_FUNC_END_ALIAS(__memcpy)
 EXPORT_SYMBOL(memcpy)
 EXPORT_SYMBOL(__memcpy)
 
@@ -50,14 +50,14 @@ EXPORT_SYMBOL(__memcpy)
  * memcpy_erms() - enhanced fast string memcpy. This is faster and
  * simpler than memcpy. Use memcpy_erms when possible.
  */
-ENTRY(memcpy_erms)
+SYM_FUNC_START(memcpy_erms)
        movq %rdi, %rax
        movq %rdx, %rcx
        rep movsb
        ret
-ENDPROC(memcpy_erms)
+SYM_FUNC_END(memcpy_erms)
 
-ENTRY(memcpy_orig)
+SYM_FUNC_START(memcpy_orig)
        movq %rdi, %rax
 
        cmpq $0x20, %rdx
@@ -182,7 +182,7 @@ ENTRY(memcpy_orig)
 
 .Lend:
        retq
-ENDPROC(memcpy_orig)
+SYM_FUNC_END(memcpy_orig)
 
 #ifndef CONFIG_UML
 
@@ -193,7 +193,7 @@ MCSAFE_TEST_CTL
  * Note that we only catch machine checks when reading the source addresses.
  * Writes to target are posted and don't generate machine checks.
  */
-ENTRY(__memcpy_mcsafe)
+SYM_FUNC_START(__memcpy_mcsafe)
        cmpl $8, %edx
        /* Less than 8 bytes? Go to byte copy loop */
        jb .L_no_whole_words
@@ -260,7 +260,7 @@ ENTRY(__memcpy_mcsafe)
        xorl %eax, %eax
 .L_done:
        ret
-ENDPROC(__memcpy_mcsafe)
+SYM_FUNC_END(__memcpy_mcsafe)
 EXPORT_SYMBOL_GPL(__memcpy_mcsafe)
 
        .section .fixup, "ax"
index f8f3dc0..fd5d25a 100644 (file)
@@ -18,8 +18,8 @@
  *
  * rax   original destination
  */
-ENTRY(memset)
-ENTRY(__memset)
+SYM_FUNC_START_ALIAS(memset)
+SYM_FUNC_START(__memset)
        /*
         * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
         * to use it when possible. If not available, use fast string instructions.
@@ -42,8 +42,8 @@ ENTRY(__memset)
        rep stosb
        movq %r9,%rax
        ret
-ENDPROC(memset)
-ENDPROC(__memset)
+SYM_FUNC_END(__memset)
+SYM_FUNC_END_ALIAS(memset)
 
 /*
  * ISO C memset - set a memory block to a byte value. This function uses
@@ -56,16 +56,16 @@ ENDPROC(__memset)
  *
  * rax   original destination
  */
-ENTRY(memset_erms)
+SYM_FUNC_START(memset_erms)
        movq %rdi,%r9
        movb %sil,%al
        movq %rdx,%rcx
        rep stosb
        movq %r9,%rax
        ret
-ENDPROC(memset_erms)
+SYM_FUNC_END(memset_erms)
 
-ENTRY(memset_orig)
+SYM_FUNC_START(memset_orig)
        movq %rdi,%r10
 
        /* expand byte value  */
@@ -136,4 +136,4 @@ ENTRY(memset_orig)
        subq %r8,%rdx
        jmp .Lafter_bad_alignment
 .Lfinal:
-ENDPROC(memset_orig)
+SYM_FUNC_END(memset_orig)
index d66131f..397e571 100644 (file)
@@ -26,7 +26,7 @@ static void btf_dumper_ptr(const void *data, json_writer_t *jw,
                           bool is_plain_text)
 {
        if (is_plain_text)
-               jsonw_printf(jw, "%p", data);
+               jsonw_printf(jw, "%p", *(void **)data);
        else
                jsonw_printf(jw, "%lu", *(unsigned long *)data);
 }
index 4535c86..2ce9c5b 100644 (file)
@@ -493,7 +493,7 @@ static int do_dump(int argc, char **argv)
 
        info = &info_linear->info;
        if (mode == DUMP_JITED) {
-               if (info->jited_prog_len == 0) {
+               if (info->jited_prog_len == 0 || !info->jited_prog_insns) {
                        p_info("no instructions returned");
                        goto err_free;
                }
index 494d7ae..5b91ee6 100644 (file)
@@ -174,7 +174,7 @@ static const char *print_call(void *private_data,
        struct kernel_sym *sym;
 
        if (insn->src_reg == BPF_PSEUDO_CALL &&
-           (__u32) insn->imm < dd->nr_jited_ksyms)
+           (__u32) insn->imm < dd->nr_jited_ksyms && dd->jited_ksyms)
                address = dd->jited_ksyms[insn->imm];
 
        sym = kernel_syms_search(dd, address);
index 8a5b2f8..868bf79 100644 (file)
@@ -778,11 +778,12 @@ struct drm_syncobj_array {
        __u32 pad;
 };
 
+#define DRM_SYNCOBJ_QUERY_FLAGS_LAST_SUBMITTED (1 << 0) /* last available point on timeline syncobj */
 struct drm_syncobj_timeline_array {
        __u64 handles;
        __u64 points;
        __u32 count_handles;
-       __u32 pad;
+       __u32 flags;
 };
 
 
index 469dc51..5400d7e 100644 (file)
@@ -611,6 +611,13 @@ typedef struct drm_i915_irq_wait {
  * See I915_EXEC_FENCE_OUT and I915_EXEC_FENCE_SUBMIT.
  */
 #define I915_PARAM_HAS_EXEC_SUBMIT_FENCE 53
+
+/*
+ * Revision of the i915-perf uAPI. The value returned helps determine what
+ * i915-perf features are available. See drm_i915_perf_property_id.
+ */
+#define I915_PARAM_PERF_REVISION       54
+
 /* Must be kept compact -- no holes and well documented */
 
 typedef struct drm_i915_getparam {
@@ -1565,6 +1572,21 @@ struct drm_i915_gem_context_param {
  *   i915_context_engines_bond (I915_CONTEXT_ENGINES_EXT_BOND)
  */
 #define I915_CONTEXT_PARAM_ENGINES     0xa
+
+/*
+ * I915_CONTEXT_PARAM_PERSISTENCE:
+ *
+ * Allow the context and active rendering to survive the process until
+ * completion. Persistence allows fire-and-forget clients to queue up a
+ * bunch of work, hand the output over to a display server and then quit.
+ * If the context is marked as not persistent, upon closing (either via
+ * an explicit DRM_I915_GEM_CONTEXT_DESTROY or implicitly from file closure
+ * or process termination), the context and any outstanding requests will be
+ * cancelled (and exported fences for cancelled requests marked as -EIO).
+ *
+ * By default, new contexts allow persistence.
+ */
+#define I915_CONTEXT_PARAM_PERSISTENCE 0xb
 /* Must be kept compact -- no holes and well documented */
 
        __u64 value;
@@ -1844,23 +1866,31 @@ enum drm_i915_perf_property_id {
         * Open the stream for a specific context handle (as used with
         * execbuffer2). A stream opened for a specific context this way
         * won't typically require root privileges.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_CTX_HANDLE = 1,
 
        /**
         * A value of 1 requests the inclusion of raw OA unit reports as
         * part of stream samples.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_SAMPLE_OA,
 
        /**
         * The value specifies which set of OA unit metrics should be
         * be configured, defining the contents of any OA unit reports.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_METRICS_SET,
 
        /**
         * The value specifies the size and layout of OA unit reports.
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_FORMAT,
 
@@ -1870,9 +1900,22 @@ enum drm_i915_perf_property_id {
         * from this exponent as follows:
         *
         *   80ns * 2^(period_exponent + 1)
+        *
+        * This property is available in perf revision 1.
         */
        DRM_I915_PERF_PROP_OA_EXPONENT,
 
+       /**
+        * Specifying this property is only valid when specify a context to
+        * filter with DRM_I915_PERF_PROP_CTX_HANDLE. Specifying this property
+        * will hold preemption of the particular context we want to gather
+        * performance data about. The execbuf2 submissions must include a
+        * drm_i915_gem_execbuffer_ext_perf parameter for this to apply.
+        *
+        * This property is available in perf revision 3.
+        */
+       DRM_I915_PERF_PROP_HOLD_PREEMPTION,
+
        DRM_I915_PERF_PROP_MAX /* non-ABI */
 };
 
@@ -1901,6 +1944,8 @@ struct drm_i915_perf_open_param {
  * to close and re-open a stream with the same configuration.
  *
  * It's undefined whether any pending data for the stream will be lost.
+ *
+ * This ioctl is available in perf revision 1.
  */
 #define I915_PERF_IOCTL_ENABLE _IO('i', 0x0)
 
@@ -1908,10 +1953,25 @@ struct drm_i915_perf_open_param {
  * Disable data capture for a stream.
  *
  * It is an error to try and read a stream that is disabled.
+ *
+ * This ioctl is available in perf revision 1.
  */
 #define I915_PERF_IOCTL_DISABLE        _IO('i', 0x1)
 
 /**
+ * Change metrics_set captured by a stream.
+ *
+ * If the stream is bound to a specific context, the configuration change
+ * will performed inline with that context such that it takes effect before
+ * the next execbuf submission.
+ *
+ * Returns the previously bound metrics set id, or a negative error code.
+ *
+ * This ioctl is available in perf revision 2.
+ */
+#define I915_PERF_IOCTL_CONFIG _IO('i', 0x2)
+
+/**
  * Common to all i915 perf records
  */
 struct drm_i915_perf_record_header {
@@ -1984,6 +2044,7 @@ struct drm_i915_query_item {
        __u64 query_id;
 #define DRM_I915_QUERY_TOPOLOGY_INFO    1
 #define DRM_I915_QUERY_ENGINE_INFO     2
+#define DRM_I915_QUERY_PERF_CONFIG      3
 /* Must be kept compact -- no holes and well documented */
 
        /*
@@ -1995,9 +2056,18 @@ struct drm_i915_query_item {
        __s32 length;
 
        /*
-        * Unused for now. Must be cleared to zero.
+        * When query_id == DRM_I915_QUERY_TOPOLOGY_INFO, must be 0.
+        *
+        * When query_id == DRM_I915_QUERY_PERF_CONFIG, must be one of the
+        * following :
+        *         - DRM_I915_QUERY_PERF_CONFIG_LIST
+        *         - DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID
+        *         - DRM_I915_QUERY_PERF_CONFIG_FOR_UUID
         */
        __u32 flags;
+#define DRM_I915_QUERY_PERF_CONFIG_LIST          1
+#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID 2
+#define DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID   3
 
        /*
         * Data will be written at the location pointed by data_ptr when the
@@ -2033,8 +2103,10 @@ struct drm_i915_query {
  *           (data[X / 8] >> (X % 8)) & 1
  *
  * - the subslice mask for each slice with one bit per subslice telling
- *   whether a subslice is available. The availability of subslice Y in slice
- *   X can be queried with the following formula :
+ *   whether a subslice is available. Gen12 has dual-subslices, which are
+ *   similar to two gen11 subslices. For gen12, this array represents dual-
+ *   subslices. The availability of subslice Y in slice X can be queried
+ *   with the following formula :
  *
  *           (data[subslice_offset +
  *                 X * subslice_stride +
@@ -2123,6 +2195,56 @@ struct drm_i915_query_engine_info {
        struct drm_i915_engine_info engines[];
 };
 
+/*
+ * Data written by the kernel with query DRM_I915_QUERY_PERF_CONFIG.
+ */
+struct drm_i915_query_perf_config {
+       union {
+               /*
+                * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 sets
+                * this fields to the number of configurations available.
+                */
+               __u64 n_configs;
+
+               /*
+                * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_ID,
+                * i915 will use the value in this field as configuration
+                * identifier to decide what data to write into config_ptr.
+                */
+               __u64 config;
+
+               /*
+                * When query_id == DRM_I915_QUERY_PERF_CONFIG_DATA_FOR_UUID,
+                * i915 will use the value in this field as configuration
+                * identifier to decide what data to write into config_ptr.
+                *
+                * String formatted like "%08x-%04x-%04x-%04x-%012x"
+                */
+               char uuid[36];
+       };
+
+       /*
+        * Unused for now. Must be cleared to zero.
+        */
+       __u32 flags;
+
+       /*
+        * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_LIST, i915 will
+        * write an array of __u64 of configuration identifiers.
+        *
+        * When query_item.flags == DRM_I915_QUERY_PERF_CONFIG_DATA, i915 will
+        * write a struct drm_i915_perf_oa_config. If the following fields of
+        * drm_i915_perf_oa_config are set not set to 0, i915 will write into
+        * the associated pointers the values of submitted when the
+        * configuration was created :
+        *
+        *         - n_mux_regs
+        *         - n_boolean_regs
+        *         - n_flex_regs
+        */
+       __u8 data[];
+};
+
 #if defined(__cplusplus)
 }
 #endif
index 39ccfe9..1beb174 100644 (file)
@@ -17,7 +17,8 @@
 #define FSCRYPT_POLICY_FLAGS_PAD_32            0x03
 #define FSCRYPT_POLICY_FLAGS_PAD_MASK          0x03
 #define FSCRYPT_POLICY_FLAG_DIRECT_KEY         0x04
-#define FSCRYPT_POLICY_FLAGS_VALID             0x07
+#define FSCRYPT_POLICY_FLAG_IV_INO_LBLK_64     0x08
+#define FSCRYPT_POLICY_FLAGS_VALID             0x0F
 
 /* Encryption algorithms */
 #define FSCRYPT_MODE_AES_256_XTS               1
index 52641d8..f0a16b4 100644 (file)
@@ -235,6 +235,7 @@ struct kvm_hyperv_exit {
 #define KVM_EXIT_S390_STSI        25
 #define KVM_EXIT_IOAPIC_EOI       26
 #define KVM_EXIT_HYPERV           27
+#define KVM_EXIT_ARM_NISV         28
 
 /* For KVM_EXIT_INTERNAL_ERROR */
 /* Emulate instruction failed. */
@@ -394,6 +395,11 @@ struct kvm_run {
                } eoi;
                /* KVM_EXIT_HYPERV */
                struct kvm_hyperv_exit hyperv;
+               /* KVM_EXIT_ARM_NISV */
+               struct {
+                       __u64 esr_iss;
+                       __u64 fault_ipa;
+               } arm_nisv;
                /* Fix the size of the union. */
                char padding[256];
        };
@@ -1000,6 +1006,9 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_PMU_EVENT_FILTER 173
 #define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174
 #define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175
+#define KVM_CAP_PPC_GUEST_DEBUG_SSTEP 176
+#define KVM_CAP_ARM_NISV_TO_USER 177
+#define KVM_CAP_ARM_INJECT_EXT_DABT 178
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1227,6 +1236,8 @@ enum kvm_device_type {
 #define KVM_DEV_TYPE_ARM_VGIC_ITS      KVM_DEV_TYPE_ARM_VGIC_ITS
        KVM_DEV_TYPE_XIVE,
 #define KVM_DEV_TYPE_XIVE              KVM_DEV_TYPE_XIVE
+       KVM_DEV_TYPE_ARM_PV_TIME,
+#define KVM_DEV_TYPE_ARM_PV_TIME       KVM_DEV_TYPE_ARM_PV_TIME
        KVM_DEV_TYPE_MAX,
 };
 
@@ -1337,6 +1348,7 @@ struct kvm_s390_ucas_mapping {
 #define KVM_PPC_GET_CPU_CHAR     _IOR(KVMIO,  0xb1, struct kvm_ppc_cpu_char)
 /* Available with KVM_CAP_PMU_EVENT_FILTER */
 #define KVM_SET_PMU_EVENT_FILTER  _IOW(KVMIO,  0xb2, struct kvm_pmu_event_filter)
+#define KVM_PPC_SVM_OFF                  _IO(KVMIO,  0xb3)
 
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE        _IOWR(KVMIO,  0xe0, struct kvm_create_device)
index 99335e1..4a02178 100644 (file)
 #define CLONE_NEWNET           0x40000000      /* New network namespace */
 #define CLONE_IO               0x80000000      /* Clone io context */
 
+/* Flags for the clone3() syscall. */
+#define CLONE_CLEAR_SIGHAND 0x100000000ULL /* Clear any signal handler and reset to SIG_DFL. */
+
 #ifndef __ASSEMBLY__
 /**
  * struct clone_args - arguments for the clone3 syscall
- * @flags:       Flags for the new process as listed above.
- *               All flags are valid except for CSIGNAL and
- *               CLONE_DETACHED.
- * @pidfd:       If CLONE_PIDFD is set, a pidfd will be
- *               returned in this argument.
- * @child_tid:   If CLONE_CHILD_SETTID is set, the TID of the
- *               child process will be returned in the child's
- *               memory.
- * @parent_tid:  If CLONE_PARENT_SETTID is set, the TID of
- *               the child process will be returned in the
- *               parent's memory.
- * @exit_signal: The exit_signal the parent process will be
- *               sent when the child exits.
- * @stack:       Specify the location of the stack for the
- *               child process.
- * @stack_size:  The size of the stack for the child process.
- * @tls:         If CLONE_SETTLS is set, the tls descriptor
- *               is set to tls.
+ * @flags:        Flags for the new process as listed above.
+ *                All flags are valid except for CSIGNAL and
+ *                CLONE_DETACHED.
+ * @pidfd:        If CLONE_PIDFD is set, a pidfd will be
+ *                returned in this argument.
+ * @child_tid:    If CLONE_CHILD_SETTID is set, the TID of the
+ *                child process will be returned in the child's
+ *                memory.
+ * @parent_tid:   If CLONE_PARENT_SETTID is set, the TID of
+ *                the child process will be returned in the
+ *                parent's memory.
+ * @exit_signal:  The exit_signal the parent process will be
+ *                sent when the child exits.
+ * @stack:        Specify the location of the stack for the
+ *                child process.
+ *                Note, @stack is expected to point to the
+ *                lowest address. The stack direction will be
+ *                determined by the kernel and set up
+ *                appropriately based on @stack_size.
+ * @stack_size:   The size of the stack for the child process.
+ * @tls:          If CLONE_SETTLS is set, the tls descriptor
+ *                is set to tls.
+ * @set_tid:      Pointer to an array of type *pid_t. The size
+ *                of the array is defined using @set_tid_size.
+ *                This array is used to select PIDs/TIDs for
+ *                newly created processes. The first element in
+ *                this defines the PID in the most nested PID
+ *                namespace. Each additional element in the array
+ *                defines the PID in the parent PID namespace of
+ *                the original PID namespace. If the array has
+ *                less entries than the number of currently
+ *                nested PID namespaces only the PIDs in the
+ *                corresponding namespaces are set.
+ * @set_tid_size: This defines the size of the array referenced
+ *                in @set_tid. This cannot be larger than the
+ *                kernel's limit of nested PID namespaces.
  *
  * The structure is versioned by size and thus extensible.
  * New struct members must go at the end of the struct and
@@ -68,10 +89,13 @@ struct clone_args {
        __aligned_u64 stack;
        __aligned_u64 stack_size;
        __aligned_u64 tls;
+       __aligned_u64 set_tid;
+       __aligned_u64 set_tid_size;
 };
 #endif
 
 #define CLONE_ARGS_SIZE_VER0 64 /* sizeof first published struct */
+#define CLONE_ARGS_SIZE_VER1 80 /* sizeof second published struct */
 
 /*
  * Scheduling policies
index 7b35e98..ad80a5c 100644 (file)
@@ -167,8 +167,8 @@ struct statx {
 #define STATX_ATTR_APPEND              0x00000020 /* [I] File is append-only */
 #define STATX_ATTR_NODUMP              0x00000040 /* [I] File is not to be dumped */
 #define STATX_ATTR_ENCRYPTED           0x00000800 /* [I] File requires key to decrypt in fs */
-
 #define STATX_ATTR_AUTOMOUNT           0x00001000 /* Dir: Automount trigger */
+#define STATX_ATTR_VERITY              0x00100000 /* [I] Verity protected file */
 
 
 #endif /* _UAPI_LINUX_STAT_H */
index defae23..97830e4 100644 (file)
@@ -138,6 +138,7 @@ STATIC_OBJDIR       := $(OUTPUT)staticobjs/
 BPF_IN_SHARED  := $(SHARED_OBJDIR)libbpf-in.o
 BPF_IN_STATIC  := $(STATIC_OBJDIR)libbpf-in.o
 VERSION_SCRIPT := libbpf.map
+BPF_HELPER_DEFS        := $(OUTPUT)bpf_helper_defs.h
 
 LIB_TARGET     := $(addprefix $(OUTPUT),$(LIB_TARGET))
 LIB_FILE       := $(addprefix $(OUTPUT),$(LIB_FILE))
@@ -159,7 +160,7 @@ all: fixdep
 
 all_cmd: $(CMD_TARGETS) check
 
-$(BPF_IN_SHARED): force elfdep bpfdep bpf_helper_defs.h
+$(BPF_IN_SHARED): force elfdep bpfdep $(BPF_HELPER_DEFS)
        @(test -f ../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \
        (diff -B ../../include/uapi/linux/bpf.h ../../../include/uapi/linux/bpf.h >/dev/null) || \
        echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf.h' differs from latest version at 'include/uapi/linux/bpf.h'" >&2 )) || true
@@ -177,12 +178,12 @@ $(BPF_IN_SHARED): force elfdep bpfdep bpf_helper_defs.h
        echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/if_xdp.h' differs from latest version at 'include/uapi/linux/if_xdp.h'" >&2 )) || true
        $(Q)$(MAKE) $(build)=libbpf OUTPUT=$(SHARED_OBJDIR) CFLAGS="$(CFLAGS) $(SHLIB_FLAGS)"
 
-$(BPF_IN_STATIC): force elfdep bpfdep bpf_helper_defs.h
+$(BPF_IN_STATIC): force elfdep bpfdep $(BPF_HELPER_DEFS)
        $(Q)$(MAKE) $(build)=libbpf OUTPUT=$(STATIC_OBJDIR)
 
-bpf_helper_defs.h: $(srctree)/tools/include/uapi/linux/bpf.h
+$(BPF_HELPER_DEFS): $(srctree)/tools/include/uapi/linux/bpf.h
        $(Q)$(srctree)/scripts/bpf_helpers_doc.py --header              \
-               --file $(srctree)/tools/include/uapi/linux/bpf.h > bpf_helper_defs.h
+               --file $(srctree)/tools/include/uapi/linux/bpf.h > $(BPF_HELPER_DEFS)
 
 $(OUTPUT)libbpf.so: $(OUTPUT)libbpf.so.$(LIBBPF_VERSION)
 
@@ -243,7 +244,7 @@ install_lib: all_cmd
                $(call do_install_mkdir,$(libdir_SQ)); \
                cp -fpR $(LIB_FILE) $(DESTDIR)$(libdir_SQ)
 
-install_headers: bpf_helper_defs.h
+install_headers: $(BPF_HELPER_DEFS)
        $(call QUIET_INSTALL, headers) \
                $(call do_install,bpf.h,$(prefix)/include/bpf,644); \
                $(call do_install,libbpf.h,$(prefix)/include/bpf,644); \
@@ -251,7 +252,7 @@ install_headers: bpf_helper_defs.h
                $(call do_install,libbpf_util.h,$(prefix)/include/bpf,644); \
                $(call do_install,xsk.h,$(prefix)/include/bpf,644); \
                $(call do_install,bpf_helpers.h,$(prefix)/include/bpf,644); \
-               $(call do_install,bpf_helper_defs.h,$(prefix)/include/bpf,644); \
+               $(call do_install,$(BPF_HELPER_DEFS),$(prefix)/include/bpf,644); \
                $(call do_install,bpf_tracing.h,$(prefix)/include/bpf,644); \
                $(call do_install,bpf_endian.h,$(prefix)/include/bpf,644); \
                $(call do_install,bpf_core_read.h,$(prefix)/include/bpf,644);
@@ -271,7 +272,7 @@ config-clean:
 clean:
        $(call QUIET_CLEAN, libbpf) $(RM) -rf $(CMD_TARGETS) \
                *.o *~ *.a *.so *.so.$(LIBBPF_MAJOR_VERSION) .*.d .*.cmd \
-               *.pc LIBBPF-CFLAGS bpf_helper_defs.h \
+               *.pc LIBBPF-CFLAGS $(BPF_HELPER_DEFS) \
                $(SHARED_OBJDIR) $(STATIC_OBJDIR)
        $(call QUIET_CLEAN, core-gen) $(RM) $(OUTPUT)FEATURE-DUMP.libbpf
 
index cbb429f..c874c01 100644 (file)
@@ -39,11 +39,12 @@ DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
 
 LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
 ifeq ($(LP64), 1)
-  libdir_relative = lib64
+  libdir_relative_temp = lib64
 else
-  libdir_relative = lib
+  libdir_relative_temp = lib
 endif
 
+libdir_relative ?= $(libdir_relative_temp)
 prefix ?= /usr/local
 libdir = $(prefix)/$(libdir_relative)
 man_dir = $(prefix)/share/man
@@ -97,6 +98,7 @@ EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
 
 LIB_TARGET  = libtraceevent.a libtraceevent.so.$(EVENT_PARSE_VERSION)
 LIB_INSTALL = libtraceevent.a libtraceevent.so*
+LIB_INSTALL := $(addprefix $(OUTPUT),$(LIB_INSTALL))
 
 INCLUDES = -I. -I $(srctree)/tools/include $(CONFIG_INCLUDES)
 
@@ -207,10 +209,11 @@ define do_install
        $(INSTALL) $(if $3,-m $3,) $1 '$(DESTDIR_SQ)$2'
 endef
 
-PKG_CONFIG_FILE = libtraceevent.pc
+PKG_CONFIG_SOURCE_FILE = libtraceevent.pc
+PKG_CONFIG_FILE := $(addprefix $(OUTPUT),$(PKG_CONFIG_SOURCE_FILE))
 define do_install_pkgconfig_file
        if [ -n "${pkgconfig_dir}" ]; then                                      \
-               cp -f ${PKG_CONFIG_FILE}.template ${PKG_CONFIG_FILE};           \
+               cp -f ${PKG_CONFIG_SOURCE_FILE}.template ${PKG_CONFIG_FILE};    \
                sed -i "s|INSTALL_PREFIX|${1}|g" ${PKG_CONFIG_FILE};            \
                sed -i "s|LIB_VERSION|${EVENT_PARSE_VERSION}|g" ${PKG_CONFIG_FILE}; \
                sed -i "s|LIB_DIR|${libdir}|g" ${PKG_CONFIG_FILE}; \
index f3cbf86..20eed71 100644 (file)
@@ -1228,8 +1228,10 @@ filter_event(struct tep_event_filter *filter, struct tep_event *event,
        }
 
        filter_type = add_filter_type(filter, event->id);
-       if (filter_type == NULL)
+       if (filter_type == NULL) {
+               free_arg(arg);
                return TEP_ERRNO__MEM_ALLOC_FAILED;
+       }
 
        if (filter_type->filter)
                free_arg(filter_type->filter);
index f440989..349bb81 100644 (file)
@@ -32,11 +32,12 @@ DESTDIR_SQ = '$(subst ','\'',$(DESTDIR))'
 
 LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
 ifeq ($(LP64), 1)
-  libdir_relative = lib64
+  libdir_relative_tmp = lib64
 else
-  libdir_relative = lib
+  libdir_relative_tmp = lib
 endif
 
+libdir_relative ?= $(libdir_relative_tmp)
 prefix ?= /usr/local
 libdir = $(prefix)/$(libdir_relative)
 
index 6a5bb2b..cf95bae 100644 (file)
@@ -68,10 +68,11 @@ OPTIONS
 -------
 -i::
 --input=<path>::
-        Input file name.
+        Input file name, for the 'report', 'diff' and 'buildid-list' subcommands.
 -o::
 --output=<path>::
-        Output file name.
+        Output file name, for the 'record' subcommand. Doesn't work with 'report',
+        just redirect the output to a file when using 'report'.
 --host::
         Collect host side performance profile.
 --guest::
index 6e2495c..4284307 100644 (file)
@@ -37,7 +37,7 @@
 
 .text
 .type perf_regs_load,%function
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        str r0, [r0, #R0]
        str r1, [r0, #R1]
        str r2, [r0, #R2]
@@ -56,4 +56,4 @@ ENTRY(perf_regs_load)
        str lr, [r0, #PC]       // store pc as lr in order to skip the call
                                //  to this function
        mov pc, lr
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
index 0704251..d49de40 100644 (file)
@@ -7,7 +7,7 @@
 #define LDR_REG(r)     ldr x##r, [x0, 8 * r]
 #define SP     (8 * 31)
 #define PC     (8 * 32)
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        STR_REG(0)
        STR_REG(1)
        STR_REG(2)
@@ -44,4 +44,4 @@ ENTRY(perf_regs_load)
        str x30, [x0, #PC]
        LDR_REG(1)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
index bbe5a0d..80f14f5 100644 (file)
@@ -28,7 +28,7 @@
 
 .text
 #ifdef HAVE_ARCH_X86_64_SUPPORT
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        movq %rax, AX(%rdi)
        movq %rbx, BX(%rdi)
        movq %rcx, CX(%rdi)
@@ -60,9 +60,9 @@ ENTRY(perf_regs_load)
        movq %r14, R14(%rdi)
        movq %r15, R15(%rdi)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
 #else
-ENTRY(perf_regs_load)
+SYM_FUNC_START(perf_regs_load)
        push %edi
        movl 8(%esp), %edi
        movl %eax, AX(%edi)
@@ -88,7 +88,7 @@ ENTRY(perf_regs_load)
        movl $0, FS(%edi)
        movl $0, GS(%edi)
        ret
-ENDPROC(perf_regs_load)
+SYM_FUNC_END(perf_regs_load)
 #endif
 
 /*
index 9664a72..7e124a7 100644 (file)
@@ -403,17 +403,6 @@ static int perf_event__repipe_tracing_data(struct perf_session *session,
        return err;
 }
 
-static int perf_event__repipe_id_index(struct perf_session *session,
-                                      union perf_event *event)
-{
-       int err;
-
-       perf_event__repipe_synth(session->tool, event);
-       err = perf_event__process_id_index(session, event);
-
-       return err;
-}
-
 static int dso__read_build_id(struct dso *dso)
 {
        if (dso->has_build_id)
@@ -651,7 +640,7 @@ static int __cmd_inject(struct perf_inject *inject)
                inject->tool.comm           = perf_event__repipe_comm;
                inject->tool.namespaces     = perf_event__repipe_namespaces;
                inject->tool.exit           = perf_event__repipe_exit;
-               inject->tool.id_index       = perf_event__repipe_id_index;
+               inject->tool.id_index       = perf_event__process_id_index;
                inject->tool.auxtrace_info  = perf_event__process_auxtrace_info;
                inject->tool.auxtrace       = perf_event__process_auxtrace;
                inject->tool.aux            = perf_event__drop_aux;
index b5063d3..fb19ef6 100644 (file)
@@ -832,7 +832,7 @@ try_again:
                        if ((errno == EINVAL || errno == EBADF) &&
                            pos->leader != pos &&
                            pos->weak_group) {
-                               pos = perf_evlist__reset_weak_group(evlist, pos);
+                               pos = perf_evlist__reset_weak_group(evlist, pos, true);
                                goto try_again;
                        }
                        rc = -errno;
index 830d563..de98858 100644 (file)
@@ -388,6 +388,14 @@ static int report__setup_sample_type(struct report *rep)
                }
        }
 
+       if (sort__mode == SORT_MODE__MEMORY) {
+               if (!is_pipe && !(sample_type & PERF_SAMPLE_DATA_SRC)) {
+                       ui__error("Selected --mem-mode but no mem data. "
+                                 "Did you call perf record without -d?\n");
+                       return -1;
+               }
+       }
+
        if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain) {
                if ((sample_type & PERF_SAMPLE_REGS_USER) &&
                    (sample_type & PERF_SAMPLE_STACK_USER)) {
@@ -1068,6 +1076,7 @@ int cmd_report(int argc, const char **argv)
        struct stat st;
        bool has_br_stack = false;
        int branch_mode = -1;
+       int last_key = 0;
        bool branch_call_mode = false;
 #define CALLCHAIN_DEFAULT_OPT  "graph,0.5,caller,function,percent"
        static const char report_callchain_help[] = "Display call graph (stack chain/backtrace):\n\n"
@@ -1442,7 +1451,8 @@ repeat:
                sort_order = sort_tmp;
        }
 
-       if (setup_sorting(session->evlist) < 0) {
+       if ((last_key != K_SWITCH_INPUT_DATA) &&
+           (setup_sorting(session->evlist) < 0)) {
                if (sort_order)
                        parse_options_usage(report_usage, options, "s", 1);
                if (field_order)
@@ -1522,6 +1532,7 @@ repeat:
        ret = __cmd_report(&report);
        if (ret == K_SWITCH_INPUT_DATA) {
                perf_session__delete(session);
+               last_key = K_SWITCH_INPUT_DATA;
                goto repeat;
        } else
                ret = 0;
index 0a15253..a098c2e 100644 (file)
@@ -65,6 +65,7 @@
 #include "util/target.h"
 #include "util/time-utils.h"
 #include "util/top.h"
+#include "util/affinity.h"
 #include "asm/bug.h"
 
 #include <linux/time64.h>
@@ -265,15 +266,10 @@ static int read_single_counter(struct evsel *counter, int cpu,
  * Read out the results of a single counter:
  * do not aggregate counts across CPUs in system-wide mode
  */
-static int read_counter(struct evsel *counter, struct timespec *rs)
+static int read_counter_cpu(struct evsel *counter, struct timespec *rs, int cpu)
 {
        int nthreads = perf_thread_map__nr(evsel_list->core.threads);
-       int ncpus, cpu, thread;
-
-       if (target__has_cpu(&target) && !target__has_per_thread(&target))
-               ncpus = perf_evsel__nr_cpus(counter);
-       else
-               ncpus = 1;
+       int thread;
 
        if (!counter->supported)
                return -ENOENT;
@@ -282,40 +278,38 @@ static int read_counter(struct evsel *counter, struct timespec *rs)
                nthreads = 1;
 
        for (thread = 0; thread < nthreads; thread++) {
-               for (cpu = 0; cpu < ncpus; cpu++) {
-                       struct perf_counts_values *count;
-
-                       count = perf_counts(counter->counts, cpu, thread);
-
-                       /*
-                        * The leader's group read loads data into its group members
-                        * (via perf_evsel__read_counter) and sets threir count->loaded.
-                        */
-                       if (!perf_counts__is_loaded(counter->counts, cpu, thread) &&
-                           read_single_counter(counter, cpu, thread, rs)) {
-                               counter->counts->scaled = -1;
-                               perf_counts(counter->counts, cpu, thread)->ena = 0;
-                               perf_counts(counter->counts, cpu, thread)->run = 0;
-                               return -1;
-                       }
+               struct perf_counts_values *count;
 
-                       perf_counts__set_loaded(counter->counts, cpu, thread, false);
+               count = perf_counts(counter->counts, cpu, thread);
 
-                       if (STAT_RECORD) {
-                               if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
-                                       pr_err("failed to write stat event\n");
-                                       return -1;
-                               }
-                       }
+               /*
+                * The leader's group read loads data into its group members
+                * (via perf_evsel__read_counter()) and sets their count->loaded.
+                */
+               if (!perf_counts__is_loaded(counter->counts, cpu, thread) &&
+                   read_single_counter(counter, cpu, thread, rs)) {
+                       counter->counts->scaled = -1;
+                       perf_counts(counter->counts, cpu, thread)->ena = 0;
+                       perf_counts(counter->counts, cpu, thread)->run = 0;
+                       return -1;
+               }
+
+               perf_counts__set_loaded(counter->counts, cpu, thread, false);
 
-                       if (verbose > 1) {
-                               fprintf(stat_config.output,
-                                       "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
-                                               perf_evsel__name(counter),
-                                               cpu,
-                                               count->val, count->ena, count->run);
+               if (STAT_RECORD) {
+                       if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
+                               pr_err("failed to write stat event\n");
+                               return -1;
                        }
                }
+
+               if (verbose > 1) {
+                       fprintf(stat_config.output,
+                               "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
+                                       perf_evsel__name(counter),
+                                       cpu,
+                                       count->val, count->ena, count->run);
+               }
        }
 
        return 0;
@@ -324,15 +318,37 @@ static int read_counter(struct evsel *counter, struct timespec *rs)
 static void read_counters(struct timespec *rs)
 {
        struct evsel *counter;
-       int ret;
+       struct affinity affinity;
+       int i, ncpus, cpu;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
+
+       ncpus = perf_cpu_map__nr(evsel_list->core.all_cpus);
+       if (!target__has_cpu(&target) || target__has_per_thread(&target))
+               ncpus = 1;
+       evlist__for_each_cpu(evsel_list, i, cpu) {
+               if (i >= ncpus)
+                       break;
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evsel_list, counter) {
+                       if (evsel__cpu_iter_skip(counter, cpu))
+                               continue;
+                       if (!counter->err) {
+                               counter->err = read_counter_cpu(counter, rs,
+                                                               counter->cpu_iter - 1);
+                       }
+               }
+       }
+       affinity__cleanup(&affinity);
 
        evlist__for_each_entry(evsel_list, counter) {
-               ret = read_counter(counter, rs);
-               if (ret)
+               if (counter->err)
                        pr_debug("failed to read counter %s\n", counter->name);
-
-               if (ret == 0 && perf_stat_process_counter(&stat_config, counter))
+               if (counter->err == 0 && perf_stat_process_counter(&stat_config, counter))
                        pr_warning("failed to process counter %s\n", counter->name);
+               counter->err = 0;
        }
 }
 
@@ -420,6 +436,62 @@ static bool is_target_alive(struct target *_target,
        return false;
 }
 
+enum counter_recovery {
+       COUNTER_SKIP,
+       COUNTER_RETRY,
+       COUNTER_FATAL,
+};
+
+static enum counter_recovery stat_handle_error(struct evsel *counter)
+{
+       char msg[BUFSIZ];
+       /*
+        * PPC returns ENXIO for HW counters until 2.6.37
+        * (behavior changed with commit b0a873e).
+        */
+       if (errno == EINVAL || errno == ENOSYS ||
+           errno == ENOENT || errno == EOPNOTSUPP ||
+           errno == ENXIO) {
+               if (verbose > 0)
+                       ui__warning("%s event is not supported by the kernel.\n",
+                                   perf_evsel__name(counter));
+               counter->supported = false;
+               /*
+                * errored is a sticky flag that means one of the counter's
+                * cpu event had a problem and needs to be reexamined.
+                */
+               counter->errored = true;
+
+               if ((counter->leader != counter) ||
+                   !(counter->leader->core.nr_members > 1))
+                       return COUNTER_SKIP;
+       } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
+               if (verbose > 0)
+                       ui__warning("%s\n", msg);
+               return COUNTER_RETRY;
+       } else if (target__has_per_thread(&target) &&
+                  evsel_list->core.threads &&
+                  evsel_list->core.threads->err_thread != -1) {
+               /*
+                * For global --per-thread case, skip current
+                * error thread.
+                */
+               if (!thread_map__remove(evsel_list->core.threads,
+                                       evsel_list->core.threads->err_thread)) {
+                       evsel_list->core.threads->err_thread = -1;
+                       return COUNTER_RETRY;
+               }
+       }
+
+       perf_evsel__open_strerror(counter, &target,
+                                 errno, msg, sizeof(msg));
+       ui__error("%s\n", msg);
+
+       if (child_pid != -1)
+               kill(child_pid, SIGTERM);
+       return COUNTER_FATAL;
+}
+
 static int __run_perf_stat(int argc, const char **argv, int run_idx)
 {
        int interval = stat_config.interval;
@@ -433,6 +505,9 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        int status = 0;
        const bool forks = (argc > 0);
        bool is_pipe = STAT_RECORD ? perf_stat.data.is_pipe : false;
+       struct affinity affinity;
+       int i, cpu;
+       bool second_pass = false;
 
        if (interval) {
                ts.tv_sec  = interval / USEC_PER_MSEC;
@@ -457,61 +532,104 @@ static int __run_perf_stat(int argc, const char **argv, int run_idx)
        if (group)
                perf_evlist__set_leader(evsel_list);
 
-       evlist__for_each_entry(evsel_list, counter) {
+       if (affinity__setup(&affinity) < 0)
+               return -1;
+
+       evlist__for_each_cpu (evsel_list, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evsel_list, counter) {
+                       if (evsel__cpu_iter_skip(counter, cpu))
+                               continue;
+                       if (counter->reset_group || counter->errored)
+                               continue;
 try_again:
-               if (create_perf_stat_counter(counter, &stat_config, &target) < 0) {
-
-                       /* Weak group failed. Reset the group. */
-                       if ((errno == EINVAL || errno == EBADF) &&
-                           counter->leader != counter &&
-                           counter->weak_group) {
-                               counter = perf_evlist__reset_weak_group(evsel_list, counter);
-                               goto try_again;
-                       }
+                       if (create_perf_stat_counter(counter, &stat_config, &target,
+                                                    counter->cpu_iter - 1) < 0) {
 
-                       /*
-                        * PPC returns ENXIO for HW counters until 2.6.37
-                        * (behavior changed with commit b0a873e).
-                        */
-                       if (errno == EINVAL || errno == ENOSYS ||
-                           errno == ENOENT || errno == EOPNOTSUPP ||
-                           errno == ENXIO) {
-                               if (verbose > 0)
-                                       ui__warning("%s event is not supported by the kernel.\n",
-                                                   perf_evsel__name(counter));
-                               counter->supported = false;
-
-                               if ((counter->leader != counter) ||
-                                   !(counter->leader->core.nr_members > 1))
-                                       continue;
-                       } else if (perf_evsel__fallback(counter, errno, msg, sizeof(msg))) {
-                                if (verbose > 0)
-                                        ui__warning("%s\n", msg);
-                                goto try_again;
-                       } else if (target__has_per_thread(&target) &&
-                                  evsel_list->core.threads &&
-                                  evsel_list->core.threads->err_thread != -1) {
                                /*
-                                * For global --per-thread case, skip current
-                                * error thread.
+                                * Weak group failed. We cannot just undo this here
+                                * because earlier CPUs might be in group mode, and the kernel
+                                * doesn't support mixing group and non group reads. Defer
+                                * it to later.
+                                * Don't close here because we're in the wrong affinity.
                                 */
-                               if (!thread_map__remove(evsel_list->core.threads,
-                                                       evsel_list->core.threads->err_thread)) {
-                                       evsel_list->core.threads->err_thread = -1;
+                               if ((errno == EINVAL || errno == EBADF) &&
+                                   counter->leader != counter &&
+                                   counter->weak_group) {
+                                       perf_evlist__reset_weak_group(evsel_list, counter, false);
+                                       assert(counter->reset_group);
+                                       second_pass = true;
+                                       continue;
+                               }
+
+                               switch (stat_handle_error(counter)) {
+                               case COUNTER_FATAL:
+                                       return -1;
+                               case COUNTER_RETRY:
                                        goto try_again;
+                               case COUNTER_SKIP:
+                                       continue;
+                               default:
+                                       break;
                                }
+
                        }
+                       counter->supported = true;
+               }
+       }
 
-                       perf_evsel__open_strerror(counter, &target,
-                                                 errno, msg, sizeof(msg));
-                       ui__error("%s\n", msg);
+       if (second_pass) {
+               /*
+                * Now redo all the weak group after closing them,
+                * and also close errored counters.
+                */
 
-                       if (child_pid != -1)
-                               kill(child_pid, SIGTERM);
+               evlist__for_each_cpu(evsel_list, i, cpu) {
+                       affinity__set(&affinity, cpu);
+                       /* First close errored or weak retry */
+                       evlist__for_each_entry(evsel_list, counter) {
+                               if (!counter->reset_group && !counter->errored)
+                                       continue;
+                               if (evsel__cpu_iter_skip_no_inc(counter, cpu))
+                                       continue;
+                               perf_evsel__close_cpu(&counter->core, counter->cpu_iter);
+                       }
+                       /* Now reopen weak */
+                       evlist__for_each_entry(evsel_list, counter) {
+                               if (!counter->reset_group && !counter->errored)
+                                       continue;
+                               if (evsel__cpu_iter_skip(counter, cpu))
+                                       continue;
+                               if (!counter->reset_group)
+                                       continue;
+try_again_reset:
+                               pr_debug2("reopening weak %s\n", perf_evsel__name(counter));
+                               if (create_perf_stat_counter(counter, &stat_config, &target,
+                                                            counter->cpu_iter - 1) < 0) {
+
+                                       switch (stat_handle_error(counter)) {
+                                       case COUNTER_FATAL:
+                                               return -1;
+                                       case COUNTER_RETRY:
+                                               goto try_again_reset;
+                                       case COUNTER_SKIP:
+                                               continue;
+                                       default:
+                                               break;
+                                       }
+                               }
+                               counter->supported = true;
+                       }
+               }
+       }
+       affinity__cleanup(&affinity);
 
-                       return -1;
+       evlist__for_each_entry(evsel_list, counter) {
+               if (!counter->supported) {
+                       perf_evsel__free_fd(&counter->core);
+                       continue;
                }
-               counter->supported = true;
 
                l = strlen(counter->unit);
                if (l > stat_config.unit_width)
index dc80044..795e353 100644 (file)
@@ -1568,9 +1568,13 @@ int cmd_top(int argc, const char **argv)
         */
        status = perf_env__read_cpuid(&perf_env);
        if (status) {
-               pr_err("Couldn't read the cpuid for this machine: %s\n",
-                      str_error_r(errno, errbuf, sizeof(errbuf)));
-               goto out_delete_evlist;
+               /*
+                * Some arches do not provide a get_cpuid(), so just use pr_debug, otherwise
+                * warn the user explicitely.
+                */
+               eprintf(status == ENOSYS ? 1 : 0, verbose,
+                       "Couldn't read the cpuid for this machine: %s\n",
+                       str_error_r(errno, errbuf, sizeof(errbuf)));
        }
        top.evlist->env = &perf_env;
 
index a1dc167..68039a9 100755 (executable)
@@ -110,8 +110,8 @@ for i in $FILES; do
 done
 
 # diff with extra ignore lines
-check arch/x86/lib/memcpy_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
-check arch/x86/lib/memset_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"'
+check arch/x86/lib/memcpy_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memcpy_\(erms\|orig\))"'
+check arch/x86/lib/memset_64.S        '-I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>" -I"^SYM_FUNC_START\(_LOCAL\)*(memset_\(erms\|orig\))"'
 check include/uapi/asm-generic/mman.h '-I "^#include <\(uapi/\)*asm-generic/mman-common\(-tools\)*.h>"'
 check include/uapi/linux/mman.h       '-I "^#include <\(uapi/\)*asm/mman.h>"'
 check include/linux/ctype.h          '-I "isdigit("'
index 2ca1faf..f93f4e7 100644 (file)
@@ -68,14 +68,28 @@ static struct perf_cpu_map *cpu_map__default_new(void)
        return cpus;
 }
 
+static int cmp_int(const void *a, const void *b)
+{
+       return *(const int *)a - *(const int*)b;
+}
+
 static struct perf_cpu_map *cpu_map__trim_new(int nr_cpus, int *tmp_cpus)
 {
        size_t payload_size = nr_cpus * sizeof(int);
        struct perf_cpu_map *cpus = malloc(sizeof(*cpus) + payload_size);
+       int i, j;
 
        if (cpus != NULL) {
-               cpus->nr = nr_cpus;
                memcpy(cpus->map, tmp_cpus, payload_size);
+               qsort(cpus->map, nr_cpus, sizeof(int), cmp_int);
+               /* Remove dups */
+               j = 0;
+               for (i = 0; i < nr_cpus; i++) {
+                       if (i == 0 || cpus->map[i] != cpus->map[i - 1])
+                               cpus->map[j++] = cpus->map[i];
+               }
+               cpus->nr = j;
+               assert(j <= nr_cpus);
                refcount_set(&cpus->refcnt, 1);
        }
 
@@ -272,3 +286,60 @@ int perf_cpu_map__max(struct perf_cpu_map *map)
 
        return max;
 }
+
+/*
+ * Merge two cpumaps
+ *
+ * orig either gets freed and replaced with a new map, or reused
+ * with no reference count change (similar to "realloc")
+ * other has its reference count increased.
+ */
+
+struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
+                                        struct perf_cpu_map *other)
+{
+       int *tmp_cpus;
+       int tmp_len;
+       int i, j, k;
+       struct perf_cpu_map *merged;
+
+       if (!orig && !other)
+               return NULL;
+       if (!orig) {
+               perf_cpu_map__get(other);
+               return other;
+       }
+       if (!other)
+               return orig;
+       if (orig->nr == other->nr &&
+           !memcmp(orig->map, other->map, orig->nr * sizeof(int)))
+               return orig;
+
+       tmp_len = orig->nr + other->nr;
+       tmp_cpus = malloc(tmp_len * sizeof(int));
+       if (!tmp_cpus)
+               return NULL;
+
+       /* Standard merge algorithm from wikipedia */
+       i = j = k = 0;
+       while (i < orig->nr && j < other->nr) {
+               if (orig->map[i] <= other->map[j]) {
+                       if (orig->map[i] == other->map[j])
+                               j++;
+                       tmp_cpus[k++] = orig->map[i++];
+               } else
+                       tmp_cpus[k++] = other->map[j++];
+       }
+
+       while (i < orig->nr)
+               tmp_cpus[k++] = orig->map[i++];
+
+       while (j < other->nr)
+               tmp_cpus[k++] = other->map[j++];
+       assert(k <= tmp_len);
+
+       merged = cpu_map__trim_new(k, tmp_cpus);
+       free(tmp_cpus);
+       perf_cpu_map__put(orig);
+       return merged;
+}
index 205ddbb..ae9e65a 100644 (file)
@@ -54,6 +54,7 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
 
        perf_thread_map__put(evsel->threads);
        evsel->threads = perf_thread_map__get(evlist->threads);
+       evlist->all_cpus = perf_cpu_map__merge(evlist->all_cpus, evsel->cpus);
 }
 
 static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
index 5a89857..4dc0628 100644 (file)
@@ -114,16 +114,23 @@ int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
        return err;
 }
 
+static void perf_evsel__close_fd_cpu(struct perf_evsel *evsel, int cpu)
+{
+       int thread;
+
+       for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
+               if (FD(evsel, cpu, thread) >= 0)
+                       close(FD(evsel, cpu, thread));
+               FD(evsel, cpu, thread) = -1;
+       }
+}
+
 void perf_evsel__close_fd(struct perf_evsel *evsel)
 {
-       int cpu, thread;
+       int cpu;
 
        for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++)
-               for (thread = 0; thread < xyarray__max_y(evsel->fd); ++thread) {
-                       if (FD(evsel, cpu, thread) >= 0)
-                               close(FD(evsel, cpu, thread));
-                       FD(evsel, cpu, thread) = -1;
-               }
+               perf_evsel__close_fd_cpu(evsel, cpu);
 }
 
 void perf_evsel__free_fd(struct perf_evsel *evsel)
@@ -141,6 +148,14 @@ void perf_evsel__close(struct perf_evsel *evsel)
        perf_evsel__free_fd(evsel);
 }
 
+void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu)
+{
+       if (evsel->fd == NULL)
+               return;
+
+       perf_evsel__close_fd_cpu(evsel, cpu);
+}
+
 int perf_evsel__read_size(struct perf_evsel *evsel)
 {
        u64 read_format = evsel->attr.read_format;
@@ -183,38 +198,61 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
 }
 
 static int perf_evsel__run_ioctl(struct perf_evsel *evsel,
-                                int ioc,  void *arg)
+                                int ioc,  void *arg,
+                                int cpu)
 {
-       int cpu, thread;
+       int thread;
 
-       for (cpu = 0; cpu < xyarray__max_x(evsel->fd); cpu++) {
-               for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
-                       int fd = FD(evsel, cpu, thread),
-                           err = ioctl(fd, ioc, arg);
+       for (thread = 0; thread < xyarray__max_y(evsel->fd); thread++) {
+               int fd = FD(evsel, cpu, thread),
+                   err = ioctl(fd, ioc, arg);
 
-                       if (err)
-                               return err;
-               }
+               if (err)
+                       return err;
        }
 
        return 0;
 }
 
+int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu)
+{
+       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, cpu);
+}
+
 int perf_evsel__enable(struct perf_evsel *evsel)
 {
-       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, 0);
+       int i;
+       int err = 0;
+
+       for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
+               err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_ENABLE, NULL, i);
+       return err;
+}
+
+int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu)
+{
+       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, cpu);
 }
 
 int perf_evsel__disable(struct perf_evsel *evsel)
 {
-       return perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, 0);
+       int i;
+       int err = 0;
+
+       for (i = 0; i < xyarray__max_x(evsel->fd) && !err; i++)
+               err = perf_evsel__run_ioctl(evsel, PERF_EVENT_IOC_DISABLE, NULL, i);
+       return err;
 }
 
 int perf_evsel__apply_filter(struct perf_evsel *evsel, const char *filter)
 {
-       return perf_evsel__run_ioctl(evsel,
+       int err = 0, i;
+
+       for (i = 0; i < evsel->cpus->nr && !err; i++)
+               err = perf_evsel__run_ioctl(evsel,
                                     PERF_EVENT_IOC_SET_FILTER,
-                                    (void *)filter);
+                                    (void *)filter, i);
+       return err;
 }
 
 struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel)
index a2fbccf..74dc8c3 100644 (file)
@@ -18,6 +18,7 @@ struct perf_evlist {
        int                      nr_entries;
        bool                     has_user_cpus;
        struct perf_cpu_map     *cpus;
+       struct perf_cpu_map     *all_cpus;
        struct perf_thread_map  *threads;
        int                      nr_mmaps;
        size_t                   mmap_len;
index ac9aa49..6a17ad7 100644 (file)
@@ -12,6 +12,8 @@ LIBPERF_API struct perf_cpu_map *perf_cpu_map__dummy_new(void);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__new(const char *cpu_list);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__read(FILE *file);
 LIBPERF_API struct perf_cpu_map *perf_cpu_map__get(struct perf_cpu_map *map);
+LIBPERF_API struct perf_cpu_map *perf_cpu_map__merge(struct perf_cpu_map *orig,
+                                                    struct perf_cpu_map *other);
 LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);
 LIBPERF_API int perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx);
 LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus);
index 557f581..c82ec39 100644 (file)
@@ -26,10 +26,13 @@ LIBPERF_API void perf_evsel__delete(struct perf_evsel *evsel);
 LIBPERF_API int perf_evsel__open(struct perf_evsel *evsel, struct perf_cpu_map *cpus,
                                 struct perf_thread_map *threads);
 LIBPERF_API void perf_evsel__close(struct perf_evsel *evsel);
+LIBPERF_API void perf_evsel__close_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread,
                                 struct perf_counts_values *count);
 LIBPERF_API int perf_evsel__enable(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__enable_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API int perf_evsel__disable(struct perf_evsel *evsel);
+LIBPERF_API int perf_evsel__disable_cpu(struct perf_evsel *evsel, int cpu);
 LIBPERF_API struct perf_cpu_map *perf_evsel__cpus(struct perf_evsel *evsel);
 LIBPERF_API struct perf_thread_map *perf_evsel__threads(struct perf_evsel *evsel);
 LIBPERF_API struct perf_event_attr *perf_evsel__attr(struct perf_evsel *evsel);
index 436ce33..5da8296 100644 (file)
@@ -32,7 +32,7 @@
                "EventCode": "132",
                "EventName": "DTLB1_GPAGE_WRITES",
                "BriefDescription": "DTLB1 Two-Gigabyte Page Writes",
-               "PublicDescription": "Counter:132       Name:DTLB1_GPAGE_WRITES A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
+               "PublicDescription": "A translation entry has been written to the Level-1 Data Translation Lookaside Buffer for a two-gigabyte page."
        },
        {
                "Unit": "CPU-M-CF",
index 6861815..89e0707 100644 (file)
@@ -4,7 +4,7 @@
                "EventCode": "128",
                "EventName": "L1D_RO_EXCL_WRITES",
                "BriefDescription": "L1D Read-only Exclusive Writes",
-               "PublicDescription": "L1D_RO_EXCL_WRITES A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
+               "PublicDescription": "A directory write to the Level-1 Data cache where the line was originally in a Read-Only state in the cache but has been updated to be in the Exclusive state that allows stores to the cache line"
        },
        {
                "Unit": "CPU-M-CF",
index bc7151d..45a34ce 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 49c5f12..961fe43 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 113d19e..746734c 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 2ba32af..f946532 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index c80f16f..5402cd3 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index e501729..832f3cb 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index e244696..d69b2a8 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 9294769..5f465fd 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 603ff9c..3e909b3 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index c6b485b..50c0532 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 0ca539b..e7feb60 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index 047d7e1..21d7a0c 100644 (file)
     },
     {
         "BriefDescription": "Fraction of cycles spent in Kernel mode",
-        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:u / CPU_CLK_UNHALTED.REF_TSC",
+        "MetricExpr": "CPU_CLK_UNHALTED.REF_TSC:k / CPU_CLK_UNHALTED.REF_TSC",
         "MetricGroup": "Summary",
         "MetricName": "Kernel_Utilization"
     },
index a3c595f..1692529 100644 (file)
@@ -54,6 +54,7 @@ perf-y += unit_number__scnprintf.o
 perf-y += mem2node.o
 perf-y += maps.o
 perf-y += time-utils-test.o
+perf-y += genelf.o
 
 $(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
        $(call rule_mkdir)
index 7115aa3..5f05db7 100644 (file)
@@ -260,6 +260,11 @@ static struct test generic_tests[] = {
                .func = test__cpu_map_print,
        },
        {
+               .desc = "Merge cpu map",
+               .func = test__cpu_map_merge,
+       },
+
+       {
                .desc = "Probe SDT events",
                .func = test__sdt_event,
        },
@@ -297,6 +302,10 @@ static struct test generic_tests[] = {
                .func = test__time_utils,
        },
        {
+               .desc = "Test jit_write_elf",
+               .func = test__jit_write_elf,
+       },
+       {
                .desc = "maps__merge_in",
                .func = test__maps__merge_in,
        },
index 8a0d236..4ac5674 100644 (file)
@@ -120,3 +120,19 @@ int test__cpu_map_print(struct test *test __maybe_unused, int subtest __maybe_un
        TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1-10,12-20,22-30,32-40"));
        return 0;
 }
+
+int test__cpu_map_merge(struct test *test __maybe_unused, int subtest __maybe_unused)
+{
+       struct perf_cpu_map *a = perf_cpu_map__new("4,2,1");
+       struct perf_cpu_map *b = perf_cpu_map__new("4,5,7");
+       struct perf_cpu_map *c = perf_cpu_map__merge(a, b);
+       char buf[100];
+
+       TEST_ASSERT_VAL("failed to merge map: bad nr", c->nr == 5);
+       cpu_map__snprint(c, buf, sizeof(buf));
+       TEST_ASSERT_VAL("failed to merge map: bad result", !strcmp(buf, "1-2,4-5,7"));
+       perf_cpu_map__put(a);
+       perf_cpu_map__put(b);
+       perf_cpu_map__put(c);
+       return 0;
+}
index 1ee8704..1e8a9f5 100644 (file)
@@ -125,7 +125,7 @@ static int attach__cpu_disabled(struct evlist *evlist)
 
        evsel->core.attr.disabled = 1;
 
-       err = perf_evsel__open_per_cpu(evsel, cpus);
+       err = perf_evsel__open_per_cpu(evsel, cpus, -1);
        if (err) {
                if (err == -EACCES)
                        return TEST_SKIP;
@@ -152,7 +152,7 @@ static int attach__cpu_enabled(struct evlist *evlist)
                return -1;
        }
 
-       err = perf_evsel__open_per_cpu(evsel, cpus);
+       err = perf_evsel__open_per_cpu(evsel, cpus, -1);
        if (err == -EACCES)
                return TEST_SKIP;
 
diff --git a/tools/perf/tests/genelf.c b/tools/perf/tests/genelf.c
new file mode 100644 (file)
index 0000000..f797f98
--- /dev/null
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <linux/compiler.h>
+
+#include "debug.h"
+#include "tests.h"
+
+#ifdef HAVE_JITDUMP
+#include <libelf.h>
+#include "../util/genelf.h"
+#endif
+
+#define TEMPL "/tmp/perf-test-XXXXXX"
+
+int test__jit_write_elf(struct test *test __maybe_unused,
+                       int subtest __maybe_unused)
+{
+#ifdef HAVE_JITDUMP
+       static unsigned char x86_code[] = {
+               0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
+               0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
+               0xCD, 0x80            /* int $0x80 */
+       };
+       char path[PATH_MAX];
+       int fd, ret;
+
+       strcpy(path, TEMPL);
+
+       fd = mkstemp(path);
+       if (fd < 0) {
+               perror("mkstemp failed");
+               return TEST_FAIL;
+       }
+
+       pr_info("Writing jit code to: %s\n", path);
+
+       ret = jit_write_elf(fd, 0, "main", x86_code, sizeof(x86_code),
+                       NULL, 0, NULL, 0, 0);
+       close(fd);
+
+       unlink(path);
+
+       return ret ? TEST_FAIL : 0;
+#else
+       return TEST_SKIP;
+#endif
+}
index 25aea38..9a160fe 100644 (file)
@@ -98,6 +98,7 @@ int test__event_update(struct test *test, int subtest);
 int test__event_times(struct test *test, int subtest);
 int test__backward_ring_buffer(struct test *test, int subtest);
 int test__cpu_map_print(struct test *test, int subtest);
+int test__cpu_map_merge(struct test *test, int subtest);
 int test__sdt_event(struct test *test, int subtest);
 int test__is_printable_array(struct test *test, int subtest);
 int test__bitmap_print(struct test *test, int subtest);
@@ -109,6 +110,7 @@ int test__unit_number__scnprint(struct test *test, int subtest);
 int test__mem2node(struct test *t, int subtest);
 int test__maps__merge_in(struct test *t, int subtest);
 int test__time_utils(struct test *t, int subtest);
+int test__jit_write_elf(struct test *test, int subtest);
 
 bool test__bp_signal_is_supported(void);
 bool test__bp_account_is_supported(void);
index 1a8d3be..062ca84 100644 (file)
@@ -45,6 +45,7 @@ static size_t clone__scnprintf_flags(unsigned long flags, char *bf, size_t size,
        P_FLAG(NEWPID);
        P_FLAG(NEWNET);
        P_FLAG(IO);
+       P_FLAG(CLEAR_SIGHAND);
 #undef P_FLAG
 
        if (flags)
index 57943f3..3a442f0 100644 (file)
@@ -63,4 +63,5 @@ int cpu_map__build_map(struct perf_cpu_map *cpus, struct perf_cpu_map **res,
 
 int cpu_map__cpu(struct perf_cpu_map *cpus, int idx);
 bool cpu_map__has(struct perf_cpu_map *cpus, int cpu);
+
 #endif /* __PERF_CPUMAP_H */
index fdce590..1548237 100644 (file)
@@ -18,6 +18,7 @@
 #include "debug.h"
 #include "units.h"
 #include <internal/lib.h> // page_size
+#include "affinity.h"
 #include "../perf.h"
 #include "asm/bug.h"
 #include "bpf-event.h"
@@ -342,14 +343,63 @@ static int perf_evlist__nr_threads(struct evlist *evlist,
                return perf_thread_map__nr(evlist->core.threads);
 }
 
+void evlist__cpu_iter_start(struct evlist *evlist)
+{
+       struct evsel *pos;
+
+       /*
+        * Reset the per evsel cpu_iter. This is needed because
+        * each evsel's cpumap may have a different index space,
+        * and some operations need the index to modify
+        * the FD xyarray (e.g. open, close)
+        */
+       evlist__for_each_entry(evlist, pos)
+               pos->cpu_iter = 0;
+}
+
+bool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu)
+{
+       if (ev->cpu_iter >= ev->core.cpus->nr)
+               return true;
+       if (cpu >= 0 && ev->core.cpus->map[ev->cpu_iter] != cpu)
+               return true;
+       return false;
+}
+
+bool evsel__cpu_iter_skip(struct evsel *ev, int cpu)
+{
+       if (!evsel__cpu_iter_skip_no_inc(ev, cpu)) {
+               ev->cpu_iter++;
+               return false;
+       }
+       return true;
+}
+
 void evlist__disable(struct evlist *evlist)
 {
        struct evsel *pos;
+       struct affinity affinity;
+       int cpu, i;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
 
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evlist, pos) {
+                       if (evsel__cpu_iter_skip(pos, cpu))
+                               continue;
+                       if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
+                               continue;
+                       evsel__disable_cpu(pos, pos->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
-               if (pos->disabled || !perf_evsel__is_group_leader(pos) || !pos->core.fd)
+               if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
-               evsel__disable(pos);
+               pos->disabled = true;
        }
 
        evlist->enabled = false;
@@ -358,11 +408,28 @@ void evlist__disable(struct evlist *evlist)
 void evlist__enable(struct evlist *evlist)
 {
        struct evsel *pos;
+       struct affinity affinity;
+       int cpu, i;
+
+       if (affinity__setup(&affinity) < 0)
+               return;
 
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry(evlist, pos) {
+                       if (evsel__cpu_iter_skip(pos, cpu))
+                               continue;
+                       if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
+                               continue;
+                       evsel__enable_cpu(pos, pos->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
        evlist__for_each_entry(evlist, pos) {
                if (!perf_evsel__is_group_leader(pos) || !pos->core.fd)
                        continue;
-               evsel__enable(pos);
+               pos->disabled = false;
        }
 
        evlist->enabled = true;
@@ -1137,9 +1204,35 @@ void perf_evlist__set_selected(struct evlist *evlist,
 void evlist__close(struct evlist *evlist)
 {
        struct evsel *evsel;
+       struct affinity affinity;
+       int cpu, i;
 
-       evlist__for_each_entry_reverse(evlist, evsel)
-               evsel__close(evsel);
+       /*
+        * With perf record core.cpus is usually NULL.
+        * Use the old method to handle this for now.
+        */
+       if (!evlist->core.cpus) {
+               evlist__for_each_entry_reverse(evlist, evsel)
+                       evsel__close(evsel);
+               return;
+       }
+
+       if (affinity__setup(&affinity) < 0)
+               return;
+       evlist__for_each_cpu(evlist, i, cpu) {
+               affinity__set(&affinity, cpu);
+
+               evlist__for_each_entry_reverse(evlist, evsel) {
+                       if (evsel__cpu_iter_skip(evsel, cpu))
+                           continue;
+                       perf_evsel__close_cpu(&evsel->core, evsel->cpu_iter - 1);
+               }
+       }
+       affinity__cleanup(&affinity);
+       evlist__for_each_entry_reverse(evlist, evsel) {
+               perf_evsel__free_fd(&evsel->core);
+               perf_evsel__free_id(&evsel->core);
+       }
 }
 
 static int perf_evlist__create_syswide_maps(struct evlist *evlist)
@@ -1577,7 +1670,8 @@ void perf_evlist__force_leader(struct evlist *evlist)
 }
 
 struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
-                                                struct evsel *evsel)
+                                                struct evsel *evsel,
+                                               bool close)
 {
        struct evsel *c2, *leader;
        bool is_open = true;
@@ -1594,10 +1688,15 @@ struct evsel *perf_evlist__reset_weak_group(struct evlist *evsel_list,
                if (c2 == evsel)
                        is_open = false;
                if (c2->leader == leader) {
-                       if (is_open)
+                       if (is_open && close)
                                perf_evsel__close(&c2->core);
                        c2->leader = c2;
                        c2->core.nr_members = 0;
+                       /*
+                        * Set this for all former members of the group
+                        * to indicate they get reopened.
+                        */
+                       c2->reset_group = true;
                }
        }
        return leader;
index 3655b9e..f5bd5c3 100644 (file)
@@ -334,9 +334,17 @@ void perf_evlist__to_front(struct evlist *evlist,
 #define evlist__for_each_entry_safe(evlist, tmp, evsel) \
        __evlist__for_each_entry_safe(&(evlist)->core.entries, tmp, evsel)
 
+#define evlist__for_each_cpu(evlist, index, cpu)       \
+       evlist__cpu_iter_start(evlist);                 \
+       perf_cpu_map__for_each_cpu (cpu, index, (evlist)->core.all_cpus)
+
 void perf_evlist__set_tracking_event(struct evlist *evlist,
                                     struct evsel *tracking_evsel);
 
+void evlist__cpu_iter_start(struct evlist *evlist);
+bool evsel__cpu_iter_skip(struct evsel *ev, int cpu);
+bool evsel__cpu_iter_skip_no_inc(struct evsel *ev, int cpu);
+
 struct evsel *
 perf_evlist__find_evsel_by_str(struct evlist *evlist, const char *str);
 
@@ -348,5 +356,6 @@ bool perf_evlist__exclude_kernel(struct evlist *evlist);
 void perf_evlist__force_leader(struct evlist *evlist);
 
 struct evsel *perf_evlist__reset_weak_group(struct evlist *evlist,
-                                                struct evsel *evsel);
+                                                struct evsel *evsel,
+                                               bool close);
 #endif /* __PERF_EVLIST_H */
index f4dea05..a69e642 100644 (file)
@@ -1223,16 +1223,27 @@ int perf_evsel__append_addr_filter(struct evsel *evsel, const char *filter)
        return perf_evsel__append_filter(evsel, "%s,%s", filter);
 }
 
+/* Caller has to clear disabled after going through all CPUs. */
+int evsel__enable_cpu(struct evsel *evsel, int cpu)
+{
+       return perf_evsel__enable_cpu(&evsel->core, cpu);
+}
+
 int evsel__enable(struct evsel *evsel)
 {
        int err = perf_evsel__enable(&evsel->core);
 
        if (!err)
                evsel->disabled = false;
-
        return err;
 }
 
+/* Caller has to set disabled after going through all CPUs. */
+int evsel__disable_cpu(struct evsel *evsel, int cpu)
+{
+       return perf_evsel__disable_cpu(&evsel->core, cpu);
+}
+
 int evsel__disable(struct evsel *evsel)
 {
        int err = perf_evsel__disable(&evsel->core);
@@ -1587,8 +1598,9 @@ static int perf_event_open(struct evsel *evsel,
        return fd;
 }
 
-int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
-               struct perf_thread_map *threads)
+static int evsel__open_cpu(struct evsel *evsel, struct perf_cpu_map *cpus,
+               struct perf_thread_map *threads,
+               int start_cpu, int end_cpu)
 {
        int cpu, thread, nthreads;
        unsigned long flags = PERF_FLAG_FD_CLOEXEC;
@@ -1665,7 +1677,7 @@ retry_sample_id:
 
        display_attr(&evsel->core.attr);
 
-       for (cpu = 0; cpu < cpus->nr; cpu++) {
+       for (cpu = start_cpu; cpu < end_cpu; cpu++) {
 
                for (thread = 0; thread < nthreads; thread++) {
                        int fd, group_fd;
@@ -1843,6 +1855,12 @@ out_close:
        return err;
 }
 
+int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
+               struct perf_thread_map *threads)
+{
+       return evsel__open_cpu(evsel, cpus, threads, 0, cpus ? cpus->nr : 1);
+}
+
 void evsel__close(struct evsel *evsel)
 {
        perf_evsel__close(&evsel->core);
@@ -1850,9 +1868,14 @@ void evsel__close(struct evsel *evsel)
 }
 
 int perf_evsel__open_per_cpu(struct evsel *evsel,
-                            struct perf_cpu_map *cpus)
+                            struct perf_cpu_map *cpus,
+                            int cpu)
 {
-       return evsel__open(evsel, cpus, NULL);
+       if (cpu == -1)
+               return evsel__open_cpu(evsel, cpus, NULL, 0,
+                                       cpus ? cpus->nr : 1);
+
+       return evsel__open_cpu(evsel, cpus, NULL, cpu, cpu + 1);
 }
 
 int perf_evsel__open_per_thread(struct evsel *evsel,
index ddc5ee6..dc14f4a 100644 (file)
@@ -86,6 +86,7 @@ struct evsel {
        struct list_head        config_terms;
        struct bpf_object       *bpf_obj;
        int                     bpf_fd;
+       int                     err;
        bool                    auto_merge_stats;
        bool                    merged_stat;
        const char *            metric_expr;
@@ -94,7 +95,10 @@ struct evsel {
        struct evsel            *metric_leader;
        bool                    collect_stat;
        bool                    weak_group;
+       bool                    reset_group;
+       bool                    errored;
        bool                    percore;
+       int                     cpu_iter;
        const char              *pmu_name;
        struct {
                perf_evsel__sb_cb_t     *cb;
@@ -218,11 +222,14 @@ int perf_evsel__set_filter(struct evsel *evsel, const char *filter);
 int perf_evsel__append_tp_filter(struct evsel *evsel, const char *filter);
 int perf_evsel__append_addr_filter(struct evsel *evsel,
                                   const char *filter);
+int evsel__enable_cpu(struct evsel *evsel, int cpu);
 int evsel__enable(struct evsel *evsel);
 int evsel__disable(struct evsel *evsel);
+int evsel__disable_cpu(struct evsel *evsel, int cpu);
 
 int perf_evsel__open_per_cpu(struct evsel *evsel,
-                            struct perf_cpu_map *cpus);
+                            struct perf_cpu_map *cpus,
+                            int cpu);
 int perf_evsel__open_per_thread(struct evsel *evsel,
                                struct perf_thread_map *threads);
 int evsel__open(struct evsel *evsel, struct perf_cpu_map *cpus,
index f9f18b8..aed4980 100644 (file)
@@ -8,15 +8,12 @@
  */
 
 #include <sys/types.h>
-#include <stdio.h>
-#include <getopt.h>
 #include <stddef.h>
 #include <libelf.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <inttypes.h>
-#include <limits.h>
 #include <fcntl.h>
 #include <err.h>
 #ifdef HAVE_DWARF_SUPPORT
@@ -31,8 +28,6 @@
 #define NT_GNU_BUILD_ID 3
 #endif
 
-#define JVMTI
-
 #define BUILD_ID_URANDOM /* different uuid for each run */
 
 #ifdef HAVE_LIBCRYPTO
@@ -511,44 +506,3 @@ error:
 
        return retval;
 }
-
-#ifndef JVMTI
-
-static unsigned char x86_code[] = {
-    0xBB, 0x2A, 0x00, 0x00, 0x00, /* movl $42, %ebx */
-    0xB8, 0x01, 0x00, 0x00, 0x00, /* movl $1, %eax */
-    0xCD, 0x80            /* int $0x80 */
-};
-
-static struct options options;
-
-int main(int argc, char **argv)
-{
-       int c, fd, ret;
-
-       while ((c = getopt(argc, argv, "o:h")) != -1) {
-               switch (c) {
-               case 'o':
-                       options.output = optarg;
-                       break;
-               case 'h':
-                       printf("Usage: genelf -o output_file [-h]\n");
-                       return 0;
-               default:
-                       errx(1, "unknown option");
-               }
-       }
-
-       fd = open(options.output, O_CREAT|O_TRUNC|O_RDWR, 0666);
-       if (fd == -1)
-               err(1, "cannot create file %s", options.output);
-
-       ret = jit_write_elf(fd, "main", x86_code, sizeof(x86_code));
-       close(fd);
-
-       if (ret != 0)
-               unlink(options.output);
-
-       return ret;
-}
-#endif
index becc2d1..93ad278 100644 (file)
@@ -850,7 +850,7 @@ int __weak strcmp_cpuid_str(const char *mapcpuid, const char *cpuid)
  */
 int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
 {
-       return -1;
+       return ENOSYS; /* Not implemented */
 }
 
 static int write_cpuid(struct feat_fd *ff,
@@ -1089,21 +1089,18 @@ static void cpu_cache_level__fprintf(FILE *out, struct cpu_cache_level *c)
        fprintf(out, "L%d %-15s %8s [%s]\n", c->level, c->type, c->size, c->map);
 }
 
-static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
+#define MAX_CACHE_LVL 4
+
+static int build_caches(struct cpu_cache_level caches[], u32 *cntp)
 {
        u32 i, cnt = 0;
-       long ncpus;
        u32 nr, cpu;
        u16 level;
 
-       ncpus = sysconf(_SC_NPROCESSORS_CONF);
-       if (ncpus < 0)
-               return -1;
-
-       nr = (u32)(ncpus & UINT_MAX);
+       nr = cpu__max_cpu();
 
        for (cpu = 0; cpu < nr; cpu++) {
-               for (level = 0; level < 10; level++) {
+               for (level = 0; level < MAX_CACHE_LVL; level++) {
                        struct cpu_cache_level c;
                        int err;
 
@@ -1123,18 +1120,12 @@ static int build_caches(struct cpu_cache_level caches[], u32 size, u32 *cntp)
                                caches[cnt++] = c;
                        else
                                cpu_cache_level__free(&c);
-
-                       if (WARN_ONCE(cnt == size, "way too many cpu caches.."))
-                               goto out;
                }
        }
- out:
        *cntp = cnt;
        return 0;
 }
 
-#define MAX_CACHE_LVL 4
-
 static int write_cache(struct feat_fd *ff,
                       struct evlist *evlist __maybe_unused)
 {
@@ -1143,7 +1134,7 @@ static int write_cache(struct feat_fd *ff,
        u32 cnt = 0, i, version = 1;
        int ret;
 
-       ret = build_caches(caches, max_caches, &cnt);
+       ret = build_caches(caches, &cnt);
        if (ret)
                goto out;
 
index 4528690..0aa63ae 100644 (file)
@@ -339,10 +339,10 @@ static inline void perf_hpp__prepend_sort_field(struct perf_hpp_fmt *format)
        list_for_each_entry_safe(format, tmp, &(_list)->sorts, sort_list)
 
 #define hists__for_each_format(hists, format) \
-       perf_hpp_list__for_each_format((hists)->hpp_list, fmt)
+       perf_hpp_list__for_each_format((hists)->hpp_list, format)
 
 #define hists__for_each_sort_list(hists, format) \
-       perf_hpp_list__for_each_sort_list((hists)->hpp_list, fmt)
+       perf_hpp_list__for_each_sort_list((hists)->hpp_list, format)
 
 extern struct perf_hpp_fmt perf_hpp__format[];
 
index f01d48a..b8a5159 100644 (file)
@@ -5,10 +5,93 @@
 
 /* linkage.h ... for including arch/x86/lib/memcpy_64.S */
 
-#define ENTRY(name)                            \
-       .globl name;                            \
+/* Some toolchains use other characters (e.g. '`') to mark new line in macro */
+#ifndef ASM_NL
+#define ASM_NL          ;
+#endif
+
+#ifndef __ALIGN
+#define __ALIGN                .align 4,0x90
+#define __ALIGN_STR    ".align 4,0x90"
+#endif
+
+/* SYM_T_FUNC -- type used by assembler to mark functions */
+#ifndef SYM_T_FUNC
+#define SYM_T_FUNC                             STT_FUNC
+#endif
+
+/* SYM_A_* -- align the symbol? */
+#define SYM_A_ALIGN                            ALIGN
+
+/* SYM_L_* -- linkage of symbols */
+#define SYM_L_GLOBAL(name)                     .globl name
+#define SYM_L_LOCAL(name)                      /* nothing */
+
+#define ALIGN __ALIGN
+
+/* === generic annotations === */
+
+/* SYM_ENTRY -- use only if you have to for non-paired symbols */
+#ifndef SYM_ENTRY
+#define SYM_ENTRY(name, linkage, align...)             \
+       linkage(name) ASM_NL                            \
+       align ASM_NL                                    \
        name:
+#endif
+
+/* SYM_START -- use only if you have to */
+#ifndef SYM_START
+#define SYM_START(name, linkage, align...)             \
+       SYM_ENTRY(name, linkage, align)
+#endif
+
+/* SYM_END -- use only if you have to */
+#ifndef SYM_END
+#define SYM_END(name, sym_type)                                \
+       .type name sym_type ASM_NL                      \
+       .size name, .-name
+#endif
+
+/*
+ * SYM_FUNC_START_ALIAS -- use where there are two global names for one
+ * function
+ */
+#ifndef SYM_FUNC_START_ALIAS
+#define SYM_FUNC_START_ALIAS(name)                     \
+       SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_START -- use for global functions */
+#ifndef SYM_FUNC_START
+/*
+ * The same as SYM_FUNC_START_ALIAS, but we will need to distinguish these two
+ * later.
+ */
+#define SYM_FUNC_START(name)                           \
+       SYM_START(name, SYM_L_GLOBAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_START_LOCAL -- use for local functions */
+#ifndef SYM_FUNC_START_LOCAL
+/* the same as SYM_FUNC_START_LOCAL_ALIAS, see comment near SYM_FUNC_START */
+#define SYM_FUNC_START_LOCAL(name)                     \
+       SYM_START(name, SYM_L_LOCAL, SYM_A_ALIGN)
+#endif
+
+/* SYM_FUNC_END_ALIAS -- the end of LOCAL_ALIASed or ALIASed function */
+#ifndef SYM_FUNC_END_ALIAS
+#define SYM_FUNC_END_ALIAS(name)                       \
+       SYM_END(name, SYM_T_FUNC)
+#endif
 
-#define ENDPROC(name)
+/*
+ * SYM_FUNC_END -- the end of SYM_FUNC_START_LOCAL, SYM_FUNC_START,
+ * SYM_FUNC_START_WEAK, ...
+ */
+#ifndef SYM_FUNC_END
+/* the same as SYM_FUNC_END_ALIAS, see comment near SYM_FUNC_START */
+#define SYM_FUNC_END(name)                             \
+       SYM_END(name, SYM_T_FUNC)
+#endif
 
 #endif /* PERF_LINUX_LINKAGE_H_ */
index 416d174..c8c5410 100644 (file)
@@ -2446,6 +2446,7 @@ static int append_inlines(struct callchain_cursor *cursor, struct map_symbol *ms
 
        list_for_each_entry(ilist, &inline_node->val, list) {
                struct map_symbol ilist_ms = {
+                       .maps = ms->maps,
                        .map = map,
                        .sym = ilist->symbol,
                };
index 6a4d350..02aee94 100644 (file)
@@ -103,8 +103,11 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                if (!strcmp(ev->name, ids[i])) {
                        if (!metric_events[i])
                                metric_events[i] = ev;
+                       i++;
+                       if (i == idnum)
+                               break;
                } else {
-                       if (++i == idnum) {
+                       if (i + 1 == idnum) {
                                /* Discard the whole match and start again */
                                i = 0;
                                memset(metric_events, 0,
@@ -124,7 +127,7 @@ static struct evsel *find_evsel_group(struct evlist *perf_evlist,
                }
        }
 
-       if (i != idnum - 1) {
+       if (i != idnum) {
                /* Not whole match */
                return NULL;
        }
index 345b5cc..9fcba28 100644 (file)
@@ -2681,12 +2681,12 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
                        ret = sort_dimension__add(list, tok, evlist, level);
                        if (ret == -EINVAL) {
                                if (!cacheline_size() && !strncasecmp(tok, "dcacheline", strlen(tok)))
-                                       pr_err("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
+                                       ui__error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
                                else
-                                       pr_err("Invalid --sort key: `%s'", tok);
+                                       ui__error("Invalid --sort key: `%s'", tok);
                                break;
                        } else if (ret == -ESRCH) {
-                               pr_err("Unknown --sort key: `%s'", tok);
+                               ui__error("Unknown --sort key: `%s'", tok);
                                break;
                        }
                }
@@ -2743,7 +2743,7 @@ static int setup_sort_order(struct evlist *evlist)
                return 0;
 
        if (sort_order[1] == '\0') {
-               pr_err("Invalid --sort key: `+'");
+               ui__error("Invalid --sort key: `+'");
                return -EINVAL;
        }
 
@@ -2959,6 +2959,9 @@ int output_field_add(struct perf_hpp_list *list, char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
+               if (sort__mode != SORT_MODE__MEMORY)
+                       return -EINVAL;
+
                return __sort_dimension__add_output(list, sd);
        }
 
@@ -2968,6 +2971,9 @@ int output_field_add(struct perf_hpp_list *list, char *tok)
                if (strncasecmp(tok, sd->name, strlen(tok)))
                        continue;
 
+               if (sort__mode != SORT_MODE__BRANCH)
+                       return -EINVAL;
+
                return __sort_dimension__add_output(list, sd);
        }
 
@@ -3034,7 +3040,7 @@ static int __setup_output_field(void)
                strp++;
 
        if (!strlen(strp)) {
-               pr_err("Invalid --fields key: `+'");
+               ui__error("Invalid --fields key: `+'");
                goto out;
        }
 
index 332cb73..5f26137 100644 (file)
@@ -464,7 +464,8 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp)
 
 int create_perf_stat_counter(struct evsel *evsel,
                             struct perf_stat_config *config,
-                            struct target *target)
+                            struct target *target,
+                            int cpu)
 {
        struct perf_event_attr *attr = &evsel->core.attr;
        struct evsel *leader = evsel->leader;
@@ -518,7 +519,7 @@ int create_perf_stat_counter(struct evsel *evsel,
        }
 
        if (target__has_cpu(target) && !target__has_per_thread(target))
-               return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel));
+               return perf_evsel__open_per_cpu(evsel, evsel__cpus(evsel), cpu);
 
        return perf_evsel__open_per_thread(evsel, evsel->core.threads);
 }
index bfa9aaf..fb990ef 100644 (file)
@@ -214,7 +214,8 @@ size_t perf_event__fprintf_stat_config(union perf_event *event, FILE *fp);
 
 int create_perf_stat_counter(struct evsel *evsel,
                             struct perf_stat_config *config,
-                            struct target *target);
+                            struct target *target,
+                            int cpu);
 void
 perf_evlist__print_counters(struct evlist *evlist,
                            struct perf_stat_config *config,
index 6658fbf..1965aef 100644 (file)
@@ -920,6 +920,9 @@ static int dso__process_kernel_symbol(struct dso *dso, struct map *map,
                if (curr_map == NULL)
                        return -1;
 
+               if (curr_dso->kernel)
+                       map__kmap(curr_map)->kmaps = kmaps;
+
                if (adjust_kernel_syms) {
                        curr_map->start  = shdr->sh_addr + ref_reloc(kmap);
                        curr_map->end    = curr_map->start + shdr->sh_size;
index efe06d6..e59eb9e 100755 (executable)
@@ -31,15 +31,12 @@ class KunitStatus(Enum):
        TEST_FAILURE = auto()
 
 def create_default_kunitconfig():
-       if not os.path.exists(kunit_kernel.KUNITCONFIG_PATH):
+       if not os.path.exists(kunit_kernel.kunitconfig_path):
                shutil.copyfile('arch/um/configs/kunit_defconfig',
-                               kunit_kernel.KUNITCONFIG_PATH)
+                               kunit_kernel.kunitconfig_path)
 
 def run_tests(linux: kunit_kernel.LinuxSourceTree,
              request: KunitRequest) -> KunitResult:
-       if request.defconfig:
-               create_default_kunitconfig()
-
        config_start = time.time()
        success = linux.build_reconfig(request.build_dir)
        config_end = time.time()
@@ -108,15 +105,22 @@ def main(argv, linux=None):
        run_parser.add_argument('--build_dir',
                                help='As in the make command, it specifies the build '
                                'directory.',
-                               type=str, default=None, metavar='build_dir')
+                               type=str, default='', metavar='build_dir')
 
        run_parser.add_argument('--defconfig',
-                               help='Uses a default kunitconfig.',
+                               help='Uses a default .kunitconfig.',
                                action='store_true')
 
        cli_args = parser.parse_args(argv)
 
        if cli_args.subcommand == 'run':
+               if cli_args.build_dir:
+                       if not os.path.exists(cli_args.build_dir):
+                               os.mkdir(cli_args.build_dir)
+                       kunit_kernel.kunitconfig_path = os.path.join(
+                               cli_args.build_dir,
+                               kunit_kernel.kunitconfig_path)
+
                if cli_args.defconfig:
                        create_default_kunitconfig()
 
index bf38768..cc5d844 100644 (file)
@@ -14,7 +14,7 @@ import os
 import kunit_config
 
 KCONFIG_PATH = '.config'
-KUNITCONFIG_PATH = 'kunitconfig'
+kunitconfig_path = '.kunitconfig'
 
 class ConfigError(Exception):
        """Represents an error trying to configure the Linux kernel."""
@@ -82,7 +82,7 @@ class LinuxSourceTree(object):
 
        def __init__(self):
                self._kconfig = kunit_config.Kconfig()
-               self._kconfig.read_from_file(KUNITCONFIG_PATH)
+               self._kconfig.read_from_file(kunitconfig_path)
                self._ops = LinuxSourceTreeOperations()
 
        def clean(self):
@@ -111,7 +111,7 @@ class LinuxSourceTree(object):
                return True
 
        def build_reconfig(self, build_dir):
-               """Creates a new .config if it is not a subset of the kunitconfig."""
+               """Creates a new .config if it is not a subset of the .kunitconfig."""
                kconfig_path = get_kconfig_path(build_dir)
                if os.path.exists(kconfig_path):
                        existing_kconfig = kunit_config.Kconfig()
@@ -140,10 +140,10 @@ class LinuxSourceTree(object):
                        return False
                return True
 
-       def run_kernel(self, args=[], timeout=None, build_dir=None):
+       def run_kernel(self, args=[], timeout=None, build_dir=''):
                args.extend(['mem=256M'])
                process = self._ops.linux_bin(args, timeout, build_dir)
-               with open('test.log', 'w') as f:
+               with open(os.path.join(build_dir, 'test.log'), 'w') as f:
                        for line in process.stdout:
                                f.write(line.rstrip().decode('ascii') + '\n')
                                yield line.rstrip().decode('ascii')
index 4a12baa..cba9775 100755 (executable)
@@ -174,6 +174,7 @@ class KUnitMainTest(unittest.TestCase):
                kunit.main(['run'], self.linux_source_mock)
                assert self.linux_source_mock.build_reconfig.call_count == 1
                assert self.linux_source_mock.run_kernel.call_count == 1
+               self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='', timeout=300)
                self.print_mock.assert_any_call(StrContains('Testing complete.'))
 
        def test_run_passes_args_fail(self):
@@ -199,7 +200,14 @@ class KUnitMainTest(unittest.TestCase):
                timeout = 3453
                kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock)
                assert self.linux_source_mock.build_reconfig.call_count == 1
-               self.linux_source_mock.run_kernel.assert_called_once_with(timeout=timeout)
+               self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='', timeout=timeout)
+               self.print_mock.assert_any_call(StrContains('Testing complete.'))
+
+       def test_run_builddir(self):
+               build_dir = '.kunit'
+               kunit.main(['run', '--build_dir', build_dir], self.linux_source_mock)
+               assert self.linux_source_mock.build_reconfig.call_count == 1
+               self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=build_dir, timeout=300)
                self.print_mock.assert_any_call(StrContains('Testing complete.'))
 
 if __name__ == '__main__':
index c4a9196..6aca8d5 100644 (file)
@@ -5,6 +5,7 @@ ldflags-y += --wrap=devm_ioremap_nocache
 ldflags-y += --wrap=devm_memremap
 ldflags-y += --wrap=devm_memunmap
 ldflags-y += --wrap=ioremap_nocache
+ldflags-y += --wrap=ioremap
 ldflags-y += --wrap=iounmap
 ldflags-y += --wrap=memunmap
 ldflags-y += --wrap=__devm_request_region
index 3f55f2f..6271ac7 100644 (file)
@@ -193,6 +193,12 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset, unsigned long size)
 }
 EXPORT_SYMBOL(__wrap_ioremap_nocache);
 
+void __iomem *__wrap_ioremap(resource_size_t offset, unsigned long size)
+{
+       return __nfit_test_ioremap(offset, size, ioremap);
+}
+EXPORT_SYMBOL(__wrap_ioremap);
+
 void __iomem *__wrap_ioremap_wc(resource_size_t offset, unsigned long size)
 {
        return __nfit_test_ioremap(offset, size, ioremap_wc);
index 4196524..1ff0a9f 100644 (file)
@@ -40,3 +40,4 @@ xdping
 test_cpp
 /no_alu32
 /bpf_gcc
+bpf_helper_defs.h
index e0fe01d..e2fd6f8 100644 (file)
@@ -120,9 +120,9 @@ force:
 $(BPFOBJ): force
        $(MAKE) -C $(BPFDIR) OUTPUT=$(OUTPUT)/
 
-BPF_HELPERS := $(BPFDIR)/bpf_helper_defs.h $(wildcard $(BPFDIR)/bpf_*.h)
-$(BPFDIR)/bpf_helper_defs.h:
-       $(MAKE) -C $(BPFDIR) OUTPUT=$(OUTPUT)/ bpf_helper_defs.h
+BPF_HELPERS := $(OUTPUT)/bpf_helper_defs.h $(wildcard $(BPFDIR)/bpf_*.h)
+$(OUTPUT)/bpf_helper_defs.h:
+       $(MAKE) -C $(BPFDIR) OUTPUT=$(OUTPUT)/ $(OUTPUT)/bpf_helper_defs.h
 
 # Get Clang's default includes on this system, as opposed to those seen by
 # '-target bpf'. This fixes "missing" files on some architectures/distros,
diff --git a/tools/testing/selftests/bpf/test_ftrace.sh b/tools/testing/selftests/bpf/test_ftrace.sh
new file mode 100755 (executable)
index 0000000..20de7bb
--- /dev/null
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+TR=/sys/kernel/debug/tracing/
+clear_trace() { # reset trace output
+    echo > $TR/trace
+}
+
+disable_tracing() { # stop trace recording
+    echo 0 > $TR/tracing_on
+}
+
+enable_tracing() { # start trace recording
+    echo 1 > $TR/tracing_on
+}
+
+reset_tracer() { # reset the current tracer
+    echo nop > $TR/current_tracer
+}
+
+disable_tracing
+clear_trace
+
+echo "" > $TR/set_ftrace_filter
+echo '*printk* *console* *wake* *serial* *lock*' > $TR/set_ftrace_notrace
+
+echo "bpf_prog_test*" > $TR/set_graph_function
+echo "" > $TR/set_graph_notrace
+
+echo function_graph > $TR/current_tracer
+
+enable_tracing
+./test_progs -t fentry
+./test_progs -t fexit
+disable_tracing
+clear_trace
+
+reset_tracer
+
+exit 0
index d27fd92..87eaa49 100644 (file)
@@ -408,10 +408,10 @@ static void update_map(int fd, int index)
        assert(!bpf_map_update_elem(fd, &index, &value, 0));
 }
 
-static int create_prog_dummy1(enum bpf_prog_type prog_type)
+static int create_prog_dummy_simple(enum bpf_prog_type prog_type, int ret)
 {
        struct bpf_insn prog[] = {
-               BPF_MOV64_IMM(BPF_REG_0, 42),
+               BPF_MOV64_IMM(BPF_REG_0, ret),
                BPF_EXIT_INSN(),
        };
 
@@ -419,14 +419,15 @@ static int create_prog_dummy1(enum bpf_prog_type prog_type)
                                ARRAY_SIZE(prog), "GPL", 0, NULL, 0);
 }
 
-static int create_prog_dummy2(enum bpf_prog_type prog_type, int mfd, int idx)
+static int create_prog_dummy_loop(enum bpf_prog_type prog_type, int mfd,
+                                 int idx, int ret)
 {
        struct bpf_insn prog[] = {
                BPF_MOV64_IMM(BPF_REG_3, idx),
                BPF_LD_MAP_FD(BPF_REG_2, mfd),
                BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0,
                             BPF_FUNC_tail_call),
-               BPF_MOV64_IMM(BPF_REG_0, 41),
+               BPF_MOV64_IMM(BPF_REG_0, ret),
                BPF_EXIT_INSN(),
        };
 
@@ -435,10 +436,9 @@ static int create_prog_dummy2(enum bpf_prog_type prog_type, int mfd, int idx)
 }
 
 static int create_prog_array(enum bpf_prog_type prog_type, uint32_t max_elem,
-                            int p1key)
+                            int p1key, int p2key, int p3key)
 {
-       int p2key = 1;
-       int mfd, p1fd, p2fd;
+       int mfd, p1fd, p2fd, p3fd;
 
        mfd = bpf_create_map(BPF_MAP_TYPE_PROG_ARRAY, sizeof(int),
                             sizeof(int), max_elem, 0);
@@ -449,23 +449,24 @@ static int create_prog_array(enum bpf_prog_type prog_type, uint32_t max_elem,
                return -1;
        }
 
-       p1fd = create_prog_dummy1(prog_type);
-       p2fd = create_prog_dummy2(prog_type, mfd, p2key);
-       if (p1fd < 0 || p2fd < 0)
-               goto out;
+       p1fd = create_prog_dummy_simple(prog_type, 42);
+       p2fd = create_prog_dummy_loop(prog_type, mfd, p2key, 41);
+       p3fd = create_prog_dummy_simple(prog_type, 24);
+       if (p1fd < 0 || p2fd < 0 || p3fd < 0)
+               goto err;
        if (bpf_map_update_elem(mfd, &p1key, &p1fd, BPF_ANY) < 0)
-               goto out;
+               goto err;
        if (bpf_map_update_elem(mfd, &p2key, &p2fd, BPF_ANY) < 0)
-               goto out;
+               goto err;
+       if (bpf_map_update_elem(mfd, &p3key, &p3fd, BPF_ANY) < 0) {
+err:
+               close(mfd);
+               mfd = -1;
+       }
+       close(p3fd);
        close(p2fd);
        close(p1fd);
-
        return mfd;
-out:
-       close(p2fd);
-       close(p1fd);
-       close(mfd);
-       return -1;
 }
 
 static int create_map_in_map(void)
@@ -684,7 +685,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
        }
 
        if (*fixup_prog1) {
-               map_fds[4] = create_prog_array(prog_type, 4, 0);
+               map_fds[4] = create_prog_array(prog_type, 4, 0, 1, 2);
                do {
                        prog[*fixup_prog1].imm = map_fds[4];
                        fixup_prog1++;
@@ -692,7 +693,7 @@ static void do_test_fixup(struct bpf_test *test, enum bpf_prog_type prog_type,
        }
 
        if (*fixup_prog2) {
-               map_fds[5] = create_prog_array(prog_type, 8, 7);
+               map_fds[5] = create_prog_array(prog_type, 8, 7, 1, 2);
                do {
                        prog[*fixup_prog2].imm = map_fds[5];
                        fixup_prog2++;
index ebcbf15..604b461 100644 (file)
        BPF_MOV64_REG(BPF_REG_1, BPF_REG_0),
        BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 7),
        /* bpf_tail_call() */
-       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_MOV64_IMM(BPF_REG_3, 3),
        BPF_LD_MAP_FD(BPF_REG_2, 0),
        BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
        BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
        BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 1),
        BPF_EMIT_CALL(BPF_FUNC_sk_release),
        /* bpf_tail_call() */
-       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_MOV64_IMM(BPF_REG_3, 3),
        BPF_LD_MAP_FD(BPF_REG_2, 0),
        BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
        BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
        BPF_SK_LOOKUP(sk_lookup_tcp),
        /* bpf_tail_call() */
        BPF_MOV64_REG(BPF_REG_6, BPF_REG_0),
-       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_MOV64_IMM(BPF_REG_3, 3),
        BPF_LD_MAP_FD(BPF_REG_2, 0),
        BPF_MOV64_REG(BPF_REG_1, BPF_REG_7),
        BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
index a9a8f62..94c399d 100644 (file)
 {
        "runtime/jit: tail_call within bounds, no prog",
        .insns = {
+       BPF_MOV64_IMM(BPF_REG_3, 3),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_prog1 = { 1 },
+       .result = ACCEPT,
+       .retval = 1,
+},
+{
+       "runtime/jit: tail_call within bounds, key 2",
+       .insns = {
        BPF_MOV64_IMM(BPF_REG_3, 2),
        BPF_LD_MAP_FD(BPF_REG_2, 0),
        BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
        },
        .fixup_prog1 = { 1 },
        .result = ACCEPT,
+       .retval = 24,
+},
+{
+       "runtime/jit: tail_call within bounds, key 2 / key 2, first branch",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 13),
+       BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
+       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 3),
+       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_prog1 = { 5, 9 },
+       .result = ACCEPT,
+       .retval = 24,
+},
+{
+       "runtime/jit: tail_call within bounds, key 2 / key 2, second branch",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 14),
+       BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
+       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 3),
+       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_prog1 = { 5, 9 },
+       .result = ACCEPT,
+       .retval = 24,
+},
+{
+       "runtime/jit: tail_call within bounds, key 0 / key 2, first branch",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 13),
+       BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 3),
+       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_prog1 = { 5, 9 },
+       .result = ACCEPT,
+       .retval = 24,
+},
+{
+       "runtime/jit: tail_call within bounds, key 0 / key 2, second branch",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 14),
+       BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 3),
+       BPF_MOV64_IMM(BPF_REG_3, 2),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_prog1 = { 5, 9 },
+       .result = ACCEPT,
+       .retval = 42,
+},
+{
+       "runtime/jit: tail_call within bounds, different maps, first branch",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 13),
+       BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 3),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_prog1 = { 5 },
+       .fixup_prog2 = { 9 },
+       .result_unpriv = REJECT,
+       .errstr_unpriv = "tail_call abusing map_ptr",
+       .result = ACCEPT,
        .retval = 1,
 },
 {
+       "runtime/jit: tail_call within bounds, different maps, second branch",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 14),
+       BPF_STX_MEM(BPF_B, BPF_REG_1, BPF_REG_0,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1,
+                   offsetof(struct __sk_buff, cb[0])),
+       BPF_JMP_IMM(BPF_JEQ, BPF_REG_0, 13, 4),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_JMP_IMM(BPF_JA, 0, 0, 3),
+       BPF_MOV64_IMM(BPF_REG_3, 0),
+       BPF_LD_MAP_FD(BPF_REG_2, 0),
+       BPF_RAW_INSN(BPF_JMP | BPF_CALL, 0, 0, 0, BPF_FUNC_tail_call),
+       BPF_MOV64_IMM(BPF_REG_0, 1),
+       BPF_EXIT_INSN(),
+       },
+       .fixup_prog1 = { 5 },
+       .fixup_prog2 = { 9 },
+       .result_unpriv = REJECT,
+       .errstr_unpriv = "tail_call abusing map_ptr",
+       .result = ACCEPT,
+       .retval = 42,
+},
+{
        "runtime/jit: tail_call out of bounds",
        .insns = {
        BPF_MOV64_IMM(BPF_REG_3, 256),
index 47315fe..24dd8ed 100755 (executable)
@@ -232,7 +232,7 @@ test_mc_aware()
        stop_traffic
        local ucth1=${uc_rate[1]}
 
-       start_traffic $h1 own bc bc
+       start_traffic $h1 192.0.2.65 bc bc
 
        local d0=$(date +%s)
        local t0=$(ethtool_stats_get $h3 rx_octets_prio_0)
@@ -254,7 +254,11 @@ test_mc_aware()
                        ret = 100 * ($ucth1 - $ucth2) / $ucth1
                        if (ret > 0) { ret } else { 0 }
                    ")
-       check_err $(bc <<< "$deg > 25")
+
+       # Minimum shaper of 200Mbps on MC TCs should cause about 20% of
+       # degradation on 1Gbps link.
+       check_err $(bc <<< "$deg < 15") "Minimum shaper not in effect"
+       check_err $(bc <<< "$deg > 25") "MC traffic degrades UC performance too much"
 
        local interval=$((d1 - d0))
        local mc_ir=$(rate $u0 $u1 $interval)
index e62f3d4..78ae4aa 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 CFLAGS += -I../../../../../usr/include/
-LDFLAGS += -lpthread
+LDLIBS += -lpthread
 TEST_GEN_PROGS := epoll_wakeup_test
 
 include ../../lib.mk
index b879305..5b8c0fe 100755 (executable)
@@ -34,6 +34,12 @@ test_modprobe()
 
 check_mods()
 {
+       local uid=$(id -u)
+       if [ $uid -ne 0 ]; then
+               echo "skip all tests: must be run as root" >&2
+               exit $ksft_skip
+       fi
+
        trap "test_modprobe" EXIT
        if [ ! -d $DIR ]; then
                modprobe test_firmware
index 36fb59f..1a52f28 100644 (file)
@@ -3,6 +3,8 @@
 # description: ftrace - stacktrace filter command
 # flags: instance
 
+[ ! -f set_ftrace_filter ] && exit_unsupported
+
 echo _do_fork:stacktrace >> set_ftrace_filter
 
 grep -q "_do_fork:stacktrace:unlimited" set_ftrace_filter
index 86a1f07..71fa3f4 100644 (file)
@@ -15,6 +15,11 @@ if [ $NP -eq 1 ] ;then
   exit_unresolved
 fi
 
+if ! grep -q "function" available_tracers ; then
+  echo "Function trace is not enabled"
+  exit_unsupported
+fi
+
 ORIG_CPUMASK=`cat tracing_cpumask`
 
 do_reset() {
index 86986c4..5d45505 100644 (file)
@@ -46,6 +46,9 @@ reset_events_filter() { # reset all current setting filters
 }
 
 reset_ftrace_filter() { # reset all triggers in set_ftrace_filter
+    if [ ! -f set_ftrace_filter ]; then
+      return 0
+    fi
     echo > set_ftrace_filter
     grep -v '^#' set_ftrace_filter | while read t; do
        tr=`echo $t | cut -d: -f2`
@@ -93,7 +96,7 @@ initialize_ftrace() { # Reset ftrace to initial-state
     disable_events
     [ -f set_event_pid ] && echo > set_event_pid
     [ -f set_ftrace_pid ] && echo > set_ftrace_pid
-    [ -f set_ftrace_filter ] && echo | tee set_ftrace_*
+    [ -f set_ftrace_notrace ] && echo > set_ftrace_notrace
     [ -f set_graph_function ] && echo | tee set_graph_*
     [ -f stack_trace_filter ] && echo > stack_trace_filter
     [ -f kprobe_events ] && echo > kprobe_events
index 5862eee..6e3dbe5 100644 (file)
@@ -20,9 +20,9 @@ while read i; do
   test $N -eq 256 && break
 done
 
-L=`wc -l kprobe_events`
-if [ $L -ne $N ]; then
-  echo "The number of kprobes events ($L) is not $N"
+L=`cat kprobe_events | wc -l`
+if [ $L -ne 256 ]; then
+  echo "The number of kprobes events ($L) is not 256"
   exit_fail
 fi
 
index 1221240..3f2aee1 100644 (file)
@@ -21,10 +21,10 @@ grep -q "snapshot()" README || exit_unsupported # version issue
 
 echo "Test expected snapshot action failure"
 
-echo 'hist:keys=comm:onmatch(sched.sched_wakeup).snapshot()' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger && exit_fail
+echo 'hist:keys=comm:onmatch(sched.sched_wakeup).snapshot()' >> events/sched/sched_waking/trigger && exit_fail
 
 echo "Test expected save action failure"
 
-echo 'hist:keys=comm:onmatch(sched.sched_wakeup).save(comm,prio)' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger && exit_fail
+echo 'hist:keys=comm:onmatch(sched.sched_wakeup).save(comm,prio)' >> events/sched/sched_waking/trigger && exit_fail
 
 exit_xfail
index 064a284..c80007a 100644 (file)
@@ -16,7 +16,7 @@ grep -q "onchange(var)" README || exit_unsupported # version issue
 
 echo "Test onchange action"
 
-echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio) if comm=="ping"' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger
+echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio) if comm=="ping"' >> events/sched/sched_waking/trigger
 
 ping $LOCALHOST -c 3
 nice -n 1 ping $LOCALHOST -c 3
index 18fff69..f546c1b 100644 (file)
@@ -23,9 +23,9 @@ grep -q "snapshot()" README || exit_unsupported # version issue
 
 echo "Test snapshot action"
 
-echo 1 > /sys/kernel/debug/tracing/events/sched/enable
+echo 1 > events/sched/enable
 
-echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio):onchange($newprio).snapshot() if comm=="ping"' >> /sys/kernel/debug/tracing/events/sched/sched_waking/trigger
+echo 'hist:keys=comm:newprio=prio:onchange($newprio).save(comm,prio):onchange($newprio).snapshot() if comm=="ping"' >> events/sched/sched_waking/trigger
 
 ping $LOCALHOST -c 3
 nice -n 1 ping $LOCALHOST -c 3
index 18e1c79..fb4733f 100755 (executable)
@@ -9,7 +9,7 @@
 #
 #   #!/bin/sh
 #   SPDX-License-Identifier: GPL-2.0+
-#   $(dirname $0)/../kselftest_module.sh "description" module_name
+#   $(dirname $0)/../kselftest/module.sh "description" module_name
 #
 # Example: tools/testing/selftests/lib/printf.sh
 
index ec7e481..31f7c2a 100755 (executable)
@@ -3,6 +3,7 @@
 # Prefix all lines with "# ", unbuffered. Command being piped in may need
 # to have unbuffering forced with "stdbuf -i0 -o0 -e0 $cmd".
 use strict;
+use IO::Handle;
 
 binmode STDIN;
 binmode STDOUT;
index 84de7bc..a8d20cb 100644 (file)
@@ -79,6 +79,7 @@ run_one()
                if [ $rc -eq $skip_rc ]; then   \
                        echo "not ok $test_num $TEST_HDR_MSG # SKIP"
                elif [ $rc -eq $timeout_rc ]; then \
+                       echo "#"
                        echo "not ok $test_num $TEST_HDR_MSG # TIMEOUT"
                else
                        echo "not ok $test_num $TEST_HDR_MSG # exit=$rc"
index 31eb09e..a6e3d55 100644 (file)
@@ -7,6 +7,9 @@
 MAX_RETRIES=600
 RETRY_INTERVAL=".1"    # seconds
 
+# Kselftest framework requirement - SKIP code is 4
+ksft_skip=4
+
 # log(msg) - write message to kernel log
 #      msg - insightful words
 function log() {
@@ -18,7 +21,16 @@ function log() {
 function skip() {
        log "SKIP: $1"
        echo "SKIP: $1" >&2
-       exit 4
+       exit $ksft_skip
+}
+
+# root test
+function is_root() {
+       uid=$(id -u)
+       if [ $uid -ne 0 ]; then
+               echo "skip all tests: must be run as root" >&2
+               exit $ksft_skip
+       fi
 }
 
 # die(msg) - game over, man
@@ -62,6 +74,7 @@ function set_ftrace_enabled() {
 #               for verbose livepatching output and turn on
 #               the ftrace_enabled sysctl.
 function setup_config() {
+       is_root
        push_config
        set_dynamic_debug
        set_ftrace_enabled 1
index dc2908c..a082127 100755 (executable)
@@ -8,8 +8,7 @@ MOD_LIVEPATCH=test_klp_state
 MOD_LIVEPATCH2=test_klp_state2
 MOD_LIVEPATCH3=test_klp_state3
 
-set_dynamic_debug
-
+setup_config
 
 # TEST: Loading and removing a module that modifies the system state
 
index 6e4626a..8f40573 100755 (executable)
@@ -1,6 +1,9 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+
 ALL_TESTS="loopback_test"
 NUM_NETIFS=2
 source tc_common.sh
@@ -72,6 +75,11 @@ setup_prepare()
 
        h1_create
        h2_create
+
+       if ethtool -k $h1 | grep loopback | grep -q fixed; then
+               log_test "SKIP: dev $h1 does not support loopback feature"
+               exit $ksft_skip
+       fi
 }
 
 cleanup()
index fef88eb..fa6a88c 100755 (executable)
@@ -36,7 +36,7 @@ h2_destroy()
 {
        ip -6 route del 2001:db8:1::/64 vrf v$h2
        ip -4 route del 192.0.2.0/28 vrf v$h2
-       simple_if_fini $h2 192.0.2.130/28
+       simple_if_fini $h2 192.0.2.130/28 2001:db8:2::2/64
 }
 
 router_create()
index d697815..71a62e7 100755 (executable)
@@ -11,9 +11,9 @@
 #      R1 and R2 (also implemented with namespaces), with different MTUs:
 #
 #        segment a_r1    segment b_r1          a_r1: 2000
-#      .--------------R1--------------.        a_r2: 1500
-#      A                               B       a_r3: 2000
-#      '--------------R2--------------'        a_r4: 1400
+#      .--------------R1--------------.        b_r1: 1400
+#      A                               B       a_r2: 2000
+#      '--------------R2--------------'        b_r2: 1500
 #        segment a_r2    segment b_r2
 #
 #      Check that PMTU exceptions with the correct PMTU are created. Then
index 13e5ef6..0ea44d9 100644 (file)
@@ -722,34 +722,6 @@ TEST_F(tls, recv_lowat)
        EXPECT_EQ(memcmp(send_mem, recv_mem + 10, 5), 0);
 }
 
-TEST_F(tls, recv_rcvbuf)
-{
-       char send_mem[4096];
-       char recv_mem[4096];
-       int rcv_buf = 1024;
-
-       memset(send_mem, 0x1c, sizeof(send_mem));
-
-       EXPECT_EQ(setsockopt(self->cfd, SOL_SOCKET, SO_RCVBUF,
-                            &rcv_buf, sizeof(rcv_buf)), 0);
-
-       EXPECT_EQ(send(self->fd, send_mem, 512, 0), 512);
-       memset(recv_mem, 0, sizeof(recv_mem));
-       EXPECT_EQ(recv(self->cfd, recv_mem, sizeof(recv_mem), 0), 512);
-       EXPECT_EQ(memcmp(send_mem, recv_mem, 512), 0);
-
-       if (self->notls)
-               return;
-
-       EXPECT_EQ(send(self->fd, send_mem, 4096, 0), 4096);
-       memset(recv_mem, 0, sizeof(recv_mem));
-       EXPECT_EQ(recv(self->cfd, recv_mem, sizeof(recv_mem), 0), -1);
-       EXPECT_EQ(errno, EMSGSIZE);
-
-       EXPECT_EQ(recv(self->cfd, recv_mem, sizeof(recv_mem), 0), -1);
-       EXPECT_EQ(errno, EMSGSIZE);
-}
-
 TEST_F(tls, bidir)
 {
        char const *test_str = "test_read";
index 16571ac..d3e0809 100755 (executable)
@@ -226,17 +226,19 @@ check_transfer()
        return 0
 }
 
-test_tcp_forwarding()
+test_tcp_forwarding_ip()
 {
        local nsa=$1
        local nsb=$2
+       local dstip=$3
+       local dstport=$4
        local lret=0
 
        ip netns exec $nsb nc -w 5 -l -p 12345 < "$ns2in" > "$ns2out" &
        lpid=$!
 
        sleep 1
-       ip netns exec $nsa nc -w 4 10.0.2.99 12345 < "$ns1in" > "$ns1out" &
+       ip netns exec $nsa nc -w 4 "$dstip" "$dstport" < "$ns1in" > "$ns1out" &
        cpid=$!
 
        sleep 3
@@ -258,6 +260,28 @@ test_tcp_forwarding()
        return $lret
 }
 
+test_tcp_forwarding()
+{
+       test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
+
+       return $?
+}
+
+test_tcp_forwarding_nat()
+{
+       local lret
+
+       test_tcp_forwarding_ip "$1" "$2" 10.0.2.99 12345
+       lret=$?
+
+       if [ $lret -eq 0 ] ; then
+               test_tcp_forwarding_ip "$1" "$2" 10.6.6.6 1666
+               lret=$?
+       fi
+
+       return $lret
+}
+
 make_file "$ns1in" "ns1"
 make_file "$ns2in" "ns2"
 
@@ -283,14 +307,19 @@ ip -net ns2 route add 192.168.10.1 via 10.0.2.1
 # Same, but with NAT enabled.
 ip netns exec nsr1 nft -f - <<EOF
 table ip nat {
+   chain prerouting {
+      type nat hook prerouting priority 0; policy accept;
+      meta iif "veth0" ip daddr 10.6.6.6 tcp dport 1666 counter dnat ip to 10.0.2.99:12345
+   }
+
    chain postrouting {
       type nat hook postrouting priority 0; policy accept;
-      meta oifname "veth1" masquerade
+      meta oifname "veth1" counter masquerade
    }
 }
 EOF
 
-test_tcp_forwarding ns1 ns2
+test_tcp_forwarding_nat ns1 ns2
 
 if [ $? -eq 0 ] ;then
        echo "PASS: flow offloaded for ns1/ns2 with NAT"
@@ -313,7 +342,7 @@ fi
 ip netns exec ns1 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null
 ip netns exec ns2 sysctl net.ipv4.ip_no_pmtu_disc=0 > /dev/null
 
-test_tcp_forwarding ns1 ns2
+test_tcp_forwarding_nat ns1 ns2
 if [ $? -eq 0 ] ;then
        echo "PASS: flow offloaded for ns1/ns2 with NAT and pmtu discovery"
 else
index 1be55e7..d7e07f4 100755 (executable)
@@ -8,9 +8,14 @@ ksft_skip=4
 ret=0
 test_inet_nat=true
 
+sfx=$(mktemp -u "XXXXXXXX")
+ns0="ns0-$sfx"
+ns1="ns1-$sfx"
+ns2="ns2-$sfx"
+
 cleanup()
 {
-       for i in 0 1 2; do ip netns del ns$i;done
+       for i in 0 1 2; do ip netns del ns$i-"$sfx";done
 }
 
 nft --version > /dev/null 2>&1
@@ -25,40 +30,49 @@ if [ $? -ne 0 ];then
        exit $ksft_skip
 fi
 
-ip netns add ns0
+ip netns add "$ns0"
 if [ $? -ne 0 ];then
-       echo "SKIP: Could not create net namespace"
+       echo "SKIP: Could not create net namespace $ns0"
        exit $ksft_skip
 fi
 
 trap cleanup EXIT
 
-ip netns add ns1
-ip netns add ns2
+ip netns add "$ns1"
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not create net namespace $ns1"
+       exit $ksft_skip
+fi
+
+ip netns add "$ns2"
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not create net namespace $ns2"
+       exit $ksft_skip
+fi
 
-ip link add veth0 netns ns0 type veth peer name eth0 netns ns1 > /dev/null 2>&1
+ip link add veth0 netns "$ns0" type veth peer name eth0 netns "$ns1" > /dev/null 2>&1
 if [ $? -ne 0 ];then
     echo "SKIP: No virtual ethernet pair device support in kernel"
     exit $ksft_skip
 fi
-ip link add veth1 netns ns0 type veth peer name eth0 netns ns2
+ip link add veth1 netns "$ns0" type veth peer name eth0 netns "$ns2"
 
-ip -net ns0 link set lo up
-ip -net ns0 link set veth0 up
-ip -net ns0 addr add 10.0.1.1/24 dev veth0
-ip -net ns0 addr add dead:1::1/64 dev veth0
+ip -net "$ns0" link set lo up
+ip -net "$ns0" link set veth0 up
+ip -net "$ns0" addr add 10.0.1.1/24 dev veth0
+ip -net "$ns0" addr add dead:1::1/64 dev veth0
 
-ip -net ns0 link set veth1 up
-ip -net ns0 addr add 10.0.2.1/24 dev veth1
-ip -net ns0 addr add dead:2::1/64 dev veth1
+ip -net "$ns0" link set veth1 up
+ip -net "$ns0" addr add 10.0.2.1/24 dev veth1
+ip -net "$ns0" addr add dead:2::1/64 dev veth1
 
 for i in 1 2; do
-  ip -net ns$i link set lo up
-  ip -net ns$i link set eth0 up
-  ip -net ns$i addr add 10.0.$i.99/24 dev eth0
-  ip -net ns$i route add default via 10.0.$i.1
-  ip -net ns$i addr add dead:$i::99/64 dev eth0
-  ip -net ns$i route add default via dead:$i::1
+  ip -net ns$i-$sfx link set lo up
+  ip -net ns$i-$sfx link set eth0 up
+  ip -net ns$i-$sfx addr add 10.0.$i.99/24 dev eth0
+  ip -net ns$i-$sfx route add default via 10.0.$i.1
+  ip -net ns$i-$sfx addr add dead:$i::99/64 dev eth0
+  ip -net ns$i-$sfx route add default via dead:$i::1
 done
 
 bad_counter()
@@ -66,8 +80,9 @@ bad_counter()
        local ns=$1
        local counter=$2
        local expect=$3
+       local tag=$4
 
-       echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2
+       echo "ERROR: $counter counter in $ns has unexpected value (expected $expect) at $tag" 1>&2
        ip netns exec $ns nft list counter inet filter $counter 1>&2
 }
 
@@ -78,24 +93,24 @@ check_counters()
 
        cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
        if [ $? -ne 0 ]; then
-               bad_counter $ns ns0in "packets 1 bytes 84"
+               bad_counter $ns ns0in "packets 1 bytes 84" "check_counters 1"
                lret=1
        fi
        cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
        if [ $? -ne 0 ]; then
-               bad_counter $ns ns0out "packets 1 bytes 84"
+               bad_counter $ns ns0out "packets 1 bytes 84" "check_counters 2"
                lret=1
        fi
 
        expect="packets 1 bytes 104"
        cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
        if [ $? -ne 0 ]; then
-               bad_counter $ns ns0in6 "$expect"
+               bad_counter $ns ns0in6 "$expect" "check_counters 3"
                lret=1
        fi
        cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
        if [ $? -ne 0 ]; then
-               bad_counter $ns ns0out6 "$expect"
+               bad_counter $ns ns0out6 "$expect" "check_counters 4"
                lret=1
        fi
 
@@ -107,41 +122,41 @@ check_ns0_counters()
        local ns=$1
        local lret=0
 
-       cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
+       cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
        if [ $? -ne 0 ]; then
-               bad_counter ns0 ns0in "packets 0 bytes 0"
+               bad_counter "$ns0" ns0in "packets 0 bytes 0" "check_ns0_counters 1"
                lret=1
        fi
 
-       cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
+       cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
        if [ $? -ne 0 ]; then
-               bad_counter ns0 ns0in6 "packets 0 bytes 0"
+               bad_counter "$ns0" ns0in6 "packets 0 bytes 0"
                lret=1
        fi
 
-       cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
+       cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
        if [ $? -ne 0 ]; then
-               bad_counter ns0 ns0out "packets 0 bytes 0"
+               bad_counter "$ns0" ns0out "packets 0 bytes 0" "check_ns0_counters 2"
                lret=1
        fi
-       cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
+       cnt=$(ip netns exec "$ns0" nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
        if [ $? -ne 0 ]; then
-               bad_counter ns0 ns0out6 "packets 0 bytes 0"
+               bad_counter "$ns0" ns0out6 "packets 0 bytes 0" "check_ns0_counters3 "
                lret=1
        fi
 
        for dir in "in" "out" ; do
                expect="packets 1 bytes 84"
-               cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns0 $ns$dir "$expect"
+                       bad_counter "$ns0" $ns$dir "$expect" "check_ns0_counters 4"
                        lret=1
                fi
 
                expect="packets 1 bytes 104"
-               cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns0 $ns$dir6 "$expect"
+                       bad_counter "$ns0" $ns$dir6 "$expect" "check_ns0_counters 5"
                        lret=1
                fi
        done
@@ -152,7 +167,7 @@ check_ns0_counters()
 reset_counters()
 {
        for i in 0 1 2;do
-               ip netns exec ns$i nft reset counters inet > /dev/null
+               ip netns exec ns$i-$sfx nft reset counters inet > /dev/null
        done
 }
 
@@ -166,7 +181,7 @@ test_local_dnat6()
                IPF="ip6"
        fi
 
-ip netns exec ns0 nft -f - <<EOF
+ip netns exec "$ns0" nft -f /dev/stdin <<EOF
 table $family nat {
        chain output {
                type nat hook output priority 0; policy accept;
@@ -180,7 +195,7 @@ EOF
        fi
 
        # ping netns1, expect rewrite to netns2
-       ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null
+       ip netns exec "$ns0" ping -q -c 1 dead:1::99 > /dev/null
        if [ $? -ne 0 ]; then
                lret=1
                echo "ERROR: ping6 failed"
@@ -189,18 +204,18 @@ EOF
 
        expect="packets 0 bytes 0"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns0 ns1$dir "$expect"
+                       bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat6 1"
                        lret=1
                fi
        done
 
        expect="packets 1 bytes 104"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns0 ns2$dir "$expect"
+                       bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat6 2"
                        lret=1
                fi
        done
@@ -208,9 +223,9 @@ EOF
        # expect 0 count in ns1
        expect="packets 0 bytes 0"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat6 3"
                        lret=1
                fi
        done
@@ -218,15 +233,15 @@ EOF
        # expect 1 packet in ns2
        expect="packets 1 bytes 104"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns0$dir "$expect"
+                       bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat6 4"
                        lret=1
                fi
        done
 
-       test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was $family NATted to ns2"
-       ip netns exec ns0 nft flush chain ip6 nat output
+       test $lret -eq 0 && echo "PASS: ipv6 ping to $ns1 was $family NATted to $ns2"
+       ip netns exec "$ns0" nft flush chain ip6 nat output
 
        return $lret
 }
@@ -241,7 +256,7 @@ test_local_dnat()
                IPF="ip"
        fi
 
-ip netns exec ns0 nft -f - <<EOF 2>/dev/null
+ip netns exec "$ns0" nft -f /dev/stdin <<EOF 2>/dev/null
 table $family nat {
        chain output {
                type nat hook output priority 0; policy accept;
@@ -260,7 +275,7 @@ EOF
        fi
 
        # ping netns1, expect rewrite to netns2
-       ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
+       ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null
        if [ $? -ne 0 ]; then
                lret=1
                echo "ERROR: ping failed"
@@ -269,18 +284,18 @@ EOF
 
        expect="packets 0 bytes 0"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns0 ns1$dir "$expect"
+                       bad_counter "$ns0" ns1$dir "$expect" "test_local_dnat 1"
                        lret=1
                fi
        done
 
        expect="packets 1 bytes 84"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns0 ns2$dir "$expect"
+                       bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 2"
                        lret=1
                fi
        done
@@ -288,9 +303,9 @@ EOF
        # expect 0 count in ns1
        expect="packets 0 bytes 0"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_local_dnat 3"
                        lret=1
                fi
        done
@@ -298,19 +313,19 @@ EOF
        # expect 1 packet in ns2
        expect="packets 1 bytes 84"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns0$dir "$expect"
+                       bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 4"
                        lret=1
                fi
        done
 
-       test $lret -eq 0 && echo "PASS: ping to ns1 was $family NATted to ns2"
+       test $lret -eq 0 && echo "PASS: ping to $ns1 was $family NATted to $ns2"
 
-       ip netns exec ns0 nft flush chain $family nat output
+       ip netns exec "$ns0" nft flush chain $family nat output
 
        reset_counters
-       ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
+       ip netns exec "$ns0" ping -q -c 1 10.0.1.99 > /dev/null
        if [ $? -ne 0 ]; then
                lret=1
                echo "ERROR: ping failed"
@@ -319,17 +334,17 @@ EOF
 
        expect="packets 1 bytes 84"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns1$dir "$expect"
+                       bad_counter "$ns1" ns1$dir "$expect" "test_local_dnat 5"
                        lret=1
                fi
        done
        expect="packets 0 bytes 0"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns0 ns2$dir "$expect"
+                       bad_counter "$ns0" ns2$dir "$expect" "test_local_dnat 6"
                        lret=1
                fi
        done
@@ -337,9 +352,9 @@ EOF
        # expect 1 count in ns1
        expect="packets 1 bytes 84"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns0 ns0$dir "$expect"
+                       bad_counter "$ns0" ns0$dir "$expect" "test_local_dnat 7"
                        lret=1
                fi
        done
@@ -347,14 +362,14 @@ EOF
        # expect 0 packet in ns2
        expect="packets 0 bytes 0"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns0${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns2$dir "$expect"
+                       bad_counter "$ns2" ns0$dir "$expect" "test_local_dnat 8"
                        lret=1
                fi
        done
 
-       test $lret -eq 0 && echo "PASS: ping to ns1 OK after $family nat output chain flush"
+       test $lret -eq 0 && echo "PASS: ping to $ns1 OK after $family nat output chain flush"
 
        return $lret
 }
@@ -366,26 +381,26 @@ test_masquerade6()
        local natflags=$2
        local lret=0
 
-       ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
+       ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
 
-       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2 via ipv6"
+               echo "ERROR: cannot ping $ns1 from $ns2 via ipv6"
                return 1
                lret=1
        fi
 
        expect="packets 1 bytes 104"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns2$dir "$expect"
+                       bad_counter "$ns1" ns2$dir "$expect" "test_masquerade6 1"
                        lret=1
                fi
 
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns1$dir "$expect"
+                       bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 2"
                        lret=1
                fi
        done
@@ -393,7 +408,7 @@ test_masquerade6()
        reset_counters
 
 # add masquerading rule
-ip netns exec ns0 nft -f - <<EOF
+ip netns exec "$ns0" nft -f /dev/stdin <<EOF
 table $family nat {
        chain postrouting {
                type nat hook postrouting priority 0; policy accept;
@@ -406,24 +421,24 @@ EOF
                return $ksft_skip
        fi
 
-       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags"
+               echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags"
                lret=1
        fi
 
        # ns1 should have seen packets from ns0, due to masquerade
        expect="packets 1 bytes 104"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 3"
                        lret=1
                fi
 
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns1$dir "$expect"
+                       bad_counter "$ns2" ns1$dir "$expect" "test_masquerade6 4"
                        lret=1
                fi
        done
@@ -431,32 +446,32 @@ EOF
        # ns1 should not have seen packets from ns2, due to masquerade
        expect="packets 0 bytes 0"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_masquerade6 5"
                        lret=1
                fi
 
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns1$dir "$expect"
+                       bad_counter "$ns0" ns1$dir "$expect" "test_masquerade6 6"
                        lret=1
                fi
        done
 
-       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerade $natflags (attempt 2)"
+               echo "ERROR: cannot ping $ns1 from $ns2 with active ipv6 masquerade $natflags (attempt 2)"
                lret=1
        fi
 
-       ip netns exec ns0 nft flush chain $family nat postrouting
+       ip netns exec "$ns0" nft flush chain $family nat postrouting
        if [ $? -ne 0 ]; then
                echo "ERROR: Could not flush $family nat postrouting" 1>&2
                lret=1
        fi
 
-       test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for ns2"
+       test $lret -eq 0 && echo "PASS: $family IPv6 masquerade $natflags for $ns2"
 
        return $lret
 }
@@ -467,26 +482,26 @@ test_masquerade()
        local natflags=$2
        local lret=0
 
-       ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
-       ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
+       ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
+       ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
 
-       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2 $natflags"
+               echo "ERROR: cannot ping $ns1 from "$ns2" $natflags"
                lret=1
        fi
 
        expect="packets 1 bytes 84"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns2$dir "$expect"
+                       bad_counter "$ns1" ns2$dir "$expect" "test_masquerade 1"
                        lret=1
                fi
 
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns1$dir "$expect"
+                       bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 2"
                        lret=1
                fi
        done
@@ -494,7 +509,7 @@ test_masquerade()
        reset_counters
 
 # add masquerading rule
-ip netns exec ns0 nft -f - <<EOF
+ip netns exec "$ns0" nft -f /dev/stdin <<EOF
 table $family nat {
        chain postrouting {
                type nat hook postrouting priority 0; policy accept;
@@ -507,24 +522,24 @@ EOF
                return $ksft_skip
        fi
 
-       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2 with active $family masquerade $natflags"
+               echo "ERROR: cannot ping $ns1 from $ns2 with active $family masquerade $natflags"
                lret=1
        fi
 
        # ns1 should have seen packets from ns0, due to masquerade
        expect="packets 1 bytes 84"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns0${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 3"
                        lret=1
                fi
 
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns1$dir "$expect"
+                       bad_counter "$ns2" ns1$dir "$expect" "test_masquerade 4"
                        lret=1
                fi
        done
@@ -532,32 +547,32 @@ EOF
        # ns1 should not have seen packets from ns2, due to masquerade
        expect="packets 0 bytes 0"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_masquerade 5"
                        lret=1
                fi
 
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns1$dir "$expect"
+                       bad_counter "$ns0" ns1$dir "$expect" "test_masquerade 6"
                        lret=1
                fi
        done
 
-       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2 with active ip masquerade $natflags (attempt 2)"
+               echo "ERROR: cannot ping $ns1 from $ns2 with active ip masquerade $natflags (attempt 2)"
                lret=1
        fi
 
-       ip netns exec ns0 nft flush chain $family nat postrouting
+       ip netns exec "$ns0" nft flush chain $family nat postrouting
        if [ $? -ne 0 ]; then
                echo "ERROR: Could not flush $family nat postrouting" 1>&2
                lret=1
        fi
 
-       test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for ns2"
+       test $lret -eq 0 && echo "PASS: $family IP masquerade $natflags for $ns2"
 
        return $lret
 }
@@ -567,25 +582,25 @@ test_redirect6()
        local family=$1
        local lret=0
 
-       ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
+       ip netns exec "$ns0" sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
 
-       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannnot ping ns1 from ns2 via ipv6"
+               echo "ERROR: cannnot ping $ns1 from $ns2 via ipv6"
                lret=1
        fi
 
        expect="packets 1 bytes 104"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns2$dir "$expect"
+                       bad_counter "$ns1" ns2$dir "$expect" "test_redirect6 1"
                        lret=1
                fi
 
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns1$dir "$expect"
+                       bad_counter "$ns2" ns1$dir "$expect" "test_redirect6 2"
                        lret=1
                fi
        done
@@ -593,7 +608,7 @@ test_redirect6()
        reset_counters
 
 # add redirect rule
-ip netns exec ns0 nft -f - <<EOF
+ip netns exec "$ns0" nft -f /dev/stdin <<EOF
 table $family nat {
        chain prerouting {
                type nat hook prerouting priority 0; policy accept;
@@ -606,18 +621,18 @@ EOF
                return $ksft_skip
        fi
 
-       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2 via ipv6 with active $family redirect"
+               echo "ERROR: cannot ping $ns1 from $ns2 via ipv6 with active $family redirect"
                lret=1
        fi
 
        # ns1 should have seen no packets from ns2, due to redirection
        expect="packets 0 bytes 0"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 3"
                        lret=1
                fi
        done
@@ -625,20 +640,20 @@ EOF
        # ns0 should have seen packets from ns2, due to masquerade
        expect="packets 1 bytes 104"
        for dir in "in6" "out6" ; do
-               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_redirect6 4"
                        lret=1
                fi
        done
 
-       ip netns exec ns0 nft delete table $family nat
+       ip netns exec "$ns0" nft delete table $family nat
        if [ $? -ne 0 ]; then
                echo "ERROR: Could not delete $family nat table" 1>&2
                lret=1
        fi
 
-       test $lret -eq 0 && echo "PASS: $family IPv6 redirection for ns2"
+       test $lret -eq 0 && echo "PASS: $family IPv6 redirection for $ns2"
 
        return $lret
 }
@@ -648,26 +663,26 @@ test_redirect()
        local family=$1
        local lret=0
 
-       ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
-       ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
+       ip netns exec "$ns0" sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
+       ip netns exec "$ns0" sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
 
-       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2"
+               echo "ERROR: cannot ping $ns1 from $ns2"
                lret=1
        fi
 
        expect="packets 1 bytes 84"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns2$dir "$expect"
+                       bad_counter "$ns1" $ns2$dir "$expect" "test_redirect 1"
                        lret=1
                fi
 
-               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns2" nft list counter inet filter ns1${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns2 ns1$dir "$expect"
+                       bad_counter "$ns2" ns1$dir "$expect" "test_redirect 2"
                        lret=1
                fi
        done
@@ -675,7 +690,7 @@ test_redirect()
        reset_counters
 
 # add redirect rule
-ip netns exec ns0 nft -f - <<EOF
+ip netns exec "$ns0" nft -f /dev/stdin <<EOF
 table $family nat {
        chain prerouting {
                type nat hook prerouting priority 0; policy accept;
@@ -688,9 +703,9 @@ EOF
                return $ksft_skip
        fi
 
-       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       ip netns exec "$ns2" ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
        if [ $? -ne 0 ] ; then
-               echo "ERROR: cannot ping ns1 from ns2 with active $family ip redirect"
+               echo "ERROR: cannot ping $ns1 from $ns2 with active $family ip redirect"
                lret=1
        fi
 
@@ -698,9 +713,9 @@ EOF
        expect="packets 0 bytes 0"
        for dir in "in" "out" ; do
 
-               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns1" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns1" ns0$dir "$expect" "test_redirect 3"
                        lret=1
                fi
        done
@@ -708,28 +723,28 @@ EOF
        # ns0 should have seen packets from ns2, due to masquerade
        expect="packets 1 bytes 84"
        for dir in "in" "out" ; do
-               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               cnt=$(ip netns exec "$ns0" nft list counter inet filter ns2${dir} | grep -q "$expect")
                if [ $? -ne 0 ]; then
-                       bad_counter ns1 ns0$dir "$expect"
+                       bad_counter "$ns0" ns0$dir "$expect" "test_redirect 4"
                        lret=1
                fi
        done
 
-       ip netns exec ns0 nft delete table $family nat
+       ip netns exec "$ns0" nft delete table $family nat
        if [ $? -ne 0 ]; then
                echo "ERROR: Could not delete $family nat table" 1>&2
                lret=1
        fi
 
-       test $lret -eq 0 && echo "PASS: $family IP redirection for ns2"
+       test $lret -eq 0 && echo "PASS: $family IP redirection for $ns2"
 
        return $lret
 }
 
 
-# ip netns exec ns0 ping -c 1 -q 10.0.$i.99
+# ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99
 for i in 0 1 2; do
-ip netns exec ns$i nft -f - <<EOF
+ip netns exec ns$i-$sfx nft -f /dev/stdin <<EOF
 table inet filter {
        counter ns0in {}
        counter ns1in {}
@@ -796,18 +811,18 @@ done
 sleep 3
 # test basic connectivity
 for i in 1 2; do
-  ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null
+  ip netns exec "$ns0" ping -c 1 -q 10.0.$i.99 > /dev/null
   if [ $? -ne 0 ];then
        echo "ERROR: Could not reach other namespace(s)" 1>&2
        ret=1
   fi
 
-  ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null
+  ip netns exec "$ns0" ping -c 1 -q dead:$i::99 > /dev/null
   if [ $? -ne 0 ];then
        echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
        ret=1
   fi
-  check_counters ns$i
+  check_counters ns$i-$sfx
   if [ $? -ne 0 ]; then
        ret=1
   fi
@@ -820,7 +835,7 @@ for i in 1 2; do
 done
 
 if [ $ret -eq 0 ];then
-       echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2"
+       echo "PASS: netns routing/connectivity: $ns0 can reach $ns1 and $ns2"
 fi
 
 reset_counters
@@ -846,4 +861,9 @@ reset_counters
 $test_inet_nat && test_redirect inet
 $test_inet_nat && test_redirect6 inet
 
+if [ $ret -ne 0 ];then
+       echo -n "FAIL: "
+       nft --version
+fi
+
 exit $ret
index eec2663..e8a657a 100644 (file)
@@ -15,7 +15,7 @@
 #include <errno.h>
 #include <stddef.h>
 
-static inline pid_t gettid(void)
+static inline pid_t rseq_gettid(void)
 {
        return syscall(__NR_gettid);
 }
@@ -373,11 +373,12 @@ void *test_percpu_spinlock_thread(void *arg)
                rseq_percpu_unlock(&data->lock, cpu);
 #ifndef BENCHMARK
                if (i != 0 && !(i % (reps / 10)))
-                       printf_verbose("tid %d: count %lld\n", (int) gettid(), i);
+                       printf_verbose("tid %d: count %lld\n",
+                                      (int) rseq_gettid(), i);
 #endif
        }
        printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
-                      (int) gettid(), nr_abort, signals_delivered);
+                      (int) rseq_gettid(), nr_abort, signals_delivered);
        if (!opt_disable_rseq && thread_data->reg &&
            rseq_unregister_current_thread())
                abort();
@@ -454,11 +455,12 @@ void *test_percpu_inc_thread(void *arg)
                } while (rseq_unlikely(ret));
 #ifndef BENCHMARK
                if (i != 0 && !(i % (reps / 10)))
-                       printf_verbose("tid %d: count %lld\n", (int) gettid(), i);
+                       printf_verbose("tid %d: count %lld\n",
+                                      (int) rseq_gettid(), i);
 #endif
        }
        printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
-                      (int) gettid(), nr_abort, signals_delivered);
+                      (int) rseq_gettid(), nr_abort, signals_delivered);
        if (!opt_disable_rseq && thread_data->reg &&
            rseq_unregister_current_thread())
                abort();
@@ -605,7 +607,7 @@ void *test_percpu_list_thread(void *arg)
        }
 
        printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
-                      (int) gettid(), nr_abort, signals_delivered);
+                      (int) rseq_gettid(), nr_abort, signals_delivered);
        if (!opt_disable_rseq && rseq_unregister_current_thread())
                abort();
 
@@ -796,7 +798,7 @@ void *test_percpu_buffer_thread(void *arg)
        }
 
        printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
-                      (int) gettid(), nr_abort, signals_delivered);
+                      (int) rseq_gettid(), nr_abort, signals_delivered);
        if (!opt_disable_rseq && rseq_unregister_current_thread())
                abort();
 
@@ -1011,7 +1013,7 @@ void *test_percpu_memcpy_buffer_thread(void *arg)
        }
 
        printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
-                      (int) gettid(), nr_abort, signals_delivered);
+                      (int) rseq_gettid(), nr_abort, signals_delivered);
        if (!opt_disable_rseq && rseq_unregister_current_thread())
                abort();
 
index d40d60e..3f63eb3 100644 (file)
@@ -149,11 +149,13 @@ static inline void rseq_clear_rseq_cs(void)
 /*
  * rseq_prepare_unload() should be invoked by each thread executing a rseq
  * critical section at least once between their last critical section and
- * library unload of the library defining the rseq critical section
- * (struct rseq_cs). This also applies to use of rseq in code generated by
- * JIT: rseq_prepare_unload() should be invoked at least once by each
- * thread executing a rseq critical section before reclaim of the memory
- * holding the struct rseq_cs.
+ * library unload of the library defining the rseq critical section (struct
+ * rseq_cs) or the code referred to by the struct rseq_cs start_ip and
+ * post_commit_offset fields. This also applies to use of rseq in code
+ * generated by JIT: rseq_prepare_unload() should be invoked at least once by
+ * each thread executing a rseq critical section before reclaim of the memory
+ * holding the struct rseq_cs or reclaim of the code pointed to by struct
+ * rseq_cs start_ip and post_commit_offset fields.
  */
 static inline void rseq_prepare_unload(void)
 {
diff --git a/tools/testing/selftests/rseq/settings b/tools/testing/selftests/rseq/settings
new file mode 100644 (file)
index 0000000..e7b9417
--- /dev/null
@@ -0,0 +1 @@
+timeout=0
index 98da7a5..fa02c4d 100644 (file)
@@ -1,8 +1,9 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for mount selftests.
-CFLAGS = -Wall -lcap -O2
+CFLAGS = -Wall -O2
+LDLIBS = -lcap
 
-TEST_PROGS := run_tests.sh
+TEST_PROGS := safesetid-test.sh
 TEST_GEN_FILES := safesetid-test
 
 include ../lib.mk
index 8f40c6e..0c4d506 100644 (file)
@@ -213,7 +213,8 @@ static void test_setuid(uid_t child_uid, bool expect_success)
        }
 
        if (cpid == 0) {            /* Code executed by child */
-               setuid(child_uid);
+               if (setuid(child_uid) < 0)
+                       exit(EXIT_FAILURE);
                if (getuid() == child_uid)
                        exit(EXIT_SUCCESS);
                else
@@ -291,8 +292,10 @@ int main(int argc, char **argv)
 
        // First test to make sure we can write userns mappings from a user
        // that doesn't have any restrictions (as long as it has CAP_SETUID);
-       setuid(NO_POLICY_USER);
-       setgid(NO_POLICY_USER);
+       if (setuid(NO_POLICY_USER) < 0)
+               die("Error with set uid(%d)\n", NO_POLICY_USER);
+       if (setgid(NO_POLICY_USER) < 0)
+               die("Error with set gid(%d)\n", NO_POLICY_USER);
 
        // Take away all but setid caps
        drop_caps(true);
@@ -306,8 +309,10 @@ int main(int argc, char **argv)
                die("test_userns failed when it should work\n");
        }
 
-       setuid(RESTRICTED_PARENT);
-       setgid(RESTRICTED_PARENT);
+       if (setuid(RESTRICTED_PARENT) < 0)
+               die("Error with set uid(%d)\n", RESTRICTED_PARENT);
+       if (setgid(RESTRICTED_PARENT) < 0)
+               die("Error with set gid(%d)\n", RESTRICTED_PARENT);
 
        test_setuid(ROOT_USER, false);
        test_setuid(ALLOWED_CHILD1, true);
index 6944b89..ee1b727 100644 (file)
@@ -3158,7 +3158,18 @@ TEST(user_notification_basic)
        EXPECT_GT(poll(&pollfd, 1, -1), 0);
        EXPECT_EQ(pollfd.revents, POLLIN);
 
-       EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
+       /* Test that we can't pass garbage to the kernel. */
+       memset(&req, 0, sizeof(req));
+       req.pid = -1;
+       errno = 0;
+       ret = ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req);
+       EXPECT_EQ(-1, ret);
+       EXPECT_EQ(EINVAL, errno);
+
+       if (ret) {
+               req.pid = 0;
+               EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
+       }
 
        pollfd.fd = listener;
        pollfd.events = POLLIN | POLLOUT;
@@ -3278,6 +3289,7 @@ TEST(user_notification_signal)
 
        close(sk_pair[1]);
 
+       memset(&req, 0, sizeof(req));
        EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
 
        EXPECT_EQ(kill(pid, SIGUSR1), 0);
@@ -3296,6 +3308,7 @@ TEST(user_notification_signal)
        EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_SEND, &resp), -1);
        EXPECT_EQ(errno, ENOENT);
 
+       memset(&req, 0, sizeof(req));
        EXPECT_EQ(ioctl(listener, SECCOMP_IOCTL_NOTIF_RECV, &req), 0);
 
        resp.id = req.id;
index 76ae03a..2e361ce 100644 (file)
         ]
     },
     {
-        "id": "6f5e",
+        "id": "b99c",
         "name": "Add basic filter with cmp ematch u8/transport layer and default action",
         "category": [
             "filter",
index 0f89cd5..8877f7b 100644 (file)
@@ -1,27 +1,5 @@
 [
     {
-        "id": "e9a3",
-        "name": "Add u32 with source match",
-        "category": [
-            "filter",
-            "u32"
-        ],
-        "plugins": {
-                "requires": "nsPlugin"
-        },
-        "setup": [
-            "$TC qdisc add dev $DEV1 ingress"
-        ],
-        "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: protocol ip prio 1 u32 match ip src 127.0.0.1/32 flowid 1:1 action ok",
-        "expExitCode": "0",
-        "verifyCmd": "$TC filter show dev $DEV1 parent ffff:",
-        "matchPattern": "match 7f000001/ffffffff at 12",
-        "matchCount": "1",
-        "teardown": [
-            "$TC qdisc del dev $DEV1 ingress"
-        ]
-    },
-    {
         "id": "2638",
         "name": "Add matchall and try to get it",
         "category": [
diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/u32.json b/tools/testing/selftests/tc-testing/tc-tests/filters/u32.json
new file mode 100644 (file)
index 0000000..e09d3c0
--- /dev/null
@@ -0,0 +1,205 @@
+[
+    {
+        "id": "afa9",
+        "name": "Add u32 with source match",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress"
+        ],
+        "cmdUnderTest": "$TC filter add dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.1/32 flowid 1:1 action ok",
+        "expExitCode": "0",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "filter protocol ip pref 1 u32 chain (0[ ]+$|0 fh 800: ht divisor 1|0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1.*match 7f000001/ffffffff at 12)",
+        "matchCount": "3",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    },
+    {
+        "id": "6aa7",
+        "name": "Add/Replace u32 with source match and invalid indev",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress"
+        ],
+        "cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.1/32 indev notexist20 flowid 1:1 action ok",
+        "expExitCode": "2",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "filter protocol ip pref 1 u32 chain 0",
+        "matchCount": "0",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    },
+    {
+        "id": "bc4d",
+        "name": "Replace valid u32 with source match and invalid indev",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress",
+            "$TC filter add dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.3/32 flowid 1:3 action ok"
+        ],
+        "cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 1 u32 match ip src 127.0.0.2/32 indev notexist20 flowid 1:2 action ok",
+        "expExitCode": "2",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "filter protocol ip pref 1 u32 chain (0[ ]+$|0 fh 800: ht divisor 1|0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:3.*match 7f000003/ffffffff at 12)",
+        "matchCount": "3",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    },
+    {
+        "id": "648b",
+        "name": "Add u32 with custom hash table",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress"
+        ],
+        "cmdUnderTest": "$TC filter add dev $DEV1 ingress prio 99 handle 42: u32 divisor 256",
+        "expExitCode": "0",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "pref 99 u32 chain (0[ ]+$|0 fh 42: ht divisor 256|0 fh 800: ht divisor 1)",
+        "matchCount": "3",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    },
+    {
+        "id": "6658",
+        "name": "Add/Replace u32 with custom hash table and invalid handle",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress"
+        ],
+        "cmdUnderTest": "$TC filter replace dev $DEV1 ingress prio 99 handle 42:42 u32 divisor 256",
+        "expExitCode": "2",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "pref 99 u32 chain 0",
+        "matchCount": "0",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    },
+    {
+        "id": "9d0a",
+        "name": "Replace valid u32 with custom hash table and invalid handle",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress",
+            "$TC filter add dev $DEV1 ingress prio 99 handle 42: u32 divisor 256"
+        ],
+        "cmdUnderTest": "$TC filter replace dev $DEV1 ingress prio 99 handle 42:42 u32 divisor 128",
+        "expExitCode": "2",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "pref 99 u32 chain (0[ ]+$|0 fh 42: ht divisor 256|0 fh 800: ht divisor 1)",
+        "matchCount": "3",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    },
+    {
+        "id": "1644",
+        "name": "Add u32 filter that links to a custom hash table",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress",
+            "$TC filter add dev $DEV1 ingress prio 99 handle 43: u32 divisor 256"
+        ],
+        "cmdUnderTest": "$TC filter add dev $DEV1 ingress protocol ip prio 98 u32 link 43: hashkey mask 0x0000ff00 at 12 match ip src 192.168.0.0/16",
+        "expExitCode": "0",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "filter protocol ip pref 98 u32 chain (0[ ]+$|0 fh 801: ht divisor 1|0 fh 801::800 order 2048 key ht 801 bkt 0 link 43:.*match c0a80000/ffff0000 at 12.*hash mask 0000ff00 at 12)",
+        "matchCount": "3",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    },
+    {
+        "id": "74c2",
+        "name": "Add/Replace u32 filter with invalid hash table id",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress"
+        ],
+        "cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 20 u32 ht 47:47 action drop",
+        "expExitCode": "2",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "filter protocol ip pref 20 u32 chain 0",
+        "matchCount": "0",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    },
+    {
+        "id": "1fe6",
+        "name": "Replace valid u32 filter with invalid hash table id",
+        "category": [
+            "filter",
+            "u32"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$TC qdisc add dev $DEV1 ingress",
+            "$TC filter add dev $DEV1 ingress protocol ip prio 99 handle 43: u32 divisor 1",
+            "$TC filter add dev $DEV1 ingress protocol ip prio 98 u32 ht 43: match tcp src 22 FFFF classid 1:3"
+        ],
+        "cmdUnderTest": "$TC filter replace dev $DEV1 ingress protocol ip prio 98 u32 ht 43:1 match tcp src 23 FFFF classid 1:4",
+        "expExitCode": "2",
+        "verifyCmd": "$TC filter show dev $DEV1 ingress",
+        "matchPattern": "filter protocol ip pref 99 u32 chain (0[ ]+$|0 fh (43|800): ht divisor 1|0 fh 43::800 order 2048 key ht 43 bkt 0 flowid 1:3.*match 00160000/ffff0000 at nexthdr\\+0)",
+        "matchCount": "4",
+        "teardown": [
+            "$TC qdisc del dev $DEV1 ingress"
+        ]
+    }
+]
index 80521d4..8155c2e 100755 (executable)
@@ -2,3 +2,9 @@
 # SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
 
 python -m unittest -v tpm2_tests.SmokeTest
+python -m unittest -v tpm2_tests.AsyncTest
+
+CLEAR_CMD=$(which tpm2_clear)
+if [ -n $CLEAR_CMD ]; then
+       tpm2_clear -T device
+fi
index 828c185..d0fcb66 100644 (file)
@@ -6,8 +6,8 @@ import socket
 import struct
 import sys
 import unittest
-from fcntl import ioctl
-
+import fcntl
+import select
 
 TPM2_ST_NO_SESSIONS = 0x8001
 TPM2_ST_SESSIONS = 0x8002
@@ -352,6 +352,7 @@ def hex_dump(d):
 class Client:
     FLAG_DEBUG = 0x01
     FLAG_SPACE = 0x02
+    FLAG_NONBLOCK = 0x04
     TPM_IOC_NEW_SPACE = 0xa200
 
     def __init__(self, flags = 0):
@@ -362,13 +363,27 @@ class Client:
         else:
             self.tpm = open('/dev/tpmrm0', 'r+b', buffering=0)
 
+        if (self.flags & Client.FLAG_NONBLOCK):
+            flags = fcntl.fcntl(self.tpm, fcntl.F_GETFL)
+            flags |= os.O_NONBLOCK
+            fcntl.fcntl(self.tpm, fcntl.F_SETFL, flags)
+            self.tpm_poll = select.poll()
+
     def close(self):
         self.tpm.close()
 
     def send_cmd(self, cmd):
         self.tpm.write(cmd)
+
+        if (self.flags & Client.FLAG_NONBLOCK):
+            self.tpm_poll.register(self.tpm, select.POLLIN)
+            self.tpm_poll.poll(10000)
+
         rsp = self.tpm.read()
 
+        if (self.flags & Client.FLAG_NONBLOCK):
+            self.tpm_poll.unregister(self.tpm)
+
         if (self.flags & Client.FLAG_DEBUG) != 0:
             sys.stderr.write('cmd' + os.linesep)
             sys.stderr.write(hex_dump(cmd) + os.linesep)
index d4973be..728be7c 100644 (file)
@@ -288,3 +288,16 @@ class SpaceTest(unittest.TestCase):
 
         self.assertEqual(rc, tpm2.TPM2_RC_COMMAND_CODE |
                          tpm2.TSS2_RESMGR_TPM_RC_LAYER)
+
+class AsyncTest(unittest.TestCase):
+    def setUp(self):
+        logging.basicConfig(filename='AsyncTest.log', level=logging.DEBUG)
+
+    def test_async(self):
+        log = logging.getLogger(__name__)
+        log.debug(sys._getframe().f_code.co_name)
+
+        async_client = tpm2.Client(tpm2.Client.FLAG_NONBLOCK)
+        log.debug("Calling get_cap in a NON_BLOCKING mode")
+        async_client.get_cap(tpm2.TPM2_CAP_HANDLES, tpm2.HR_LOADED_SESSION)
+        async_client.close()
index 0aad760..2bbac73 100755 (executable)
@@ -128,7 +128,7 @@ parse() {
                        str="${ftype} ${name} ${location} ${str}"
                        ;;
                "nod")
-                       local dev=`LC_ALL=C ls -l "${location}"`
+                       local dev="`LC_ALL=C ls -l "${location}"`"
                        local maj=`field 5 ${dev}`
                        local min=`field 6 ${dev}`
                        maj=${maj%,}
index 4a753a4..8459846 100644 (file)
@@ -91,7 +91,7 @@ endif
 # asm-generic/*.h is used by asm/*.h, and should not be included directly
 header-test- += asm-generic/%
 
-extra-y := $(patsubst $(obj)/%.h,%.hdrtest, $(shell find $(obj) -name '*.h'))
+extra-y := $(patsubst $(obj)/%.h,%.hdrtest, $(shell find $(obj) -name '*.h' 2>/dev/null))
 
 quiet_cmd_hdrtest = HDRTEST $<
       cmd_hdrtest = \
index 12e0280..8de4daf 100644 (file)
@@ -1352,7 +1352,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
        }
 }
 
-static void cpu_init_hyp_mode(void *dummy)
+static void cpu_init_hyp_mode(void)
 {
        phys_addr_t pgd_ptr;
        unsigned long hyp_stack_ptr;
@@ -1386,7 +1386,7 @@ static void cpu_hyp_reinit(void)
        if (is_kernel_in_hyp_mode())
                kvm_timer_init_vhe();
        else
-               cpu_init_hyp_mode(NULL);
+               cpu_init_hyp_mode();
 
        kvm_arm_init_debug();
 
index 38b4c91..0b32a90 100644 (file)
@@ -38,6 +38,11 @@ static unsigned long io_map_base;
 #define KVM_S2PTE_FLAG_IS_IOMAP                (1UL << 0)
 #define KVM_S2_FLAG_LOGGING_ACTIVE     (1UL << 1)
 
+static bool is_iomap(unsigned long flags)
+{
+       return flags & KVM_S2PTE_FLAG_IS_IOMAP;
+}
+
 static bool memslot_is_logging(struct kvm_memory_slot *memslot)
 {
        return memslot->dirty_bitmap && !(memslot->flags & KVM_MEM_READONLY);
@@ -1698,6 +1703,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 
        vma_pagesize = vma_kernel_pagesize(vma);
        if (logging_active ||
+           (vma->vm_flags & VM_PFNMAP) ||
            !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) {
                force_pte = true;
                vma_pagesize = PAGE_SIZE;
@@ -1760,6 +1766,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                        writable = false;
        }
 
+       if (exec_fault && is_iomap(flags))
+               return -ENOEXEC;
+
        spin_lock(&kvm->mmu_lock);
        if (mmu_notifier_retry(kvm, mmu_seq))
                goto out_unlock;
@@ -1781,7 +1790,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
        if (writable)
                kvm_set_pfn_dirty(pfn);
 
-       if (fault_status != FSC_PERM)
+       if (fault_status != FSC_PERM && !is_iomap(flags))
                clean_dcache_guest_page(pfn, vma_pagesize);
 
        if (exec_fault)
@@ -1948,9 +1957,8 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
        if (kvm_is_error_hva(hva) || (write_fault && !writable)) {
                if (is_iabt) {
                        /* Prefetch Abort on I/O address */
-                       kvm_inject_pabt(vcpu, kvm_vcpu_get_hfar(vcpu));
-                       ret = 1;
-                       goto out_unlock;
+                       ret = -ENOEXEC;
+                       goto out;
                }
 
                /*
@@ -1992,6 +2000,11 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
        ret = user_mem_abort(vcpu, fault_ipa, memslot, hva, fault_status);
        if (ret == 0)
                ret = 1;
+out:
+       if (ret == -ENOEXEC) {
+               kvm_inject_pabt(vcpu, kvm_vcpu_get_hfar(vcpu));
+               ret = 1;
+       }
 out_unlock:
        srcu_read_unlock(&vcpu->kvm->srcu, idx);
        return ret;
@@ -2302,15 +2315,6 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
                        break;
 
                /*
-                * Mapping a read-only VMA is only allowed if the
-                * memory region is configured as read-only.
-                */
-               if (writable && !(vma->vm_flags & VM_WRITE)) {
-                       ret = -EPERM;
-                       break;
-               }
-
-               /*
                 * Take the intersection of this VMA with the memory region
                 */
                vm_start = max(hva, vma->vm_start);
index b3c5de4..a963b9d 100644 (file)
@@ -70,7 +70,7 @@ void kvm_vgic_early_init(struct kvm *kvm)
  */
 int kvm_vgic_create(struct kvm *kvm, u32 type)
 {
-       int i, vcpu_lock_idx = -1, ret;
+       int i, ret;
        struct kvm_vcpu *vcpu;
 
        if (irqchip_in_kernel(kvm))
@@ -86,17 +86,9 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
                !kvm_vgic_global_state.can_emulate_gicv2)
                return -ENODEV;
 
-       /*
-        * Any time a vcpu is run, vcpu_load is called which tries to grab the
-        * vcpu->mutex.  By grabbing the vcpu->mutex of all VCPUs we ensure
-        * that no other VCPUs are run while we create the vgic.
-        */
        ret = -EBUSY;
-       kvm_for_each_vcpu(i, vcpu, kvm) {
-               if (!mutex_trylock(&vcpu->mutex))
-                       goto out_unlock;
-               vcpu_lock_idx = i;
-       }
+       if (!lock_all_vcpus(kvm))
+               return ret;
 
        kvm_for_each_vcpu(i, vcpu, kvm) {
                if (vcpu->arch.has_run_once)
@@ -125,10 +117,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
                INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
 
 out_unlock:
-       for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
-               vcpu = kvm_get_vcpu(kvm, vcpu_lock_idx);
-               mutex_unlock(&vcpu->mutex);
-       }
+       unlock_all_vcpus(kvm);
        return ret;
 }
 
@@ -177,6 +166,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
                        break;
                default:
                        kfree(dist->spis);
+                       dist->spis = NULL;
                        return -EINVAL;
                }
        }