Merge tag 'fsnotify_for_v5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 30 Aug 2021 17:04:31 +0000 (10:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 30 Aug 2021 17:04:31 +0000 (10:04 -0700)
Pull fsnotify updates from Jan Kara:
 "fsnotify speedups when notification actually isn't used and support
  for identifying processes which caused fanotify events through pidfd
  instead of normal pid"

* tag 'fsnotify_for_v5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
  fsnotify: optimize the case of no marks of any type
  fsnotify: count all objects with attached connectors
  fsnotify: count s_fsnotify_inode_refs for attached connectors
  fsnotify: replace igrab() with ihold() on attach connector
  fanotify: add pidfd support to the fanotify API
  fanotify: introduce a generic info record copying helper
  fanotify: minor cosmetic adjustments to fid labels
  kernel/pid.c: implement additional checks upon pidfd_create() parameters
  kernel/pid.c: remove static qualifier from pidfd_create()

762 files changed:
Documentation/bpf/libbpf/libbpf_naming_convention.rst
Documentation/devicetree/bindings/iio/st,st-sensors.yaml
Documentation/devicetree/bindings/riscv/sifive-l2-cache.yaml
Documentation/gpu/rfc/i915_gem_lmem.rst
Documentation/i2c/index.rst
Documentation/networking/nf_conntrack-sysctl.rst
Documentation/userspace-api/seccomp_filter.rst
Documentation/virt/kvm/locking.rst
MAINTAINERS
Makefile
arch/arc/Kconfig
arch/arc/include/asm/checksum.h
arch/arc/include/asm/perf_event.h
arch/arc/kernel/fpu.c
arch/arc/kernel/unwind.c
arch/arc/kernel/vmlinux.lds.S
arch/arm/boot/dts/am437x-l4.dtsi
arch/arm/boot/dts/am43x-epos-evm.dts
arch/arm/boot/dts/imx53-m53menlo.dts
arch/arm/boot/dts/imx6qdl-sr-som.dtsi
arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
arch/arm/boot/dts/omap5-board-common.dtsi
arch/arm/boot/dts/ste-nomadik-stn8815.dtsi
arch/arm/boot/dts/stm32mp15xx-dhcom-pdk2.dtsi
arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi
arch/arm/configs/nhk8815_defconfig
arch/arm/include/asm/memory.h
arch/arm/kernel/head.S
arch/arm/mach-imx/common.h
arch/arm/mach-imx/mmdc.c
arch/arm/mach-ixp4xx/Kconfig
arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mm/mmu.c
arch/arm/mm/pv-fixup-asm.S
arch/arm64/Kconfig
arch/arm64/Makefile
arch/arm64/boot/dts/freescale/fsl-ls1028a-kontron-sl28-var2.dts
arch/arm64/boot/dts/freescale/fsl-ls1028a.dtsi
arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts
arch/arm64/boot/dts/nvidia/tegra194.dtsi
arch/arm64/boot/dts/qcom/msm8992-bullhead-rev-101.dts
arch/arm64/boot/dts/qcom/msm8994-angler-rev-101.dts
arch/arm64/boot/dts/qcom/sc7280.dtsi
arch/arm64/boot/dts/qcom/sdm845-oneplus-common.dtsi
arch/arm64/boot/dts/qcom/sdm850-lenovo-yoga-c630.dts
arch/arm64/include/asm/el2_setup.h
arch/arm64/include/asm/page.h
arch/arm64/include/asm/ptrace.h
arch/arm64/include/asm/stacktrace.h
arch/arm64/include/asm/syscall.h
arch/arm64/kernel/kaslr.c
arch/arm64/kernel/ptrace.c
arch/arm64/kernel/signal.c
arch/arm64/kernel/stacktrace.c
arch/arm64/kernel/syscall.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/nvhe/mem_protect.c
arch/arm64/mm/init.c
arch/mips/Makefile
arch/mips/include/asm/pgalloc.h
arch/mips/mti-malta/malta-platform.c
arch/parisc/include/asm/string.h
arch/parisc/kernel/parisc_ksyms.c
arch/parisc/lib/Makefile
arch/parisc/lib/memset.c [new file with mode: 0644]
arch/parisc/lib/string.S [deleted file]
arch/powerpc/include/asm/book3s/32/kup.h
arch/powerpc/include/asm/interrupt.h
arch/powerpc/include/asm/irq.h
arch/powerpc/include/asm/ptrace.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/head_book3s_32.S
arch/powerpc/kernel/head_booke.h
arch/powerpc/kernel/irq.c
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/mm/pageattr.c
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/pseries/setup.c
arch/powerpc/sysdev/xive/common.c
arch/riscv/Kconfig
arch/riscv/boot/dts/microchip/microchip-mpfs-icicle-kit.dts
arch/riscv/boot/dts/microchip/microchip-mpfs.dtsi
arch/riscv/boot/dts/sifive/hifive-unmatched-a00.dts
arch/riscv/include/asm/page.h
arch/riscv/kernel/Makefile
arch/riscv/kernel/ptrace.c
arch/riscv/kernel/setup.c
arch/riscv/kernel/stacktrace.c
arch/riscv/mm/init.c
arch/s390/pci/pci.c
arch/s390/pci/pci_bus.h
arch/x86/boot/compressed/efi_thunk_64.S
arch/x86/boot/compressed/head_64.S
arch/x86/events/amd/ibs.c
arch/x86/events/amd/power.c
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/intel/pt.c
arch/x86/events/intel/uncore_snbep.c
arch/x86/events/perf_event.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/svm.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/msi.c
arch/x86/kernel/cpu/resctrl/monitor.c
arch/x86/kernel/hpet.c
arch/x86/kvm/cpuid.c
arch/x86/kvm/hyperv.c
arch/x86/kvm/mmu/mmu.c
arch/x86/kvm/mmu/tdp_mmu.c
arch/x86/kvm/svm/nested.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/nested.c
arch/x86/kvm/vmx/vmx.h
arch/x86/tools/chkobjdump.awk
arch/x86/tools/relocs.c
block/Kconfig.iosched
block/Makefile
block/blk-cgroup.c
block/blk-core.c
block/blk-flush.c
block/blk-iocost.c
block/blk-iolatency.c
block/blk-mq.c
block/blk.h
block/kyber-iosched.c
block/mq-deadline-cgroup.c [deleted file]
block/mq-deadline-cgroup.h [deleted file]
block/mq-deadline-main.c [deleted file]
block/mq-deadline.c [new file with mode: 0644]
block/partitions/ldm.c
crypto/Kconfig
drivers/acpi/acpica/nsrepair2.c
drivers/acpi/nfit/core.c
drivers/acpi/prmt.c
drivers/acpi/x86/s2idle.c
drivers/base/core.c
drivers/base/dd.c
drivers/base/firmware_loader/fallback.c
drivers/base/firmware_loader/firmware.h
drivers/base/firmware_loader/main.c
drivers/base/power/domain.c
drivers/block/Kconfig
drivers/block/cryptoloop.c
drivers/block/n64cart.c
drivers/block/nbd.c
drivers/block/paride/pd.c
drivers/block/virtio_blk.c
drivers/bus/mhi/core/internal.h
drivers/bus/mhi/core/main.c
drivers/bus/ti-sysc.c
drivers/char/tpm/tpm_ftpm_tee.c
drivers/clk/imx/clk-imx6q.c
drivers/clk/qcom/gdsc.c
drivers/clk/renesas/rcar-usb2-clock-sel.c
drivers/cpufreq/armada-37xx-cpufreq.c
drivers/cpufreq/cpufreq-dt-platdev.c
drivers/cpufreq/scmi-cpufreq.c
drivers/cpuidle/governors/teo.c
drivers/dax/super.c
drivers/dma/idxd/idxd.h
drivers/dma/idxd/init.c
drivers/dma/idxd/irq.c
drivers/dma/idxd/submit.c
drivers/dma/idxd/sysfs.c
drivers/dma/imx-dma.c
drivers/dma/of-dma.c
drivers/dma/sh/usb-dmac.c
drivers/dma/stm32-dma.c
drivers/dma/stm32-dmamux.c
drivers/dma/uniphier-xdmac.c
drivers/dma/xilinx/xilinx_dma.c
drivers/firmware/broadcom/tee_bnxt_fw.c
drivers/firmware/efi/libstub/arm64-stub.c
drivers/firmware/efi/libstub/randomalloc.c
drivers/fpga/dfl-fme-perf.c
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
drivers/gpu/drm/amd/amdgpu/amdgpu_res_cursor.h
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdkfd/kfd_svm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn21/rn_clk_mgr.c
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c
drivers/gpu/drm/amd/display/dc/core/dc_vm_helper.c
drivers/gpu/drm/amd/display/dc/dc.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
drivers/gpu/drm/amd/display/dc/dcn303/dcn303_resource.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_hwseq.h
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_init.c
drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c
drivers/gpu/drm/amd/display/dc/inc/hw_sequencer.h
drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h
drivers/gpu/drm/amd/display/dmub/src/dmub_dcn31.c
drivers/gpu/drm/amd/include/atomfirmware.h
drivers/gpu/drm/amd/pm/inc/smu_v13_0.h
drivers/gpu/drm/amd/pm/inc/smu_v13_0_1_pmfw.h
drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
drivers/gpu/drm/drm_ioc32.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_dp_link_training.c
drivers/gpu/drm/i915/gt/intel_timeline.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/mmio_context.c
drivers/gpu/drm/i915/i915_globals.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_reg.h
drivers/gpu/drm/imx/ipuv3-plane.c
drivers/gpu/drm/kmb/kmb_drv.c
drivers/gpu/drm/kmb/kmb_drv.h
drivers/gpu/drm/kmb/kmb_plane.c
drivers/gpu/drm/mediatek/mtk_disp_color.c
drivers/gpu/drm/mediatek/mtk_disp_ovl.c
drivers/gpu/drm/mediatek/mtk_dpi.c
drivers/gpu/drm/mediatek/mtk_drm_crtc.c
drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c
drivers/gpu/drm/mediatek/mtk_drm_plane.c
drivers/gpu/drm/meson/meson_registers.h
drivers/gpu/drm/meson/meson_viu.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/dispnv50/head.c
drivers/gpu/drm/nouveau/dispnv50/head.h
drivers/gpu/drm/nouveau/include/nvif/cl0080.h
drivers/gpu/drm/nouveau/include/nvif/class.h
drivers/gpu/drm/nouveau/include/nvif/client.h
drivers/gpu/drm/nouveau/include/nvif/driver.h
drivers/gpu/drm/nouveau/include/nvkm/core/client.h
drivers/gpu/drm/nouveau/include/nvkm/core/ioctl.h
drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_mem.c
drivers/gpu/drm/nouveau/nouveau_nvif.c
drivers/gpu/drm/nouveau/nouveau_svm.c
drivers/gpu/drm/nouveau/nouveau_usif.c
drivers/gpu/drm/nouveau/nvif/client.c
drivers/gpu/drm/nouveau/nvif/object.c
drivers/gpu/drm/nouveau/nvkm/core/ioctl.c
drivers/gpu/drm/nouveau/nvkm/engine/device/base.c
drivers/gpu/drm/nouveau/nvkm/engine/device/user.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c
drivers/gpu/drm/nouveau/nvkm/engine/dma/user.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/Kbuild
drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c [deleted file]
drivers/gpu/drm/nouveau/nvkm/engine/fifo/g84.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogv100.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifotu102.c
drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c
drivers/gpu/drm/ttm/ttm_device.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/ipu-v3/ipu-cpmem.c
drivers/i2c/busses/i2c-bcm-iproc.c
drivers/i2c/i2c-dev.c
drivers/iio/accel/Kconfig
drivers/iio/accel/fxls8962af-core.c
drivers/iio/adc/palmas_gpadc.c
drivers/iio/adc/ti-ads7950.c
drivers/iio/humidity/hdc100x.c
drivers/iio/imu/adis.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/uverbs_std_types_mr.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/main.c
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/cxgb4/ev.c
drivers/infiniband/hw/cxgb4/iw_cxgb4.h
drivers/infiniband/hw/efa/efa_main.c
drivers/infiniband/hw/hfi1/sdma.c
drivers/infiniband/hw/hns/hns_roce_cmd.c
drivers/infiniband/hw/hns/hns_roce_main.c
drivers/infiniband/hw/irdma/Kconfig
drivers/infiniband/hw/mlx5/cq.c
drivers/infiniband/hw/mlx5/devx.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/sw/rxe/rxe_mcast.c
drivers/infiniband/sw/rxe/rxe_net.c
drivers/infiniband/sw/rxe/rxe_queue.c
drivers/infiniband/sw/rxe/rxe_resp.c
drivers/interconnect/core.c
drivers/interconnect/qcom/icc-rpmh.c
drivers/iommu/dma-iommu.c
drivers/iommu/intel/pasid.c
drivers/iommu/intel/pasid.h
drivers/iommu/intel/svm.c
drivers/iommu/iommu.c
drivers/ipack/carriers/tpci200.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/media/pci/intel/ipu3/cio2-bridge.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mmci_stm32_sdmmc.c
drivers/mmc/host/sdhci-iproc.c
drivers/mmc/host/sdhci-msm.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/devices/mchp48l640.c
drivers/mtd/mtd_blkdevs.c
drivers/mtd/mtdcore.c
drivers/mtd/nand/raw/nand_base.c
drivers/net/bareudp.c
drivers/net/can/m_can/m_can.c
drivers/net/can/usb/esd_usb2.c
drivers/net/dsa/hirschmann/hellcreek.c
drivers/net/dsa/lan9303-core.c
drivers/net/dsa/lantiq_gswip.c
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz8795_reg.h
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/mt7530.c
drivers/net/dsa/mv88e6xxx/serdes.c
drivers/net/dsa/qca/ar9331.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/dsa/sja1105/sja1105_mdio.c
drivers/net/ethernet/apm/xgene-v2/main.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_hsi.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
drivers/net/ethernet/cadence/macb_ptp.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.h
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_mbx.c
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/ich8lan.h
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_devlink.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_ptp.c
drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/igc/igc_ptp.c
drivers/net/ethernet/intel/ixgbe/ixgbe_xsk.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/mvpp2/mvpp2.h
drivers/net/ethernet/marvell/prestera/prestera_switchdev.c
drivers/net/ethernet/mellanox/mlx5/core/cq.c
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/eq.c
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
drivers/net/ethernet/mellanox/mlx5/core/esw/sample.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fpga/conn.c
drivers/net/ethernet/mellanox/mlx5/core/lib/eq.h
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h
drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_send.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/microchip/sparx5/sparx5_mactable.c
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_io.c
drivers/net/ethernet/qlogic/qed/qed_ll2.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_rdma.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/rocker/rocker_main.c
drivers/net/ethernet/rocker/rocker_ofdpa.c
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
drivers/net/ethernet/stmicro/stmmac/stmmac_xdp.c
drivers/net/ethernet/ti/am65-cpsw-switchdev.c
drivers/net/ethernet/ti/cpsw_new.c
drivers/net/ethernet/ti/cpsw_priv.h
drivers/net/ethernet/ti/cpsw_switchdev.c
drivers/net/hamradio/6pack.c
drivers/net/ieee802154/mac802154_hwsim.c
drivers/net/mdio/mdio-mux.c
drivers/net/mhi/net.c
drivers/net/pcs/pcs-xpcs.c
drivers/net/phy/mediatek-ge.c
drivers/net/phy/micrel.c
drivers/net/ppp/ppp_generic.c
drivers/net/usb/asix.h
drivers/net/usb/asix_common.c
drivers/net/usb/asix_devices.c
drivers/net/usb/pegasus.c
drivers/net/usb/r8152.c
drivers/net/virtio_net.c
drivers/net/vrf.c
drivers/net/wireless/intel/iwlwifi/fw/pnvm.c
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
drivers/net/wwan/iosm/iosm_ipc_chnl_cfg.c
drivers/net/wwan/mhi_wwan_ctrl.c
drivers/net/wwan/wwan_core.c
drivers/nvdimm/namespace_devs.c
drivers/opp/core.c
drivers/opp/of.c
drivers/pci/controller/pci-ixp4xx.c
drivers/pci/msi.c
drivers/pci/pci-sysfs.c
drivers/pci/quirks.c
drivers/pinctrl/intel/pinctrl-tigerlake.c
drivers/pinctrl/mediatek/pinctrl-mtk-common-v2.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-k210.c
drivers/pinctrl/qcom/Kconfig
drivers/pinctrl/sunxi/pinctrl-sunxi.c
drivers/platform/x86/Kconfig
drivers/platform/x86/asus-nb-wmi.c
drivers/platform/x86/dual_accel_detect.h [new file with mode: 0644]
drivers/platform/x86/gigabyte-wmi.c
drivers/platform/x86/intel-hid.c
drivers/platform/x86/intel-vbtn.c
drivers/platform/x86/pcengines-apuv2.c
drivers/platform/x86/thinkpad_acpi.c
drivers/ptp/Kconfig
drivers/ptp/ptp_sysfs.c
drivers/reset/Kconfig
drivers/reset/reset-zynqmp.c
drivers/s390/block/dasd_eckd.c
drivers/s390/net/qeth_l2_main.c
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/mpt3sas/mpt3sas_base.c
drivers/scsi/scsi_sysfs.c
drivers/scsi/storvsc_drv.c
drivers/slimbus/messaging.c
drivers/slimbus/qcom-ngd-ctrl.c
drivers/soc/Makefile
drivers/soc/fsl/qe/qe_ic.c
drivers/soc/imx/soc-imx8m.c
drivers/soc/ixp4xx/ixp4xx-npe.c
drivers/soc/ixp4xx/ixp4xx-qmgr.c
drivers/soc/tegra/Kconfig
drivers/spi/spi-cadence-quadspi.c
drivers/spi/spi-imx.c
drivers/spi/spi-meson-spicc.c
drivers/spi/spi-mt65xx.c
drivers/spi/spi-mux.c
drivers/spi/spi.c
drivers/staging/media/av7110/audio.h [deleted file]
drivers/staging/media/av7110/av7110.h
drivers/staging/media/av7110/osd.h [deleted file]
drivers/staging/media/av7110/video.h [deleted file]
drivers/staging/mt7621-pci/pci-mt7621.c
drivers/staging/rtl8712/hal_init.c
drivers/staging/rtl8712/rtl8712_led.c
drivers/staging/rtl8712/rtl871x_led.h
drivers/staging/rtl8712/rtl871x_pwrctrl.c
drivers/staging/rtl8712/rtl871x_pwrctrl.h
drivers/staging/rtl8712/usb_intf.c
drivers/staging/rtl8723bs/Kconfig
drivers/staging/rtl8723bs/hal/sdio_ops.c
drivers/tee/optee/call.c
drivers/tee/optee/core.c
drivers/tee/optee/optee_private.h
drivers/tee/optee/rpc.c
drivers/tee/optee/shm_pool.c
drivers/tee/tee_shm.c
drivers/thunderbolt/switch.c
drivers/tty/serial/8250/8250_aspeed_vuart.c
drivers/tty/serial/8250/8250_fsl.c
drivers/tty/serial/8250/8250_mtk.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/max310x.c
drivers/tty/serial/serial-tegra.c
drivers/tty/vt/vt.c
drivers/tty/vt/vt_ioctl.c
drivers/usb/cdns3/cdns3-ep0.c
drivers/usb/cdns3/cdnsp-gadget.c
drivers/usb/cdns3/cdnsp-gadget.h
drivers/usb/cdns3/cdnsp-ring.c
drivers/usb/class/usbtmc.c
drivers/usb/common/usb-otg-fsm.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/function/f_hid.c
drivers/usb/gadget/function/u_audio.c
drivers/usb/gadget/udc/max3420_udc.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/xhci-pci-renesas.c
drivers/usb/musb/omap2430.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/typec/tcpm/tcpm.c
drivers/vdpa/ifcvf/ifcvf_main.c
drivers/vdpa/mlx5/core/mr.c
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/vdpa/vdpa_sim/vdpa_sim.c
drivers/vdpa/virtio_pci/vp_vdpa.c
drivers/vhost/vdpa.c
drivers/vhost/vhost.c
drivers/vhost/vringh.c
drivers/virt/acrn/vm.c
drivers/virtio/virtio.c
drivers/virtio/virtio_mem.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_ring.c
drivers/virtio/virtio_vdpa.c
drivers/xen/events/events_base.c
fs/btrfs/inode.c
fs/ceph/caps.c
fs/ceph/mds_client.c
fs/ceph/mdsmap.c
fs/ceph/snap.c
fs/ceph/super.h
fs/cifs/cifsglob.h
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/cifs/smb2pdu.c
fs/configfs/file.c
fs/dax.c
fs/ext4/ext4_jbd2.c
fs/ext4/mmp.c
fs/ext4/namei.c
fs/fuse/dax.c
fs/io-wq.c
fs/io_uring.c
fs/namespace.c
fs/notify/fanotify/fanotify_user.c
fs/notify/inotify/inotify_user.c
fs/overlayfs/export.c
fs/overlayfs/file.c
fs/overlayfs/readdir.c
fs/pipe.c
include/asm-generic/vmlinux.lds.h
include/linux/bpf-cgroup.h
include/linux/device.h
include/linux/inetdevice.h
include/linux/irq.h
include/linux/kfence.h
include/linux/memcontrol.h
include/linux/mhi.h
include/linux/mlx5/driver.h
include/linux/mlx5/mlx5_ifc_vdpa.h
include/linux/msi.h
include/linux/netfilter/ipset/ip_set.h
include/linux/once.h
include/linux/pipe_fs_i.h
include/linux/security.h
include/linux/serial_core.h
include/linux/tee_drv.h
include/linux/usb/otg-fsm.h
include/linux/vdpa.h
include/linux/virtio.h
include/linux/vringh.h
include/net/flow_offload.h
include/net/ip6_fib.h
include/net/netns/conntrack.h
include/net/psample.h
include/trace/events/mmflags.h
include/uapi/linux/dvb/audio.h [new file with mode: 0644]
include/uapi/linux/dvb/osd.h [new file with mode: 0644]
include/uapi/linux/dvb/video.h [new file with mode: 0644]
include/uapi/linux/neighbour.h
include/uapi/linux/netfilter/nfnetlink_hook.h
init/main.c
kernel/bpf/core.c
kernel/bpf/hashtab.c
kernel/bpf/helpers.c
kernel/bpf/verifier.c
kernel/cfi.c
kernel/cgroup/rstat.c
kernel/cred.c
kernel/events/core.c
kernel/fork.c
kernel/irq/chip.c
kernel/irq/msi.c
kernel/irq/timings.c
kernel/locking/rtmutex.c
kernel/sched/core.c
kernel/sched/sched.h
kernel/seccomp.c
kernel/time/timer.c
kernel/trace/Kconfig
kernel/trace/bpf_trace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_events_hist.c
kernel/trace/trace_osnoise.c
kernel/tracepoint.c
kernel/ucount.c
lib/devmem_is_allowed.c
lib/once.c
lib/string.c
mm/gup.c
mm/hugetlb.c
mm/kmemleak.c
mm/madvise.c
mm/memcontrol.c
mm/memory-failure.c
mm/memory_hotplug.c
mm/page_alloc.c
mm/shmem.c
mm/slub.c
mm/swap_state.c
mm/vmscan.c
net/bpf/test_run.c
net/bridge/br.c
net/bridge/br_fdb.c
net/bridge/br_if.c
net/bridge/br_private.h
net/bridge/netfilter/nf_conntrack_bridge.c
net/core/link_watch.c
net/core/page_pool.c
net/core/rtnetlink.c
net/dccp/dccp.h
net/dsa/slave.c
net/ieee802154/socket.c
net/ipv4/cipso_ipv4.c
net/ipv4/igmp.c
net/ipv4/ip_gre.c
net/ipv4/route.c
net/ipv4/tcp_bbr.c
net/ipv6/ip6_fib.c
net/ipv6/ip6_gre.c
net/ipv6/route.c
net/mac80211/main.c
net/mptcp/options.c
net/mptcp/pm_netlink.c
net/netfilter/ipset/ip_set_hash_ip.c
net/netfilter/ipset/ip_set_hash_ipmark.c
net/netfilter/ipset/ip_set_hash_ipport.c
net/netfilter/ipset/ip_set_hash_ipportip.c
net/netfilter/ipset/ip_set_hash_ipportnet.c
net/netfilter/ipset/ip_set_hash_net.c
net/netfilter/ipset/ip_set_hash_netiface.c
net/netfilter/ipset/ip_set_hash_netnet.c
net/netfilter/ipset/ip_set_hash_netport.c
net/netfilter/ipset/ip_set_hash_netportnet.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nf_conntrack_proto_udp.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nfnetlink_hook.c
net/openvswitch/flow.c
net/openvswitch/vport.c
net/qrtr/mhi.c
net/qrtr/qrtr.c
net/rds/ib_frmr.c
net/sched/act_mirred.c
net/sched/sch_cake.c
net/sched/sch_ets.c
net/smc/af_smc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_llc.c
net/smc/smc_tx.c
net/smc/smc_wr.c
net/sunrpc/svc_xprt.c
net/tipc/link.c
net/tipc/socket.c
net/vmw_vsock/virtio_transport.c
scripts/checkversion.pl
security/security.c
sound/core/memalloc.c
sound/core/pcm_native.c
sound/core/seq/seq_ports.c
sound/firewire/oxfw/oxfw-stream.c
sound/firewire/oxfw/oxfw.c
sound/firewire/oxfw/oxfw.h
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_via.c
sound/soc/Kconfig
sound/soc/amd/acp-da7219-max98357a.c
sound/soc/amd/acp-pcm-dma.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/amd/renoir/acp3x-pdm-dma.c
sound/soc/amd/renoir/rn-pci-acp3x.c
sound/soc/codecs/Kconfig
sound/soc/codecs/Makefile
sound/soc/codecs/cs42l42.c
sound/soc/codecs/cs42l42.h
sound/soc/codecs/nau8824.c
sound/soc/codecs/rt5682.c
sound/soc/codecs/tlv320aic31xx.c
sound/soc/codecs/tlv320aic32x4.c
sound/soc/codecs/wm_adsp.c
sound/soc/intel/atom/sst-mfld-platform-pcm.c
sound/soc/intel/boards/sof_da7219_max98373.c
sound/soc/kirkwood/kirkwood-dma.c
sound/soc/soc-component.c
sound/soc/sof/intel/Kconfig
sound/soc/sof/intel/hda-ipc.c
sound/soc/sof/intel/hda.c
sound/soc/uniphier/aio-dma.c
sound/soc/xilinx/xlnx_formatter_pcm.c
sound/usb/card.c
sound/usb/clock.c
sound/usb/mixer.c
sound/usb/mixer_scarlett_gen2.c
sound/usb/quirks.c
tools/io_uring/io_uring-cp.c
tools/lib/bpf/btf.c
tools/lib/bpf/libbpf_probes.c
tools/testing/nvdimm/test/nfit.c
tools/testing/selftests/bpf/verifier/dead_code.c
tools/testing/selftests/sgx/sigstruct.c
tools/virtio/Makefile
tools/virtio/linux/spinlock.h [new file with mode: 0644]
tools/virtio/linux/virtio.h

index 3de1d51..6bf9c5a 100644 (file)
@@ -108,7 +108,7 @@ This bump in ABI version is at most once per kernel development cycle.
 
 For example, if current state of ``libbpf.map`` is:
 
-.. code-block:: c
+.. code-block:: none
 
         LIBBPF_0.0.1 {
                global:
@@ -121,7 +121,7 @@ For example, if current state of ``libbpf.map`` is:
 , and a new symbol ``bpf_func_c`` is being introduced, then
 ``libbpf.map`` should be changed like this:
 
-.. code-block:: c
+.. code-block:: none
 
         LIBBPF_0.0.1 {
                global:
index b2a1e42..71de563 100644 (file)
@@ -152,47 +152,6 @@ allOf:
           maxItems: 1
         st,drdy-int-pin: false
 
-  - if:
-      properties:
-        compatible:
-          enum:
-            # Two intertial interrupts i.e. accelerometer/gyro interrupts
-            - st,h3lis331dl-accel
-            - st,l3g4200d-gyro
-            - st,l3g4is-gyro
-            - st,l3gd20-gyro
-            - st,l3gd20h-gyro
-            - st,lis2de12
-            - st,lis2dw12
-            - st,lis2hh12
-            - st,lis2dh12-accel
-            - st,lis331dl-accel
-            - st,lis331dlh-accel
-            - st,lis3de
-            - st,lis3dh-accel
-            - st,lis3dhh
-            - st,lis3mdl-magn
-            - st,lng2dm-accel
-            - st,lps331ap-press
-            - st,lsm303agr-accel
-            - st,lsm303dlh-accel
-            - st,lsm303dlhc-accel
-            - st,lsm303dlm-accel
-            - st,lsm330-accel
-            - st,lsm330-gyro
-            - st,lsm330d-accel
-            - st,lsm330d-gyro
-            - st,lsm330dl-accel
-            - st,lsm330dl-gyro
-            - st,lsm330dlc-accel
-            - st,lsm330dlc-gyro
-            - st,lsm9ds0-gyro
-            - st,lsm9ds1-magn
-    then:
-      properties:
-        interrupts:
-          maxItems: 2
-
 required:
   - compatible
   - reg
index 1d38ff7..2b1f916 100644 (file)
@@ -24,10 +24,10 @@ allOf:
 select:
   properties:
     compatible:
-      items:
-        enum:
-            - sifive,fu540-c000-ccache
-            - sifive,fu740-c000-ccache
+      contains:
+        enum:
+          - sifive,fu540-c000-ccache
+          - sifive,fu740-c000-ccache
 
   required:
     - compatible
index 675ba86..b421a3c 100644 (file)
@@ -18,114 +18,5 @@ real, with all the uAPI bits is:
         * Route shmem backend over to TTM SYSTEM for discrete
         * TTM purgeable object support
         * Move i915 buddy allocator over to TTM
-        * MMAP ioctl mode(see `I915 MMAP`_)
-        * SET/GET ioctl caching(see `I915 SET/GET CACHING`_)
 * Send RFC(with mesa-dev on cc) for final sign off on the uAPI
 * Add pciid for DG1 and turn on uAPI for real
-
-New object placement and region query uAPI
-==========================================
-Starting from DG1 we need to give userspace the ability to allocate buffers from
-device local-memory. Currently the driver supports gem_create, which can place
-buffers in system memory via shmem, and the usual assortment of other
-interfaces, like dumb buffers and userptr.
-
-To support this new capability, while also providing a uAPI which will work
-beyond just DG1, we propose to offer three new bits of uAPI:
-
-DRM_I915_QUERY_MEMORY_REGIONS
------------------------------
-New query ID which allows userspace to discover the list of supported memory
-regions(like system-memory and local-memory) for a given device. We identify
-each region with a class and instance pair, which should be unique. The class
-here would be DEVICE or SYSTEM, and the instance would be zero, on platforms
-like DG1.
-
-Side note: The class/instance design is borrowed from our existing engine uAPI,
-where we describe every physical engine in terms of its class, and the
-particular instance, since we can have more than one per class.
-
-In the future we also want to expose more information which can further
-describe the capabilities of a region.
-
-.. kernel-doc:: include/uapi/drm/i915_drm.h
-        :functions: drm_i915_gem_memory_class drm_i915_gem_memory_class_instance drm_i915_memory_region_info drm_i915_query_memory_regions
-
-GEM_CREATE_EXT
---------------
-New ioctl which is basically just gem_create but now allows userspace to provide
-a chain of possible extensions. Note that if we don't provide any extensions and
-set flags=0 then we get the exact same behaviour as gem_create.
-
-Side note: We also need to support PXP[1] in the near future, which is also
-applicable to integrated platforms, and adds its own gem_create_ext extension,
-which basically lets userspace mark a buffer as "protected".
-
-.. kernel-doc:: include/uapi/drm/i915_drm.h
-        :functions: drm_i915_gem_create_ext
-
-I915_GEM_CREATE_EXT_MEMORY_REGIONS
-----------------------------------
-Implemented as an extension for gem_create_ext, we would now allow userspace to
-optionally provide an immutable list of preferred placements at creation time,
-in priority order, for a given buffer object.  For the placements we expect
-them each to use the class/instance encoding, as per the output of the regions
-query. Having the list in priority order will be useful in the future when
-placing an object, say during eviction.
-
-.. kernel-doc:: include/uapi/drm/i915_drm.h
-        :functions: drm_i915_gem_create_ext_memory_regions
-
-One fair criticism here is that this seems a little over-engineered[2]. If we
-just consider DG1 then yes, a simple gem_create.flags or something is totally
-all that's needed to tell the kernel to allocate the buffer in local-memory or
-whatever. However looking to the future we need uAPI which can also support
-upcoming Xe HP multi-tile architecture in a sane way, where there can be
-multiple local-memory instances for a given device, and so using both class and
-instance in our uAPI to describe regions is desirable, although specifically
-for DG1 it's uninteresting, since we only have a single local-memory instance.
-
-Existing uAPI issues
-====================
-Some potential issues we still need to resolve.
-
-I915 MMAP
----------
-In i915 there are multiple ways to MMAP GEM object, including mapping the same
-object using different mapping types(WC vs WB), i.e multiple active mmaps per
-object. TTM expects one MMAP at most for the lifetime of the object. If it
-turns out that we have to backpedal here, there might be some potential
-userspace fallout.
-
-I915 SET/GET CACHING
---------------------
-In i915 we have set/get_caching ioctl. TTM doesn't let us to change this, but
-DG1 doesn't support non-snooped pcie transactions, so we can just always
-allocate as WB for smem-only buffers.  If/when our hw gains support for
-non-snooped pcie transactions then we must fix this mode at allocation time as
-a new GEM extension.
-
-This is related to the mmap problem, because in general (meaning, when we're
-not running on intel cpus) the cpu mmap must not, ever, be inconsistent with
-allocation mode.
-
-Possible idea is to let the kernel picks the mmap mode for userspace from the
-following table:
-
-smem-only: WB. Userspace does not need to call clflush.
-
-smem+lmem: We only ever allow a single mode, so simply allocate this as uncached
-memory, and always give userspace a WC mapping. GPU still does snooped access
-here(assuming we can't turn it off like on DG1), which is a bit inefficient.
-
-lmem only: always WC
-
-This means on discrete you only get a single mmap mode, all others must be
-rejected. That's probably going to be a new default mode or something like
-that.
-
-Links
-=====
-[1] https://patchwork.freedesktop.org/series/86798/
-
-[2] https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5599#note_553791
index 8b76217..6270f1f 100644 (file)
@@ -17,6 +17,7 @@ Introduction
    busses/index
    i2c-topology
    muxes/i2c-mux-gpio
+   i2c-sysfs
 
 Writing device drivers
 ======================
index d31ed6c..024d784 100644 (file)
@@ -191,19 +191,9 @@ nf_flowtable_tcp_timeout - INTEGER (seconds)
         TCP connections may be offloaded from nf conntrack to nf flow table.
         Once aged, the connection is returned to nf conntrack with tcp pickup timeout.
 
-nf_flowtable_tcp_pickup - INTEGER (seconds)
-        default 120
-
-        TCP connection timeout after being aged from nf flow table offload.
-
 nf_flowtable_udp_timeout - INTEGER (seconds)
         default 30
 
         Control offload timeout for udp connections.
         UDP connections may be offloaded from nf conntrack to nf flow table.
         Once aged, the connection is returned to nf conntrack with udp pickup timeout.
-
-nf_flowtable_udp_pickup - INTEGER (seconds)
-        default 30
-
-        UDP connection timeout after being aged from nf flow table offload.
index d612198..539e9d4 100644 (file)
@@ -263,7 +263,7 @@ Userspace can also add file descriptors to the notifying process via
 ``ioctl(SECCOMP_IOCTL_NOTIF_ADDFD)``. The ``id`` member of
 ``struct seccomp_notif_addfd`` should be the same ``id`` as in
 ``struct seccomp_notif``. The ``newfd_flags`` flag may be used to set flags
-like O_EXEC on the file descriptor in the notifying process. If the supervisor
+like O_CLOEXEC on the file descriptor in the notifying process. If the supervisor
 wants to inject the file descriptor with a specific number, the
 ``SECCOMP_ADDFD_FLAG_SETFD`` flag can be used, and set the ``newfd`` member to
 the specific number to use. If that file descriptor is already open in the
index 35eca37..88fa495 100644 (file)
@@ -25,10 +25,10 @@ On x86:
 
 - vcpu->mutex is taken outside kvm->arch.hyperv.hv_lock
 
-- kvm->arch.mmu_lock is an rwlock.  kvm->arch.tdp_mmu_pages_lock is
-  taken inside kvm->arch.mmu_lock, and cannot be taken without already
-  holding kvm->arch.mmu_lock (typically with ``read_lock``, otherwise
-  there's no need to take kvm->arch.tdp_mmu_pages_lock at all).
+- kvm->arch.mmu_lock is an rwlock.  kvm->arch.tdp_mmu_pages_lock and
+  kvm->arch.mmu_unsync_pages_lock are taken inside kvm->arch.mmu_lock, and
+  cannot be taken without already holding kvm->arch.mmu_lock (typically with
+  ``read_lock`` for the TDP MMU, thus the need for additional spinlocks).
 
 Everything else is a leaf: no other lock is taken inside the critical
 sections.
index c9467d2..d7b4f32 100644 (file)
@@ -3866,6 +3866,16 @@ L:       bcm-kernel-feedback-list@broadcom.com
 S:     Maintained
 F:     drivers/mtd/nand/raw/brcmnand/
 
+BROADCOM STB PCIE DRIVER
+M:     Jim Quinlan <jim2101024@gmail.com>
+M:     Nicolas Saenz Julienne <nsaenz@kernel.org>
+M:     Florian Fainelli <f.fainelli@gmail.com>
+M:     bcm-kernel-feedback-list@broadcom.com
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/pci/brcm,stb-pcie.yaml
+F:     drivers/pci/controller/pcie-brcmstb.c
+
 BROADCOM SYSTEMPORT ETHERNET DRIVER
 M:     Florian Fainelli <f.fainelli@gmail.com>
 L:     bcm-kernel-feedback-list@broadcom.com
@@ -4498,7 +4508,7 @@ L:        clang-built-linux@googlegroups.com
 S:     Supported
 W:     https://clangbuiltlinux.github.io/
 B:     https://github.com/ClangBuiltLinux/linux/issues
-C:     irc://chat.freenode.net/clangbuiltlinux
+C:     irc://irc.libera.chat/clangbuiltlinux
 F:     Documentation/kbuild/llvm.rst
 F:     include/linux/compiler-clang.h
 F:     scripts/clang-tools/
@@ -6945,7 +6955,7 @@ F:        include/uapi/linux/mdio.h
 F:     include/uapi/linux/mii.h
 
 EXFAT FILE SYSTEM
-M:     Namjae Jeon <namjae.jeon@samsung.com>
+M:     Namjae Jeon <linkinjeon@kernel.org>
 M:     Sungjong Seo <sj1557.seo@samsung.com>
 L:     linux-fsdevel@vger.kernel.org
 S:     Maintained
@@ -11327,7 +11337,7 @@ W:      https://linuxtv.org
 T:     git git://linuxtv.org/media_tree.git
 F:     drivers/media/radio/radio-maxiradio*
 
-MCAB MICROCHIP CAN BUS ANALYZER TOOL DRIVER
+MCBA MICROCHIP CAN BUS ANALYZER TOOL DRIVER
 R:     Yasushi SHOJI <yashi@spacecubics.com>
 L:     linux-can@vger.kernel.org
 S:     Maintained
@@ -14430,6 +14440,13 @@ S:     Maintained
 F:     Documentation/devicetree/bindings/pci/hisilicon-histb-pcie.txt
 F:     drivers/pci/controller/dwc/pcie-histb.c
 
+PCIE DRIVER FOR INTEL LGM GW SOC
+M:     Rahul Tanwar <rtanwar@maxlinear.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/devicetree/bindings/pci/intel-gw-pcie.yaml
+F:     drivers/pci/controller/dwc/pcie-intel-gw.c
+
 PCIE DRIVER FOR MEDIATEK
 M:     Ryder Lee <ryder.lee@mediatek.com>
 M:     Jianjun Wang <jianjun.wang@mediatek.com>
@@ -15803,7 +15820,7 @@ F:      Documentation/devicetree/bindings/i2c/renesas,iic-emev2.yaml
 F:     drivers/i2c/busses/i2c-emev2.c
 
 RENESAS ETHERNET DRIVERS
-R:     Sergei Shtylyov <sergei.shtylyov@gmail.com>
+R:     Sergey Shtylyov <s.shtylyov@omp.ru>
 L:     netdev@vger.kernel.org
 L:     linux-renesas-soc@vger.kernel.org
 F:     Documentation/devicetree/bindings/net/renesas,*.yaml
@@ -17815,7 +17832,7 @@ F:      include/linux/sync_file.h
 F:     include/uapi/linux/sync_file.h
 
 SYNOPSYS ARC ARCHITECTURE
-M:     Vineet Gupta <vgupta@synopsys.com>
+M:     Vineet Gupta <vgupta@kernel.org>
 L:     linux-snps-arc@lists.infradead.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git
@@ -20017,7 +20034,8 @@ F:      Documentation/devicetree/bindings/extcon/wlf,arizona.yaml
 F:     Documentation/devicetree/bindings/mfd/wlf,arizona.yaml
 F:     Documentation/devicetree/bindings/mfd/wm831x.txt
 F:     Documentation/devicetree/bindings/regulator/wlf,arizona.yaml
-F:     Documentation/devicetree/bindings/sound/wlf,arizona.yaml
+F:     Documentation/devicetree/bindings/sound/wlf,*.yaml
+F:     Documentation/devicetree/bindings/sound/wm*
 F:     Documentation/hwmon/wm83??.rst
 F:     arch/arm/mach-s3c/mach-crag6410*
 F:     drivers/clk/clk-wm83*.c
index b6ee64d..61741e9 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 14
 SUBLEVEL = 0
-EXTRAVERSION = -rc4
+EXTRAVERSION =
 NAME = Opossums on Parade
 
 # *DOCUMENTATION*
@@ -1316,6 +1316,16 @@ PHONY += scripts_unifdef
 scripts_unifdef: scripts_basic
        $(Q)$(MAKE) $(build)=scripts scripts/unifdef
 
+# ---------------------------------------------------------------------------
+# Install
+
+# Many distributions have the custom install script, /sbin/installkernel.
+# If DKMS is installed, 'make install' will eventually recuses back
+# to the this Makefile to build and install external modules.
+# Cancel sub_make_done so that options such as M=, V=, etc. are parsed.
+
+install: sub_make_done :=
+
 # ---------------------------------------------------------------------------
 # Tools
 
index d8f51eb..b5bf68e 100644 (file)
@@ -409,7 +409,7 @@ choice
        help
          Depending on the configuration, CPU can contain DSP registers
          (ACC0_GLO, ACC0_GHI, DSP_BFLY0, DSP_CTRL, DSP_FFT_CTRL).
-         Bellow is options describing how to handle these registers in
+         Below are options describing how to handle these registers in
          interrupt entry / exit and in context switch.
 
 config ARC_DSP_NONE
index 69debd7..0b48580 100644 (file)
@@ -24,7 +24,7 @@
  */
 static inline __sum16 csum_fold(__wsum s)
 {
-       unsigned r = s << 16 | s >> 16; /* ror */
+       unsigned int r = s << 16 | s >> 16;     /* ror */
        s = ~s;
        s -= r;
        return s >> 16;
index 30b9ae5..e1971d3 100644 (file)
@@ -123,7 +123,7 @@ static const char * const arc_pmu_ev_hw_map[] = {
 #define C(_x)                  PERF_COUNT_HW_CACHE_##_x
 #define CACHE_OP_UNSUPPORTED   0xffff
 
-static const unsigned arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
+static const unsigned int arc_pmu_cache_map[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
        [C(L1D)] = {
                [C(OP_READ)] = {
                        [C(RESULT_ACCESS)]      = PERF_COUNT_ARC_LDC,
index c67c0f0..ec64021 100644 (file)
@@ -57,23 +57,26 @@ void fpu_save_restore(struct task_struct *prev, struct task_struct *next)
 
 void fpu_init_task(struct pt_regs *regs)
 {
+       const unsigned int fwe = 0x80000000;
+
        /* default rounding mode */
        write_aux_reg(ARC_REG_FPU_CTRL, 0x100);
 
-       /* set "Write enable" to allow explicit write to exception flags */
-       write_aux_reg(ARC_REG_FPU_STATUS, 0x80000000);
+       /* Initialize to zero: setting requires FWE be set */
+       write_aux_reg(ARC_REG_FPU_STATUS, fwe);
 }
 
 void fpu_save_restore(struct task_struct *prev, struct task_struct *next)
 {
        struct arc_fpu *save = &prev->thread.fpu;
        struct arc_fpu *restore = &next->thread.fpu;
+       const unsigned int fwe = 0x80000000;
 
        save->ctrl = read_aux_reg(ARC_REG_FPU_CTRL);
        save->status = read_aux_reg(ARC_REG_FPU_STATUS);
 
        write_aux_reg(ARC_REG_FPU_CTRL, restore->ctrl);
-       write_aux_reg(ARC_REG_FPU_STATUS, restore->status);
+       write_aux_reg(ARC_REG_FPU_STATUS, (fwe | restore->status));
 }
 
 #endif
index 47bab67..9e28058 100644 (file)
@@ -260,7 +260,7 @@ static void init_unwind_hdr(struct unwind_table *table,
 {
        const u8 *ptr;
        unsigned long tableSize = table->size, hdrSize;
-       unsigned n;
+       unsigned int n;
        const u32 *fde;
        struct {
                u8 version;
@@ -462,7 +462,7 @@ static uleb128_t get_uleb128(const u8 **pcur, const u8 *end)
 {
        const u8 *cur = *pcur;
        uleb128_t value;
-       unsigned shift;
+       unsigned int shift;
 
        for (shift = 0, value = 0; cur < end; shift += 7) {
                if (shift + 7 > 8 * sizeof(value)
@@ -483,7 +483,7 @@ static sleb128_t get_sleb128(const u8 **pcur, const u8 *end)
 {
        const u8 *cur = *pcur;
        sleb128_t value;
-       unsigned shift;
+       unsigned int shift;
 
        for (shift = 0, value = 0; cur < end; shift += 7) {
                if (shift + 7 > 8 * sizeof(value)
@@ -609,7 +609,7 @@ static unsigned long read_pointer(const u8 **pLoc, const void *end,
 static signed fde_pointer_type(const u32 *cie)
 {
        const u8 *ptr = (const u8 *)(cie + 2);
-       unsigned version = *ptr;
+       unsigned int version = *ptr;
 
        if (*++ptr) {
                const char *aug;
@@ -904,7 +904,7 @@ int arc_unwind(struct unwind_frame_info *frame)
        const u8 *ptr = NULL, *end = NULL;
        unsigned long pc = UNW_PC(frame) - frame->call_frame;
        unsigned long startLoc = 0, endLoc = 0, cfa;
-       unsigned i;
+       unsigned int i;
        signed ptrType = -1;
        uleb128_t retAddrReg = 0;
        const struct unwind_table *table;
index e2146a8..529ae50 100644 (file)
@@ -88,6 +88,8 @@ SECTIONS
                CPUIDLE_TEXT
                LOCK_TEXT
                KPROBES_TEXT
+               IRQENTRY_TEXT
+               SOFTIRQENTRY_TEXT
                *(.fixup)
                *(.gnu.warning)
        }
index 40ef397..ba58e6b 100644 (file)
                                compatible = "ti,am4372-d_can", "ti,am3352-d_can";
                                reg = <0x0 0x2000>;
                                clocks = <&dcan1_fck>;
-                               clock-name = "fck";
+                               clock-names = "fck";
                                syscon-raminit = <&scm_conf 0x644 1>;
                                interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
index aae0af1..2aa75ab 100644 (file)
        status = "okay";
        pinctrl-names = "default";
        pinctrl-0 = <&i2c0_pins>;
-       clock-frequency = <400000>;
+       clock-frequency = <100000>;
 
        tps65218: tps65218@24 {
                reg = <0x24>;
index f98691a..d3082b9 100644 (file)
 
                pinctrl_power_button: powerbutgrp {
                        fsl,pins = <
-                               MX53_PAD_SD2_DATA2__GPIO1_13            0x1e4
+                               MX53_PAD_SD2_DATA0__GPIO1_15            0x1e4
                        >;
                };
 
                pinctrl_power_out: poweroutgrp {
                        fsl,pins = <
-                               MX53_PAD_SD2_DATA0__GPIO1_15            0x1e4
+                               MX53_PAD_SD2_DATA2__GPIO1_13            0x1e4
                        >;
                };
 
index 0ad8ccd..f86efd0 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_microsom_enet_ar8035>;
        phy-mode = "rgmii-id";
-       phy-reset-duration = <2>;
+
+       /*
+        * The PHY seems to require a long-enough reset duration to avoid
+        * some rare issues where the PHY gets stuck in an inconsistent and
+        * non-functional state at boot-up. 10ms proved to be fine .
+        */
+       phy-reset-duration = <10>;
        phy-reset-gpios = <&gpio4 15 GPIO_ACTIVE_LOW>;
        status = "okay";
 
index a054543..9f1e382 100644 (file)
@@ -43,6 +43,7 @@
        assigned-clock-rates = <0>, <198000000>;
        cap-power-off-card;
        keep-power-in-suspend;
+       max-frequency = <25000000>;
        mmc-pwrseq = <&wifi_pwrseq>;
        no-1-8-v;
        non-removable;
index 45435bb..373984c 100644 (file)
                regulator-max-microvolt = <5000000>;
        };
 
-       vdds_1v8_main: fixedregulator-vdds_1v8_main {
-               compatible = "regulator-fixed";
-               regulator-name = "vdds_1v8_main";
-               vin-supply = <&smps7_reg>;
-               regulator-min-microvolt = <1800000>;
-               regulator-max-microvolt = <1800000>;
-       };
-
        vmmcsd_fixed: fixedregulator-mmcsd {
                compatible = "regulator-fixed";
                regulator-name = "vmmcsd_fixed";
                                        regulator-boot-on;
                                };
 
+                               vdds_1v8_main:
                                smps7_reg: smps7 {
                                        /* VDDS_1v8_OMAP over VDDS_1v8_MAIN */
                                        regulator-name = "smps7";
index c9b9064..1815361 100644 (file)
                        status = "disabled";
                };
 
-               vica: intc@10140000 {
+               vica: interrupt-controller@10140000 {
                        compatible = "arm,versatile-vic";
                        interrupt-controller;
                        #interrupt-cells = <1>;
                        reg = <0x10140000 0x20>;
                };
 
-               vicb: intc@10140020 {
+               vicb: interrupt-controller@10140020 {
                        compatible = "arm,versatile-vic";
                        interrupt-controller;
                        #interrupt-cells = <1>;
index c5ea08f..6cf1c8b 100644 (file)
@@ -37,7 +37,7 @@
                poll-interval = <20>;
 
                /*
-                * The EXTi IRQ line 3 is shared with touchscreen and ethernet,
+                * The EXTi IRQ line 3 is shared with ethernet,
                 * so mark this as polled GPIO key.
                 */
                button-0 {
                        gpios = <&gpiof 3 GPIO_ACTIVE_LOW>;
                };
 
+               /*
+                * The EXTi IRQ line 6 is shared with touchscreen,
+                * so mark this as polled GPIO key.
+                */
+               button-1 {
+                       label = "TA2-GPIO-B";
+                       linux,code = <KEY_B>;
+                       gpios = <&gpiod 6 GPIO_ACTIVE_LOW>;
+               };
+
                /*
                 * The EXTi IRQ line 0 is shared with PMIC,
                 * so mark this as polled GPIO key.
        gpio-keys {
                compatible = "gpio-keys";
 
-               button-1 {
-                       label = "TA2-GPIO-B";
-                       linux,code = <KEY_B>;
-                       gpios = <&gpiod 6 GPIO_ACTIVE_LOW>;
-                       wakeup-source;
-               };
-
                button-3 {
                        label = "TA4-GPIO-D";
                        linux,code = <KEY_D>;
@@ -82,6 +85,7 @@
                        label = "green:led5";
                        gpios = <&gpioc 6 GPIO_ACTIVE_HIGH>;
                        default-state = "off";
+                       status = "disabled";
                };
 
                led-1 {
        touchscreen@38 {
                compatible = "edt,edt-ft5406";
                reg = <0x38>;
-               interrupt-parent = <&gpiog>;
-               interrupts = <2 IRQ_TYPE_EDGE_FALLING>; /* GPIO E */
+               interrupt-parent = <&gpioc>;
+               interrupts = <6 IRQ_TYPE_EDGE_FALLING>; /* GPIO E */
        };
 };
 
index 2af0a67..8c41f81 100644 (file)
@@ -12,6 +12,8 @@
        aliases {
                ethernet0 = &ethernet0;
                ethernet1 = &ksz8851;
+               rtc0 = &hwrtc;
+               rtc1 = &rtc;
        };
 
        memory@c0000000 {
                        reset-gpios = <&gpioh 3 GPIO_ACTIVE_LOW>;
                        reset-assert-us = <500>;
                        reset-deassert-us = <500>;
+                       smsc,disable-energy-detect;
                        interrupt-parent = <&gpioi>;
                        interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
                };
        /delete-property/dmas;
        /delete-property/dma-names;
 
-       rtc@32 {
+       hwrtc: rtc@32 {
                compatible = "microcrystal,rv8803";
                reg = <0x32>;
        };
index 3f35761..23595fc 100644 (file)
@@ -15,8 +15,6 @@ CONFIG_SLAB=y
 CONFIG_ARCH_NOMADIK=y
 CONFIG_MACH_NOMADIK_8815NHK=y
 CONFIG_AEABI=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
@@ -52,9 +50,9 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_ONENAND=y
 CONFIG_MTD_ONENAND_VERIFY_WRITE=y
 CONFIG_MTD_ONENAND_GENERIC=y
-CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC=y
 CONFIG_MTD_RAW_NAND=y
 CONFIG_MTD_NAND_FSMC=y
+CONFIG_MTD_NAND_ECC_SW_HAMMING_SMC=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
@@ -97,6 +95,7 @@ CONFIG_REGULATOR=y
 CONFIG_DRM=y
 CONFIG_DRM_PANEL_TPO_TPG110=y
 CONFIG_DRM_PL111=y
+CONFIG_FB=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
@@ -136,9 +135,8 @@ CONFIG_NLS_ISO8859_15=y
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_SHA1=y
 CONFIG_CRYPTO_DES=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_ENABLE_MUST_CHECK is not set
 CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
index cfc9dfd..f673e13 100644 (file)
@@ -160,10 +160,11 @@ extern unsigned long vectors_base;
 
 /*
  * Physical start and end address of the kernel sections. These addresses are
- * 2MB-aligned to match the section mappings placed over the kernel.
+ * 2MB-aligned to match the section mappings placed over the kernel. We use
+ * u64 so that LPAE mappings beyond the 32bit limit will work out as well.
  */
-extern u32 kernel_sec_start;
-extern u32 kernel_sec_end;
+extern u64 kernel_sec_start;
+extern u64 kernel_sec_end;
 
 /*
  * Physical vs virtual RAM address space conversion.  These are
index 9eb0b4d..29070eb 100644 (file)
@@ -49,7 +49,8 @@
 
        /*
         * This needs to be assigned at runtime when the linker symbols are
-        * resolved.
+        * resolved. These are unsigned 64bit really, but in this assembly code
+        * We store them as 32bit.
         */
        .pushsection .data
        .align  2
@@ -57,7 +58,9 @@
        .globl  kernel_sec_end
 kernel_sec_start:
        .long   0
+       .long   0
 kernel_sec_end:
+       .long   0
        .long   0
        .popsection
 
@@ -250,7 +253,11 @@ __create_page_tables:
        add     r0, r4, #KERNEL_OFFSET >> (SECTION_SHIFT - PMD_ORDER)
        ldr     r6, =(_end - 1)
        adr_l   r5, kernel_sec_start            @ _pa(kernel_sec_start)
-       str     r8, [r5]                        @ Save physical start of kernel
+#ifdef CONFIG_CPU_ENDIAN_BE8
+       str     r8, [r5, #4]                    @ Save physical start of kernel (BE)
+#else
+       str     r8, [r5]                        @ Save physical start of kernel (LE)
+#endif
        orr     r3, r8, r7                      @ Add the MMU flags
        add     r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER)
 1:     str     r3, [r0], #1 << PMD_ORDER
@@ -259,7 +266,11 @@ __create_page_tables:
        bls     1b
        eor     r3, r3, r7                      @ Remove the MMU flags
        adr_l   r5, kernel_sec_end              @ _pa(kernel_sec_end)
-       str     r3, [r5]                        @ Save physical end of kernel
+#ifdef CONFIG_CPU_ENDIAN_BE8
+       str     r3, [r5, #4]                    @ Save physical end of kernel (BE)
+#else
+       str     r3, [r5]                        @ Save physical end of kernel (LE)
+#endif
 
 #ifdef CONFIG_XIP_KERNEL
        /*
index f0a073a..13f3068 100644 (file)
@@ -68,7 +68,6 @@ void imx_set_cpu_arg(int cpu, u32 arg);
 void v7_secondary_startup(void);
 void imx_scu_map_io(void);
 void imx_smp_prepare(void);
-void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn);
 #else
 static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
@@ -81,6 +80,7 @@ void imx_gpc_mask_all(void);
 void imx_gpc_restore_all(void);
 void imx_gpc_hwirq_mask(unsigned int hwirq);
 void imx_gpc_hwirq_unmask(unsigned int hwirq);
+void imx_gpcv2_set_core1_pdn_pup_by_software(bool pdn);
 void imx_anatop_init(void);
 void imx_anatop_pre_suspend(void);
 void imx_anatop_post_resume(void);
index 0dfd0ae..af12668 100644 (file)
@@ -103,6 +103,7 @@ struct mmdc_pmu {
        struct perf_event *mmdc_events[MMDC_NUM_COUNTERS];
        struct hlist_node node;
        struct fsl_mmdc_devtype_data *devtype_data;
+       struct clk *mmdc_ipg_clk;
 };
 
 /*
@@ -462,11 +463,14 @@ static int imx_mmdc_remove(struct platform_device *pdev)
 
        cpuhp_state_remove_instance_nocalls(cpuhp_mmdc_state, &pmu_mmdc->node);
        perf_pmu_unregister(&pmu_mmdc->pmu);
+       iounmap(pmu_mmdc->mmdc_base);
+       clk_disable_unprepare(pmu_mmdc->mmdc_ipg_clk);
        kfree(pmu_mmdc);
        return 0;
 }
 
-static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base)
+static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_base,
+                             struct clk *mmdc_ipg_clk)
 {
        struct mmdc_pmu *pmu_mmdc;
        char *name;
@@ -494,6 +498,7 @@ static int imx_mmdc_perf_init(struct platform_device *pdev, void __iomem *mmdc_b
        }
 
        mmdc_num = mmdc_pmu_init(pmu_mmdc, mmdc_base, &pdev->dev);
+       pmu_mmdc->mmdc_ipg_clk = mmdc_ipg_clk;
        if (mmdc_num == 0)
                name = "mmdc";
        else
@@ -529,7 +534,7 @@ pmu_free:
 
 #else
 #define imx_mmdc_remove NULL
-#define imx_mmdc_perf_init(pdev, mmdc_base) 0
+#define imx_mmdc_perf_init(pdev, mmdc_base, mmdc_ipg_clk) 0
 #endif
 
 static int imx_mmdc_probe(struct platform_device *pdev)
@@ -567,7 +572,13 @@ static int imx_mmdc_probe(struct platform_device *pdev)
        val &= ~(1 << BP_MMDC_MAPSR_PSD);
        writel_relaxed(val, reg);
 
-       return imx_mmdc_perf_init(pdev, mmdc_base);
+       err = imx_mmdc_perf_init(pdev, mmdc_base, mmdc_ipg_clk);
+       if (err) {
+               iounmap(mmdc_base);
+               clk_disable_unprepare(mmdc_ipg_clk);
+       }
+
+       return err;
 }
 
 int imx_mmdc_get_ddr_type(void)
index bf14d65..34a1c77 100644 (file)
@@ -91,6 +91,7 @@ config MACH_IXDP465
 
 config MACH_GORAMO_MLR
        bool "GORAMO Multi Link Router"
+       depends on IXP4XX_PCI_LEGACY
        help
          Say 'Y' here if you want your kernel to support GORAMO
          MultiLink router.
index abb07f1..74e63d4 100644 (file)
 /*
  * PCI Control/Status Registers
  */
-#define IXP4XX_PCI_CSR(x) ((volatile u32 *)(IXP4XX_PCI_CFG_BASE_VIRT+(x)))
-
-#define PCI_NP_AD               IXP4XX_PCI_CSR(PCI_NP_AD_OFFSET)
-#define PCI_NP_CBE              IXP4XX_PCI_CSR(PCI_NP_CBE_OFFSET)
-#define PCI_NP_WDATA            IXP4XX_PCI_CSR(PCI_NP_WDATA_OFFSET)
-#define PCI_NP_RDATA            IXP4XX_PCI_CSR(PCI_NP_RDATA_OFFSET)
-#define PCI_CRP_AD_CBE          IXP4XX_PCI_CSR(PCI_CRP_AD_CBE_OFFSET)
-#define PCI_CRP_WDATA           IXP4XX_PCI_CSR(PCI_CRP_WDATA_OFFSET)
-#define PCI_CRP_RDATA           IXP4XX_PCI_CSR(PCI_CRP_RDATA_OFFSET)
-#define PCI_CSR                 IXP4XX_PCI_CSR(PCI_CSR_OFFSET) 
-#define PCI_ISR                 IXP4XX_PCI_CSR(PCI_ISR_OFFSET)
-#define PCI_INTEN               IXP4XX_PCI_CSR(PCI_INTEN_OFFSET)
-#define PCI_DMACTRL             IXP4XX_PCI_CSR(PCI_DMACTRL_OFFSET)
-#define PCI_AHBMEMBASE          IXP4XX_PCI_CSR(PCI_AHBMEMBASE_OFFSET)
-#define PCI_AHBIOBASE           IXP4XX_PCI_CSR(PCI_AHBIOBASE_OFFSET)
-#define PCI_PCIMEMBASE          IXP4XX_PCI_CSR(PCI_PCIMEMBASE_OFFSET)
-#define PCI_AHBDOORBELL         IXP4XX_PCI_CSR(PCI_AHBDOORBELL_OFFSET)
-#define PCI_PCIDOORBELL         IXP4XX_PCI_CSR(PCI_PCIDOORBELL_OFFSET)
-#define PCI_ATPDMA0_AHBADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_AHBADDR_OFFSET)
-#define PCI_ATPDMA0_PCIADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_PCIADDR_OFFSET)
-#define PCI_ATPDMA0_LENADDR     IXP4XX_PCI_CSR(PCI_ATPDMA0_LENADDR_OFFSET)
-#define PCI_ATPDMA1_AHBADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_AHBADDR_OFFSET)
-#define PCI_ATPDMA1_PCIADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_PCIADDR_OFFSET)
-#define PCI_ATPDMA1_LENADDR     IXP4XX_PCI_CSR(PCI_ATPDMA1_LENADDR_OFFSET)
+#define _IXP4XX_PCI_CSR(x) ((volatile u32 *)(IXP4XX_PCI_CFG_BASE_VIRT+(x)))
+
+#define PCI_NP_AD               _IXP4XX_PCI_CSR(PCI_NP_AD_OFFSET)
+#define PCI_NP_CBE              _IXP4XX_PCI_CSR(PCI_NP_CBE_OFFSET)
+#define PCI_NP_WDATA            _IXP4XX_PCI_CSR(PCI_NP_WDATA_OFFSET)
+#define PCI_NP_RDATA            _IXP4XX_PCI_CSR(PCI_NP_RDATA_OFFSET)
+#define PCI_CRP_AD_CBE          _IXP4XX_PCI_CSR(PCI_CRP_AD_CBE_OFFSET)
+#define PCI_CRP_WDATA           _IXP4XX_PCI_CSR(PCI_CRP_WDATA_OFFSET)
+#define PCI_CRP_RDATA           _IXP4XX_PCI_CSR(PCI_CRP_RDATA_OFFSET)
+#define PCI_CSR                 _IXP4XX_PCI_CSR(PCI_CSR_OFFSET) 
+#define PCI_ISR                 _IXP4XX_PCI_CSR(PCI_ISR_OFFSET)
+#define PCI_INTEN               _IXP4XX_PCI_CSR(PCI_INTEN_OFFSET)
+#define PCI_DMACTRL             _IXP4XX_PCI_CSR(PCI_DMACTRL_OFFSET)
+#define PCI_AHBMEMBASE          _IXP4XX_PCI_CSR(PCI_AHBMEMBASE_OFFSET)
+#define PCI_AHBIOBASE           _IXP4XX_PCI_CSR(PCI_AHBIOBASE_OFFSET)
+#define PCI_PCIMEMBASE          _IXP4XX_PCI_CSR(PCI_PCIMEMBASE_OFFSET)
+#define PCI_AHBDOORBELL         _IXP4XX_PCI_CSR(PCI_AHBDOORBELL_OFFSET)
+#define PCI_PCIDOORBELL         _IXP4XX_PCI_CSR(PCI_PCIDOORBELL_OFFSET)
+#define PCI_ATPDMA0_AHBADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA0_AHBADDR_OFFSET)
+#define PCI_ATPDMA0_PCIADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA0_PCIADDR_OFFSET)
+#define PCI_ATPDMA0_LENADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA0_LENADDR_OFFSET)
+#define PCI_ATPDMA1_AHBADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA1_AHBADDR_OFFSET)
+#define PCI_ATPDMA1_PCIADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA1_PCIADDR_OFFSET)
+#define PCI_ATPDMA1_LENADDR     _IXP4XX_PCI_CSR(PCI_ATPDMA1_LENADDR_OFFSET)
 
 /*
  * PCI register values and bit definitions 
index 65934b2..12b26e0 100644 (file)
@@ -3776,6 +3776,7 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
        struct omap_hwmod_ocp_if *oi;
        struct clockdomain *clkdm;
        struct clk_hw_omap *clk;
+       struct clk_hw *hw;
 
        if (!oh)
                return NULL;
@@ -3792,7 +3793,14 @@ struct powerdomain *omap_hwmod_get_pwrdm(struct omap_hwmod *oh)
                c = oi->_clk;
        }
 
-       clk = to_clk_hw_omap(__clk_get_hw(c));
+       hw = __clk_get_hw(c);
+       if (!hw)
+               return NULL;
+
+       clk = to_clk_hw_omap(hw);
+       if (!clk)
+               return NULL;
+
        clkdm = clk->clkdm;
        if (!clkdm)
                return NULL;
index 7583bda..a4e0060 100644 (file)
@@ -1608,6 +1608,13 @@ static void __init early_paging_init(const struct machine_desc *mdesc)
        if (offset == 0)
                return;
 
+       /*
+        * Offset the kernel section physical offsets so that the kernel
+        * mapping will work out later on.
+        */
+       kernel_sec_start += offset;
+       kernel_sec_end += offset;
+
        /*
         * Get the address of the remap function in the 1:1 identity
         * mapping setup by the early page table assembly code.  We
@@ -1716,7 +1723,7 @@ void __init paging_init(const struct machine_desc *mdesc)
 {
        void *zero_page;
 
-       pr_debug("physical kernel sections: 0x%08x-0x%08x\n",
+       pr_debug("physical kernel sections: 0x%08llx-0x%08llx\n",
                 kernel_sec_start, kernel_sec_end);
 
        prepare_page_table();
index 5c5e195..f8e11f7 100644 (file)
@@ -29,7 +29,7 @@ ENTRY(lpae_pgtables_remap_asm)
        ldr     r6, =(_end - 1)
        add     r7, r2, #0x1000
        add     r6, r7, r6, lsr #SECTION_SHIFT - L2_ORDER
-       add     r7, r7, #PAGE_OFFSET >> (SECTION_SHIFT - L2_ORDER)
+       add     r7, r7, #KERNEL_OFFSET >> (SECTION_SHIFT - L2_ORDER)
 1:     ldrd    r4, r5, [r7]
        adds    r4, r4, r0
        adc     r5, r5, r1
index b5b13a9..62c3c1d 100644 (file)
@@ -156,6 +156,7 @@ config ARM64
        select HAVE_ARCH_KGDB
        select HAVE_ARCH_MMAP_RND_BITS
        select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
+       select HAVE_ARCH_PFN_VALID
        select HAVE_ARCH_PREL32_RELOCATIONS
        select HAVE_ARCH_RANDOMIZE_KSTACK_OFFSET
        select HAVE_ARCH_SECCOMP_FILTER
@@ -1800,11 +1801,11 @@ config RANDOMIZE_BASE
          If unsure, say N.
 
 config RANDOMIZE_MODULE_REGION_FULL
-       bool "Randomize the module region over a 4 GB range"
+       bool "Randomize the module region over a 2 GB range"
        depends on RANDOMIZE_BASE
        default y
        help
-         Randomizes the location of the module region inside a 4 GB window
+         Randomizes the location of the module region inside a 2 GB window
          covering the core kernel. This way, it is less likely for modules
          to leak information about the location of core kernel data structures
          but it does imply that function calls between modules and the core
@@ -1812,7 +1813,10 @@ config RANDOMIZE_MODULE_REGION_FULL
 
          When this option is not set, the module region will be randomized over
          a limited range that contains the [_stext, _etext] interval of the
-         core kernel, so branch relocations are always in range.
+         core kernel, so branch relocations are almost always in range unless
+         ARM64_MODULE_PLTS is enabled and the region is exhausted. In this
+         particular case of region exhaustion, modules might be able to fall
+         back to a larger 2GB area.
 
 config CC_HAVE_STACKPROTECTOR_SYSREG
        def_bool $(cc-option,-mstack-protector-guard=sysreg -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard-offset=0)
index 7bc37d0..1110d38 100644 (file)
@@ -21,19 +21,11 @@ LDFLAGS_vmlinux             += -shared -Bsymbolic -z notext \
 endif
 
 ifeq ($(CONFIG_ARM64_ERRATUM_843419),y)
-  ifneq ($(CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419),y)
-$(warning ld does not support --fix-cortex-a53-843419; kernel may be susceptible to erratum)
-  else
+  ifeq ($(CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419),y)
 LDFLAGS_vmlinux        += --fix-cortex-a53-843419
   endif
 endif
 
-ifeq ($(CONFIG_ARM64_USE_LSE_ATOMICS), y)
-  ifneq ($(CONFIG_ARM64_LSE_ATOMICS), y)
-$(warning LSE atomics not supported by binutils)
-  endif
-endif
-
 cc_has_k_constraint := $(call try-run,echo                             \
        'int main(void) {                                               \
                asm volatile("and w0, w0, %w0" :: "K" (4294967295));    \
@@ -176,10 +168,23 @@ vdso_install:
 
 archprepare:
        $(Q)$(MAKE) $(build)=arch/arm64/tools kapi
+ifeq ($(CONFIG_ARM64_ERRATUM_843419),y)
+  ifneq ($(CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419),y)
+       @echo "warning: ld does not support --fix-cortex-a53-843419; kernel may be susceptible to erratum" >&2
+  endif
+endif
+ifeq ($(CONFIG_ARM64_USE_LSE_ATOMICS),y)
+  ifneq ($(CONFIG_ARM64_LSE_ATOMICS),y)
+       @echo "warning: LSE atomics not supported by binutils" >&2
+  endif
+endif
+
 
 # We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
+       $(Q)$(MAKE) $(clean)=arch/arm64/kernel/vdso
+       $(Q)$(MAKE) $(clean)=arch/arm64/kernel/vdso32
 
 ifeq ($(KBUILD_EXTMOD),)
 # We need to generate vdso-offsets.h before compiling certain files in kernel/.
index dd764b7..f6a79c8 100644 (file)
@@ -54,6 +54,7 @@
 
 &mscc_felix_port0 {
        label = "swp0";
+       managed = "in-band-status";
        phy-handle = <&phy0>;
        phy-mode = "sgmii";
        status = "okay";
@@ -61,6 +62,7 @@
 
 &mscc_felix_port1 {
        label = "swp1";
+       managed = "in-band-status";
        phy-handle = <&phy1>;
        phy-mode = "sgmii";
        status = "okay";
index b2e3e5d..343ecf0 100644 (file)
@@ -66,7 +66,7 @@
                };
        };
 
-       sysclk: clock-sysclk {
+       sysclk: sysclk {
                compatible = "fixed-clock";
                #clock-cells = <0>;
                clock-frequency = <100000000>;
index ce2bcdd..a05b1ab 100644 (file)
@@ -19,6 +19,8 @@
        aliases {
                spi0 = &spi0;
                ethernet1 = &eth1;
+               mmc0 = &sdhci0;
+               mmc1 = &sdhci1;
        };
 
        chosen {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c1_pins>;
        clock-frequency = <100000>;
+       /delete-property/ mrvl,i2c-fast-mode;
        status = "okay";
 
        rtc@6f {
index 076d5ef..5ba7a45 100644 (file)
 
                interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE1R &emc>,
                                <&mc TEGRA194_MEMORY_CLIENT_PCIE1W &emc>;
-               interconnect-names = "read", "write";
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE1>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE1 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        pcie@14120000 {
 
                interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE2AR &emc>,
                                <&mc TEGRA194_MEMORY_CLIENT_PCIE2AW &emc>;
-               interconnect-names = "read", "write";
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE2>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE2 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        pcie@14140000 {
 
                interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE3R &emc>,
                                <&mc TEGRA194_MEMORY_CLIENT_PCIE3W &emc>;
-               interconnect-names = "read", "write";
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE3>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE3 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        pcie@14160000 {
 
                interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE4R &emc>,
                                <&mc TEGRA194_MEMORY_CLIENT_PCIE4W &emc>;
-               interconnect-names = "read", "write";
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE4>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE4 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        pcie@14180000 {
 
                interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE0R &emc>,
                                <&mc TEGRA194_MEMORY_CLIENT_PCIE0W &emc>;
-               interconnect-names = "read", "write";
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE0>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE0 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        pcie@141a0000 {
 
                interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE5R &emc>,
                                <&mc TEGRA194_MEMORY_CLIENT_PCIE5W &emc>;
-               interconnect-names = "read", "write";
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE5>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE5 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        pcie_ep@14160000 {
                nvidia,aspm-cmrt-us = <60>;
                nvidia,aspm-pwr-on-t-us = <20>;
                nvidia,aspm-l0s-entrance-latency-us = <3>;
+
+               interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE4R &emc>,
+                               <&mc TEGRA194_MEMORY_CLIENT_PCIE4W &emc>;
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE4>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE4 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        pcie_ep@14180000 {
                nvidia,aspm-cmrt-us = <60>;
                nvidia,aspm-pwr-on-t-us = <20>;
                nvidia,aspm-l0s-entrance-latency-us = <3>;
+
+               interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE0R &emc>,
+                               <&mc TEGRA194_MEMORY_CLIENT_PCIE0W &emc>;
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE0>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE0 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        pcie_ep@141a0000 {
                nvidia,aspm-cmrt-us = <60>;
                nvidia,aspm-pwr-on-t-us = <20>;
                nvidia,aspm-l0s-entrance-latency-us = <3>;
+
+               interconnects = <&mc TEGRA194_MEMORY_CLIENT_PCIE5R &emc>,
+                               <&mc TEGRA194_MEMORY_CLIENT_PCIE5W &emc>;
+               interconnect-names = "dma-mem", "write";
+               iommus = <&smmu TEGRA194_SID_PCIE5>;
+               iommu-map = <0x0 &smmu TEGRA194_SID_PCIE5 0x1000>;
+               iommu-map-mask = <0x0>;
+               dma-coherent;
        };
 
        sram@40000000 {
index 23cdcc9..1ccca83 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2015, LGE Inc. All rights reserved.
  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
  */
 
 /dts-v1/;
@@ -9,6 +10,9 @@
 #include "pm8994.dtsi"
 #include "pmi8994.dtsi"
 
+/* cont_splash_mem has different memory mapping */
+/delete-node/ &cont_splash_mem;
+
 / {
        model = "LG Nexus 5X";
        compatible = "lg,bullhead", "qcom,msm8992";
@@ -17,6 +21,9 @@
        qcom,board-id = <0xb64 0>;
        qcom,pmic-id = <0x10009 0x1000A 0x0 0x0>;
 
+       /* Bullhead firmware doesn't support PSCI */
+       /delete-node/ psci;
+
        aliases {
                serial0 = &blsp1_uart2;
        };
                        ftrace-size = <0x10000>;
                        pmsg-size = <0x20000>;
                };
+
+               cont_splash_mem: memory@3400000 {
+                       reg = <0 0x03400000 0 0x1200000>;
+                       no-map;
+               };
        };
 };
 
index ffe1a9b..c096b77 100644 (file)
@@ -1,12 +1,16 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /* Copyright (c) 2015, Huawei Inc. All rights reserved.
  * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2021, Petr Vorel <petr.vorel@gmail.com>
  */
 
 /dts-v1/;
 
 #include "msm8994.dtsi"
 
+/* Angler's firmware does not report where the memory is allocated */
+/delete-node/ &cont_splash_mem;
+
 / {
        model = "Huawei Nexus 6P";
        compatible = "huawei,angler", "qcom,msm8994";
index a8c274a..188c576 100644 (file)
                                           &BIG_CPU_SLEEP_1
                                           &CLUSTER_SLEEP_0>;
                        next-level-cache = <&L2_700>;
-                       qcom,freq-domain = <&cpufreq_hw 1>;
+                       qcom,freq-domain = <&cpufreq_hw 2>;
                        #cooling-cells = <2>;
                        L2_700: l2-cache {
                                compatible = "cache";
index 4d052e3..eb6b1d1 100644 (file)
@@ -69,7 +69,7 @@
                };
                rmtfs_upper_guard: memory@f5d01000 {
                        no-map;
-                       reg = <0 0xf5d01000 0 0x2000>;
+                       reg = <0 0xf5d01000 0 0x1000>;
                };
 
                /*
@@ -78,7 +78,7 @@
                 */
                removed_region: memory@88f00000 {
                        no-map;
-                       reg = <0 0x88f00000 0 0x200000>;
+                       reg = <0 0x88f00000 0 0x1c00000>;
                };
 
                ramoops: ramoops@ac300000 {
index c2a709a..d7591a4 100644 (file)
                left_spkr: wsa8810-left{
                        compatible = "sdw10217211000";
                        reg = <0 3>;
-                       powerdown-gpios = <&wcdgpio 2 GPIO_ACTIVE_HIGH>;
+                       powerdown-gpios = <&wcdgpio 1 GPIO_ACTIVE_HIGH>;
                        #thermal-sensor-cells = <0>;
                        sound-name-prefix = "SpkrLeft";
                        #sound-dai-cells = <0>;
 
                right_spkr: wsa8810-right{
                        compatible = "sdw10217211000";
-                       powerdown-gpios = <&wcdgpio 3 GPIO_ACTIVE_HIGH>;
+                       powerdown-gpios = <&wcdgpio 2 GPIO_ACTIVE_HIGH>;
                        reg = <0 4>;
                        #thermal-sensor-cells = <0>;
                        sound-name-prefix = "SpkrRight";
index 21fa330..b83fb24 100644 (file)
@@ -33,8 +33,7 @@
  * EL2.
  */
 .macro __init_el2_timers
-       mrs     x0, cnthctl_el2
-       orr     x0, x0, #3                      // Enable EL1 physical timers
+       mov     x0, #3                          // Enable EL1 physical timers
        msr     cnthctl_el2, x0
        msr     cntvoff_el2, xzr                // Clear virtual offset
 .endm
index 993a27e..f98c91b 100644 (file)
@@ -41,6 +41,7 @@ void tag_clear_highpage(struct page *to);
 
 typedef struct page *pgtable_t;
 
+int pfn_valid(unsigned long pfn);
 int pfn_is_map_memory(unsigned long pfn);
 
 #include <asm/memory.h>
index e58bca8..41b332c 100644 (file)
@@ -320,7 +320,17 @@ static inline unsigned long kernel_stack_pointer(struct pt_regs *regs)
 
 static inline unsigned long regs_return_value(struct pt_regs *regs)
 {
-       return regs->regs[0];
+       unsigned long val = regs->regs[0];
+
+       /*
+        * Audit currently uses regs_return_value() instead of
+        * syscall_get_return_value(). Apply the same sign-extension here until
+        * audit is updated to use syscall_get_return_value().
+        */
+       if (compat_user_mode(regs))
+               val = sign_extend64(val, 31);
+
+       return val;
 }
 
 static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
index 1801399..8aebc00 100644 (file)
@@ -35,7 +35,7 @@ struct stack_info {
  * accounting information necessary for robust unwinding.
  *
  * @fp:          The fp value in the frame record (or the real fp)
- * @pc:          The fp value in the frame record (or the real lr)
+ * @pc:          The lr value in the frame record (or the real lr)
  *
  * @stacks_done: Stacks which have been entirely unwound, for which it is no
  *               longer valid to unwind to.
index cfc0672..03e2089 100644 (file)
@@ -29,22 +29,23 @@ static inline void syscall_rollback(struct task_struct *task,
        regs->regs[0] = regs->orig_x0;
 }
 
-
-static inline long syscall_get_error(struct task_struct *task,
-                                    struct pt_regs *regs)
+static inline long syscall_get_return_value(struct task_struct *task,
+                                           struct pt_regs *regs)
 {
-       unsigned long error = regs->regs[0];
+       unsigned long val = regs->regs[0];
 
        if (is_compat_thread(task_thread_info(task)))
-               error = sign_extend64(error, 31);
+               val = sign_extend64(val, 31);
 
-       return IS_ERR_VALUE(error) ? error : 0;
+       return val;
 }
 
-static inline long syscall_get_return_value(struct task_struct *task,
-                                           struct pt_regs *regs)
+static inline long syscall_get_error(struct task_struct *task,
+                                    struct pt_regs *regs)
 {
-       return regs->regs[0];
+       unsigned long error = syscall_get_return_value(task, regs);
+
+       return IS_ERR_VALUE(error) ? error : 0;
 }
 
 static inline void syscall_set_return_value(struct task_struct *task,
index cfa2cfd..418b2bb 100644 (file)
@@ -162,7 +162,9 @@ u64 __init kaslr_early_init(void)
                 * a PAGE_SIZE multiple in the range [_etext - MODULES_VSIZE,
                 * _stext) . This guarantees that the resulting region still
                 * covers [_stext, _etext], and that all relative branches can
-                * be resolved without veneers.
+                * be resolved without veneers unless this region is exhausted
+                * and we fall back to a larger 2GB window in module_alloc()
+                * when ARM64_MODULE_PLTS is enabled.
                 */
                module_range = MODULES_VSIZE - (u64)(_etext - _stext);
                module_alloc_base = (u64)_etext + offset - MODULES_VSIZE;
index 499b6b2..b381a1e 100644 (file)
@@ -1862,7 +1862,7 @@ void syscall_trace_exit(struct pt_regs *regs)
        audit_syscall_exit(regs);
 
        if (flags & _TIF_SYSCALL_TRACEPOINT)
-               trace_sys_exit(regs, regs_return_value(regs));
+               trace_sys_exit(regs, syscall_get_return_value(current, regs));
 
        if (flags & (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP))
                tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
index f8192f4..2303633 100644 (file)
@@ -29,6 +29,7 @@
 #include <asm/unistd.h>
 #include <asm/fpsimd.h>
 #include <asm/ptrace.h>
+#include <asm/syscall.h>
 #include <asm/signal32.h>
 #include <asm/traps.h>
 #include <asm/vdso.h>
@@ -890,7 +891,7 @@ static void do_signal(struct pt_regs *regs)
                     retval == -ERESTART_RESTARTBLOCK ||
                     (retval == -ERESTARTSYS &&
                      !(ksig.ka.sa.sa_flags & SA_RESTART)))) {
-                       regs->regs[0] = -EINTR;
+                       syscall_set_return_value(current, regs, -EINTR, 0);
                        regs->pc = continue_addr;
                }
 
index b83c8d9..8982a2b 100644 (file)
@@ -218,7 +218,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
 
 #ifdef CONFIG_STACKTRACE
 
-noinline void arch_stack_walk(stack_trace_consume_fn consume_entry,
+noinline notrace void arch_stack_walk(stack_trace_consume_fn consume_entry,
                              void *cookie, struct task_struct *task,
                              struct pt_regs *regs)
 {
index 263d6c1..50a0f1a 100644 (file)
@@ -54,10 +54,7 @@ static void invoke_syscall(struct pt_regs *regs, unsigned int scno,
                ret = do_ni_syscall(regs, scno);
        }
 
-       if (is_compat_task())
-               ret = lower_32_bits(ret);
-
-       regs->regs[0] = ret;
+       syscall_set_return_value(current, regs, 0, ret);
 
        /*
         * Ultimately, this value will get limited by KSTACK_OFFSET_MAX(),
@@ -115,7 +112,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
                 * syscall. do_notify_resume() will send a signal to userspace
                 * before the syscall is restarted.
                 */
-               regs->regs[0] = -ERESTARTNOINTR;
+               syscall_set_return_value(current, regs, -ERESTARTNOINTR, 0);
                return;
        }
 
@@ -136,7 +133,7 @@ static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
                 * anyway.
                 */
                if (scno == NO_SYSCALL)
-                       regs->regs[0] = -ENOSYS;
+                       syscall_set_return_value(current, regs, -ENOSYS, 0);
                scno = syscall_trace_enter(regs);
                if (scno == NO_SYSCALL)
                        goto trace_exit;
index e9a2b8f..0ca72f5 100644 (file)
@@ -94,10 +94,14 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
                kvm->arch.return_nisv_io_abort_to_user = true;
                break;
        case KVM_CAP_ARM_MTE:
-               if (!system_supports_mte() || kvm->created_vcpus)
-                       return -EINVAL;
-               r = 0;
-               kvm->arch.mte_enabled = true;
+               mutex_lock(&kvm->lock);
+               if (!system_supports_mte() || kvm->created_vcpus) {
+                       r = -EINVAL;
+               } else {
+                       r = 0;
+                       kvm->arch.mte_enabled = true;
+               }
+               mutex_unlock(&kvm->lock);
                break;
        default:
                r = -EINVAL;
index d938ce9..a6ce991 100644 (file)
@@ -193,7 +193,7 @@ static bool range_is_memory(u64 start, u64 end)
 {
        struct kvm_mem_range r1, r2;
 
-       if (!find_mem_range(start, &r1) || !find_mem_range(end, &r2))
+       if (!find_mem_range(start, &r1) || !find_mem_range(end - 1, &r2))
                return false;
        if (r1.start != r2.start)
                return false;
index 8490ed2..1fdb7bb 100644 (file)
@@ -219,6 +219,43 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
        free_area_init(max_zone_pfns);
 }
 
+int pfn_valid(unsigned long pfn)
+{
+       phys_addr_t addr = PFN_PHYS(pfn);
+       struct mem_section *ms;
+
+       /*
+        * Ensure the upper PAGE_SHIFT bits are clear in the
+        * pfn. Else it might lead to false positives when
+        * some of the upper bits are set, but the lower bits
+        * match a valid pfn.
+        */
+       if (PHYS_PFN(addr) != pfn)
+               return 0;
+
+       if (pfn_to_section_nr(pfn) >= NR_MEM_SECTIONS)
+               return 0;
+
+       ms = __pfn_to_section(pfn);
+       if (!valid_section(ms))
+               return 0;
+
+       /*
+        * ZONE_DEVICE memory does not have the memblock entries.
+        * memblock_is_map_memory() check for ZONE_DEVICE based
+        * addresses will always fail. Even the normal hotplugged
+        * memory will never have MEMBLOCK_NOMAP flag set in their
+        * memblock entries. Skip memblock search for all non early
+        * memory sections covering all of hotplug memory including
+        * both normal and ZONE_DEVICE based.
+        */
+       if (!early_section(ms))
+               return pfn_section_valid(ms, pfn);
+
+       return memblock_is_memory(addr);
+}
+EXPORT_SYMBOL(pfn_valid);
+
 int pfn_is_map_memory(unsigned long pfn)
 {
        phys_addr_t addr = PFN_PHYS(pfn);
index 4e942b7..653befc 100644 (file)
@@ -321,7 +321,7 @@ KBUILD_LDFLAGS              += -m $(ld-emul)
 
 ifdef CONFIG_MIPS
 CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
-       egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \
+       egrep -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
        sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
 endif
 
index 4b2567d..c7925d0 100644 (file)
@@ -58,15 +58,20 @@ do {                                                        \
 
 static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-       pmd_t *pmd = NULL;
+       pmd_t *pmd;
        struct page *pg;
 
-       pg = alloc_pages(GFP_KERNEL | __GFP_ACCOUNT, PMD_ORDER);
-       if (pg) {
-               pgtable_pmd_page_ctor(pg);
-               pmd = (pmd_t *)page_address(pg);
-               pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
+       pg = alloc_pages(GFP_KERNEL_ACCOUNT, PMD_ORDER);
+       if (!pg)
+               return NULL;
+
+       if (!pgtable_pmd_page_ctor(pg)) {
+               __free_pages(pg, PMD_ORDER);
+               return NULL;
        }
+
+       pmd = (pmd_t *)page_address(pg);
+       pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table);
        return pmd;
 }
 
index ee74719..4ffbcc5 100644 (file)
@@ -48,7 +48,8 @@ static struct plat_serial8250_port uart8250_data[] = {
                .mapbase        = 0x1f000900,   /* The CBUS UART */
                .irq            = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_MB2,
                .uartclk        = 3686400,      /* Twice the usual clk! */
-               .iotype         = UPIO_MEM32,
+               .iotype         = IS_ENABLED(CONFIG_CPU_BIG_ENDIAN) ?
+                                 UPIO_MEM32BE : UPIO_MEM32,
                .flags          = CBUS_UART_FLAGS,
                .regshift       = 3,
        },
index 4a0c9db..f6e1132 100644 (file)
@@ -8,19 +8,4 @@ extern void * memset(void *, int, size_t);
 #define __HAVE_ARCH_MEMCPY
 void * memcpy(void * dest,const void *src,size_t count);
 
-#define __HAVE_ARCH_STRLEN
-extern size_t strlen(const char *s);
-
-#define __HAVE_ARCH_STRCPY
-extern char *strcpy(char *dest, const char *src);
-
-#define __HAVE_ARCH_STRNCPY
-extern char *strncpy(char *dest, const char *src, size_t count);
-
-#define __HAVE_ARCH_STRCAT
-extern char *strcat(char *dest, const char *src);
-
-#define __HAVE_ARCH_MEMSET
-extern void *memset(void *, int, size_t);
-
 #endif
index 8ed409e..e8a6a75 100644 (file)
 
 #include <linux/string.h>
 EXPORT_SYMBOL(memset);
-EXPORT_SYMBOL(strlen);
-EXPORT_SYMBOL(strcpy);
-EXPORT_SYMBOL(strncpy);
-EXPORT_SYMBOL(strcat);
 
 #include <linux/atomic.h>
 EXPORT_SYMBOL(__xchg8);
index 2d7a997..7b19766 100644 (file)
@@ -3,7 +3,7 @@
 # Makefile for parisc-specific library files
 #
 
-lib-y  := lusercopy.o bitops.o checksum.o io.o memcpy.o \
-          ucmpdi2.o delay.o string.o
+lib-y  := lusercopy.o bitops.o checksum.o io.o memset.o memcpy.o \
+          ucmpdi2.o delay.o
 
 obj-y  := iomap.o
diff --git a/arch/parisc/lib/memset.c b/arch/parisc/lib/memset.c
new file mode 100644 (file)
index 0000000..133e480
--- /dev/null
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <linux/types.h>
+#include <asm/string.h>
+
+#define OPSIZ (BITS_PER_LONG/8)
+typedef unsigned long op_t;
+
+void *
+memset (void *dstpp, int sc, size_t len)
+{
+  unsigned int c = sc;
+  long int dstp = (long int) dstpp;
+
+  if (len >= 8)
+    {
+      size_t xlen;
+      op_t cccc;
+
+      cccc = (unsigned char) c;
+      cccc |= cccc << 8;
+      cccc |= cccc << 16;
+      if (OPSIZ > 4)
+       /* Do the shift in two steps to avoid warning if long has 32 bits.  */
+       cccc |= (cccc << 16) << 16;
+
+      /* There are at least some bytes to set.
+        No need to test for LEN == 0 in this alignment loop.  */
+      while (dstp % OPSIZ != 0)
+       {
+         ((unsigned char *) dstp)[0] = c;
+         dstp += 1;
+         len -= 1;
+       }
+
+      /* Write 8 `op_t' per iteration until less than 8 `op_t' remain.  */
+      xlen = len / (OPSIZ * 8);
+      while (xlen > 0)
+       {
+         ((op_t *) dstp)[0] = cccc;
+         ((op_t *) dstp)[1] = cccc;
+         ((op_t *) dstp)[2] = cccc;
+         ((op_t *) dstp)[3] = cccc;
+         ((op_t *) dstp)[4] = cccc;
+         ((op_t *) dstp)[5] = cccc;
+         ((op_t *) dstp)[6] = cccc;
+         ((op_t *) dstp)[7] = cccc;
+         dstp += 8 * OPSIZ;
+         xlen -= 1;
+       }
+      len %= OPSIZ * 8;
+
+      /* Write 1 `op_t' per iteration until less than OPSIZ bytes remain.  */
+      xlen = len / OPSIZ;
+      while (xlen > 0)
+       {
+         ((op_t *) dstp)[0] = cccc;
+         dstp += OPSIZ;
+         xlen -= 1;
+       }
+      len %= OPSIZ;
+    }
+
+  /* Write the last few bytes.  */
+  while (len > 0)
+    {
+      ((unsigned char *) dstp)[0] = c;
+      dstp += 1;
+      len -= 1;
+    }
+
+  return dstpp;
+}
diff --git a/arch/parisc/lib/string.S b/arch/parisc/lib/string.S
deleted file mode 100644 (file)
index 4a64264..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *    PA-RISC assembly string functions
- *
- *    Copyright (C) 2019 Helge Deller <deller@gmx.de>
- */
-
-#include <asm/assembly.h>
-#include <linux/linkage.h>
-
-       .section .text.hot
-       .level PA_ASM_LEVEL
-
-       t0 = r20
-       t1 = r21
-       t2 = r22
-
-ENTRY_CFI(strlen, frame=0,no_calls)
-       or,COND(<>) arg0,r0,ret0
-       b,l,n   .Lstrlen_null_ptr,r0
-       depwi   0,31,2,ret0
-       cmpb,COND(<>) arg0,ret0,.Lstrlen_not_aligned
-       ldw,ma  4(ret0),t0
-       cmpib,tr 0,r0,.Lstrlen_loop
-       uxor,nbz r0,t0,r0
-.Lstrlen_not_aligned:
-       uaddcm  arg0,ret0,t1
-       shladd  t1,3,r0,t1
-       mtsar   t1
-       depwi   -1,%sar,32,t0
-       uxor,nbz r0,t0,r0
-.Lstrlen_loop:
-       b,l,n   .Lstrlen_end_loop,r0
-       ldw,ma  4(ret0),t0
-       cmpib,tr 0,r0,.Lstrlen_loop
-       uxor,nbz r0,t0,r0
-.Lstrlen_end_loop:
-       extrw,u,<> t0,7,8,r0
-       addib,tr,n -3,ret0,.Lstrlen_out
-       extrw,u,<> t0,15,8,r0
-       addib,tr,n -2,ret0,.Lstrlen_out
-       extrw,u,<> t0,23,8,r0
-       addi    -1,ret0,ret0
-.Lstrlen_out:
-       bv r0(rp)
-       uaddcm ret0,arg0,ret0
-.Lstrlen_null_ptr:
-       bv,n r0(rp)
-ENDPROC_CFI(strlen)
-
-
-ENTRY_CFI(strcpy, frame=0,no_calls)
-       ldb     0(arg1),t0
-       stb     t0,0(arg0)
-       ldo     0(arg0),ret0
-       ldo     1(arg1),t1
-       cmpb,=  r0,t0,2f
-       ldo     1(arg0),t2
-1:     ldb     0(t1),arg1
-       stb     arg1,0(t2)
-       ldo     1(t1),t1
-       cmpb,<> r0,arg1,1b
-       ldo     1(t2),t2
-2:     bv,n    r0(rp)
-ENDPROC_CFI(strcpy)
-
-
-ENTRY_CFI(strncpy, frame=0,no_calls)
-       ldb     0(arg1),t0
-       stb     t0,0(arg0)
-       ldo     1(arg1),t1
-       ldo     0(arg0),ret0
-       cmpb,=  r0,t0,2f
-       ldo     1(arg0),arg1
-1:     ldo     -1(arg2),arg2
-       cmpb,COND(=),n r0,arg2,2f
-       ldb     0(t1),arg0
-       stb     arg0,0(arg1)
-       ldo     1(t1),t1
-       cmpb,<> r0,arg0,1b
-       ldo     1(arg1),arg1
-2:     bv,n    r0(rp)
-ENDPROC_CFI(strncpy)
-
-
-ENTRY_CFI(strcat, frame=0,no_calls)
-       ldb     0(arg0),t0
-       cmpb,=  t0,r0,2f
-       ldo     0(arg0),ret0
-       ldo     1(arg0),arg0
-1:     ldb     0(arg0),t1
-       cmpb,<>,n r0,t1,1b
-       ldo     1(arg0),arg0
-2:     ldb     0(arg1),t2
-       stb     t2,0(arg0)
-       ldo     1(arg0),arg0
-       ldb     0(arg1),t0
-       cmpb,<> r0,t0,2b
-       ldo     1(arg1),arg1
-       bv,n    r0(rp)
-ENDPROC_CFI(strcat)
-
-
-ENTRY_CFI(memset, frame=0,no_calls)
-       copy    arg0,ret0
-       cmpb,COND(=) r0,arg0,4f
-       copy    arg0,t2
-       cmpb,COND(=) r0,arg2,4f
-       ldo     -1(arg2),arg3
-       subi    -1,arg3,t0
-       subi    0,t0,t1
-       cmpiclr,COND(>=) 0,t1,arg2
-       ldo     -1(t1),arg2
-       extru arg2,31,2,arg0
-2:     stb     arg1,0(t2)
-       ldo     1(t2),t2
-       addib,>= -1,arg0,2b
-       ldo     -1(arg3),arg3
-       cmpiclr,COND(<=) 4,arg2,r0
-       b,l,n   4f,r0
-#ifdef CONFIG_64BIT
-       depd,*  r0,63,2,arg2
-#else
-       depw    r0,31,2,arg2
-#endif
-       ldo     1(t2),t2
-3:     stb     arg1,-1(t2)
-       stb     arg1,0(t2)
-       stb     arg1,1(t2)
-       stb     arg1,2(t2)
-       addib,COND(>) -4,arg2,3b
-       ldo     4(t2),t2
-4:     bv,n    r0(rp)
-ENDPROC_CFI(memset)
-
-       .end
index 6420112..d4b145b 100644 (file)
@@ -4,6 +4,8 @@
 
 #include <asm/bug.h>
 #include <asm/book3s/32/mmu-hash.h>
+#include <asm/mmu.h>
+#include <asm/synch.h>
 
 #ifndef __ASSEMBLY__
 
@@ -28,6 +30,15 @@ static inline void kuep_lock(void)
                return;
 
        update_user_segments(mfsr(0) | SR_NX);
+       /*
+        * This isync() shouldn't be necessary as the kernel is not excepted to
+        * run any instruction in userspace soon after the update of segments,
+        * but hash based cores (at least G3) seem to exhibit a random
+        * behaviour when the 'isync' is not there. 603 cores don't have this
+        * behaviour so don't do the 'isync' as it saves several CPU cycles.
+        */
+       if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
+               isync();        /* Context sync required after mtsr() */
 }
 
 static inline void kuep_unlock(void)
@@ -36,6 +47,15 @@ static inline void kuep_unlock(void)
                return;
 
        update_user_segments(mfsr(0) & ~SR_NX);
+       /*
+        * This isync() shouldn't be necessary as a 'rfi' will soon be executed
+        * to return to userspace, but hash based cores (at least G3) seem to
+        * exhibit a random behaviour when the 'isync' is not there. 603 cores
+        * don't have this behaviour so don't do the 'isync' as it saves several
+        * CPU cycles.
+        */
+       if (mmu_has_feature(MMU_FTR_HPTE_TABLE))
+               isync();        /* Context sync required after mtsr() */
 }
 
 #ifdef CONFIG_PPC_KUAP
index d4bdf7d..6b800d3 100644 (file)
@@ -583,6 +583,9 @@ DECLARE_INTERRUPT_HANDLER_NMI(hmi_exception_realmode);
 
 DECLARE_INTERRUPT_HANDLER_ASYNC(TAUException);
 
+/* irq.c */
+DECLARE_INTERRUPT_HANDLER_ASYNC(do_IRQ);
+
 void __noreturn unrecoverable_exception(struct pt_regs *regs);
 
 void replay_system_reset(void);
index 4982f37..2b32785 100644 (file)
@@ -52,7 +52,7 @@ extern void *mcheckirq_ctx[NR_CPUS];
 extern void *hardirq_ctx[NR_CPUS];
 extern void *softirq_ctx[NR_CPUS];
 
-extern void do_IRQ(struct pt_regs *regs);
+void __do_IRQ(struct pt_regs *regs);
 extern void __init init_IRQ(void);
 extern void __do_irq(struct pt_regs *regs);
 
index 3e5d470..14422e8 100644 (file)
@@ -70,6 +70,22 @@ struct pt_regs
                unsigned long __pad[4]; /* Maintain 16 byte interrupt stack alignment */
        };
 #endif
+#if defined(CONFIG_PPC32) && defined(CONFIG_BOOKE)
+       struct { /* Must be a multiple of 16 bytes */
+               unsigned long mas0;
+               unsigned long mas1;
+               unsigned long mas2;
+               unsigned long mas3;
+               unsigned long mas6;
+               unsigned long mas7;
+               unsigned long srr0;
+               unsigned long srr1;
+               unsigned long csrr0;
+               unsigned long csrr1;
+               unsigned long dsrr0;
+               unsigned long dsrr1;
+       };
+#endif
 };
 #endif
 
index a47eefa..5bee245 100644 (file)
@@ -309,24 +309,21 @@ int main(void)
        STACK_PT_REGS_OFFSET(STACK_REGS_IAMR, iamr);
 #endif
 
-#if defined(CONFIG_PPC32)
-#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
-       DEFINE(EXC_LVL_SIZE, STACK_EXC_LVL_FRAME_SIZE);
-       DEFINE(MAS0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0));
+#if defined(CONFIG_PPC32) && defined(CONFIG_BOOKE)
+       STACK_PT_REGS_OFFSET(MAS0, mas0);
        /* we overload MMUCR for 44x on MAS0 since they are mutually exclusive */
-       DEFINE(MMUCR, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0));
-       DEFINE(MAS1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas1));
-       DEFINE(MAS2, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas2));
-       DEFINE(MAS3, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas3));
-       DEFINE(MAS6, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas6));
-       DEFINE(MAS7, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas7));
-       DEFINE(_SRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, srr0));
-       DEFINE(_SRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, srr1));
-       DEFINE(_CSRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, csrr0));
-       DEFINE(_CSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, csrr1));
-       DEFINE(_DSRR0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr0));
-       DEFINE(_DSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr1));
-#endif
+       STACK_PT_REGS_OFFSET(MMUCR, mas0);
+       STACK_PT_REGS_OFFSET(MAS1, mas1);
+       STACK_PT_REGS_OFFSET(MAS2, mas2);
+       STACK_PT_REGS_OFFSET(MAS3, mas3);
+       STACK_PT_REGS_OFFSET(MAS6, mas6);
+       STACK_PT_REGS_OFFSET(MAS7, mas7);
+       STACK_PT_REGS_OFFSET(_SRR0, srr0);
+       STACK_PT_REGS_OFFSET(_SRR1, srr1);
+       STACK_PT_REGS_OFFSET(_CSRR0, csrr0);
+       STACK_PT_REGS_OFFSET(_CSRR1, csrr1);
+       STACK_PT_REGS_OFFSET(_DSRR0, dsrr0);
+       STACK_PT_REGS_OFFSET(_DSRR1, dsrr1);
 #endif
 
        /* About the CPU features table */
index 4aec59a..37859e6 100644 (file)
@@ -812,7 +812,6 @@ __start_interrupts:
  * syscall register convention is in Documentation/powerpc/syscall64-abi.rst
  */
 EXC_VIRT_BEGIN(system_call_vectored, 0x3000, 0x1000)
-1:
        /* SCV 0 */
        mr      r9,r13
        GET_PACA(r13)
@@ -842,10 +841,12 @@ EXC_VIRT_BEGIN(system_call_vectored, 0x3000, 0x1000)
        b       system_call_vectored_sigill
 #endif
        .endr
-2:
 EXC_VIRT_END(system_call_vectored, 0x3000, 0x1000)
 
-SOFT_MASK_TABLE(1b, 2b) // Treat scv vectors as soft-masked, see comment above.
+// Treat scv vectors as soft-masked, see comment above.
+// Use absolute values rather than labels here, so they don't get relocated,
+// because this code runs unrelocated.
+SOFT_MASK_TABLE(0xc000000000003000, 0xc000000000004000)
 
 #ifdef CONFIG_RELOCATABLE
 TRAMP_VIRT_BEGIN(system_call_vectored_tramp)
index 764edd8..68e5c0a 100644 (file)
@@ -300,7 +300,7 @@ ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_HPTE_TABLE)
        EXCEPTION_PROLOG_1
        EXCEPTION_PROLOG_2 INTERRUPT_DATA_STORAGE DataAccess handle_dar_dsisr=1
        prepare_transfer_to_handler
-       lwz     r5, _DSISR(r11)
+       lwz     r5, _DSISR(r1)
        andis.  r0, r5, DSISR_DABRMATCH@h
        bne-    1f
        bl      do_page_fault
index 87b806e..e550342 100644 (file)
@@ -168,20 +168,18 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
 /* only on e500mc */
 #define DBG_STACK_BASE         dbgirq_ctx
 
-#define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE)
-
 #ifdef CONFIG_SMP
 #define BOOKE_LOAD_EXC_LEVEL_STACK(level)              \
        mfspr   r8,SPRN_PIR;                            \
        slwi    r8,r8,2;                                \
        addis   r8,r8,level##_STACK_BASE@ha;            \
        lwz     r8,level##_STACK_BASE@l(r8);            \
-       addi    r8,r8,EXC_LVL_FRAME_OVERHEAD;
+       addi    r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
 #else
 #define BOOKE_LOAD_EXC_LEVEL_STACK(level)              \
        lis     r8,level##_STACK_BASE@ha;               \
        lwz     r8,level##_STACK_BASE@l(r8);            \
-       addi    r8,r8,EXC_LVL_FRAME_OVERHEAD;
+       addi    r8,r8,THREAD_SIZE - INT_FRAME_SIZE;
 #endif
 
 /*
@@ -208,7 +206,7 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_EMB_HV)
        mtmsr   r11;                                                    \
        mfspr   r11,SPRN_SPRG_THREAD;   /* if from user, start at top of   */\
        lwz     r11, TASK_STACK - THREAD(r11); /* this thread's kernel stack */\
-       addi    r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame    */\
+       addi    r11,r11,THREAD_SIZE - INT_FRAME_SIZE;   /* allocate stack frame    */\
        beq     1f;                                                          \
        /* COMING FROM USER MODE */                                          \
        stw     r9,_CCR(r11);           /* save CR                         */\
@@ -516,24 +514,5 @@ label:
        bl      kernel_fp_unavailable_exception;                              \
        b       interrupt_return
 
-#else /* __ASSEMBLY__ */
-struct exception_regs {
-       unsigned long mas0;
-       unsigned long mas1;
-       unsigned long mas2;
-       unsigned long mas3;
-       unsigned long mas6;
-       unsigned long mas7;
-       unsigned long srr0;
-       unsigned long srr1;
-       unsigned long csrr0;
-       unsigned long csrr1;
-       unsigned long dsrr0;
-       unsigned long dsrr1;
-};
-
-/* ensure this structure is always sized to a multiple of the stack alignment */
-#define STACK_EXC_LVL_FRAME_SIZE       ALIGN(sizeof (struct exception_regs), 16)
-
 #endif /* __ASSEMBLY__ */
 #endif /* __HEAD_BOOKE_H__ */
index 91e63ea..551b653 100644 (file)
@@ -750,7 +750,7 @@ void __do_irq(struct pt_regs *regs)
        trace_irq_exit(regs);
 }
 
-DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
+void __do_IRQ(struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
        void *cursp, *irqsp, *sirqsp;
@@ -774,6 +774,11 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
        set_irq_regs(old_regs);
 }
 
+DEFINE_INTERRUPT_HANDLER_ASYNC(do_IRQ)
+{
+       __do_IRQ(regs);
+}
+
 static void *__init alloc_vm_stack(void)
 {
        return __vmalloc_node(THREAD_SIZE, THREAD_ALIGN, THREADINFO_GFP,
index cbc28d1..7a7cd6b 100644 (file)
@@ -292,7 +292,8 @@ int kprobe_handler(struct pt_regs *regs)
        if (user_mode(regs))
                return 0;
 
-       if (!(regs->msr & MSR_IR) || !(regs->msr & MSR_DR))
+       if (!IS_ENABLED(CONFIG_BOOKE) &&
+           (!(regs->msr & MSR_IR) || !(regs->msr & MSR_DR)))
                return 0;
 
        /*
index 5ff0e55..defecb3 100644 (file)
@@ -1167,7 +1167,7 @@ static int __init topology_init(void)
                 * CPU.  For instance, the boot cpu might never be valid
                 * for hotplugging.
                 */
-               if (smp_ops->cpu_offline_self)
+               if (smp_ops && smp_ops->cpu_offline_self)
                        c->hotpluggable = 1;
 #endif
 
index e45ce42..c487ba5 100644 (file)
@@ -586,7 +586,7 @@ DEFINE_INTERRUPT_HANDLER_ASYNC(timer_interrupt)
 
 #if defined(CONFIG_PPC32) && defined(CONFIG_PPC_PMAC)
        if (atomic_read(&ppc_n_lost_interrupts) != 0)
-               do_IRQ(regs);
+               __do_IRQ(regs);
 #endif
 
        old_regs = set_irq_regs(regs);
index dfbce52..d56254f 100644 (file)
@@ -1104,7 +1104,7 @@ DEFINE_INTERRUPT_HANDLER(RunModeException)
        _exception(SIGTRAP, regs, TRAP_UNK, 0);
 }
 
-DEFINE_INTERRUPT_HANDLER(single_step_exception)
+static void __single_step_exception(struct pt_regs *regs)
 {
        clear_single_step(regs);
        clear_br_trace(regs);
@@ -1121,6 +1121,11 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)
        _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip);
 }
 
+DEFINE_INTERRUPT_HANDLER(single_step_exception)
+{
+       __single_step_exception(regs);
+}
+
 /*
  * After we have successfully emulated an instruction, we have to
  * check if the instruction was being single-stepped, and if so,
@@ -1130,7 +1135,7 @@ DEFINE_INTERRUPT_HANDLER(single_step_exception)
 static void emulate_single_step(struct pt_regs *regs)
 {
        if (single_stepping(regs))
-               single_step_exception(regs);
+               __single_step_exception(regs);
 }
 
 static inline int __parse_fpscr(unsigned long fpscr)
index 0876216..edea388 100644 (file)
 /*
  * Updates the attributes of a page in three steps:
  *
- * 1. invalidate the page table entry
- * 2. flush the TLB
- * 3. install the new entry with the updated attributes
- *
- * Invalidating the pte means there are situations where this will not work
- * when in theory it should.
- * For example:
- * - removing write from page whilst it is being executed
- * - setting a page read-only whilst it is being read by another CPU
+ * 1. take the page_table_lock
+ * 2. install the new entry with the updated attributes
+ * 3. flush the TLB
  *
+ * This sequence is safe against concurrent updates, and also allows updating the
+ * attributes of a page currently being executed or accessed.
  */
 static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
 {
@@ -36,9 +32,7 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
 
        spin_lock(&init_mm.page_table_lock);
 
-       /* invalidate the PTE so it's safe to modify */
-       pte = ptep_get_and_clear(&init_mm, addr, ptep);
-       flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+       pte = ptep_get(ptep);
 
        /* modify the PTE bits as desired, then apply */
        switch (action) {
@@ -59,11 +53,14 @@ static int change_page_attr(pte_t *ptep, unsigned long addr, void *data)
                break;
        }
 
-       set_pte_at(&init_mm, addr, ptep, pte);
+       pte_update(&init_mm, addr, ptep, ~0UL, pte_val(pte), 0);
 
        /* See ptesync comment in radix__set_pte_at() */
        if (radix_enabled())
                asm volatile("ptesync": : :"memory");
+
+       flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+
        spin_unlock(&init_mm.page_table_lock);
 
        return 0;
index 6794145..a208997 100644 (file)
@@ -98,7 +98,7 @@ config PPC_BOOK3S_64
        select PPC_HAVE_PMU_SUPPORT
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
-       select ARCH_ENABLE_PMD_SPLIT_PTLOCK
+       select ARCH_ENABLE_SPLIT_PMD_PTLOCK
        select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
        select ARCH_SUPPORTS_HUGETLBFS
        select ARCH_SUPPORTS_NUMA_BALANCING
index 6b08866..0dfaa6a 100644 (file)
@@ -539,9 +539,10 @@ static void init_cpu_char_feature_flags(struct h_cpu_char_result *result)
         * H_CPU_BEHAV_FAVOUR_SECURITY_H could be set only if
         * H_CPU_BEHAV_FAVOUR_SECURITY is.
         */
-       if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY))
+       if (!(result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY)) {
                security_ftr_clear(SEC_FTR_FAVOUR_SECURITY);
-       else if (result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY_H)
+               pseries_security_flavor = 0;
+       } else if (result->behaviour & H_CPU_BEHAV_FAVOUR_SECURITY_H)
                pseries_security_flavor = 1;
        else
                pseries_security_flavor = 2;
index dbdbbc2..8183ca3 100644 (file)
@@ -67,6 +67,7 @@ static struct irq_domain *xive_irq_domain;
 static struct xive_ipi_desc {
        unsigned int irq;
        char name[16];
+       atomic_t started;
 } *xive_ipis;
 
 /*
@@ -1120,7 +1121,7 @@ static const struct irq_domain_ops xive_ipi_irq_domain_ops = {
        .alloc  = xive_ipi_irq_domain_alloc,
 };
 
-static int __init xive_request_ipi(void)
+static int __init xive_init_ipis(void)
 {
        struct fwnode_handle *fwnode;
        struct irq_domain *ipi_domain;
@@ -1144,10 +1145,6 @@ static int __init xive_request_ipi(void)
                struct xive_ipi_desc *xid = &xive_ipis[node];
                struct xive_ipi_alloc_info info = { node };
 
-               /* Skip nodes without CPUs */
-               if (cpumask_empty(cpumask_of_node(node)))
-                       continue;
-
                /*
                 * Map one IPI interrupt per node for all cpus of that node.
                 * Since the HW interrupt number doesn't have any meaning,
@@ -1159,11 +1156,6 @@ static int __init xive_request_ipi(void)
                xid->irq = ret;
 
                snprintf(xid->name, sizeof(xid->name), "IPI-%d", node);
-
-               ret = request_irq(xid->irq, xive_muxed_ipi_action,
-                                 IRQF_PERCPU | IRQF_NO_THREAD, xid->name, NULL);
-
-               WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
        }
 
        return ret;
@@ -1178,6 +1170,22 @@ out:
        return ret;
 }
 
+static int xive_request_ipi(unsigned int cpu)
+{
+       struct xive_ipi_desc *xid = &xive_ipis[early_cpu_to_node(cpu)];
+       int ret;
+
+       if (atomic_inc_return(&xid->started) > 1)
+               return 0;
+
+       ret = request_irq(xid->irq, xive_muxed_ipi_action,
+                         IRQF_PERCPU | IRQF_NO_THREAD,
+                         xid->name, NULL);
+
+       WARN(ret < 0, "Failed to request IPI %d: %d\n", xid->irq, ret);
+       return ret;
+}
+
 static int xive_setup_cpu_ipi(unsigned int cpu)
 {
        unsigned int xive_ipi_irq = xive_ipi_cpu_to_irq(cpu);
@@ -1192,6 +1200,9 @@ static int xive_setup_cpu_ipi(unsigned int cpu)
        if (xc->hw_ipi != XIVE_BAD_IRQ)
                return 0;
 
+       /* Register the IPI */
+       xive_request_ipi(cpu);
+
        /* Grab an IPI from the backend, this will populate xc->hw_ipi */
        if (xive_ops->get_ipi(cpu, xc))
                return -EIO;
@@ -1231,6 +1242,8 @@ static void xive_cleanup_cpu_ipi(unsigned int cpu, struct xive_cpu *xc)
        if (xc->hw_ipi == XIVE_BAD_IRQ)
                return;
 
+       /* TODO: clear IPI mapping */
+
        /* Mask the IPI */
        xive_do_source_set_mask(&xc->ipi_data, true);
 
@@ -1253,7 +1266,7 @@ void __init xive_smp_probe(void)
        smp_ops->cause_ipi = xive_cause_ipi;
 
        /* Register the IPI */
-       xive_request_ipi();
+       xive_init_ipis();
 
        /* Allocate and setup IPI for the boot CPU */
        xive_setup_cpu_ipi(smp_processor_id());
index 8fcceb8..4f7b70a 100644 (file)
@@ -492,10 +492,16 @@ config CC_HAVE_STACKPROTECTOR_TLS
 
 config STACKPROTECTOR_PER_TASK
        def_bool y
+       depends on !GCC_PLUGIN_RANDSTRUCT
        depends on STACKPROTECTOR && CC_HAVE_STACKPROTECTOR_TLS
 
+config PHYS_RAM_BASE_FIXED
+       bool "Explicitly specified physical RAM address"
+       default n
+
 config PHYS_RAM_BASE
        hex "Platform Physical RAM address"
+       depends on PHYS_RAM_BASE_FIXED
        default "0x80000000"
        help
          This is the physical address of RAM in the system. It has to be
@@ -508,6 +514,7 @@ config XIP_KERNEL
        # This prevents XIP from being enabled by all{yes,mod}config, which
        # fail to build since XIP doesn't support large kernels.
        depends on !COMPILE_TEST
+       select PHYS_RAM_BASE_FIXED
        help
          Execute-In-Place allows the kernel to run from non-volatile storage
          directly addressable by the CPU, such as NOR flash. This saves RAM
index ec79944..baea7d2 100644 (file)
        model = "Microchip PolarFire-SoC Icicle Kit";
        compatible = "microchip,mpfs-icicle-kit";
 
+       aliases {
+               ethernet0 = &emac1;
+       };
+
        chosen {
                stdout-path = &serial0;
        };
index b981957..9d2fbbc 100644 (file)
                        reg = <0x0 0x20112000 0x0 0x2000>;
                        interrupt-parent = <&plic>;
                        interrupts = <70 71 72 73>;
-                       mac-address = [00 00 00 00 00 00];
+                       local-mac-address = [00 00 00 00 00 00];
                        clocks = <&clkcfg 5>, <&clkcfg 2>;
                        status = "disabled";
                        clock-names = "pclk", "hclk";
index b1c3c59..2e4ea84 100644 (file)
@@ -24,7 +24,7 @@
 
        memory@80000000 {
                device_type = "memory";
-               reg = <0x0 0x80000000 0x2 0x00000000>;
+               reg = <0x0 0x80000000 0x4 0x00000000>;
        };
 
        soc {
index cca8764..b0ca505 100644 (file)
@@ -103,6 +103,7 @@ struct kernel_mapping {
 };
 
 extern struct kernel_mapping kernel_map;
+extern phys_addr_t phys_ram_base;
 
 #ifdef CONFIG_64BIT
 #define is_kernel_mapping(x)   \
@@ -113,9 +114,9 @@ extern struct kernel_mapping kernel_map;
 #define linear_mapping_pa_to_va(x)     ((void *)((unsigned long)(x) + kernel_map.va_pa_offset))
 #define kernel_mapping_pa_to_va(y)     ({                                              \
        unsigned long _y = y;                                                           \
-       (_y >= CONFIG_PHYS_RAM_BASE) ?                                                  \
-               (void *)((unsigned long)(_y) + kernel_map.va_kernel_pa_offset + XIP_OFFSET) :   \
-               (void *)((unsigned long)(_y) + kernel_map.va_kernel_xip_pa_offset);             \
+       (IS_ENABLED(CONFIG_XIP_KERNEL) && _y < phys_ram_base) ?                                 \
+               (void *)((unsigned long)(_y) + kernel_map.va_kernel_xip_pa_offset) :            \
+               (void *)((unsigned long)(_y) + kernel_map.va_kernel_pa_offset + XIP_OFFSET);    \
        })
 #define __pa_to_va_nodebug(x)          linear_mapping_pa_to_va(x)
 
index d3081e4..3397dda 100644 (file)
@@ -11,7 +11,7 @@ endif
 CFLAGS_syscall_table.o += $(call cc-option,-Wno-override-init,)
 
 ifdef CONFIG_KEXEC
-AFLAGS_kexec_relocate.o := -mcmodel=medany -mno-relax
+AFLAGS_kexec_relocate.o := -mcmodel=medany $(call cc-option,-mno-relax)
 endif
 
 extra-y += head.o
index 1a85305..9c05111 100644 (file)
@@ -10,6 +10,7 @@
 #include <asm/ptrace.h>
 #include <asm/syscall.h>
 #include <asm/thread_info.h>
+#include <asm/switch_to.h>
 #include <linux/audit.h>
 #include <linux/ptrace.h>
 #include <linux/elf.h>
@@ -56,6 +57,9 @@ static int riscv_fpr_get(struct task_struct *target,
 {
        struct __riscv_d_ext_state *fstate = &target->thread.fstate;
 
+       if (target == current)
+               fstate_save(current, task_pt_regs(current));
+
        membuf_write(&to, fstate, offsetof(struct __riscv_d_ext_state, fcsr));
        membuf_store(&to, fstate->fcsr);
        return membuf_zero(&to, 4);     // explicitly pad
index 18bd0e4..120b2f6 100644 (file)
@@ -229,8 +229,8 @@ static void __init init_resources(void)
        }
 
        /* Clean-up any unused pre-allocated resources */
-       mem_res_sz = (num_resources - res_idx + 1) * sizeof(*mem_res);
-       memblock_free(__pa(mem_res), mem_res_sz);
+       if (res_idx >= 0)
+               memblock_free(__pa(mem_res), (res_idx + 1) * sizeof(*mem_res));
        return;
 
  error:
index ac75936..315db3d 100644 (file)
@@ -27,7 +27,7 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
                fp = frame_pointer(regs);
                sp = user_stack_pointer(regs);
                pc = instruction_pointer(regs);
-       } else if (task == current) {
+       } else if (task == NULL || task == current) {
                fp = (unsigned long)__builtin_frame_address(1);
                sp = (unsigned long)__builtin_frame_address(0);
                pc = (unsigned long)__builtin_return_address(0);
index a14bf39..7cb4f39 100644 (file)
@@ -36,6 +36,9 @@ EXPORT_SYMBOL(kernel_map);
 #define kernel_map     (*(struct kernel_mapping *)XIP_FIXUP(&kernel_map))
 #endif
 
+phys_addr_t phys_ram_base __ro_after_init;
+EXPORT_SYMBOL(phys_ram_base);
+
 #ifdef CONFIG_XIP_KERNEL
 extern char _xiprom[], _exiprom[];
 #endif
@@ -160,7 +163,7 @@ static void __init setup_bootmem(void)
        phys_addr_t vmlinux_end = __pa_symbol(&_end);
        phys_addr_t vmlinux_start = __pa_symbol(&_start);
        phys_addr_t __maybe_unused max_mapped_addr;
-       phys_addr_t dram_end;
+       phys_addr_t phys_ram_end;
 
 #ifdef CONFIG_XIP_KERNEL
        vmlinux_start = __pa_symbol(&_sdata);
@@ -181,9 +184,12 @@ static void __init setup_bootmem(void)
 #endif
        memblock_reserve(vmlinux_start, vmlinux_end - vmlinux_start);
 
-       dram_end = memblock_end_of_DRAM();
 
+       phys_ram_end = memblock_end_of_DRAM();
 #ifndef CONFIG_64BIT
+#ifndef CONFIG_XIP_KERNEL
+       phys_ram_base = memblock_start_of_DRAM();
+#endif
        /*
         * memblock allocator is not aware of the fact that last 4K bytes of
         * the addressable memory can not be mapped because of IS_ERR_VALUE
@@ -191,15 +197,15 @@ static void __init setup_bootmem(void)
         * if end of dram is equal to maximum addressable memory.  For 64-bit
         * kernel, this problem can't happen here as the end of the virtual
         * address space is occupied by the kernel mapping then this check must
-        * be done in create_kernel_page_table.
+        * be done as soon as the kernel mapping base address is determined.
         */
        max_mapped_addr = __pa(~(ulong)0);
-       if (max_mapped_addr == (dram_end - 1))
+       if (max_mapped_addr == (phys_ram_end - 1))
                memblock_set_current_limit(max_mapped_addr - 4096);
 #endif
 
-       min_low_pfn = PFN_UP(memblock_start_of_DRAM());
-       max_low_pfn = max_pfn = PFN_DOWN(dram_end);
+       min_low_pfn = PFN_UP(phys_ram_base);
+       max_low_pfn = max_pfn = PFN_DOWN(phys_ram_end);
 
        dma32_phys_limit = min(4UL * SZ_1G, (unsigned long)PFN_PHYS(max_low_pfn));
        set_max_mapnr(max_low_pfn - ARCH_PFN_OFFSET);
@@ -558,6 +564,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa)
        kernel_map.xiprom = (uintptr_t)CONFIG_XIP_PHYS_ADDR;
        kernel_map.xiprom_sz = (uintptr_t)(&_exiprom) - (uintptr_t)(&_xiprom);
 
+       phys_ram_base = CONFIG_PHYS_RAM_BASE;
        kernel_map.phys_addr = (uintptr_t)CONFIG_PHYS_RAM_BASE;
        kernel_map.size = (uintptr_t)(&_end) - (uintptr_t)(&_sdata);
 
index b0993e0..8fcb7ec 100644 (file)
@@ -560,9 +560,12 @@ static void zpci_cleanup_bus_resources(struct zpci_dev *zdev)
 
 int pcibios_add_device(struct pci_dev *pdev)
 {
+       struct zpci_dev *zdev = to_zpci(pdev);
        struct resource *res;
        int i;
 
+       /* The pdev has a reference to the zdev via its bus */
+       zpci_zdev_get(zdev);
        if (pdev->is_physfn)
                pdev->no_vf_scan = 1;
 
@@ -582,7 +585,10 @@ int pcibios_add_device(struct pci_dev *pdev)
 
 void pcibios_release_device(struct pci_dev *pdev)
 {
+       struct zpci_dev *zdev = to_zpci(pdev);
+
        zpci_unmap_resources(pdev);
+       zpci_zdev_put(zdev);
 }
 
 int pcibios_enable_device(struct pci_dev *pdev, int mask)
index b877a97..e359d26 100644 (file)
@@ -22,6 +22,11 @@ static inline void zpci_zdev_put(struct zpci_dev *zdev)
        kref_put(&zdev->kref, zpci_release_device);
 }
 
+static inline void zpci_zdev_get(struct zpci_dev *zdev)
+{
+       kref_get(&zdev->kref);
+}
+
 int zpci_alloc_domain(int domain);
 void zpci_free_domain(int domain);
 int zpci_setup_bus_resources(struct zpci_dev *zdev,
index 95a223b..8bb92e9 100644 (file)
@@ -5,9 +5,8 @@
  * Early support for invoking 32-bit EFI services from a 64-bit kernel.
  *
  * Because this thunking occurs before ExitBootServices() we have to
- * restore the firmware's 32-bit GDT before we make EFI service calls,
- * since the firmware's 32-bit IDT is still currently installed and it
- * needs to be able to service interrupts.
+ * restore the firmware's 32-bit GDT and IDT before we make EFI service
+ * calls.
  *
  * On the plus side, we don't have to worry about mangling 64-bit
  * addresses into 32-bits because we're executing with an identity
@@ -39,7 +38,7 @@ SYM_FUNC_START(__efi64_thunk)
        /*
         * Convert x86-64 ABI params to i386 ABI
         */
-       subq    $32, %rsp
+       subq    $64, %rsp
        movl    %esi, 0x0(%rsp)
        movl    %edx, 0x4(%rsp)
        movl    %ecx, 0x8(%rsp)
@@ -49,14 +48,19 @@ SYM_FUNC_START(__efi64_thunk)
        leaq    0x14(%rsp), %rbx
        sgdt    (%rbx)
 
+       addq    $16, %rbx
+       sidt    (%rbx)
+
        /*
-        * Switch to gdt with 32-bit segments. This is the firmware GDT
-        * that was installed when the kernel started executing. This
-        * pointer was saved at the EFI stub entry point in head_64.S.
+        * Switch to IDT and GDT with 32-bit segments. This is the firmware GDT
+        * and IDT that was installed when the kernel started executing. The
+        * pointers were saved at the EFI stub entry point in head_64.S.
         *
         * Pass the saved DS selector to the 32-bit code, and use far return to
         * restore the saved CS selector.
         */
+       leaq    efi32_boot_idt(%rip), %rax
+       lidt    (%rax)
        leaq    efi32_boot_gdt(%rip), %rax
        lgdt    (%rax)
 
@@ -67,7 +71,7 @@ SYM_FUNC_START(__efi64_thunk)
        pushq   %rax
        lretq
 
-1:     addq    $32, %rsp
+1:     addq    $64, %rsp
        movq    %rdi, %rax
 
        pop     %rbx
@@ -128,10 +132,13 @@ SYM_FUNC_START_LOCAL(efi_enter32)
 
        /*
         * Some firmware will return with interrupts enabled. Be sure to
-        * disable them before we switch GDTs.
+        * disable them before we switch GDTs and IDTs.
         */
        cli
 
+       lidtl   (%ebx)
+       subl    $16, %ebx
+
        lgdtl   (%ebx)
 
        movl    %cr4, %eax
@@ -166,6 +173,11 @@ SYM_DATA_START(efi32_boot_gdt)
        .quad   0
 SYM_DATA_END(efi32_boot_gdt)
 
+SYM_DATA_START(efi32_boot_idt)
+       .word   0
+       .quad   0
+SYM_DATA_END(efi32_boot_idt)
+
 SYM_DATA_START(efi32_boot_cs)
        .word   0
 SYM_DATA_END(efi32_boot_cs)
index a2347de..572c535 100644 (file)
@@ -319,6 +319,9 @@ SYM_INNER_LABEL(efi32_pe_stub_entry, SYM_L_LOCAL)
        movw    %cs, rva(efi32_boot_cs)(%ebp)
        movw    %ds, rva(efi32_boot_ds)(%ebp)
 
+       /* Store firmware IDT descriptor */
+       sidtl   rva(efi32_boot_idt)(%ebp)
+
        /* Disable paging */
        movl    %cr0, %eax
        btrl    $X86_CR0_PG_BIT, %eax
index 40669ea..ccc9ee1 100644 (file)
@@ -90,6 +90,7 @@ struct perf_ibs {
        unsigned long                   offset_mask[1];
        int                             offset_max;
        unsigned int                    fetch_count_reset_broken : 1;
+       unsigned int                    fetch_ignore_if_zero_rip : 1;
        struct cpu_perf_ibs __percpu    *pcpu;
 
        struct attribute                **format_attrs;
@@ -570,6 +571,7 @@ static struct perf_ibs perf_ibs_op = {
                .start          = perf_ibs_start,
                .stop           = perf_ibs_stop,
                .read           = perf_ibs_read,
+               .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
        },
        .msr                    = MSR_AMD64_IBSOPCTL,
        .config_mask            = IBS_OP_CONFIG_MASK,
@@ -672,6 +674,10 @@ fail:
        if (check_rip && (ibs_data.regs[2] & IBS_RIP_INVALID)) {
                regs.flags &= ~PERF_EFLAGS_EXACT;
        } else {
+               /* Workaround for erratum #1197 */
+               if (perf_ibs->fetch_ignore_if_zero_rip && !(ibs_data.regs[1]))
+                       goto out;
+
                set_linear_ip(&regs, ibs_data.regs[1]);
                regs.flags |= PERF_EFLAGS_EXACT;
        }
@@ -769,6 +775,9 @@ static __init void perf_event_ibs_init(void)
        if (boot_cpu_data.x86 >= 0x16 && boot_cpu_data.x86 <= 0x18)
                perf_ibs_fetch.fetch_count_reset_broken = 1;
 
+       if (boot_cpu_data.x86 == 0x19 && boot_cpu_data.x86_model < 0x10)
+               perf_ibs_fetch.fetch_ignore_if_zero_rip = 1;
+
        perf_ibs_pmu_init(&perf_ibs_fetch, "ibs_fetch");
 
        if (ibs_caps & IBS_CAPS_OPCNT) {
index 16a2369..37d5b38 100644 (file)
@@ -213,6 +213,7 @@ static struct pmu pmu_class = {
        .stop           = pmu_event_stop,
        .read           = pmu_event_read,
        .capabilities   = PERF_PMU_CAP_NO_EXCLUDE,
+       .module         = THIS_MODULE,
 };
 
 static int power_cpu_exit(unsigned int cpu)
index 1eb4513..3092fbf 100644 (file)
@@ -2489,13 +2489,15 @@ void perf_clear_dirty_counters(void)
                return;
 
        for_each_set_bit(i, cpuc->dirty, X86_PMC_IDX_MAX) {
-               /* Metrics and fake events don't have corresponding HW counters. */
-               if (is_metric_idx(i) || (i == INTEL_PMC_IDX_FIXED_VLBR))
-                       continue;
-               else if (i >= INTEL_PMC_IDX_FIXED)
+               if (i >= INTEL_PMC_IDX_FIXED) {
+                       /* Metrics and fake events don't have corresponding HW counters. */
+                       if ((i - INTEL_PMC_IDX_FIXED) >= hybrid(cpuc->pmu, num_counters_fixed))
+                               continue;
+
                        wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + (i - INTEL_PMC_IDX_FIXED), 0);
-               else
+               } else {
                        wrmsrl(x86_pmu_event_addr(i), 0);
+               }
        }
 
        bitmap_zero(cpuc->dirty, X86_PMC_IDX_MAX);
index fca7a6e..ac6fd2d 100644 (file)
@@ -2904,24 +2904,28 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
  */
 static int intel_pmu_handle_irq(struct pt_regs *regs)
 {
-       struct cpu_hw_events *cpuc;
+       struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+       bool late_ack = hybrid_bit(cpuc->pmu, late_ack);
+       bool mid_ack = hybrid_bit(cpuc->pmu, mid_ack);
        int loops;
        u64 status;
        int handled;
        int pmu_enabled;
 
-       cpuc = this_cpu_ptr(&cpu_hw_events);
-
        /*
         * Save the PMU state.
         * It needs to be restored when leaving the handler.
         */
        pmu_enabled = cpuc->enabled;
        /*
-        * No known reason to not always do late ACK,
-        * but just in case do it opt-in.
+        * In general, the early ACK is only applied for old platforms.
+        * For the big core starts from Haswell, the late ACK should be
+        * applied.
+        * For the small core after Tremont, we have to do the ACK right
+        * before re-enabling counters, which is in the middle of the
+        * NMI handler.
         */
-       if (!x86_pmu.late_ack)
+       if (!late_ack && !mid_ack)
                apic_write(APIC_LVTPC, APIC_DM_NMI);
        intel_bts_disable_local();
        cpuc->enabled = 0;
@@ -2958,6 +2962,8 @@ again:
                goto again;
 
 done:
+       if (mid_ack)
+               apic_write(APIC_LVTPC, APIC_DM_NMI);
        /* Only restore PMU state when it's active. See x86_pmu_disable(). */
        cpuc->enabled = pmu_enabled;
        if (pmu_enabled)
@@ -2969,7 +2975,7 @@ done:
         * have been reset. This avoids spurious NMIs on
         * Haswell CPUs.
         */
-       if (x86_pmu.late_ack)
+       if (late_ack)
                apic_write(APIC_LVTPC, APIC_DM_NMI);
        return handled;
 }
@@ -6129,7 +6135,6 @@ __init int intel_pmu_init(void)
                static_branch_enable(&perf_is_hybrid);
                x86_pmu.num_hybrid_pmus = X86_HYBRID_NUM_PMUS;
 
-               x86_pmu.late_ack = true;
                x86_pmu.pebs_aliases = NULL;
                x86_pmu.pebs_prec_dist = true;
                x86_pmu.pebs_block = true;
@@ -6167,6 +6172,7 @@ __init int intel_pmu_init(void)
                pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_CORE_IDX];
                pmu->name = "cpu_core";
                pmu->cpu_type = hybrid_big;
+               pmu->late_ack = true;
                if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) {
                        pmu->num_counters = x86_pmu.num_counters + 2;
                        pmu->num_counters_fixed = x86_pmu.num_counters_fixed + 1;
@@ -6192,6 +6198,7 @@ __init int intel_pmu_init(void)
                pmu = &x86_pmu.hybrid_pmu[X86_HYBRID_PMU_ATOM_IDX];
                pmu->name = "cpu_atom";
                pmu->cpu_type = hybrid_small;
+               pmu->mid_ack = true;
                pmu->num_counters = x86_pmu.num_counters;
                pmu->num_counters_fixed = x86_pmu.num_counters_fixed;
                pmu->max_pebs_events = x86_pmu.max_pebs_events;
index 9158476..b044577 100644 (file)
@@ -62,7 +62,7 @@ static struct pt_cap_desc {
        PT_CAP(single_range_output,     0, CPUID_ECX, BIT(2)),
        PT_CAP(output_subsys,           0, CPUID_ECX, BIT(3)),
        PT_CAP(payloads_lip,            0, CPUID_ECX, BIT(31)),
-       PT_CAP(num_address_ranges,      1, CPUID_EAX, 0x3),
+       PT_CAP(num_address_ranges,      1, CPUID_EAX, 0x7),
        PT_CAP(mtc_periods,             1, CPUID_EAX, 0xffff0000),
        PT_CAP(cycle_thresholds,        1, CPUID_EBX, 0xffff),
        PT_CAP(psb_periods,             1, CPUID_EBX, 0xffff0000),
index 609c24a..c682b09 100644 (file)
@@ -4811,7 +4811,7 @@ static void __snr_uncore_mmio_init_box(struct intel_uncore_box *box,
                return;
 
        pci_read_config_dword(pdev, SNR_IMC_MMIO_BASE_OFFSET, &pci_dword);
-       addr = (pci_dword & SNR_IMC_MMIO_BASE_MASK) << 23;
+       addr = ((resource_size_t)pci_dword & SNR_IMC_MMIO_BASE_MASK) << 23;
 
        pci_read_config_dword(pdev, mem_offset, &pci_dword);
        addr |= (pci_dword & SNR_IMC_MMIO_MEM0_MASK) << 12;
index 2bf1c7e..e3ac05c 100644 (file)
@@ -656,6 +656,10 @@ struct x86_hybrid_pmu {
        struct event_constraint         *event_constraints;
        struct event_constraint         *pebs_constraints;
        struct extra_reg                *extra_regs;
+
+       unsigned int                    late_ack        :1,
+                                       mid_ack         :1,
+                                       enabled_ack     :1;
 };
 
 static __always_inline struct x86_hybrid_pmu *hybrid_pmu(struct pmu *pmu)
@@ -686,6 +690,16 @@ extern struct static_key_false perf_is_hybrid;
        __Fp;                                           \
 }))
 
+#define hybrid_bit(_pmu, _field)                       \
+({                                                     \
+       bool __Fp = x86_pmu._field;                     \
+                                                       \
+       if (is_hybrid() && (_pmu))                      \
+               __Fp = hybrid_pmu(_pmu)->_field;        \
+                                                       \
+       __Fp;                                           \
+})
+
 enum hybrid_pmu_type {
        hybrid_big              = 0x40,
        hybrid_small            = 0x20,
@@ -755,6 +769,7 @@ struct x86_pmu {
 
        /* PMI handler bits */
        unsigned int    late_ack                :1,
+                       mid_ack                 :1,
                        enabled_ack             :1;
        /*
         * sysfs attrs
@@ -1115,9 +1130,10 @@ void x86_pmu_stop(struct perf_event *event, int flags);
 
 static inline void x86_pmu_disable_event(struct perf_event *event)
 {
+       u64 disable_mask = __this_cpu_read(cpu_hw_events.perf_ctr_virt_mask);
        struct hw_perf_event *hwc = &event->hw;
 
-       wrmsrl(hwc->config_base, hwc->config);
+       wrmsrl(hwc->config_base, hwc->config & ~disable_mask);
 
        if (is_counter_pair(hwc))
                wrmsrl(x86_pmu_config_addr(hwc->idx + 1), 0);
index 974cbfb..af6ce8d 100644 (file)
@@ -1038,6 +1038,13 @@ struct kvm_arch {
        struct list_head lpage_disallowed_mmu_pages;
        struct kvm_page_track_notifier_node mmu_sp_tracker;
        struct kvm_page_track_notifier_head track_notifier_head;
+       /*
+        * Protects marking pages unsync during page faults, as TDP MMU page
+        * faults only take mmu_lock for read.  For simplicity, the unsync
+        * pages lock is always taken when marking pages unsync regardless of
+        * whether mmu_lock is held for read or write.
+        */
+       spinlock_t mmu_unsync_pages_lock;
 
        struct list_head assigned_dev_head;
        struct iommu_domain *iommu_domain;
index e322676..b00dbc5 100644 (file)
@@ -184,6 +184,8 @@ struct __attribute__ ((__packed__)) vmcb_control_area {
 #define V_IGN_TPR_SHIFT 20
 #define V_IGN_TPR_MASK (1 << V_IGN_TPR_SHIFT)
 
+#define V_IRQ_INJECTION_BITS_MASK (V_IRQ_MASK | V_INTR_PRIO_MASK | V_IGN_TPR_MASK)
+
 #define V_INTR_MASKING_SHIFT 24
 #define V_INTR_MASKING_MASK (1 << V_INTR_MASKING_SHIFT)
 
index d5c691a..39224e0 100644 (file)
@@ -1986,7 +1986,8 @@ static struct irq_chip ioapic_chip __read_mostly = {
        .irq_set_affinity       = ioapic_set_affinity,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_get_irqchip_state  = ioapic_irq_get_chip_state,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static struct irq_chip ioapic_ir_chip __read_mostly = {
@@ -1999,7 +2000,8 @@ static struct irq_chip ioapic_ir_chip __read_mostly = {
        .irq_set_affinity       = ioapic_set_affinity,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_get_irqchip_state  = ioapic_irq_get_chip_state,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static inline void init_IO_APIC_traps(void)
index 44ebe25..dbacb9e 100644 (file)
@@ -58,11 +58,13 @@ msi_set_affinity(struct irq_data *irqd, const struct cpumask *mask, bool force)
         *   The quirk bit is not set in this case.
         * - The new vector is the same as the old vector
         * - The old vector is MANAGED_IRQ_SHUTDOWN_VECTOR (interrupt starts up)
+        * - The interrupt is not yet started up
         * - The new destination CPU is the same as the old destination CPU
         */
        if (!irqd_msi_nomask_quirk(irqd) ||
            cfg->vector == old_cfg.vector ||
            old_cfg.vector == MANAGED_IRQ_SHUTDOWN_VECTOR ||
+           !irqd_is_started(irqd) ||
            cfg->dest_apicid == old_cfg.dest_apicid) {
                irq_msi_update_msg(irqd, cfg);
                return ret;
@@ -150,7 +152,8 @@ static struct irq_chip pci_msi_controller = {
        .irq_ack                = irq_chip_ack_parent,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_set_affinity       = msi_set_affinity,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 int pci_msi_prepare(struct irq_domain *domain, struct device *dev, int nvec,
@@ -219,7 +222,8 @@ static struct irq_chip pci_msi_ir_controller = {
        .irq_mask               = pci_msi_mask_irq,
        .irq_ack                = irq_chip_ack_parent,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static struct msi_domain_info pci_msi_ir_domain_info = {
@@ -273,7 +277,8 @@ static struct irq_chip dmar_msi_controller = {
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
        .irq_compose_msi_msg    = dmar_msi_compose_msg,
        .irq_write_msi_msg      = dmar_msi_write_msg,
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
+       .flags                  = IRQCHIP_SKIP_SET_WAKE |
+                                 IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static int dmar_msi_init(struct irq_domain *domain,
index f07c10b..8caf871 100644 (file)
@@ -285,15 +285,14 @@ static u64 mbm_overflow_count(u64 prev_msr, u64 cur_msr, unsigned int width)
        return chunks >>= shift;
 }
 
-static int __mon_event_count(u32 rmid, struct rmid_read *rr)
+static u64 __mon_event_count(u32 rmid, struct rmid_read *rr)
 {
        struct mbm_state *m;
        u64 chunks, tval;
 
        tval = __rmid_read(rmid, rr->evtid);
        if (tval & (RMID_VAL_ERROR | RMID_VAL_UNAVAIL)) {
-               rr->val = tval;
-               return -EINVAL;
+               return tval;
        }
        switch (rr->evtid) {
        case QOS_L3_OCCUP_EVENT_ID:
@@ -307,10 +306,10 @@ static int __mon_event_count(u32 rmid, struct rmid_read *rr)
                break;
        default:
                /*
-                * Code would never reach here because
-                * an invalid event id would fail the __rmid_read.
+                * Code would never reach here because an invalid
+                * event id would fail the __rmid_read.
                 */
-               return -EINVAL;
+               return RMID_VAL_ERROR;
        }
 
        if (rr->first) {
@@ -361,23 +360,29 @@ void mon_event_count(void *info)
        struct rdtgroup *rdtgrp, *entry;
        struct rmid_read *rr = info;
        struct list_head *head;
+       u64 ret_val;
 
        rdtgrp = rr->rgrp;
 
-       if (__mon_event_count(rdtgrp->mon.rmid, rr))
-               return;
+       ret_val = __mon_event_count(rdtgrp->mon.rmid, rr);
 
        /*
-        * For Ctrl groups read data from child monitor groups.
+        * For Ctrl groups read data from child monitor groups and
+        * add them together. Count events which are read successfully.
+        * Discard the rmid_read's reporting errors.
         */
        head = &rdtgrp->mon.crdtgrp_list;
 
        if (rdtgrp->type == RDTCTRL_GROUP) {
                list_for_each_entry(entry, head, mon.crdtgrp_list) {
-                       if (__mon_event_count(entry->mon.rmid, rr))
-                               return;
+                       if (__mon_event_count(entry->mon.rmid, rr) == 0)
+                               ret_val = 0;
                }
        }
+
+       /* Report error if none of rmid_reads are successful */
+       if (ret_val)
+               rr->val = ret_val;
 }
 
 /*
index 08651a4..42fc41d 100644 (file)
@@ -508,7 +508,7 @@ static struct irq_chip hpet_msi_controller __ro_after_init = {
        .irq_set_affinity = msi_domain_set_affinity,
        .irq_retrigger = irq_chip_retrigger_hierarchy,
        .irq_write_msi_msg = hpet_msi_write_msg,
-       .flags = IRQCHIP_SKIP_SET_WAKE,
+       .flags = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_AFFINITY_PRE_STARTUP,
 };
 
 static int hpet_msi_init(struct irq_domain *domain,
index 739be5d..fe03bd9 100644 (file)
@@ -208,30 +208,6 @@ static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
        kvm_mmu_after_set_cpuid(vcpu);
 }
 
-static int is_efer_nx(void)
-{
-       return host_efer & EFER_NX;
-}
-
-static void cpuid_fix_nx_cap(struct kvm_vcpu *vcpu)
-{
-       int i;
-       struct kvm_cpuid_entry2 *e, *entry;
-
-       entry = NULL;
-       for (i = 0; i < vcpu->arch.cpuid_nent; ++i) {
-               e = &vcpu->arch.cpuid_entries[i];
-               if (e->function == 0x80000001) {
-                       entry = e;
-                       break;
-               }
-       }
-       if (entry && cpuid_entry_has(entry, X86_FEATURE_NX) && !is_efer_nx()) {
-               cpuid_entry_clear(entry, X86_FEATURE_NX);
-               printk(KERN_INFO "kvm: guest NX capability removed\n");
-       }
-}
-
 int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *best;
@@ -302,7 +278,6 @@ int kvm_vcpu_ioctl_set_cpuid(struct kvm_vcpu *vcpu,
        vcpu->arch.cpuid_entries = e2;
        vcpu->arch.cpuid_nent = cpuid->nent;
 
-       cpuid_fix_nx_cap(vcpu);
        kvm_update_cpuid_runtime(vcpu);
        kvm_vcpu_after_set_cpuid(vcpu);
 
@@ -401,7 +376,6 @@ static __always_inline void kvm_cpu_cap_mask(enum cpuid_leafs leaf, u32 mask)
 
 void kvm_set_cpu_caps(void)
 {
-       unsigned int f_nx = is_efer_nx() ? F(NX) : 0;
 #ifdef CONFIG_X86_64
        unsigned int f_gbpages = F(GBPAGES);
        unsigned int f_lm = F(LM);
@@ -515,7 +489,7 @@ void kvm_set_cpu_caps(void)
                F(CX8) | F(APIC) | 0 /* Reserved */ | F(SYSCALL) |
                F(MTRR) | F(PGE) | F(MCA) | F(CMOV) |
                F(PAT) | F(PSE36) | 0 /* Reserved */ |
-               f_nx | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
+               F(NX) | 0 /* Reserved */ | F(MMXEXT) | F(MMX) |
                F(FXSR) | F(FXSR_OPT) | f_gbpages | F(RDTSCP) |
                0 /* Reserved */ | f_lm | F(3DNOWEXT) | F(3DNOW)
        );
index 0b38f94..41d2a53 100644 (file)
@@ -1933,7 +1933,7 @@ ret_success:
 void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu)
 {
        struct kvm_cpuid_entry2 *entry;
-       struct kvm_vcpu_hv *hv_vcpu = to_hv_vcpu(vcpu);
+       struct kvm_vcpu_hv *hv_vcpu;
 
        entry = kvm_find_cpuid_entry(vcpu, HYPERV_CPUID_INTERFACE, 0);
        if (entry && entry->eax == HYPERV_CPUID_SIGNATURE_EAX) {
index c4f4fa2..47b7652 100644 (file)
@@ -2535,6 +2535,7 @@ static void kvm_unsync_page(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp)
 int mmu_try_to_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn, bool can_unsync)
 {
        struct kvm_mmu_page *sp;
+       bool locked = false;
 
        /*
         * Force write-protection if the page is being tracked.  Note, the page
@@ -2557,9 +2558,34 @@ int mmu_try_to_unsync_pages(struct kvm_vcpu *vcpu, gfn_t gfn, bool can_unsync)
                if (sp->unsync)
                        continue;
 
+               /*
+                * TDP MMU page faults require an additional spinlock as they
+                * run with mmu_lock held for read, not write, and the unsync
+                * logic is not thread safe.  Take the spinklock regardless of
+                * the MMU type to avoid extra conditionals/parameters, there's
+                * no meaningful penalty if mmu_lock is held for write.
+                */
+               if (!locked) {
+                       locked = true;
+                       spin_lock(&vcpu->kvm->arch.mmu_unsync_pages_lock);
+
+                       /*
+                        * Recheck after taking the spinlock, a different vCPU
+                        * may have since marked the page unsync.  A false
+                        * positive on the unprotected check above is not
+                        * possible as clearing sp->unsync _must_ hold mmu_lock
+                        * for write, i.e. unsync cannot transition from 0->1
+                        * while this CPU holds mmu_lock for read (or write).
+                        */
+                       if (READ_ONCE(sp->unsync))
+                               continue;
+               }
+
                WARN_ON(sp->role.level != PG_LEVEL_4K);
                kvm_unsync_page(vcpu, sp);
        }
+       if (locked)
+               spin_unlock(&vcpu->kvm->arch.mmu_unsync_pages_lock);
 
        /*
         * We need to ensure that the marking of unsync pages is visible
@@ -5537,6 +5563,8 @@ void kvm_mmu_init_vm(struct kvm *kvm)
 {
        struct kvm_page_track_notifier_node *node = &kvm->arch.mmu_sp_tracker;
 
+       spin_lock_init(&kvm->arch.mmu_unsync_pages_lock);
+
        if (!kvm_mmu_init_tdp_mmu(kvm))
                /*
                 * No smp_load/store wrappers needed here as we are in
index 0853370..d80cb12 100644 (file)
@@ -43,6 +43,7 @@ void kvm_mmu_uninit_tdp_mmu(struct kvm *kvm)
        if (!kvm->arch.tdp_mmu_enabled)
                return;
 
+       WARN_ON(!list_empty(&kvm->arch.tdp_mmu_pages));
        WARN_ON(!list_empty(&kvm->arch.tdp_mmu_roots));
 
        /*
@@ -81,8 +82,6 @@ static void tdp_mmu_free_sp_rcu_callback(struct rcu_head *head)
 void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
                          bool shared)
 {
-       gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
-
        kvm_lockdep_assert_mmu_lock_held(kvm, shared);
 
        if (!refcount_dec_and_test(&root->tdp_mmu_root_count))
@@ -94,7 +93,7 @@ void kvm_tdp_mmu_put_root(struct kvm *kvm, struct kvm_mmu_page *root,
        list_del_rcu(&root->link);
        spin_unlock(&kvm->arch.tdp_mmu_pages_lock);
 
-       zap_gfn_range(kvm, root, 0, max_gfn, false, false, shared);
+       zap_gfn_range(kvm, root, 0, -1ull, false, false, shared);
 
        call_rcu(&root->rcu_head, tdp_mmu_free_sp_rcu_callback);
 }
@@ -724,13 +723,29 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root,
                          gfn_t start, gfn_t end, bool can_yield, bool flush,
                          bool shared)
 {
+       gfn_t max_gfn_host = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
+       bool zap_all = (start == 0 && end >= max_gfn_host);
        struct tdp_iter iter;
 
+       /*
+        * No need to try to step down in the iterator when zapping all SPTEs,
+        * zapping the top-level non-leaf SPTEs will recurse on their children.
+        */
+       int min_level = zap_all ? root->role.level : PG_LEVEL_4K;
+
+       /*
+        * Bound the walk at host.MAXPHYADDR, guest accesses beyond that will
+        * hit a #PF(RSVD) and never get to an EPT Violation/Misconfig / #NPF,
+        * and so KVM will never install a SPTE for such addresses.
+        */
+       end = min(end, max_gfn_host);
+
        kvm_lockdep_assert_mmu_lock_held(kvm, shared);
 
        rcu_read_lock();
 
-       tdp_root_for_each_pte(iter, root, start, end) {
+       for_each_tdp_pte_min_level(iter, root->spt, root->role.level,
+                                  min_level, start, end) {
 retry:
                if (can_yield &&
                    tdp_mmu_iter_cond_resched(kvm, &iter, flush, shared)) {
@@ -744,9 +759,10 @@ retry:
                /*
                 * If this is a non-last-level SPTE that covers a larger range
                 * than should be zapped, continue, and zap the mappings at a
-                * lower level.
+                * lower level, except when zapping all SPTEs.
                 */
-               if ((iter.gfn < start ||
+               if (!zap_all &&
+                   (iter.gfn < start ||
                     iter.gfn + KVM_PAGES_PER_HPAGE(iter.level) > end) &&
                    !is_last_spte(iter.old_spte, iter.level))
                        continue;
@@ -794,12 +810,11 @@ bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, int as_id, gfn_t start,
 
 void kvm_tdp_mmu_zap_all(struct kvm *kvm)
 {
-       gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
        bool flush = false;
        int i;
 
        for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
-               flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, 0, max_gfn,
+               flush = kvm_tdp_mmu_zap_gfn_range(kvm, i, 0, -1ull,
                                                  flush, false);
 
        if (flush)
@@ -838,7 +853,6 @@ static struct kvm_mmu_page *next_invalidated_root(struct kvm *kvm,
  */
 void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm)
 {
-       gfn_t max_gfn = 1ULL << (shadow_phys_bits - PAGE_SHIFT);
        struct kvm_mmu_page *next_root;
        struct kvm_mmu_page *root;
        bool flush = false;
@@ -854,8 +868,7 @@ void kvm_tdp_mmu_zap_invalidated_roots(struct kvm *kvm)
 
                rcu_read_unlock();
 
-               flush = zap_gfn_range(kvm, root, 0, max_gfn, true, flush,
-                                     true);
+               flush = zap_gfn_range(kvm, root, 0, -1ull, true, flush, true);
 
                /*
                 * Put the reference acquired in
index 61738ff..e551547 100644 (file)
@@ -158,6 +158,9 @@ void recalc_intercepts(struct vcpu_svm *svm)
        /* If SMI is not intercepted, ignore guest SMI intercept as well  */
        if (!intercept_smi)
                vmcb_clr_intercept(c, INTERCEPT_SMI);
+
+       vmcb_set_intercept(c, INTERCEPT_VMLOAD);
+       vmcb_set_intercept(c, INTERCEPT_VMSAVE);
 }
 
 static void copy_vmcb_control_area(struct vmcb_control_area *dst,
@@ -503,7 +506,11 @@ static void nested_vmcb02_prepare_save(struct vcpu_svm *svm, struct vmcb *vmcb12
 
 static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
 {
-       const u32 mask = V_INTR_MASKING_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK;
+       const u32 int_ctl_vmcb01_bits =
+               V_INTR_MASKING_MASK | V_GIF_MASK | V_GIF_ENABLE_MASK;
+
+       const u32 int_ctl_vmcb12_bits = V_TPR_MASK | V_IRQ_INJECTION_BITS_MASK;
+
        struct kvm_vcpu *vcpu = &svm->vcpu;
 
        /*
@@ -535,8 +542,8 @@ static void nested_vmcb02_prepare_control(struct vcpu_svm *svm)
                vcpu->arch.l1_tsc_offset + svm->nested.ctl.tsc_offset;
 
        svm->vmcb->control.int_ctl             =
-               (svm->nested.ctl.int_ctl & ~mask) |
-               (svm->vmcb01.ptr->control.int_ctl & mask);
+               (svm->nested.ctl.int_ctl & int_ctl_vmcb12_bits) |
+               (svm->vmcb01.ptr->control.int_ctl & int_ctl_vmcb01_bits);
 
        svm->vmcb->control.virt_ext            = svm->nested.ctl.virt_ext;
        svm->vmcb->control.int_vector          = svm->nested.ctl.int_vector;
index e8ccab5..69639f9 100644 (file)
@@ -1589,17 +1589,18 @@ static void svm_set_vintr(struct vcpu_svm *svm)
 
 static void svm_clear_vintr(struct vcpu_svm *svm)
 {
-       const u32 mask = V_TPR_MASK | V_GIF_ENABLE_MASK | V_GIF_MASK | V_INTR_MASKING_MASK;
        svm_clr_intercept(svm, INTERCEPT_VINTR);
 
        /* Drop int_ctl fields related to VINTR injection.  */
-       svm->vmcb->control.int_ctl &= mask;
+       svm->vmcb->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
        if (is_guest_mode(&svm->vcpu)) {
-               svm->vmcb01.ptr->control.int_ctl &= mask;
+               svm->vmcb01.ptr->control.int_ctl &= ~V_IRQ_INJECTION_BITS_MASK;
 
                WARN_ON((svm->vmcb->control.int_ctl & V_TPR_MASK) !=
                        (svm->nested.ctl.int_ctl & V_TPR_MASK));
-               svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl & ~mask;
+
+               svm->vmcb->control.int_ctl |= svm->nested.ctl.int_ctl &
+                       V_IRQ_INJECTION_BITS_MASK;
        }
 
        vmcb_mark_dirty(svm->vmcb, VMCB_INTR);
index 1a52134..b3f77d1 100644 (file)
@@ -330,6 +330,31 @@ void nested_vmx_free_vcpu(struct kvm_vcpu *vcpu)
        vcpu_put(vcpu);
 }
 
+#define EPTP_PA_MASK   GENMASK_ULL(51, 12)
+
+static bool nested_ept_root_matches(hpa_t root_hpa, u64 root_eptp, u64 eptp)
+{
+       return VALID_PAGE(root_hpa) &&
+              ((root_eptp & EPTP_PA_MASK) == (eptp & EPTP_PA_MASK));
+}
+
+static void nested_ept_invalidate_addr(struct kvm_vcpu *vcpu, gpa_t eptp,
+                                      gpa_t addr)
+{
+       uint i;
+       struct kvm_mmu_root_info *cached_root;
+
+       WARN_ON_ONCE(!mmu_is_nested(vcpu));
+
+       for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) {
+               cached_root = &vcpu->arch.mmu->prev_roots[i];
+
+               if (nested_ept_root_matches(cached_root->hpa, cached_root->pgd,
+                                           eptp))
+                       vcpu->arch.mmu->invlpg(vcpu, addr, cached_root->hpa);
+       }
+}
+
 static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
                struct x86_exception *fault)
 {
@@ -342,10 +367,22 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
                vm_exit_reason = EXIT_REASON_PML_FULL;
                vmx->nested.pml_full = false;
                exit_qualification &= INTR_INFO_UNBLOCK_NMI;
-       } else if (fault->error_code & PFERR_RSVD_MASK)
-               vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
-       else
-               vm_exit_reason = EXIT_REASON_EPT_VIOLATION;
+       } else {
+               if (fault->error_code & PFERR_RSVD_MASK)
+                       vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
+               else
+                       vm_exit_reason = EXIT_REASON_EPT_VIOLATION;
+
+               /*
+                * Although the caller (kvm_inject_emulated_page_fault) would
+                * have already synced the faulting address in the shadow EPT
+                * tables for the current EPTP12, we also need to sync it for
+                * any other cached EPTP02s based on the same EP4TA, since the
+                * TLB associates mappings to the EP4TA rather than the full EPTP.
+                */
+               nested_ept_invalidate_addr(vcpu, vmcs12->ept_pointer,
+                                          fault->address);
+       }
 
        nested_vmx_vmexit(vcpu, vm_exit_reason, 0, exit_qualification);
        vmcs12->guest_physical_address = fault->address;
@@ -5325,14 +5362,6 @@ static int handle_vmptrst(struct kvm_vcpu *vcpu)
        return nested_vmx_succeed(vcpu);
 }
 
-#define EPTP_PA_MASK   GENMASK_ULL(51, 12)
-
-static bool nested_ept_root_matches(hpa_t root_hpa, u64 root_eptp, u64 eptp)
-{
-       return VALID_PAGE(root_hpa) &&
-               ((root_eptp & EPTP_PA_MASK) == (eptp & EPTP_PA_MASK));
-}
-
 /* Emulate the INVEPT instruction */
 static int handle_invept(struct kvm_vcpu *vcpu)
 {
@@ -5826,7 +5855,8 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu,
                if (is_nmi(intr_info))
                        return true;
                else if (is_page_fault(intr_info))
-                       return vcpu->arch.apf.host_apf_flags || !enable_ept;
+                       return vcpu->arch.apf.host_apf_flags ||
+                              vmx_need_pf_intercept(vcpu);
                else if (is_debug(intr_info) &&
                         vcpu->guest_debug &
                         (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))
index db88ed4..17a1cb4 100644 (file)
@@ -522,7 +522,7 @@ static inline struct vmcs *alloc_vmcs(bool shadow)
 
 static inline bool vmx_has_waitpkg(struct vcpu_vmx *vmx)
 {
-       return vmx->secondary_exec_control &
+       return secondary_exec_controls_get(vmx) &
                SECONDARY_EXEC_ENABLE_USR_WAIT_PAUSE;
 }
 
index fd1ab80..a4cf678 100644 (file)
@@ -10,6 +10,7 @@ BEGIN {
 
 /^GNU objdump/ {
        verstr = ""
+       gsub(/\(.*\)/, "");
        for (i = 3; i <= NF; i++)
                if (match($(i), "^[0-9]")) {
                        verstr = $(i);
index 04c5a44..9ba700d 100644 (file)
@@ -57,12 +57,12 @@ static const char * const sym_regex_kernel[S_NSYMTYPES] = {
        [S_REL] =
        "^(__init_(begin|end)|"
        "__x86_cpu_dev_(start|end)|"
-       "(__parainstructions|__alt_instructions)(|_end)|"
-       "(__iommu_table|__apicdrivers|__smp_locks)(|_end)|"
+       "(__parainstructions|__alt_instructions)(_end)?|"
+       "(__iommu_table|__apicdrivers|__smp_locks)(_end)?|"
        "__(start|end)_pci_.*|"
        "__(start|end)_builtin_fw|"
-       "__(start|stop)___ksymtab(|_gpl)|"
-       "__(start|stop)___kcrctab(|_gpl)|"
+       "__(start|stop)___ksymtab(_gpl)?|"
+       "__(start|stop)___kcrctab(_gpl)?|"
        "__(start|stop)___param|"
        "__(start|stop)___modver|"
        "__(start|stop)___bug_table|"
index 64053d6..2f2158e 100644 (file)
@@ -9,12 +9,6 @@ config MQ_IOSCHED_DEADLINE
        help
          MQ version of the deadline IO scheduler.
 
-config MQ_IOSCHED_DEADLINE_CGROUP
-       tristate
-       default y
-       depends on MQ_IOSCHED_DEADLINE
-       depends on BLK_CGROUP
-
 config MQ_IOSCHED_KYBER
        tristate "Kyber I/O scheduler"
        default y
index bfbe4e1..1e1afa1 100644 (file)
@@ -22,8 +22,6 @@ obj-$(CONFIG_BLK_CGROUP_IOPRIO)       += blk-ioprio.o
 obj-$(CONFIG_BLK_CGROUP_IOLATENCY)     += blk-iolatency.o
 obj-$(CONFIG_BLK_CGROUP_IOCOST)        += blk-iocost.o
 obj-$(CONFIG_MQ_IOSCHED_DEADLINE)      += mq-deadline.o
-mq-deadline-y += mq-deadline-main.o
-mq-deadline-$(CONFIG_MQ_IOSCHED_DEADLINE_CGROUP)+= mq-deadline-cgroup.o
 obj-$(CONFIG_MQ_IOSCHED_KYBER) += kyber-iosched.o
 bfq-y                          := bfq-iosched.o bfq-wf2q.o bfq-cgroup.o
 obj-$(CONFIG_IOSCHED_BFQ)      += bfq.o
index 575d7a2..31fe9be 100644 (file)
@@ -790,6 +790,7 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
                struct blkcg_gq *parent = blkg->parent;
                struct blkg_iostat_set *bisc = per_cpu_ptr(blkg->iostat_cpu, cpu);
                struct blkg_iostat cur, delta;
+               unsigned long flags;
                unsigned int seq;
 
                /* fetch the current per-cpu values */
@@ -799,21 +800,21 @@ static void blkcg_rstat_flush(struct cgroup_subsys_state *css, int cpu)
                } while (u64_stats_fetch_retry(&bisc->sync, seq));
 
                /* propagate percpu delta to global */
-               u64_stats_update_begin(&blkg->iostat.sync);
+               flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
                blkg_iostat_set(&delta, &cur);
                blkg_iostat_sub(&delta, &bisc->last);
                blkg_iostat_add(&blkg->iostat.cur, &delta);
                blkg_iostat_add(&bisc->last, &delta);
-               u64_stats_update_end(&blkg->iostat.sync);
+               u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
 
                /* propagate global delta to parent (unless that's root) */
                if (parent && parent->parent) {
-                       u64_stats_update_begin(&parent->iostat.sync);
+                       flags = u64_stats_update_begin_irqsave(&parent->iostat.sync);
                        blkg_iostat_set(&delta, &blkg->iostat.cur);
                        blkg_iostat_sub(&delta, &blkg->iostat.last);
                        blkg_iostat_add(&parent->iostat.cur, &delta);
                        blkg_iostat_add(&blkg->iostat.last, &delta);
-                       u64_stats_update_end(&parent->iostat.sync);
+                       u64_stats_update_end_irqrestore(&parent->iostat.sync, flags);
                }
        }
 
@@ -848,6 +849,7 @@ static void blkcg_fill_root_iostats(void)
                memset(&tmp, 0, sizeof(tmp));
                for_each_possible_cpu(cpu) {
                        struct disk_stats *cpu_dkstats;
+                       unsigned long flags;
 
                        cpu_dkstats = per_cpu_ptr(bdev->bd_stats, cpu);
                        tmp.ios[BLKG_IOSTAT_READ] +=
@@ -864,9 +866,9 @@ static void blkcg_fill_root_iostats(void)
                        tmp.bytes[BLKG_IOSTAT_DISCARD] +=
                                cpu_dkstats->sectors[STAT_DISCARD] << 9;
 
-                       u64_stats_update_begin(&blkg->iostat.sync);
+                       flags = u64_stats_update_begin_irqsave(&blkg->iostat.sync);
                        blkg_iostat_set(&blkg->iostat.cur, &tmp);
-                       u64_stats_update_end(&blkg->iostat.sync);
+                       u64_stats_update_end_irqrestore(&blkg->iostat.sync, flags);
                }
        }
 }
index 0447769..4f8449b 100644 (file)
@@ -122,7 +122,6 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
        rq->internal_tag = BLK_MQ_NO_TAG;
        rq->start_time_ns = ktime_get_ns();
        rq->part = NULL;
-       refcount_set(&rq->ref, 1);
        blk_crypto_rq_set_defaults(rq);
 }
 EXPORT_SYMBOL(blk_rq_init);
index 1002f6c..4201728 100644 (file)
@@ -262,6 +262,11 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error)
        spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
 }
 
+bool is_flush_rq(struct request *rq)
+{
+       return rq->end_io == flush_end_io;
+}
+
 /**
  * blk_kick_flush - consider issuing flush request
  * @q: request_queue being kicked
@@ -329,6 +334,14 @@ static void blk_kick_flush(struct request_queue *q, struct blk_flush_queue *fq,
        flush_rq->rq_flags |= RQF_FLUSH_SEQ;
        flush_rq->rq_disk = first_rq->rq_disk;
        flush_rq->end_io = flush_end_io;
+       /*
+        * Order WRITE ->end_io and WRITE rq->ref, and its pair is the one
+        * implied in refcount_inc_not_zero() called from
+        * blk_mq_find_and_get_req(), which orders WRITE/READ flush_rq->ref
+        * and READ flush_rq->end_io
+        */
+       smp_wmb();
+       refcount_set(&flush_rq->ref, 1);
 
        blk_flush_queue_rq(flush_rq, false);
 }
index 5fac375..0e56557 100644 (file)
@@ -3061,19 +3061,19 @@ static ssize_t ioc_weight_write(struct kernfs_open_file *of, char *buf,
                if (v < CGROUP_WEIGHT_MIN || v > CGROUP_WEIGHT_MAX)
                        return -EINVAL;
 
-               spin_lock(&blkcg->lock);
+               spin_lock_irq(&blkcg->lock);
                iocc->dfl_weight = v * WEIGHT_ONE;
                hlist_for_each_entry(blkg, &blkcg->blkg_list, blkcg_node) {
                        struct ioc_gq *iocg = blkg_to_iocg(blkg);
 
                        if (iocg) {
-                               spin_lock_irq(&iocg->ioc->lock);
+                               spin_lock(&iocg->ioc->lock);
                                ioc_now(iocg->ioc, &now);
                                weight_updated(iocg, &now);
-                               spin_unlock_irq(&iocg->ioc->lock);
+                               spin_unlock(&iocg->ioc->lock);
                        }
                }
-               spin_unlock(&blkcg->lock);
+               spin_unlock_irq(&blkcg->lock);
 
                return nbytes;
        }
index 81be009..d8b0d8b 100644 (file)
@@ -833,7 +833,11 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
 
        enable = iolatency_set_min_lat_nsec(blkg, lat_val);
        if (enable) {
-               WARN_ON_ONCE(!blk_get_queue(blkg->q));
+               if (!blk_get_queue(blkg->q)) {
+                       ret = -ENODEV;
+                       goto out;
+               }
+
                blkg_get(blkg);
        }
 
index 2c4ac51..9d4fdc2 100644 (file)
@@ -911,7 +911,7 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next)
 
 void blk_mq_put_rq_ref(struct request *rq)
 {
-       if (is_flush_rq(rq, rq->mq_hctx))
+       if (is_flush_rq(rq))
                rq->end_io(rq, 0);
        else if (refcount_dec_and_test(&rq->ref))
                __blk_mq_free_request(rq);
@@ -923,34 +923,14 @@ static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx,
        unsigned long *next = priv;
 
        /*
-        * Just do a quick check if it is expired before locking the request in
-        * so we're not unnecessarilly synchronizing across CPUs.
-        */
-       if (!blk_mq_req_expired(rq, next))
-               return true;
-
-       /*
-        * We have reason to believe the request may be expired. Take a
-        * reference on the request to lock this request lifetime into its
-        * currently allocated context to prevent it from being reallocated in
-        * the event the completion by-passes this timeout handler.
-        *
-        * If the reference was already released, then the driver beat the
-        * timeout handler to posting a natural completion.
-        */
-       if (!refcount_inc_not_zero(&rq->ref))
-               return true;
-
-       /*
-        * The request is now locked and cannot be reallocated underneath the
-        * timeout handler's processing. Re-verify this exact request is truly
-        * expired; if it is not expired, then the request was completed and
-        * reallocated as a new request.
+        * blk_mq_queue_tag_busy_iter() has locked the request, so it cannot
+        * be reallocated underneath the timeout handler's processing, then
+        * the expire check is reliable. If the request is not expired, then
+        * it was completed and reallocated as a new request after returning
+        * from blk_mq_check_expired().
         */
        if (blk_mq_req_expired(rq, next))
                blk_mq_rq_timed_out(rq, reserved);
-
-       blk_mq_put_rq_ref(rq);
        return true;
 }
 
@@ -2994,10 +2974,12 @@ static void queue_set_hctx_shared(struct request_queue *q, bool shared)
        int i;
 
        queue_for_each_hw_ctx(q, hctx, i) {
-               if (shared)
+               if (shared) {
                        hctx->flags |= BLK_MQ_F_TAG_QUEUE_SHARED;
-               else
+               } else {
+                       blk_mq_tag_idle(hctx);
                        hctx->flags &= ~BLK_MQ_F_TAG_QUEUE_SHARED;
+               }
        }
 }
 
index 4b885c0..cb01429 100644 (file)
@@ -44,11 +44,7 @@ static inline void __blk_get_queue(struct request_queue *q)
        kobject_get(&q->kobj);
 }
 
-static inline bool
-is_flush_rq(struct request *req, struct blk_mq_hw_ctx *hctx)
-{
-       return hctx->fq->flush_rq == req;
-}
+bool is_flush_rq(struct request *req);
 
 struct blk_flush_queue *blk_alloc_flush_queue(int node, int cmd_size,
                                              gfp_t flags);
index 81e3279..15a8be5 100644 (file)
@@ -596,13 +596,13 @@ static void kyber_insert_requests(struct blk_mq_hw_ctx *hctx,
                struct list_head *head = &kcq->rq_list[sched_domain];
 
                spin_lock(&kcq->lock);
+               trace_block_rq_insert(rq);
                if (at_head)
                        list_move(&rq->queuelist, head);
                else
                        list_move_tail(&rq->queuelist, head);
                sbitmap_set_bit(&khd->kcq_map[sched_domain],
                                rq->mq_ctx->index_hw[hctx->type]);
-               trace_block_rq_insert(rq);
                spin_unlock(&kcq->lock);
        }
 }
diff --git a/block/mq-deadline-cgroup.c b/block/mq-deadline-cgroup.c
deleted file mode 100644 (file)
index 3b4bfdd..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-
-#include <linux/blk-cgroup.h>
-#include <linux/ioprio.h>
-
-#include "mq-deadline-cgroup.h"
-
-static struct blkcg_policy dd_blkcg_policy;
-
-static struct blkcg_policy_data *dd_cpd_alloc(gfp_t gfp)
-{
-       struct dd_blkcg *pd;
-
-       pd = kzalloc(sizeof(*pd), gfp);
-       if (!pd)
-               return NULL;
-       pd->stats = alloc_percpu_gfp(typeof(*pd->stats),
-                                    GFP_KERNEL | __GFP_ZERO);
-       if (!pd->stats) {
-               kfree(pd);
-               return NULL;
-       }
-       return &pd->cpd;
-}
-
-static void dd_cpd_free(struct blkcg_policy_data *cpd)
-{
-       struct dd_blkcg *dd_blkcg = container_of(cpd, typeof(*dd_blkcg), cpd);
-
-       free_percpu(dd_blkcg->stats);
-       kfree(dd_blkcg);
-}
-
-static struct dd_blkcg *dd_blkcg_from_pd(struct blkg_policy_data *pd)
-{
-       return container_of(blkcg_to_cpd(pd->blkg->blkcg, &dd_blkcg_policy),
-                           struct dd_blkcg, cpd);
-}
-
-/*
- * Convert an association between a block cgroup and a request queue into a
- * pointer to the mq-deadline information associated with a (blkcg, queue) pair.
- */
-struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio)
-{
-       struct blkg_policy_data *pd;
-
-       pd = blkg_to_pd(bio->bi_blkg, &dd_blkcg_policy);
-       if (!pd)
-               return NULL;
-
-       return dd_blkcg_from_pd(pd);
-}
-
-static size_t dd_pd_stat(struct blkg_policy_data *pd, char *buf, size_t size)
-{
-       static const char *const prio_class_name[] = {
-               [IOPRIO_CLASS_NONE]     = "NONE",
-               [IOPRIO_CLASS_RT]       = "RT",
-               [IOPRIO_CLASS_BE]       = "BE",
-               [IOPRIO_CLASS_IDLE]     = "IDLE",
-       };
-       struct dd_blkcg *blkcg = dd_blkcg_from_pd(pd);
-       int res = 0;
-       u8 prio;
-
-       for (prio = 0; prio < ARRAY_SIZE(blkcg->stats->stats); prio++)
-               res += scnprintf(buf + res, size - res,
-                       " [%s] dispatched=%u inserted=%u merged=%u",
-                       prio_class_name[prio],
-                       ddcg_sum(blkcg, dispatched, prio) +
-                       ddcg_sum(blkcg, merged, prio) -
-                       ddcg_sum(blkcg, completed, prio),
-                       ddcg_sum(blkcg, inserted, prio) -
-                       ddcg_sum(blkcg, completed, prio),
-                       ddcg_sum(blkcg, merged, prio));
-
-       return res;
-}
-
-static struct blkg_policy_data *dd_pd_alloc(gfp_t gfp, struct request_queue *q,
-                                           struct blkcg *blkcg)
-{
-       struct dd_blkg *pd;
-
-       pd = kzalloc(sizeof(*pd), gfp);
-       if (!pd)
-               return NULL;
-       return &pd->pd;
-}
-
-static void dd_pd_free(struct blkg_policy_data *pd)
-{
-       struct dd_blkg *dd_blkg = container_of(pd, typeof(*dd_blkg), pd);
-
-       kfree(dd_blkg);
-}
-
-static struct blkcg_policy dd_blkcg_policy = {
-       .cpd_alloc_fn           = dd_cpd_alloc,
-       .cpd_free_fn            = dd_cpd_free,
-
-       .pd_alloc_fn            = dd_pd_alloc,
-       .pd_free_fn             = dd_pd_free,
-       .pd_stat_fn             = dd_pd_stat,
-};
-
-int dd_activate_policy(struct request_queue *q)
-{
-       return blkcg_activate_policy(q, &dd_blkcg_policy);
-}
-
-void dd_deactivate_policy(struct request_queue *q)
-{
-       blkcg_deactivate_policy(q, &dd_blkcg_policy);
-}
-
-int __init dd_blkcg_init(void)
-{
-       return blkcg_policy_register(&dd_blkcg_policy);
-}
-
-void __exit dd_blkcg_exit(void)
-{
-       blkcg_policy_unregister(&dd_blkcg_policy);
-}
diff --git a/block/mq-deadline-cgroup.h b/block/mq-deadline-cgroup.h
deleted file mode 100644 (file)
index 0143fd7..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#if !defined(_MQ_DEADLINE_CGROUP_H_)
-#define _MQ_DEADLINE_CGROUP_H_
-
-#include <linux/blk-cgroup.h>
-
-struct request_queue;
-
-/**
- * struct io_stats_per_prio - I/O statistics per I/O priority class.
- * @inserted: Number of inserted requests.
- * @merged: Number of merged requests.
- * @dispatched: Number of dispatched requests.
- * @completed: Number of I/O completions.
- */
-struct io_stats_per_prio {
-       local_t inserted;
-       local_t merged;
-       local_t dispatched;
-       local_t completed;
-};
-
-/* I/O statistics per I/O cgroup per I/O priority class (IOPRIO_CLASS_*). */
-struct blkcg_io_stats {
-       struct io_stats_per_prio stats[4];
-};
-
-/**
- * struct dd_blkcg - Per cgroup data.
- * @cpd: blkcg_policy_data structure.
- * @stats: I/O statistics.
- */
-struct dd_blkcg {
-       struct blkcg_policy_data cpd;   /* must be the first member */
-       struct blkcg_io_stats __percpu *stats;
-};
-
-/*
- * Count one event of type 'event_type' and with I/O priority class
- * 'prio_class'.
- */
-#define ddcg_count(ddcg, event_type, prio_class) do {                  \
-if (ddcg) {                                                            \
-       struct blkcg_io_stats *io_stats = get_cpu_ptr((ddcg)->stats);   \
-                                                                       \
-       BUILD_BUG_ON(!__same_type((ddcg), struct dd_blkcg *));          \
-       BUILD_BUG_ON(!__same_type((prio_class), u8));                   \
-       local_inc(&io_stats->stats[(prio_class)].event_type);           \
-       put_cpu_ptr(io_stats);                                          \
-}                                                                      \
-} while (0)
-
-/*
- * Returns the total number of ddcg_count(ddcg, event_type, prio_class) calls
- * across all CPUs. No locking or barriers since it is fine if the returned
- * sum is slightly outdated.
- */
-#define ddcg_sum(ddcg, event_type, prio) ({                            \
-       unsigned int cpu;                                               \
-       u32 sum = 0;                                                    \
-                                                                       \
-       BUILD_BUG_ON(!__same_type((ddcg), struct dd_blkcg *));          \
-       BUILD_BUG_ON(!__same_type((prio), u8));                         \
-       for_each_present_cpu(cpu)                                       \
-               sum += local_read(&per_cpu_ptr((ddcg)->stats, cpu)->    \
-                                 stats[(prio)].event_type);            \
-       sum;                                                            \
-})
-
-#ifdef CONFIG_BLK_CGROUP
-
-/**
- * struct dd_blkg - Per (cgroup, request queue) data.
- * @pd: blkg_policy_data structure.
- */
-struct dd_blkg {
-       struct blkg_policy_data pd;     /* must be the first member */
-};
-
-struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio);
-int dd_activate_policy(struct request_queue *q);
-void dd_deactivate_policy(struct request_queue *q);
-int __init dd_blkcg_init(void);
-void __exit dd_blkcg_exit(void);
-
-#else /* CONFIG_BLK_CGROUP */
-
-static inline struct dd_blkcg *dd_blkcg_from_bio(struct bio *bio)
-{
-       return NULL;
-}
-
-static inline int dd_activate_policy(struct request_queue *q)
-{
-       return 0;
-}
-
-static inline void dd_deactivate_policy(struct request_queue *q)
-{
-}
-
-static inline int dd_blkcg_init(void)
-{
-       return 0;
-}
-
-static inline void dd_blkcg_exit(void)
-{
-}
-
-#endif /* CONFIG_BLK_CGROUP */
-
-#endif /* _MQ_DEADLINE_CGROUP_H_ */
diff --git a/block/mq-deadline-main.c b/block/mq-deadline-main.c
deleted file mode 100644 (file)
index 6f612e6..0000000
+++ /dev/null
@@ -1,1175 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- *  MQ Deadline i/o scheduler - adaptation of the legacy deadline scheduler,
- *  for the blk-mq scheduling framework
- *
- *  Copyright (C) 2016 Jens Axboe <axboe@kernel.dk>
- */
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/blkdev.h>
-#include <linux/blk-mq.h>
-#include <linux/elevator.h>
-#include <linux/bio.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/compiler.h>
-#include <linux/rbtree.h>
-#include <linux/sbitmap.h>
-
-#include <trace/events/block.h>
-
-#include "blk.h"
-#include "blk-mq.h"
-#include "blk-mq-debugfs.h"
-#include "blk-mq-tag.h"
-#include "blk-mq-sched.h"
-#include "mq-deadline-cgroup.h"
-
-/*
- * See Documentation/block/deadline-iosched.rst
- */
-static const int read_expire = HZ / 2;  /* max time before a read is submitted. */
-static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */
-/*
- * Time after which to dispatch lower priority requests even if higher
- * priority requests are pending.
- */
-static const int aging_expire = 10 * HZ;
-static const int writes_starved = 2;    /* max times reads can starve a write */
-static const int fifo_batch = 16;       /* # of sequential requests treated as one
-                                    by the above parameters. For throughput. */
-
-enum dd_data_dir {
-       DD_READ         = READ,
-       DD_WRITE        = WRITE,
-};
-
-enum { DD_DIR_COUNT = 2 };
-
-enum dd_prio {
-       DD_RT_PRIO      = 0,
-       DD_BE_PRIO      = 1,
-       DD_IDLE_PRIO    = 2,
-       DD_PRIO_MAX     = 2,
-};
-
-enum { DD_PRIO_COUNT = 3 };
-
-/* I/O statistics for all I/O priorities (enum dd_prio). */
-struct io_stats {
-       struct io_stats_per_prio stats[DD_PRIO_COUNT];
-};
-
-/*
- * Deadline scheduler data per I/O priority (enum dd_prio). Requests are
- * present on both sort_list[] and fifo_list[].
- */
-struct dd_per_prio {
-       struct list_head dispatch;
-       struct rb_root sort_list[DD_DIR_COUNT];
-       struct list_head fifo_list[DD_DIR_COUNT];
-       /* Next request in FIFO order. Read, write or both are NULL. */
-       struct request *next_rq[DD_DIR_COUNT];
-};
-
-struct deadline_data {
-       /*
-        * run time data
-        */
-
-       /* Request queue that owns this data structure. */
-       struct request_queue *queue;
-
-       struct dd_per_prio per_prio[DD_PRIO_COUNT];
-
-       /* Data direction of latest dispatched request. */
-       enum dd_data_dir last_dir;
-       unsigned int batching;          /* number of sequential requests made */
-       unsigned int starved;           /* times reads have starved writes */
-
-       struct io_stats __percpu *stats;
-
-       /*
-        * settings that change how the i/o scheduler behaves
-        */
-       int fifo_expire[DD_DIR_COUNT];
-       int fifo_batch;
-       int writes_starved;
-       int front_merges;
-       u32 async_depth;
-       int aging_expire;
-
-       spinlock_t lock;
-       spinlock_t zone_lock;
-};
-
-/* Count one event of type 'event_type' and with I/O priority 'prio' */
-#define dd_count(dd, event_type, prio) do {                            \
-       struct io_stats *io_stats = get_cpu_ptr((dd)->stats);           \
-                                                                       \
-       BUILD_BUG_ON(!__same_type((dd), struct deadline_data *));       \
-       BUILD_BUG_ON(!__same_type((prio), enum dd_prio));               \
-       local_inc(&io_stats->stats[(prio)].event_type);                 \
-       put_cpu_ptr(io_stats);                                          \
-} while (0)
-
-/*
- * Returns the total number of dd_count(dd, event_type, prio) calls across all
- * CPUs. No locking or barriers since it is fine if the returned sum is slightly
- * outdated.
- */
-#define dd_sum(dd, event_type, prio) ({                                        \
-       unsigned int cpu;                                               \
-       u32 sum = 0;                                                    \
-                                                                       \
-       BUILD_BUG_ON(!__same_type((dd), struct deadline_data *));       \
-       BUILD_BUG_ON(!__same_type((prio), enum dd_prio));               \
-       for_each_present_cpu(cpu)                                       \
-               sum += local_read(&per_cpu_ptr((dd)->stats, cpu)->      \
-                                 stats[(prio)].event_type);            \
-       sum;                                                            \
-})
-
-/* Maps an I/O priority class to a deadline scheduler priority. */
-static const enum dd_prio ioprio_class_to_prio[] = {
-       [IOPRIO_CLASS_NONE]     = DD_BE_PRIO,
-       [IOPRIO_CLASS_RT]       = DD_RT_PRIO,
-       [IOPRIO_CLASS_BE]       = DD_BE_PRIO,
-       [IOPRIO_CLASS_IDLE]     = DD_IDLE_PRIO,
-};
-
-static inline struct rb_root *
-deadline_rb_root(struct dd_per_prio *per_prio, struct request *rq)
-{
-       return &per_prio->sort_list[rq_data_dir(rq)];
-}
-
-/*
- * Returns the I/O priority class (IOPRIO_CLASS_*) that has been assigned to a
- * request.
- */
-static u8 dd_rq_ioclass(struct request *rq)
-{
-       return IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
-}
-
-/*
- * get the request after `rq' in sector-sorted order
- */
-static inline struct request *
-deadline_latter_request(struct request *rq)
-{
-       struct rb_node *node = rb_next(&rq->rb_node);
-
-       if (node)
-               return rb_entry_rq(node);
-
-       return NULL;
-}
-
-static void
-deadline_add_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
-{
-       struct rb_root *root = deadline_rb_root(per_prio, rq);
-
-       elv_rb_add(root, rq);
-}
-
-static inline void
-deadline_del_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
-{
-       const enum dd_data_dir data_dir = rq_data_dir(rq);
-
-       if (per_prio->next_rq[data_dir] == rq)
-               per_prio->next_rq[data_dir] = deadline_latter_request(rq);
-
-       elv_rb_del(deadline_rb_root(per_prio, rq), rq);
-}
-
-/*
- * remove rq from rbtree and fifo.
- */
-static void deadline_remove_request(struct request_queue *q,
-                                   struct dd_per_prio *per_prio,
-                                   struct request *rq)
-{
-       list_del_init(&rq->queuelist);
-
-       /*
-        * We might not be on the rbtree, if we are doing an insert merge
-        */
-       if (!RB_EMPTY_NODE(&rq->rb_node))
-               deadline_del_rq_rb(per_prio, rq);
-
-       elv_rqhash_del(q, rq);
-       if (q->last_merge == rq)
-               q->last_merge = NULL;
-}
-
-static void dd_request_merged(struct request_queue *q, struct request *req,
-                             enum elv_merge type)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       const u8 ioprio_class = dd_rq_ioclass(req);
-       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];
-
-       /*
-        * if the merge was a front merge, we need to reposition request
-        */
-       if (type == ELEVATOR_FRONT_MERGE) {
-               elv_rb_del(deadline_rb_root(per_prio, req), req);
-               deadline_add_rq_rb(per_prio, req);
-       }
-}
-
-/*
- * Callback function that is invoked after @next has been merged into @req.
- */
-static void dd_merged_requests(struct request_queue *q, struct request *req,
-                              struct request *next)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       const u8 ioprio_class = dd_rq_ioclass(next);
-       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
-       struct dd_blkcg *blkcg = next->elv.priv[0];
-
-       dd_count(dd, merged, prio);
-       ddcg_count(blkcg, merged, ioprio_class);
-
-       /*
-        * if next expires before rq, assign its expire time to rq
-        * and move into next position (next will be deleted) in fifo
-        */
-       if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
-               if (time_before((unsigned long)next->fifo_time,
-                               (unsigned long)req->fifo_time)) {
-                       list_move(&req->queuelist, &next->queuelist);
-                       req->fifo_time = next->fifo_time;
-               }
-       }
-
-       /*
-        * kill knowledge of next, this one is a goner
-        */
-       deadline_remove_request(q, &dd->per_prio[prio], next);
-}
-
-/*
- * move an entry to dispatch queue
- */
-static void
-deadline_move_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
-                     struct request *rq)
-{
-       const enum dd_data_dir data_dir = rq_data_dir(rq);
-
-       per_prio->next_rq[data_dir] = deadline_latter_request(rq);
-
-       /*
-        * take it off the sort and fifo list
-        */
-       deadline_remove_request(rq->q, per_prio, rq);
-}
-
-/* Number of requests queued for a given priority level. */
-static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio)
-{
-       return dd_sum(dd, inserted, prio) - dd_sum(dd, completed, prio);
-}
-
-/*
- * deadline_check_fifo returns 0 if there are no expired requests on the fifo,
- * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
- */
-static inline int deadline_check_fifo(struct dd_per_prio *per_prio,
-                                     enum dd_data_dir data_dir)
-{
-       struct request *rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
-
-       /*
-        * rq is expired!
-        */
-       if (time_after_eq(jiffies, (unsigned long)rq->fifo_time))
-               return 1;
-
-       return 0;
-}
-
-/*
- * For the specified data direction, return the next request to
- * dispatch using arrival ordered lists.
- */
-static struct request *
-deadline_fifo_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
-                     enum dd_data_dir data_dir)
-{
-       struct request *rq;
-       unsigned long flags;
-
-       if (list_empty(&per_prio->fifo_list[data_dir]))
-               return NULL;
-
-       rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
-       if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
-               return rq;
-
-       /*
-        * Look for a write request that can be dispatched, that is one with
-        * an unlocked target zone.
-        */
-       spin_lock_irqsave(&dd->zone_lock, flags);
-       list_for_each_entry(rq, &per_prio->fifo_list[DD_WRITE], queuelist) {
-               if (blk_req_can_dispatch_to_zone(rq))
-                       goto out;
-       }
-       rq = NULL;
-out:
-       spin_unlock_irqrestore(&dd->zone_lock, flags);
-
-       return rq;
-}
-
-/*
- * For the specified data direction, return the next request to
- * dispatch using sector position sorted lists.
- */
-static struct request *
-deadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
-                     enum dd_data_dir data_dir)
-{
-       struct request *rq;
-       unsigned long flags;
-
-       rq = per_prio->next_rq[data_dir];
-       if (!rq)
-               return NULL;
-
-       if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
-               return rq;
-
-       /*
-        * Look for a write request that can be dispatched, that is one with
-        * an unlocked target zone.
-        */
-       spin_lock_irqsave(&dd->zone_lock, flags);
-       while (rq) {
-               if (blk_req_can_dispatch_to_zone(rq))
-                       break;
-               rq = deadline_latter_request(rq);
-       }
-       spin_unlock_irqrestore(&dd->zone_lock, flags);
-
-       return rq;
-}
-
-/*
- * deadline_dispatch_requests selects the best request according to
- * read/write expire, fifo_batch, etc and with a start time <= @latest.
- */
-static struct request *__dd_dispatch_request(struct deadline_data *dd,
-                                            struct dd_per_prio *per_prio,
-                                            u64 latest_start_ns)
-{
-       struct request *rq, *next_rq;
-       enum dd_data_dir data_dir;
-       struct dd_blkcg *blkcg;
-       enum dd_prio prio;
-       u8 ioprio_class;
-
-       lockdep_assert_held(&dd->lock);
-
-       if (!list_empty(&per_prio->dispatch)) {
-               rq = list_first_entry(&per_prio->dispatch, struct request,
-                                     queuelist);
-               if (rq->start_time_ns > latest_start_ns)
-                       return NULL;
-               list_del_init(&rq->queuelist);
-               goto done;
-       }
-
-       /*
-        * batches are currently reads XOR writes
-        */
-       rq = deadline_next_request(dd, per_prio, dd->last_dir);
-       if (rq && dd->batching < dd->fifo_batch)
-               /* we have a next request are still entitled to batch */
-               goto dispatch_request;
-
-       /*
-        * at this point we are not running a batch. select the appropriate
-        * data direction (read / write)
-        */
-
-       if (!list_empty(&per_prio->fifo_list[DD_READ])) {
-               BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_READ]));
-
-               if (deadline_fifo_request(dd, per_prio, DD_WRITE) &&
-                   (dd->starved++ >= dd->writes_starved))
-                       goto dispatch_writes;
-
-               data_dir = DD_READ;
-
-               goto dispatch_find_request;
-       }
-
-       /*
-        * there are either no reads or writes have been starved
-        */
-
-       if (!list_empty(&per_prio->fifo_list[DD_WRITE])) {
-dispatch_writes:
-               BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_WRITE]));
-
-               dd->starved = 0;
-
-               data_dir = DD_WRITE;
-
-               goto dispatch_find_request;
-       }
-
-       return NULL;
-
-dispatch_find_request:
-       /*
-        * we are not running a batch, find best request for selected data_dir
-        */
-       next_rq = deadline_next_request(dd, per_prio, data_dir);
-       if (deadline_check_fifo(per_prio, data_dir) || !next_rq) {
-               /*
-                * A deadline has expired, the last request was in the other
-                * direction, or we have run out of higher-sectored requests.
-                * Start again from the request with the earliest expiry time.
-                */
-               rq = deadline_fifo_request(dd, per_prio, data_dir);
-       } else {
-               /*
-                * The last req was the same dir and we have a next request in
-                * sort order. No expired requests so continue on from here.
-                */
-               rq = next_rq;
-       }
-
-       /*
-        * For a zoned block device, if we only have writes queued and none of
-        * them can be dispatched, rq will be NULL.
-        */
-       if (!rq)
-               return NULL;
-
-       dd->last_dir = data_dir;
-       dd->batching = 0;
-
-dispatch_request:
-       if (rq->start_time_ns > latest_start_ns)
-               return NULL;
-       /*
-        * rq is the selected appropriate request.
-        */
-       dd->batching++;
-       deadline_move_request(dd, per_prio, rq);
-done:
-       ioprio_class = dd_rq_ioclass(rq);
-       prio = ioprio_class_to_prio[ioprio_class];
-       dd_count(dd, dispatched, prio);
-       blkcg = rq->elv.priv[0];
-       ddcg_count(blkcg, dispatched, ioprio_class);
-       /*
-        * If the request needs its target zone locked, do it.
-        */
-       blk_req_zone_write_lock(rq);
-       rq->rq_flags |= RQF_STARTED;
-       return rq;
-}
-
-/*
- * Called from blk_mq_run_hw_queue() -> __blk_mq_sched_dispatch_requests().
- *
- * One confusing aspect here is that we get called for a specific
- * hardware queue, but we may return a request that is for a
- * different hardware queue. This is because mq-deadline has shared
- * state for all hardware queues, in terms of sorting, FIFOs, etc.
- */
-static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
-{
-       struct deadline_data *dd = hctx->queue->elevator->elevator_data;
-       const u64 now_ns = ktime_get_ns();
-       struct request *rq = NULL;
-       enum dd_prio prio;
-
-       spin_lock(&dd->lock);
-       /*
-        * Start with dispatching requests whose deadline expired more than
-        * aging_expire jiffies ago.
-        */
-       for (prio = DD_BE_PRIO; prio <= DD_PRIO_MAX; prio++) {
-               rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now_ns -
-                                          jiffies_to_nsecs(dd->aging_expire));
-               if (rq)
-                       goto unlock;
-       }
-       /*
-        * Next, dispatch requests in priority order. Ignore lower priority
-        * requests if any higher priority requests are pending.
-        */
-       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
-               rq = __dd_dispatch_request(dd, &dd->per_prio[prio], now_ns);
-               if (rq || dd_queued(dd, prio))
-                       break;
-       }
-
-unlock:
-       spin_unlock(&dd->lock);
-
-       return rq;
-}
-
-/*
- * Called by __blk_mq_alloc_request(). The shallow_depth value set by this
- * function is used by __blk_mq_get_tag().
- */
-static void dd_limit_depth(unsigned int op, struct blk_mq_alloc_data *data)
-{
-       struct deadline_data *dd = data->q->elevator->elevator_data;
-
-       /* Do not throttle synchronous reads. */
-       if (op_is_sync(op) && !op_is_write(op))
-               return;
-
-       /*
-        * Throttle asynchronous requests and writes such that these requests
-        * do not block the allocation of synchronous requests.
-        */
-       data->shallow_depth = dd->async_depth;
-}
-
-/* Called by blk_mq_update_nr_requests(). */
-static void dd_depth_updated(struct blk_mq_hw_ctx *hctx)
-{
-       struct request_queue *q = hctx->queue;
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct blk_mq_tags *tags = hctx->sched_tags;
-
-       dd->async_depth = max(1UL, 3 * q->nr_requests / 4);
-
-       sbitmap_queue_min_shallow_depth(tags->bitmap_tags, dd->async_depth);
-}
-
-/* Called by blk_mq_init_hctx() and blk_mq_init_sched(). */
-static int dd_init_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
-{
-       dd_depth_updated(hctx);
-       return 0;
-}
-
-static void dd_exit_sched(struct elevator_queue *e)
-{
-       struct deadline_data *dd = e->elevator_data;
-       enum dd_prio prio;
-
-       dd_deactivate_policy(dd->queue);
-
-       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
-               struct dd_per_prio *per_prio = &dd->per_prio[prio];
-
-               WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_READ]));
-               WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_WRITE]));
-       }
-
-       free_percpu(dd->stats);
-
-       kfree(dd);
-}
-
-/*
- * Initialize elevator private data (deadline_data) and associate with blkcg.
- */
-static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
-{
-       struct deadline_data *dd;
-       struct elevator_queue *eq;
-       enum dd_prio prio;
-       int ret = -ENOMEM;
-
-       /*
-        * Initialization would be very tricky if the queue is not frozen,
-        * hence the warning statement below.
-        */
-       WARN_ON_ONCE(!percpu_ref_is_zero(&q->q_usage_counter));
-
-       eq = elevator_alloc(q, e);
-       if (!eq)
-               return ret;
-
-       dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
-       if (!dd)
-               goto put_eq;
-
-       eq->elevator_data = dd;
-
-       dd->stats = alloc_percpu_gfp(typeof(*dd->stats),
-                                    GFP_KERNEL | __GFP_ZERO);
-       if (!dd->stats)
-               goto free_dd;
-
-       dd->queue = q;
-
-       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
-               struct dd_per_prio *per_prio = &dd->per_prio[prio];
-
-               INIT_LIST_HEAD(&per_prio->dispatch);
-               INIT_LIST_HEAD(&per_prio->fifo_list[DD_READ]);
-               INIT_LIST_HEAD(&per_prio->fifo_list[DD_WRITE]);
-               per_prio->sort_list[DD_READ] = RB_ROOT;
-               per_prio->sort_list[DD_WRITE] = RB_ROOT;
-       }
-       dd->fifo_expire[DD_READ] = read_expire;
-       dd->fifo_expire[DD_WRITE] = write_expire;
-       dd->writes_starved = writes_starved;
-       dd->front_merges = 1;
-       dd->last_dir = DD_WRITE;
-       dd->fifo_batch = fifo_batch;
-       dd->aging_expire = aging_expire;
-       spin_lock_init(&dd->lock);
-       spin_lock_init(&dd->zone_lock);
-
-       ret = dd_activate_policy(q);
-       if (ret)
-               goto free_stats;
-
-       ret = 0;
-       q->elevator = eq;
-       return 0;
-
-free_stats:
-       free_percpu(dd->stats);
-
-free_dd:
-       kfree(dd);
-
-put_eq:
-       kobject_put(&eq->kobj);
-       return ret;
-}
-
-/*
- * Try to merge @bio into an existing request. If @bio has been merged into
- * an existing request, store the pointer to that request into *@rq.
- */
-static int dd_request_merge(struct request_queue *q, struct request **rq,
-                           struct bio *bio)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       const u8 ioprio_class = IOPRIO_PRIO_CLASS(bio->bi_ioprio);
-       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];
-       sector_t sector = bio_end_sector(bio);
-       struct request *__rq;
-
-       if (!dd->front_merges)
-               return ELEVATOR_NO_MERGE;
-
-       __rq = elv_rb_find(&per_prio->sort_list[bio_data_dir(bio)], sector);
-       if (__rq) {
-               BUG_ON(sector != blk_rq_pos(__rq));
-
-               if (elv_bio_merge_ok(__rq, bio)) {
-                       *rq = __rq;
-                       return ELEVATOR_FRONT_MERGE;
-               }
-       }
-
-       return ELEVATOR_NO_MERGE;
-}
-
-/*
- * Attempt to merge a bio into an existing request. This function is called
- * before @bio is associated with a request.
- */
-static bool dd_bio_merge(struct request_queue *q, struct bio *bio,
-               unsigned int nr_segs)
-{
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct request *free = NULL;
-       bool ret;
-
-       spin_lock(&dd->lock);
-       ret = blk_mq_sched_try_merge(q, bio, nr_segs, &free);
-       spin_unlock(&dd->lock);
-
-       if (free)
-               blk_mq_free_request(free);
-
-       return ret;
-}
-
-/*
- * add rq to rbtree and fifo
- */
-static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
-                             bool at_head)
-{
-       struct request_queue *q = hctx->queue;
-       struct deadline_data *dd = q->elevator->elevator_data;
-       const enum dd_data_dir data_dir = rq_data_dir(rq);
-       u16 ioprio = req_get_ioprio(rq);
-       u8 ioprio_class = IOPRIO_PRIO_CLASS(ioprio);
-       struct dd_per_prio *per_prio;
-       enum dd_prio prio;
-       struct dd_blkcg *blkcg;
-       LIST_HEAD(free);
-
-       lockdep_assert_held(&dd->lock);
-
-       /*
-        * This may be a requeue of a write request that has locked its
-        * target zone. If it is the case, this releases the zone lock.
-        */
-       blk_req_zone_write_unlock(rq);
-
-       /*
-        * If a block cgroup has been associated with the submitter and if an
-        * I/O priority has been set in the associated block cgroup, use the
-        * lowest of the cgroup priority and the request priority for the
-        * request. If no priority has been set in the request, use the cgroup
-        * priority.
-        */
-       prio = ioprio_class_to_prio[ioprio_class];
-       dd_count(dd, inserted, prio);
-       blkcg = dd_blkcg_from_bio(rq->bio);
-       ddcg_count(blkcg, inserted, ioprio_class);
-       rq->elv.priv[0] = blkcg;
-
-       if (blk_mq_sched_try_insert_merge(q, rq, &free)) {
-               blk_mq_free_requests(&free);
-               return;
-       }
-
-       trace_block_rq_insert(rq);
-
-       per_prio = &dd->per_prio[prio];
-       if (at_head) {
-               list_add(&rq->queuelist, &per_prio->dispatch);
-       } else {
-               deadline_add_rq_rb(per_prio, rq);
-
-               if (rq_mergeable(rq)) {
-                       elv_rqhash_add(q, rq);
-                       if (!q->last_merge)
-                               q->last_merge = rq;
-               }
-
-               /*
-                * set expire time and add to fifo list
-                */
-               rq->fifo_time = jiffies + dd->fifo_expire[data_dir];
-               list_add_tail(&rq->queuelist, &per_prio->fifo_list[data_dir]);
-       }
-}
-
-/*
- * Called from blk_mq_sched_insert_request() or blk_mq_sched_insert_requests().
- */
-static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
-                              struct list_head *list, bool at_head)
-{
-       struct request_queue *q = hctx->queue;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       spin_lock(&dd->lock);
-       while (!list_empty(list)) {
-               struct request *rq;
-
-               rq = list_first_entry(list, struct request, queuelist);
-               list_del_init(&rq->queuelist);
-               dd_insert_request(hctx, rq, at_head);
-       }
-       spin_unlock(&dd->lock);
-}
-
-/* Callback from inside blk_mq_rq_ctx_init(). */
-static void dd_prepare_request(struct request *rq)
-{
-       rq->elv.priv[0] = NULL;
-}
-
-/*
- * Callback from inside blk_mq_free_request().
- *
- * For zoned block devices, write unlock the target zone of
- * completed write requests. Do this while holding the zone lock
- * spinlock so that the zone is never unlocked while deadline_fifo_request()
- * or deadline_next_request() are executing. This function is called for
- * all requests, whether or not these requests complete successfully.
- *
- * For a zoned block device, __dd_dispatch_request() may have stopped
- * dispatching requests if all the queued requests are write requests directed
- * at zones that are already locked due to on-going write requests. To ensure
- * write request dispatch progress in this case, mark the queue as needing a
- * restart to ensure that the queue is run again after completion of the
- * request and zones being unlocked.
- */
-static void dd_finish_request(struct request *rq)
-{
-       struct request_queue *q = rq->q;
-       struct deadline_data *dd = q->elevator->elevator_data;
-       struct dd_blkcg *blkcg = rq->elv.priv[0];
-       const u8 ioprio_class = dd_rq_ioclass(rq);
-       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];
-
-       dd_count(dd, completed, prio);
-       ddcg_count(blkcg, completed, ioprio_class);
-
-       if (blk_queue_is_zoned(q)) {
-               unsigned long flags;
-
-               spin_lock_irqsave(&dd->zone_lock, flags);
-               blk_req_zone_write_unlock(rq);
-               if (!list_empty(&per_prio->fifo_list[DD_WRITE]))
-                       blk_mq_sched_mark_restart_hctx(rq->mq_hctx);
-               spin_unlock_irqrestore(&dd->zone_lock, flags);
-       }
-}
-
-static bool dd_has_work_for_prio(struct dd_per_prio *per_prio)
-{
-       return !list_empty_careful(&per_prio->dispatch) ||
-               !list_empty_careful(&per_prio->fifo_list[DD_READ]) ||
-               !list_empty_careful(&per_prio->fifo_list[DD_WRITE]);
-}
-
-static bool dd_has_work(struct blk_mq_hw_ctx *hctx)
-{
-       struct deadline_data *dd = hctx->queue->elevator->elevator_data;
-       enum dd_prio prio;
-
-       for (prio = 0; prio <= DD_PRIO_MAX; prio++)
-               if (dd_has_work_for_prio(&dd->per_prio[prio]))
-                       return true;
-
-       return false;
-}
-
-/*
- * sysfs parts below
- */
-#define SHOW_INT(__FUNC, __VAR)                                                \
-static ssize_t __FUNC(struct elevator_queue *e, char *page)            \
-{                                                                      \
-       struct deadline_data *dd = e->elevator_data;                    \
-                                                                       \
-       return sysfs_emit(page, "%d\n", __VAR);                         \
-}
-#define SHOW_JIFFIES(__FUNC, __VAR) SHOW_INT(__FUNC, jiffies_to_msecs(__VAR))
-SHOW_JIFFIES(deadline_read_expire_show, dd->fifo_expire[DD_READ]);
-SHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]);
-SHOW_JIFFIES(deadline_aging_expire_show, dd->aging_expire);
-SHOW_INT(deadline_writes_starved_show, dd->writes_starved);
-SHOW_INT(deadline_front_merges_show, dd->front_merges);
-SHOW_INT(deadline_async_depth_show, dd->front_merges);
-SHOW_INT(deadline_fifo_batch_show, dd->fifo_batch);
-#undef SHOW_INT
-#undef SHOW_JIFFIES
-
-#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)                        \
-static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count)        \
-{                                                                      \
-       struct deadline_data *dd = e->elevator_data;                    \
-       int __data, __ret;                                              \
-                                                                       \
-       __ret = kstrtoint(page, 0, &__data);                            \
-       if (__ret < 0)                                                  \
-               return __ret;                                           \
-       if (__data < (MIN))                                             \
-               __data = (MIN);                                         \
-       else if (__data > (MAX))                                        \
-               __data = (MAX);                                         \
-       *(__PTR) = __CONV(__data);                                      \
-       return count;                                                   \
-}
-#define STORE_INT(__FUNC, __PTR, MIN, MAX)                             \
-       STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, )
-#define STORE_JIFFIES(__FUNC, __PTR, MIN, MAX)                         \
-       STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, msecs_to_jiffies)
-STORE_JIFFIES(deadline_read_expire_store, &dd->fifo_expire[DD_READ], 0, INT_MAX);
-STORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MAX);
-STORE_JIFFIES(deadline_aging_expire_store, &dd->aging_expire, 0, INT_MAX);
-STORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX);
-STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1);
-STORE_INT(deadline_async_depth_store, &dd->front_merges, 1, INT_MAX);
-STORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX);
-#undef STORE_FUNCTION
-#undef STORE_INT
-#undef STORE_JIFFIES
-
-#define DD_ATTR(name) \
-       __ATTR(name, 0644, deadline_##name##_show, deadline_##name##_store)
-
-static struct elv_fs_entry deadline_attrs[] = {
-       DD_ATTR(read_expire),
-       DD_ATTR(write_expire),
-       DD_ATTR(writes_starved),
-       DD_ATTR(front_merges),
-       DD_ATTR(async_depth),
-       DD_ATTR(fifo_batch),
-       DD_ATTR(aging_expire),
-       __ATTR_NULL
-};
-
-#ifdef CONFIG_BLK_DEBUG_FS
-#define DEADLINE_DEBUGFS_DDIR_ATTRS(prio, data_dir, name)              \
-static void *deadline_##name##_fifo_start(struct seq_file *m,          \
-                                         loff_t *pos)                  \
-       __acquires(&dd->lock)                                           \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-                                                                       \
-       spin_lock(&dd->lock);                                           \
-       return seq_list_start(&per_prio->fifo_list[data_dir], *pos);    \
-}                                                                      \
-                                                                       \
-static void *deadline_##name##_fifo_next(struct seq_file *m, void *v,  \
-                                        loff_t *pos)                   \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-                                                                       \
-       return seq_list_next(v, &per_prio->fifo_list[data_dir], pos);   \
-}                                                                      \
-                                                                       \
-static void deadline_##name##_fifo_stop(struct seq_file *m, void *v)   \
-       __releases(&dd->lock)                                           \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-                                                                       \
-       spin_unlock(&dd->lock);                                         \
-}                                                                      \
-                                                                       \
-static const struct seq_operations deadline_##name##_fifo_seq_ops = {  \
-       .start  = deadline_##name##_fifo_start,                         \
-       .next   = deadline_##name##_fifo_next,                          \
-       .stop   = deadline_##name##_fifo_stop,                          \
-       .show   = blk_mq_debugfs_rq_show,                               \
-};                                                                     \
-                                                                       \
-static int deadline_##name##_next_rq_show(void *data,                  \
-                                         struct seq_file *m)           \
-{                                                                      \
-       struct request_queue *q = data;                                 \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-       struct request *rq = per_prio->next_rq[data_dir];               \
-                                                                       \
-       if (rq)                                                         \
-               __blk_mq_debugfs_rq_show(m, rq);                        \
-       return 0;                                                       \
-}
-
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_READ, read0);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_WRITE, write0);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_READ, read1);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_WRITE, write1);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_READ, read2);
-DEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_WRITE, write2);
-#undef DEADLINE_DEBUGFS_DDIR_ATTRS
-
-static int deadline_batching_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u\n", dd->batching);
-       return 0;
-}
-
-static int deadline_starved_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u\n", dd->starved);
-       return 0;
-}
-
-static int dd_async_depth_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u\n", dd->async_depth);
-       return 0;
-}
-
-static int dd_queued_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u %u %u\n", dd_queued(dd, DD_RT_PRIO),
-                  dd_queued(dd, DD_BE_PRIO),
-                  dd_queued(dd, DD_IDLE_PRIO));
-       return 0;
-}
-
-/* Number of requests owned by the block driver for a given priority. */
-static u32 dd_owned_by_driver(struct deadline_data *dd, enum dd_prio prio)
-{
-       return dd_sum(dd, dispatched, prio) + dd_sum(dd, merged, prio)
-               - dd_sum(dd, completed, prio);
-}
-
-static int dd_owned_by_driver_show(void *data, struct seq_file *m)
-{
-       struct request_queue *q = data;
-       struct deadline_data *dd = q->elevator->elevator_data;
-
-       seq_printf(m, "%u %u %u\n", dd_owned_by_driver(dd, DD_RT_PRIO),
-                  dd_owned_by_driver(dd, DD_BE_PRIO),
-                  dd_owned_by_driver(dd, DD_IDLE_PRIO));
-       return 0;
-}
-
-#define DEADLINE_DISPATCH_ATTR(prio)                                   \
-static void *deadline_dispatch##prio##_start(struct seq_file *m,       \
-                                            loff_t *pos)               \
-       __acquires(&dd->lock)                                           \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-                                                                       \
-       spin_lock(&dd->lock);                                           \
-       return seq_list_start(&per_prio->dispatch, *pos);               \
-}                                                                      \
-                                                                       \
-static void *deadline_dispatch##prio##_next(struct seq_file *m,                \
-                                           void *v, loff_t *pos)       \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
-                                                                       \
-       return seq_list_next(v, &per_prio->dispatch, pos);              \
-}                                                                      \
-                                                                       \
-static void deadline_dispatch##prio##_stop(struct seq_file *m, void *v)        \
-       __releases(&dd->lock)                                           \
-{                                                                      \
-       struct request_queue *q = m->private;                           \
-       struct deadline_data *dd = q->elevator->elevator_data;          \
-                                                                       \
-       spin_unlock(&dd->lock);                                         \
-}                                                                      \
-                                                                       \
-static const struct seq_operations deadline_dispatch##prio##_seq_ops = { \
-       .start  = deadline_dispatch##prio##_start,                      \
-       .next   = deadline_dispatch##prio##_next,                       \
-       .stop   = deadline_dispatch##prio##_stop,                       \
-       .show   = blk_mq_debugfs_rq_show,                               \
-}
-
-DEADLINE_DISPATCH_ATTR(0);
-DEADLINE_DISPATCH_ATTR(1);
-DEADLINE_DISPATCH_ATTR(2);
-#undef DEADLINE_DISPATCH_ATTR
-
-#define DEADLINE_QUEUE_DDIR_ATTRS(name)                                        \
-       {#name "_fifo_list", 0400,                                      \
-                       .seq_ops = &deadline_##name##_fifo_seq_ops}
-#define DEADLINE_NEXT_RQ_ATTR(name)                                    \
-       {#name "_next_rq", 0400, deadline_##name##_next_rq_show}
-static const struct blk_mq_debugfs_attr deadline_queue_debugfs_attrs[] = {
-       DEADLINE_QUEUE_DDIR_ATTRS(read0),
-       DEADLINE_QUEUE_DDIR_ATTRS(write0),
-       DEADLINE_QUEUE_DDIR_ATTRS(read1),
-       DEADLINE_QUEUE_DDIR_ATTRS(write1),
-       DEADLINE_QUEUE_DDIR_ATTRS(read2),
-       DEADLINE_QUEUE_DDIR_ATTRS(write2),
-       DEADLINE_NEXT_RQ_ATTR(read0),
-       DEADLINE_NEXT_RQ_ATTR(write0),
-       DEADLINE_NEXT_RQ_ATTR(read1),
-       DEADLINE_NEXT_RQ_ATTR(write1),
-       DEADLINE_NEXT_RQ_ATTR(read2),
-       DEADLINE_NEXT_RQ_ATTR(write2),
-       {"batching", 0400, deadline_batching_show},
-       {"starved", 0400, deadline_starved_show},
-       {"async_depth", 0400, dd_async_depth_show},
-       {"dispatch0", 0400, .seq_ops = &deadline_dispatch0_seq_ops},
-       {"dispatch1", 0400, .seq_ops = &deadline_dispatch1_seq_ops},
-       {"dispatch2", 0400, .seq_ops = &deadline_dispatch2_seq_ops},
-       {"owned_by_driver", 0400, dd_owned_by_driver_show},
-       {"queued", 0400, dd_queued_show},
-       {},
-};
-#undef DEADLINE_QUEUE_DDIR_ATTRS
-#endif
-
-static struct elevator_type mq_deadline = {
-       .ops = {
-               .depth_updated          = dd_depth_updated,
-               .limit_depth            = dd_limit_depth,
-               .insert_requests        = dd_insert_requests,
-               .dispatch_request       = dd_dispatch_request,
-               .prepare_request        = dd_prepare_request,
-               .finish_request         = dd_finish_request,
-               .next_request           = elv_rb_latter_request,
-               .former_request         = elv_rb_former_request,
-               .bio_merge              = dd_bio_merge,
-               .request_merge          = dd_request_merge,
-               .requests_merged        = dd_merged_requests,
-               .request_merged         = dd_request_merged,
-               .has_work               = dd_has_work,
-               .init_sched             = dd_init_sched,
-               .exit_sched             = dd_exit_sched,
-               .init_hctx              = dd_init_hctx,
-       },
-
-#ifdef CONFIG_BLK_DEBUG_FS
-       .queue_debugfs_attrs = deadline_queue_debugfs_attrs,
-#endif
-       .elevator_attrs = deadline_attrs,
-       .elevator_name = "mq-deadline",
-       .elevator_alias = "deadline",
-       .elevator_features = ELEVATOR_F_ZBD_SEQ_WRITE,
-       .elevator_owner = THIS_MODULE,
-};
-MODULE_ALIAS("mq-deadline-iosched");
-
-static int __init deadline_init(void)
-{
-       int ret;
-
-       ret = elv_register(&mq_deadline);
-       if (ret)
-               goto out;
-       ret = dd_blkcg_init();
-       if (ret)
-               goto unreg;
-
-out:
-       return ret;
-
-unreg:
-       elv_unregister(&mq_deadline);
-       goto out;
-}
-
-static void __exit deadline_exit(void)
-{
-       dd_blkcg_exit();
-       elv_unregister(&mq_deadline);
-}
-
-module_init(deadline_init);
-module_exit(deadline_exit);
-
-MODULE_AUTHOR("Jens Axboe, Damien Le Moal and Bart Van Assche");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("MQ deadline IO scheduler");
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
new file mode 100644 (file)
index 0000000..3692067
--- /dev/null
@@ -0,0 +1,1104 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  MQ Deadline i/o scheduler - adaptation of the legacy deadline scheduler,
+ *  for the blk-mq scheduling framework
+ *
+ *  Copyright (C) 2016 Jens Axboe <axboe@kernel.dk>
+ */
+#include <linux/kernel.h>
+#include <linux/fs.h>
+#include <linux/blkdev.h>
+#include <linux/blk-mq.h>
+#include <linux/elevator.h>
+#include <linux/bio.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/compiler.h>
+#include <linux/rbtree.h>
+#include <linux/sbitmap.h>
+
+#include <trace/events/block.h>
+
+#include "blk.h"
+#include "blk-mq.h"
+#include "blk-mq-debugfs.h"
+#include "blk-mq-tag.h"
+#include "blk-mq-sched.h"
+
+/*
+ * See Documentation/block/deadline-iosched.rst
+ */
+static const int read_expire = HZ / 2;  /* max time before a read is submitted. */
+static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */
+static const int writes_starved = 2;    /* max times reads can starve a write */
+static const int fifo_batch = 16;       /* # of sequential requests treated as one
+                                    by the above parameters. For throughput. */
+
+enum dd_data_dir {
+       DD_READ         = READ,
+       DD_WRITE        = WRITE,
+};
+
+enum { DD_DIR_COUNT = 2 };
+
+enum dd_prio {
+       DD_RT_PRIO      = 0,
+       DD_BE_PRIO      = 1,
+       DD_IDLE_PRIO    = 2,
+       DD_PRIO_MAX     = 2,
+};
+
+enum { DD_PRIO_COUNT = 3 };
+
+/* I/O statistics per I/O priority. */
+struct io_stats_per_prio {
+       local_t inserted;
+       local_t merged;
+       local_t dispatched;
+       local_t completed;
+};
+
+/* I/O statistics for all I/O priorities (enum dd_prio). */
+struct io_stats {
+       struct io_stats_per_prio stats[DD_PRIO_COUNT];
+};
+
+/*
+ * Deadline scheduler data per I/O priority (enum dd_prio). Requests are
+ * present on both sort_list[] and fifo_list[].
+ */
+struct dd_per_prio {
+       struct list_head dispatch;
+       struct rb_root sort_list[DD_DIR_COUNT];
+       struct list_head fifo_list[DD_DIR_COUNT];
+       /* Next request in FIFO order. Read, write or both are NULL. */
+       struct request *next_rq[DD_DIR_COUNT];
+};
+
+struct deadline_data {
+       /*
+        * run time data
+        */
+
+       struct dd_per_prio per_prio[DD_PRIO_COUNT];
+
+       /* Data direction of latest dispatched request. */
+       enum dd_data_dir last_dir;
+       unsigned int batching;          /* number of sequential requests made */
+       unsigned int starved;           /* times reads have starved writes */
+
+       struct io_stats __percpu *stats;
+
+       /*
+        * settings that change how the i/o scheduler behaves
+        */
+       int fifo_expire[DD_DIR_COUNT];
+       int fifo_batch;
+       int writes_starved;
+       int front_merges;
+       u32 async_depth;
+
+       spinlock_t lock;
+       spinlock_t zone_lock;
+};
+
+/* Count one event of type 'event_type' and with I/O priority 'prio' */
+#define dd_count(dd, event_type, prio) do {                            \
+       struct io_stats *io_stats = get_cpu_ptr((dd)->stats);           \
+                                                                       \
+       BUILD_BUG_ON(!__same_type((dd), struct deadline_data *));       \
+       BUILD_BUG_ON(!__same_type((prio), enum dd_prio));               \
+       local_inc(&io_stats->stats[(prio)].event_type);                 \
+       put_cpu_ptr(io_stats);                                          \
+} while (0)
+
+/*
+ * Returns the total number of dd_count(dd, event_type, prio) calls across all
+ * CPUs. No locking or barriers since it is fine if the returned sum is slightly
+ * outdated.
+ */
+#define dd_sum(dd, event_type, prio) ({                                        \
+       unsigned int cpu;                                               \
+       u32 sum = 0;                                                    \
+                                                                       \
+       BUILD_BUG_ON(!__same_type((dd), struct deadline_data *));       \
+       BUILD_BUG_ON(!__same_type((prio), enum dd_prio));               \
+       for_each_present_cpu(cpu)                                       \
+               sum += local_read(&per_cpu_ptr((dd)->stats, cpu)->      \
+                                 stats[(prio)].event_type);            \
+       sum;                                                            \
+})
+
+/* Maps an I/O priority class to a deadline scheduler priority. */
+static const enum dd_prio ioprio_class_to_prio[] = {
+       [IOPRIO_CLASS_NONE]     = DD_BE_PRIO,
+       [IOPRIO_CLASS_RT]       = DD_RT_PRIO,
+       [IOPRIO_CLASS_BE]       = DD_BE_PRIO,
+       [IOPRIO_CLASS_IDLE]     = DD_IDLE_PRIO,
+};
+
+static inline struct rb_root *
+deadline_rb_root(struct dd_per_prio *per_prio, struct request *rq)
+{
+       return &per_prio->sort_list[rq_data_dir(rq)];
+}
+
+/*
+ * Returns the I/O priority class (IOPRIO_CLASS_*) that has been assigned to a
+ * request.
+ */
+static u8 dd_rq_ioclass(struct request *rq)
+{
+       return IOPRIO_PRIO_CLASS(req_get_ioprio(rq));
+}
+
+/*
+ * get the request after `rq' in sector-sorted order
+ */
+static inline struct request *
+deadline_latter_request(struct request *rq)
+{
+       struct rb_node *node = rb_next(&rq->rb_node);
+
+       if (node)
+               return rb_entry_rq(node);
+
+       return NULL;
+}
+
+static void
+deadline_add_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
+{
+       struct rb_root *root = deadline_rb_root(per_prio, rq);
+
+       elv_rb_add(root, rq);
+}
+
+static inline void
+deadline_del_rq_rb(struct dd_per_prio *per_prio, struct request *rq)
+{
+       const enum dd_data_dir data_dir = rq_data_dir(rq);
+
+       if (per_prio->next_rq[data_dir] == rq)
+               per_prio->next_rq[data_dir] = deadline_latter_request(rq);
+
+       elv_rb_del(deadline_rb_root(per_prio, rq), rq);
+}
+
+/*
+ * remove rq from rbtree and fifo.
+ */
+static void deadline_remove_request(struct request_queue *q,
+                                   struct dd_per_prio *per_prio,
+                                   struct request *rq)
+{
+       list_del_init(&rq->queuelist);
+
+       /*
+        * We might not be on the rbtree, if we are doing an insert merge
+        */
+       if (!RB_EMPTY_NODE(&rq->rb_node))
+               deadline_del_rq_rb(per_prio, rq);
+
+       elv_rqhash_del(q, rq);
+       if (q->last_merge == rq)
+               q->last_merge = NULL;
+}
+
+static void dd_request_merged(struct request_queue *q, struct request *req,
+                             enum elv_merge type)
+{
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const u8 ioprio_class = dd_rq_ioclass(req);
+       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];
+
+       /*
+        * if the merge was a front merge, we need to reposition request
+        */
+       if (type == ELEVATOR_FRONT_MERGE) {
+               elv_rb_del(deadline_rb_root(per_prio, req), req);
+               deadline_add_rq_rb(per_prio, req);
+       }
+}
+
+/*
+ * Callback function that is invoked after @next has been merged into @req.
+ */
+static void dd_merged_requests(struct request_queue *q, struct request *req,
+                              struct request *next)
+{
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const u8 ioprio_class = dd_rq_ioclass(next);
+       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
+
+       dd_count(dd, merged, prio);
+
+       /*
+        * if next expires before rq, assign its expire time to rq
+        * and move into next position (next will be deleted) in fifo
+        */
+       if (!list_empty(&req->queuelist) && !list_empty(&next->queuelist)) {
+               if (time_before((unsigned long)next->fifo_time,
+                               (unsigned long)req->fifo_time)) {
+                       list_move(&req->queuelist, &next->queuelist);
+                       req->fifo_time = next->fifo_time;
+               }
+       }
+
+       /*
+        * kill knowledge of next, this one is a goner
+        */
+       deadline_remove_request(q, &dd->per_prio[prio], next);
+}
+
+/*
+ * move an entry to dispatch queue
+ */
+static void
+deadline_move_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
+                     struct request *rq)
+{
+       const enum dd_data_dir data_dir = rq_data_dir(rq);
+
+       per_prio->next_rq[data_dir] = deadline_latter_request(rq);
+
+       /*
+        * take it off the sort and fifo list
+        */
+       deadline_remove_request(rq->q, per_prio, rq);
+}
+
+/* Number of requests queued for a given priority level. */
+static u32 dd_queued(struct deadline_data *dd, enum dd_prio prio)
+{
+       return dd_sum(dd, inserted, prio) - dd_sum(dd, completed, prio);
+}
+
+/*
+ * deadline_check_fifo returns 0 if there are no expired requests on the fifo,
+ * 1 otherwise. Requires !list_empty(&dd->fifo_list[data_dir])
+ */
+static inline int deadline_check_fifo(struct dd_per_prio *per_prio,
+                                     enum dd_data_dir data_dir)
+{
+       struct request *rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
+
+       /*
+        * rq is expired!
+        */
+       if (time_after_eq(jiffies, (unsigned long)rq->fifo_time))
+               return 1;
+
+       return 0;
+}
+
+/*
+ * For the specified data direction, return the next request to
+ * dispatch using arrival ordered lists.
+ */
+static struct request *
+deadline_fifo_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
+                     enum dd_data_dir data_dir)
+{
+       struct request *rq;
+       unsigned long flags;
+
+       if (list_empty(&per_prio->fifo_list[data_dir]))
+               return NULL;
+
+       rq = rq_entry_fifo(per_prio->fifo_list[data_dir].next);
+       if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
+               return rq;
+
+       /*
+        * Look for a write request that can be dispatched, that is one with
+        * an unlocked target zone.
+        */
+       spin_lock_irqsave(&dd->zone_lock, flags);
+       list_for_each_entry(rq, &per_prio->fifo_list[DD_WRITE], queuelist) {
+               if (blk_req_can_dispatch_to_zone(rq))
+                       goto out;
+       }
+       rq = NULL;
+out:
+       spin_unlock_irqrestore(&dd->zone_lock, flags);
+
+       return rq;
+}
+
+/*
+ * For the specified data direction, return the next request to
+ * dispatch using sector position sorted lists.
+ */
+static struct request *
+deadline_next_request(struct deadline_data *dd, struct dd_per_prio *per_prio,
+                     enum dd_data_dir data_dir)
+{
+       struct request *rq;
+       unsigned long flags;
+
+       rq = per_prio->next_rq[data_dir];
+       if (!rq)
+               return NULL;
+
+       if (data_dir == DD_READ || !blk_queue_is_zoned(rq->q))
+               return rq;
+
+       /*
+        * Look for a write request that can be dispatched, that is one with
+        * an unlocked target zone.
+        */
+       spin_lock_irqsave(&dd->zone_lock, flags);
+       while (rq) {
+               if (blk_req_can_dispatch_to_zone(rq))
+                       break;
+               rq = deadline_latter_request(rq);
+       }
+       spin_unlock_irqrestore(&dd->zone_lock, flags);
+
+       return rq;
+}
+
+/*
+ * deadline_dispatch_requests selects the best request according to
+ * read/write expire, fifo_batch, etc
+ */
+static struct request *__dd_dispatch_request(struct deadline_data *dd,
+                                            struct dd_per_prio *per_prio)
+{
+       struct request *rq, *next_rq;
+       enum dd_data_dir data_dir;
+       enum dd_prio prio;
+       u8 ioprio_class;
+
+       lockdep_assert_held(&dd->lock);
+
+       if (!list_empty(&per_prio->dispatch)) {
+               rq = list_first_entry(&per_prio->dispatch, struct request,
+                                     queuelist);
+               list_del_init(&rq->queuelist);
+               goto done;
+       }
+
+       /*
+        * batches are currently reads XOR writes
+        */
+       rq = deadline_next_request(dd, per_prio, dd->last_dir);
+       if (rq && dd->batching < dd->fifo_batch)
+               /* we have a next request are still entitled to batch */
+               goto dispatch_request;
+
+       /*
+        * at this point we are not running a batch. select the appropriate
+        * data direction (read / write)
+        */
+
+       if (!list_empty(&per_prio->fifo_list[DD_READ])) {
+               BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_READ]));
+
+               if (deadline_fifo_request(dd, per_prio, DD_WRITE) &&
+                   (dd->starved++ >= dd->writes_starved))
+                       goto dispatch_writes;
+
+               data_dir = DD_READ;
+
+               goto dispatch_find_request;
+       }
+
+       /*
+        * there are either no reads or writes have been starved
+        */
+
+       if (!list_empty(&per_prio->fifo_list[DD_WRITE])) {
+dispatch_writes:
+               BUG_ON(RB_EMPTY_ROOT(&per_prio->sort_list[DD_WRITE]));
+
+               dd->starved = 0;
+
+               data_dir = DD_WRITE;
+
+               goto dispatch_find_request;
+       }
+
+       return NULL;
+
+dispatch_find_request:
+       /*
+        * we are not running a batch, find best request for selected data_dir
+        */
+       next_rq = deadline_next_request(dd, per_prio, data_dir);
+       if (deadline_check_fifo(per_prio, data_dir) || !next_rq) {
+               /*
+                * A deadline has expired, the last request was in the other
+                * direction, or we have run out of higher-sectored requests.
+                * Start again from the request with the earliest expiry time.
+                */
+               rq = deadline_fifo_request(dd, per_prio, data_dir);
+       } else {
+               /*
+                * The last req was the same dir and we have a next request in
+                * sort order. No expired requests so continue on from here.
+                */
+               rq = next_rq;
+       }
+
+       /*
+        * For a zoned block device, if we only have writes queued and none of
+        * them can be dispatched, rq will be NULL.
+        */
+       if (!rq)
+               return NULL;
+
+       dd->last_dir = data_dir;
+       dd->batching = 0;
+
+dispatch_request:
+       /*
+        * rq is the selected appropriate request.
+        */
+       dd->batching++;
+       deadline_move_request(dd, per_prio, rq);
+done:
+       ioprio_class = dd_rq_ioclass(rq);
+       prio = ioprio_class_to_prio[ioprio_class];
+       dd_count(dd, dispatched, prio);
+       /*
+        * If the request needs its target zone locked, do it.
+        */
+       blk_req_zone_write_lock(rq);
+       rq->rq_flags |= RQF_STARTED;
+       return rq;
+}
+
+/*
+ * Called from blk_mq_run_hw_queue() -> __blk_mq_sched_dispatch_requests().
+ *
+ * One confusing aspect here is that we get called for a specific
+ * hardware queue, but we may return a request that is for a
+ * different hardware queue. This is because mq-deadline has shared
+ * state for all hardware queues, in terms of sorting, FIFOs, etc.
+ */
+static struct request *dd_dispatch_request(struct blk_mq_hw_ctx *hctx)
+{
+       struct deadline_data *dd = hctx->queue->elevator->elevator_data;
+       struct request *rq;
+       enum dd_prio prio;
+
+       spin_lock(&dd->lock);
+       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
+               rq = __dd_dispatch_request(dd, &dd->per_prio[prio]);
+               if (rq)
+                       break;
+       }
+       spin_unlock(&dd->lock);
+
+       return rq;
+}
+
+/*
+ * Called by __blk_mq_alloc_request(). The shallow_depth value set by this
+ * function is used by __blk_mq_get_tag().
+ */
+static void dd_limit_depth(unsigned int op, struct blk_mq_alloc_data *data)
+{
+       struct deadline_data *dd = data->q->elevator->elevator_data;
+
+       /* Do not throttle synchronous reads. */
+       if (op_is_sync(op) && !op_is_write(op))
+               return;
+
+       /*
+        * Throttle asynchronous requests and writes such that these requests
+        * do not block the allocation of synchronous requests.
+        */
+       data->shallow_depth = dd->async_depth;
+}
+
+/* Called by blk_mq_update_nr_requests(). */
+static void dd_depth_updated(struct blk_mq_hw_ctx *hctx)
+{
+       struct request_queue *q = hctx->queue;
+       struct deadline_data *dd = q->elevator->elevator_data;
+       struct blk_mq_tags *tags = hctx->sched_tags;
+
+       dd->async_depth = max(1UL, 3 * q->nr_requests / 4);
+
+       sbitmap_queue_min_shallow_depth(tags->bitmap_tags, dd->async_depth);
+}
+
+/* Called by blk_mq_init_hctx() and blk_mq_init_sched(). */
+static int dd_init_hctx(struct blk_mq_hw_ctx *hctx, unsigned int hctx_idx)
+{
+       dd_depth_updated(hctx);
+       return 0;
+}
+
+static void dd_exit_sched(struct elevator_queue *e)
+{
+       struct deadline_data *dd = e->elevator_data;
+       enum dd_prio prio;
+
+       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
+               struct dd_per_prio *per_prio = &dd->per_prio[prio];
+
+               WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_READ]));
+               WARN_ON_ONCE(!list_empty(&per_prio->fifo_list[DD_WRITE]));
+       }
+
+       free_percpu(dd->stats);
+
+       kfree(dd);
+}
+
+/*
+ * initialize elevator private data (deadline_data).
+ */
+static int dd_init_sched(struct request_queue *q, struct elevator_type *e)
+{
+       struct deadline_data *dd;
+       struct elevator_queue *eq;
+       enum dd_prio prio;
+       int ret = -ENOMEM;
+
+       eq = elevator_alloc(q, e);
+       if (!eq)
+               return ret;
+
+       dd = kzalloc_node(sizeof(*dd), GFP_KERNEL, q->node);
+       if (!dd)
+               goto put_eq;
+
+       eq->elevator_data = dd;
+
+       dd->stats = alloc_percpu_gfp(typeof(*dd->stats),
+                                    GFP_KERNEL | __GFP_ZERO);
+       if (!dd->stats)
+               goto free_dd;
+
+       for (prio = 0; prio <= DD_PRIO_MAX; prio++) {
+               struct dd_per_prio *per_prio = &dd->per_prio[prio];
+
+               INIT_LIST_HEAD(&per_prio->dispatch);
+               INIT_LIST_HEAD(&per_prio->fifo_list[DD_READ]);
+               INIT_LIST_HEAD(&per_prio->fifo_list[DD_WRITE]);
+               per_prio->sort_list[DD_READ] = RB_ROOT;
+               per_prio->sort_list[DD_WRITE] = RB_ROOT;
+       }
+       dd->fifo_expire[DD_READ] = read_expire;
+       dd->fifo_expire[DD_WRITE] = write_expire;
+       dd->writes_starved = writes_starved;
+       dd->front_merges = 1;
+       dd->last_dir = DD_WRITE;
+       dd->fifo_batch = fifo_batch;
+       spin_lock_init(&dd->lock);
+       spin_lock_init(&dd->zone_lock);
+
+       q->elevator = eq;
+       return 0;
+
+free_dd:
+       kfree(dd);
+
+put_eq:
+       kobject_put(&eq->kobj);
+       return ret;
+}
+
+/*
+ * Try to merge @bio into an existing request. If @bio has been merged into
+ * an existing request, store the pointer to that request into *@rq.
+ */
+static int dd_request_merge(struct request_queue *q, struct request **rq,
+                           struct bio *bio)
+{
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const u8 ioprio_class = IOPRIO_PRIO_CLASS(bio->bi_ioprio);
+       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];
+       sector_t sector = bio_end_sector(bio);
+       struct request *__rq;
+
+       if (!dd->front_merges)
+               return ELEVATOR_NO_MERGE;
+
+       __rq = elv_rb_find(&per_prio->sort_list[bio_data_dir(bio)], sector);
+       if (__rq) {
+               BUG_ON(sector != blk_rq_pos(__rq));
+
+               if (elv_bio_merge_ok(__rq, bio)) {
+                       *rq = __rq;
+                       return ELEVATOR_FRONT_MERGE;
+               }
+       }
+
+       return ELEVATOR_NO_MERGE;
+}
+
+/*
+ * Attempt to merge a bio into an existing request. This function is called
+ * before @bio is associated with a request.
+ */
+static bool dd_bio_merge(struct request_queue *q, struct bio *bio,
+               unsigned int nr_segs)
+{
+       struct deadline_data *dd = q->elevator->elevator_data;
+       struct request *free = NULL;
+       bool ret;
+
+       spin_lock(&dd->lock);
+       ret = blk_mq_sched_try_merge(q, bio, nr_segs, &free);
+       spin_unlock(&dd->lock);
+
+       if (free)
+               blk_mq_free_request(free);
+
+       return ret;
+}
+
+/*
+ * add rq to rbtree and fifo
+ */
+static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
+                             bool at_head)
+{
+       struct request_queue *q = hctx->queue;
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const enum dd_data_dir data_dir = rq_data_dir(rq);
+       u16 ioprio = req_get_ioprio(rq);
+       u8 ioprio_class = IOPRIO_PRIO_CLASS(ioprio);
+       struct dd_per_prio *per_prio;
+       enum dd_prio prio;
+       LIST_HEAD(free);
+
+       lockdep_assert_held(&dd->lock);
+
+       /*
+        * This may be a requeue of a write request that has locked its
+        * target zone. If it is the case, this releases the zone lock.
+        */
+       blk_req_zone_write_unlock(rq);
+
+       prio = ioprio_class_to_prio[ioprio_class];
+       dd_count(dd, inserted, prio);
+       rq->elv.priv[0] = (void *)(uintptr_t)1;
+
+       if (blk_mq_sched_try_insert_merge(q, rq, &free)) {
+               blk_mq_free_requests(&free);
+               return;
+       }
+
+       trace_block_rq_insert(rq);
+
+       per_prio = &dd->per_prio[prio];
+       if (at_head) {
+               list_add(&rq->queuelist, &per_prio->dispatch);
+       } else {
+               deadline_add_rq_rb(per_prio, rq);
+
+               if (rq_mergeable(rq)) {
+                       elv_rqhash_add(q, rq);
+                       if (!q->last_merge)
+                               q->last_merge = rq;
+               }
+
+               /*
+                * set expire time and add to fifo list
+                */
+               rq->fifo_time = jiffies + dd->fifo_expire[data_dir];
+               list_add_tail(&rq->queuelist, &per_prio->fifo_list[data_dir]);
+       }
+}
+
+/*
+ * Called from blk_mq_sched_insert_request() or blk_mq_sched_insert_requests().
+ */
+static void dd_insert_requests(struct blk_mq_hw_ctx *hctx,
+                              struct list_head *list, bool at_head)
+{
+       struct request_queue *q = hctx->queue;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       spin_lock(&dd->lock);
+       while (!list_empty(list)) {
+               struct request *rq;
+
+               rq = list_first_entry(list, struct request, queuelist);
+               list_del_init(&rq->queuelist);
+               dd_insert_request(hctx, rq, at_head);
+       }
+       spin_unlock(&dd->lock);
+}
+
+/* Callback from inside blk_mq_rq_ctx_init(). */
+static void dd_prepare_request(struct request *rq)
+{
+       rq->elv.priv[0] = NULL;
+}
+
+/*
+ * Callback from inside blk_mq_free_request().
+ *
+ * For zoned block devices, write unlock the target zone of
+ * completed write requests. Do this while holding the zone lock
+ * spinlock so that the zone is never unlocked while deadline_fifo_request()
+ * or deadline_next_request() are executing. This function is called for
+ * all requests, whether or not these requests complete successfully.
+ *
+ * For a zoned block device, __dd_dispatch_request() may have stopped
+ * dispatching requests if all the queued requests are write requests directed
+ * at zones that are already locked due to on-going write requests. To ensure
+ * write request dispatch progress in this case, mark the queue as needing a
+ * restart to ensure that the queue is run again after completion of the
+ * request and zones being unlocked.
+ */
+static void dd_finish_request(struct request *rq)
+{
+       struct request_queue *q = rq->q;
+       struct deadline_data *dd = q->elevator->elevator_data;
+       const u8 ioprio_class = dd_rq_ioclass(rq);
+       const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];
+
+       /*
+        * The block layer core may call dd_finish_request() without having
+        * called dd_insert_requests(). Hence only update statistics for
+        * requests for which dd_insert_requests() has been called. See also
+        * blk_mq_request_bypass_insert().
+        */
+       if (rq->elv.priv[0])
+               dd_count(dd, completed, prio);
+
+       if (blk_queue_is_zoned(q)) {
+               unsigned long flags;
+
+               spin_lock_irqsave(&dd->zone_lock, flags);
+               blk_req_zone_write_unlock(rq);
+               if (!list_empty(&per_prio->fifo_list[DD_WRITE]))
+                       blk_mq_sched_mark_restart_hctx(rq->mq_hctx);
+               spin_unlock_irqrestore(&dd->zone_lock, flags);
+       }
+}
+
+static bool dd_has_work_for_prio(struct dd_per_prio *per_prio)
+{
+       return !list_empty_careful(&per_prio->dispatch) ||
+               !list_empty_careful(&per_prio->fifo_list[DD_READ]) ||
+               !list_empty_careful(&per_prio->fifo_list[DD_WRITE]);
+}
+
+static bool dd_has_work(struct blk_mq_hw_ctx *hctx)
+{
+       struct deadline_data *dd = hctx->queue->elevator->elevator_data;
+       enum dd_prio prio;
+
+       for (prio = 0; prio <= DD_PRIO_MAX; prio++)
+               if (dd_has_work_for_prio(&dd->per_prio[prio]))
+                       return true;
+
+       return false;
+}
+
+/*
+ * sysfs parts below
+ */
+#define SHOW_INT(__FUNC, __VAR)                                                \
+static ssize_t __FUNC(struct elevator_queue *e, char *page)            \
+{                                                                      \
+       struct deadline_data *dd = e->elevator_data;                    \
+                                                                       \
+       return sysfs_emit(page, "%d\n", __VAR);                         \
+}
+#define SHOW_JIFFIES(__FUNC, __VAR) SHOW_INT(__FUNC, jiffies_to_msecs(__VAR))
+SHOW_JIFFIES(deadline_read_expire_show, dd->fifo_expire[DD_READ]);
+SHOW_JIFFIES(deadline_write_expire_show, dd->fifo_expire[DD_WRITE]);
+SHOW_INT(deadline_writes_starved_show, dd->writes_starved);
+SHOW_INT(deadline_front_merges_show, dd->front_merges);
+SHOW_INT(deadline_async_depth_show, dd->front_merges);
+SHOW_INT(deadline_fifo_batch_show, dd->fifo_batch);
+#undef SHOW_INT
+#undef SHOW_JIFFIES
+
+#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)                        \
+static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count)        \
+{                                                                      \
+       struct deadline_data *dd = e->elevator_data;                    \
+       int __data, __ret;                                              \
+                                                                       \
+       __ret = kstrtoint(page, 0, &__data);                            \
+       if (__ret < 0)                                                  \
+               return __ret;                                           \
+       if (__data < (MIN))                                             \
+               __data = (MIN);                                         \
+       else if (__data > (MAX))                                        \
+               __data = (MAX);                                         \
+       *(__PTR) = __CONV(__data);                                      \
+       return count;                                                   \
+}
+#define STORE_INT(__FUNC, __PTR, MIN, MAX)                             \
+       STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, )
+#define STORE_JIFFIES(__FUNC, __PTR, MIN, MAX)                         \
+       STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, msecs_to_jiffies)
+STORE_JIFFIES(deadline_read_expire_store, &dd->fifo_expire[DD_READ], 0, INT_MAX);
+STORE_JIFFIES(deadline_write_expire_store, &dd->fifo_expire[DD_WRITE], 0, INT_MAX);
+STORE_INT(deadline_writes_starved_store, &dd->writes_starved, INT_MIN, INT_MAX);
+STORE_INT(deadline_front_merges_store, &dd->front_merges, 0, 1);
+STORE_INT(deadline_async_depth_store, &dd->front_merges, 1, INT_MAX);
+STORE_INT(deadline_fifo_batch_store, &dd->fifo_batch, 0, INT_MAX);
+#undef STORE_FUNCTION
+#undef STORE_INT
+#undef STORE_JIFFIES
+
+#define DD_ATTR(name) \
+       __ATTR(name, 0644, deadline_##name##_show, deadline_##name##_store)
+
+static struct elv_fs_entry deadline_attrs[] = {
+       DD_ATTR(read_expire),
+       DD_ATTR(write_expire),
+       DD_ATTR(writes_starved),
+       DD_ATTR(front_merges),
+       DD_ATTR(async_depth),
+       DD_ATTR(fifo_batch),
+       __ATTR_NULL
+};
+
+#ifdef CONFIG_BLK_DEBUG_FS
+#define DEADLINE_DEBUGFS_DDIR_ATTRS(prio, data_dir, name)              \
+static void *deadline_##name##_fifo_start(struct seq_file *m,          \
+                                         loff_t *pos)                  \
+       __acquires(&dd->lock)                                           \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+                                                                       \
+       spin_lock(&dd->lock);                                           \
+       return seq_list_start(&per_prio->fifo_list[data_dir], *pos);    \
+}                                                                      \
+                                                                       \
+static void *deadline_##name##_fifo_next(struct seq_file *m, void *v,  \
+                                        loff_t *pos)                   \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+                                                                       \
+       return seq_list_next(v, &per_prio->fifo_list[data_dir], pos);   \
+}                                                                      \
+                                                                       \
+static void deadline_##name##_fifo_stop(struct seq_file *m, void *v)   \
+       __releases(&dd->lock)                                           \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+                                                                       \
+       spin_unlock(&dd->lock);                                         \
+}                                                                      \
+                                                                       \
+static const struct seq_operations deadline_##name##_fifo_seq_ops = {  \
+       .start  = deadline_##name##_fifo_start,                         \
+       .next   = deadline_##name##_fifo_next,                          \
+       .stop   = deadline_##name##_fifo_stop,                          \
+       .show   = blk_mq_debugfs_rq_show,                               \
+};                                                                     \
+                                                                       \
+static int deadline_##name##_next_rq_show(void *data,                  \
+                                         struct seq_file *m)           \
+{                                                                      \
+       struct request_queue *q = data;                                 \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+       struct request *rq = per_prio->next_rq[data_dir];               \
+                                                                       \
+       if (rq)                                                         \
+               __blk_mq_debugfs_rq_show(m, rq);                        \
+       return 0;                                                       \
+}
+
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_READ, read0);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_RT_PRIO, DD_WRITE, write0);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_READ, read1);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_BE_PRIO, DD_WRITE, write1);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_READ, read2);
+DEADLINE_DEBUGFS_DDIR_ATTRS(DD_IDLE_PRIO, DD_WRITE, write2);
+#undef DEADLINE_DEBUGFS_DDIR_ATTRS
+
+static int deadline_batching_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u\n", dd->batching);
+       return 0;
+}
+
+static int deadline_starved_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u\n", dd->starved);
+       return 0;
+}
+
+static int dd_async_depth_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u\n", dd->async_depth);
+       return 0;
+}
+
+static int dd_queued_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u %u %u\n", dd_queued(dd, DD_RT_PRIO),
+                  dd_queued(dd, DD_BE_PRIO),
+                  dd_queued(dd, DD_IDLE_PRIO));
+       return 0;
+}
+
+/* Number of requests owned by the block driver for a given priority. */
+static u32 dd_owned_by_driver(struct deadline_data *dd, enum dd_prio prio)
+{
+       return dd_sum(dd, dispatched, prio) + dd_sum(dd, merged, prio)
+               - dd_sum(dd, completed, prio);
+}
+
+static int dd_owned_by_driver_show(void *data, struct seq_file *m)
+{
+       struct request_queue *q = data;
+       struct deadline_data *dd = q->elevator->elevator_data;
+
+       seq_printf(m, "%u %u %u\n", dd_owned_by_driver(dd, DD_RT_PRIO),
+                  dd_owned_by_driver(dd, DD_BE_PRIO),
+                  dd_owned_by_driver(dd, DD_IDLE_PRIO));
+       return 0;
+}
+
+#define DEADLINE_DISPATCH_ATTR(prio)                                   \
+static void *deadline_dispatch##prio##_start(struct seq_file *m,       \
+                                            loff_t *pos)               \
+       __acquires(&dd->lock)                                           \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+                                                                       \
+       spin_lock(&dd->lock);                                           \
+       return seq_list_start(&per_prio->dispatch, *pos);               \
+}                                                                      \
+                                                                       \
+static void *deadline_dispatch##prio##_next(struct seq_file *m,                \
+                                           void *v, loff_t *pos)       \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+       struct dd_per_prio *per_prio = &dd->per_prio[prio];             \
+                                                                       \
+       return seq_list_next(v, &per_prio->dispatch, pos);              \
+}                                                                      \
+                                                                       \
+static void deadline_dispatch##prio##_stop(struct seq_file *m, void *v)        \
+       __releases(&dd->lock)                                           \
+{                                                                      \
+       struct request_queue *q = m->private;                           \
+       struct deadline_data *dd = q->elevator->elevator_data;          \
+                                                                       \
+       spin_unlock(&dd->lock);                                         \
+}                                                                      \
+                                                                       \
+static const struct seq_operations deadline_dispatch##prio##_seq_ops = { \
+       .start  = deadline_dispatch##prio##_start,                      \
+       .next   = deadline_dispatch##prio##_next,                       \
+       .stop   = deadline_dispatch##prio##_stop,                       \
+       .show   = blk_mq_debugfs_rq_show,                               \
+}
+
+DEADLINE_DISPATCH_ATTR(0);
+DEADLINE_DISPATCH_ATTR(1);
+DEADLINE_DISPATCH_ATTR(2);
+#undef DEADLINE_DISPATCH_ATTR
+
+#define DEADLINE_QUEUE_DDIR_ATTRS(name)                                        \
+       {#name "_fifo_list", 0400,                                      \
+                       .seq_ops = &deadline_##name##_fifo_seq_ops}
+#define DEADLINE_NEXT_RQ_ATTR(name)                                    \
+       {#name "_next_rq", 0400, deadline_##name##_next_rq_show}
+static const struct blk_mq_debugfs_attr deadline_queue_debugfs_attrs[] = {
+       DEADLINE_QUEUE_DDIR_ATTRS(read0),
+       DEADLINE_QUEUE_DDIR_ATTRS(write0),
+       DEADLINE_QUEUE_DDIR_ATTRS(read1),
+       DEADLINE_QUEUE_DDIR_ATTRS(write1),
+       DEADLINE_QUEUE_DDIR_ATTRS(read2),
+       DEADLINE_QUEUE_DDIR_ATTRS(write2),
+       DEADLINE_NEXT_RQ_ATTR(read0),
+       DEADLINE_NEXT_RQ_ATTR(write0),
+       DEADLINE_NEXT_RQ_ATTR(read1),
+       DEADLINE_NEXT_RQ_ATTR(write1),
+       DEADLINE_NEXT_RQ_ATTR(read2),
+       DEADLINE_NEXT_RQ_ATTR(write2),
+       {"batching", 0400, deadline_batching_show},
+       {"starved", 0400, deadline_starved_show},
+       {"async_depth", 0400, dd_async_depth_show},
+       {"dispatch0", 0400, .seq_ops = &deadline_dispatch0_seq_ops},
+       {"dispatch1", 0400, .seq_ops = &deadline_dispatch1_seq_ops},
+       {"dispatch2", 0400, .seq_ops = &deadline_dispatch2_seq_ops},
+       {"owned_by_driver", 0400, dd_owned_by_driver_show},
+       {"queued", 0400, dd_queued_show},
+       {},
+};
+#undef DEADLINE_QUEUE_DDIR_ATTRS
+#endif
+
+static struct elevator_type mq_deadline = {
+       .ops = {
+               .depth_updated          = dd_depth_updated,
+               .limit_depth            = dd_limit_depth,
+               .insert_requests        = dd_insert_requests,
+               .dispatch_request       = dd_dispatch_request,
+               .prepare_request        = dd_prepare_request,
+               .finish_request         = dd_finish_request,
+               .next_request           = elv_rb_latter_request,
+               .former_request         = elv_rb_former_request,
+               .bio_merge              = dd_bio_merge,
+               .request_merge          = dd_request_merge,
+               .requests_merged        = dd_merged_requests,
+               .request_merged         = dd_request_merged,
+               .has_work               = dd_has_work,
+               .init_sched             = dd_init_sched,
+               .exit_sched             = dd_exit_sched,
+               .init_hctx              = dd_init_hctx,
+       },
+
+#ifdef CONFIG_BLK_DEBUG_FS
+       .queue_debugfs_attrs = deadline_queue_debugfs_attrs,
+#endif
+       .elevator_attrs = deadline_attrs,
+       .elevator_name = "mq-deadline",
+       .elevator_alias = "deadline",
+       .elevator_features = ELEVATOR_F_ZBD_SEQ_WRITE,
+       .elevator_owner = THIS_MODULE,
+};
+MODULE_ALIAS("mq-deadline-iosched");
+
+static int __init deadline_init(void)
+{
+       return elv_register(&mq_deadline);
+}
+
+static void __exit deadline_exit(void)
+{
+       elv_unregister(&mq_deadline);
+}
+
+module_init(deadline_init);
+module_exit(deadline_exit);
+
+MODULE_AUTHOR("Jens Axboe, Damien Le Moal and Bart Van Assche");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MQ deadline IO scheduler");
index cc86534..b8b518d 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
-/**
+/*
  * ldm - Support for Windows Logical Disk Manager (Dynamic Disks)
  *
  * Copyright (C) 2001,2002 Richard Russon <ldm@flatcap.org>
index ca3b02d..64b772c 100644 (file)
@@ -1768,7 +1768,7 @@ config CRYPTO_DRBG_HMAC
        bool
        default y
        select CRYPTO_HMAC
-       select CRYPTO_SHA256
+       select CRYPTO_SHA512
 
 config CRYPTO_DRBG_HASH
        bool "Enable Hash DRBG"
index 38e10ab..14b71b4 100644 (file)
@@ -379,13 +379,6 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
 
                        (*element_ptr)->common.reference_count =
                            original_ref_count;
-
-                       /*
-                        * The original_element holds a reference from the package object
-                        * that represents _HID. Since a new element was created by _HID,
-                        * remove the reference from the _CID package.
-                        */
-                       acpi_ut_remove_reference(original_element);
                }
 
                element_ptr++;
index 23d9a09..a3ef6cc 100644 (file)
@@ -3021,6 +3021,9 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
                struct acpi_nfit_memory_map *memdev = nfit_memdev->memdev;
                struct nd_mapping_desc *mapping;
 
+               /* range index 0 == unmapped in SPA or invalid-SPA */
+               if (memdev->range_index == 0 || spa->range_index == 0)
+                       continue;
                if (memdev->range_index != spa->range_index)
                        continue;
                if (count >= ND_MAX_MAPPINGS) {
index 31cf9ae..1f6007a 100644 (file)
@@ -292,6 +292,12 @@ void __init init_prmt(void)
        int mc = acpi_table_parse_entries(ACPI_SIG_PRMT, sizeof(struct acpi_table_prmt) +
                                          sizeof (struct acpi_table_prmt_header),
                                          0, acpi_parse_prmt, 0);
+       /*
+        * Return immediately if PRMT table is not present or no PRM module found.
+        */
+       if (mc <= 0)
+               return;
+
        pr_info("PRM: found %u modules\n", mc);
 
        status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT,
index fbdbef0..3a30846 100644 (file)
@@ -452,7 +452,7 @@ int acpi_s2idle_prepare_late(void)
        if (lps0_dsm_func_mask_microsoft > 0) {
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_OFF,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-               acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
+               acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_ENTRY,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
@@ -479,7 +479,7 @@ void acpi_s2idle_restore_early(void)
        if (lps0_dsm_func_mask_microsoft > 0) {
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_EXIT,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
-               acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_ENTRY,
+               acpi_sleep_run_lps0_dsm(ACPI_LPS0_MS_EXIT,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
                acpi_sleep_run_lps0_dsm(ACPI_LPS0_SCREEN_ON,
                                lps0_dsm_func_mask_microsoft, lps0_dsm_guid_microsoft);
index f636049..6c0ef9d 100644 (file)
@@ -2837,6 +2837,7 @@ void device_initialize(struct device *dev)
        device_pm_init(dev);
        set_dev_node(dev, -1);
 #ifdef CONFIG_GENERIC_MSI_IRQ
+       raw_spin_lock_init(&dev->msi_lock);
        INIT_LIST_HEAD(&dev->msi_list);
 #endif
        INIT_LIST_HEAD(&dev->links.consumers);
index daeb9b5..437cd61 100644 (file)
@@ -653,8 +653,6 @@ dev_groups_failed:
        else if (drv->remove)
                drv->remove(dev);
 probe_failed:
-       kfree(dev->dma_range_map);
-       dev->dma_range_map = NULL;
        if (dev->bus)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                             BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
@@ -662,6 +660,8 @@ pinctrl_bind_failed:
        device_links_no_driver(dev);
        devres_release_all(dev);
        arch_teardown_dma_ops(dev);
+       kfree(dev->dma_range_map);
+       dev->dma_range_map = NULL;
        driver_sysfs_remove(dev);
        dev->driver = NULL;
        dev_set_drvdata(dev, NULL);
index 91899d1..d7d63c1 100644 (file)
@@ -89,12 +89,11 @@ static void __fw_load_abort(struct fw_priv *fw_priv)
 {
        /*
         * There is a small window in which user can write to 'loading'
-        * between loading done and disappearance of 'loading'
+        * between loading done/aborted and disappearance of 'loading'
         */
-       if (fw_sysfs_done(fw_priv))
+       if (fw_state_is_aborted(fw_priv) || fw_sysfs_done(fw_priv))
                return;
 
-       list_del_init(&fw_priv->pending_list);
        fw_state_aborted(fw_priv);
 }
 
@@ -280,7 +279,6 @@ static ssize_t firmware_loading_store(struct device *dev,
                         * Same logic as fw_load_abort, only the DONE bit
                         * is ignored and we set ABORT only on failure.
                         */
-                       list_del_init(&fw_priv->pending_list);
                        if (rc) {
                                fw_state_aborted(fw_priv);
                                written = rc;
@@ -513,6 +511,11 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout)
        }
 
        mutex_lock(&fw_lock);
+       if (fw_state_is_aborted(fw_priv)) {
+               mutex_unlock(&fw_lock);
+               retval = -EINTR;
+               goto out;
+       }
        list_add(&fw_priv->pending_list, &pending_fw_head);
        mutex_unlock(&fw_lock);
 
@@ -535,11 +538,10 @@ static int fw_load_sysfs_fallback(struct fw_sysfs *fw_sysfs, long timeout)
        if (fw_state_is_aborted(fw_priv)) {
                if (retval == -ERESTARTSYS)
                        retval = -EINTR;
-               else
-                       retval = -EAGAIN;
        } else if (fw_priv->is_paged_buf && !fw_priv->data)
                retval = -ENOMEM;
 
+out:
        device_del(f_dev);
 err_put_dev:
        put_device(f_dev);
index 63bd29f..a3014e9 100644 (file)
@@ -117,8 +117,16 @@ static inline void __fw_state_set(struct fw_priv *fw_priv,
 
        WRITE_ONCE(fw_st->status, status);
 
-       if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED)
+       if (status == FW_STATUS_DONE || status == FW_STATUS_ABORTED) {
+#ifdef CONFIG_FW_LOADER_USER_HELPER
+               /*
+                * Doing this here ensures that the fw_priv is deleted from
+                * the pending list in all abort/done paths.
+                */
+               list_del_init(&fw_priv->pending_list);
+#endif
                complete_all(&fw_st->completion);
+       }
 }
 
 static inline void fw_state_aborted(struct fw_priv *fw_priv)
index 4fdb821..68c549d 100644 (file)
@@ -783,8 +783,10 @@ static void fw_abort_batch_reqs(struct firmware *fw)
                return;
 
        fw_priv = fw->priv;
+       mutex_lock(&fw_lock);
        if (!fw_state_is_aborted(fw_priv))
                fw_state_aborted(fw_priv);
+       mutex_unlock(&fw_lock);
 }
 
 /* called from request_firmware() and request_firmware_work_func() */
index a934c67..f10688e 100644 (file)
@@ -435,7 +435,7 @@ static void genpd_restore_performance_state(struct device *dev,
 int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
 {
        struct generic_pm_domain *genpd;
-       int ret;
+       int ret = 0;
 
        genpd = dev_to_genpd_safe(dev);
        if (!genpd)
@@ -446,7 +446,13 @@ int dev_pm_genpd_set_performance_state(struct device *dev, unsigned int state)
                return -EINVAL;
 
        genpd_lock(genpd);
-       ret = genpd_set_performance_state(dev, state);
+       if (pm_runtime_suspended(dev)) {
+               dev_gpd_data(dev)->rpm_pstate = state;
+       } else {
+               ret = genpd_set_performance_state(dev, state);
+               if (!ret)
+                       dev_gpd_data(dev)->rpm_pstate = 0;
+       }
        genpd_unlock(genpd);
 
        return ret;
index 63056cf..fbb3a55 100644 (file)
@@ -213,7 +213,7 @@ config BLK_DEV_LOOP_MIN_COUNT
          dynamically allocated with the /dev/loop-control interface.
 
 config BLK_DEV_CRYPTOLOOP
-       tristate "Cryptoloop Support"
+       tristate "Cryptoloop Support (DEPRECATED)"
        select CRYPTO
        select CRYPTO_CBC
        depends on BLK_DEV_LOOP
@@ -225,7 +225,7 @@ config BLK_DEV_CRYPTOLOOP
          WARNING: This device is not safe for journaled file systems like
          ext3 or Reiserfs. Please use the Device Mapper crypto module
          instead, which can be configured to be on-disk compatible with the
-         cryptoloop device.
+         cryptoloop device.  cryptoloop support will be removed in Linux 5.16.
 
 source "drivers/block/drbd/Kconfig"
 
index 3cabc33..f0a91fa 100644 (file)
@@ -189,6 +189,8 @@ init_cryptoloop(void)
 
        if (rc)
                printk(KERN_ERR "cryptoloop: loop_register_transfer failed\n");
+       else
+               pr_warn("the cryptoloop driver has been deprecated and will be removed in in Linux 5.16\n");
        return rc;
 }
 
index 7b4dd10..c84be00 100644 (file)
@@ -74,7 +74,7 @@ static bool n64cart_do_bvec(struct device *dev, struct bio_vec *bv, u32 pos)
 
        n64cart_wait_dma();
 
-       n64cart_write_reg(PI_DRAM_REG, dma_addr + bv->bv_offset);
+       n64cart_write_reg(PI_DRAM_REG, dma_addr);
        n64cart_write_reg(PI_CART_REG, (bstart | CART_DOMAIN) & CART_MAX);
        n64cart_write_reg(PI_WRITE_REG, bv->bv_len - 1);
 
index c383179..19f5d5a 100644 (file)
@@ -818,6 +818,10 @@ static bool nbd_clear_req(struct request *req, void *data, bool reserved)
 {
        struct nbd_cmd *cmd = blk_mq_rq_to_pdu(req);
 
+       /* don't abort one completed request */
+       if (blk_mq_request_completed(req))
+               return true;
+
        mutex_lock(&cmd->lock);
        cmd->status = BLK_STS_IOERR;
        mutex_unlock(&cmd->lock);
@@ -2004,15 +2008,19 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd)
 {
        mutex_lock(&nbd->config_lock);
        nbd_disconnect(nbd);
-       nbd_clear_sock(nbd);
-       mutex_unlock(&nbd->config_lock);
+       sock_shutdown(nbd);
        /*
         * Make sure recv thread has finished, so it does not drop the last
         * config ref and try to destroy the workqueue from inside the work
-        * queue.
+        * queue. And this also ensure that we can safely call nbd_clear_que()
+        * to cancel the inflight I/Os.
         */
        if (nbd->recv_workq)
                flush_workqueue(nbd->recv_workq);
+       nbd_clear_que(nbd);
+       nbd->task_setup = NULL;
+       mutex_unlock(&nbd->config_lock);
+
        if (test_and_clear_bit(NBD_RT_HAS_CONFIG_REF,
                               &nbd->config->runtime_flags))
                nbd_config_put(nbd);
index 9b32989..675327d 100644 (file)
@@ -892,7 +892,7 @@ static void pd_probe_drive(struct pd_unit *disk)
                return;
 
        p = blk_mq_alloc_disk(&disk->tag_set, disk);
-       if (!p) {
+       if (IS_ERR(p)) {
                blk_mq_free_tag_set(&disk->tag_set);
                return;
        }
index 4b49df2..afb37aa 100644 (file)
@@ -692,6 +692,28 @@ static const struct blk_mq_ops virtio_mq_ops = {
 static unsigned int virtblk_queue_depth;
 module_param_named(queue_depth, virtblk_queue_depth, uint, 0444);
 
+static int virtblk_validate(struct virtio_device *vdev)
+{
+       u32 blk_size;
+
+       if (!vdev->config->get) {
+               dev_err(&vdev->dev, "%s failure: config access disabled\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (!virtio_has_feature(vdev, VIRTIO_BLK_F_BLK_SIZE))
+               return 0;
+
+       blk_size = virtio_cread32(vdev,
+                       offsetof(struct virtio_blk_config, blk_size));
+
+       if (blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)
+               __virtio_clear_bit(vdev, VIRTIO_BLK_F_BLK_SIZE);
+
+       return 0;
+}
+
 static int virtblk_probe(struct virtio_device *vdev)
 {
        struct virtio_blk *vblk;
@@ -703,12 +725,6 @@ static int virtblk_probe(struct virtio_device *vdev)
        u8 physical_block_exp, alignment_offset;
        unsigned int queue_depth;
 
-       if (!vdev->config->get) {
-               dev_err(&vdev->dev, "%s failure: config access disabled\n",
-                       __func__);
-               return -EINVAL;
-       }
-
        err = ida_simple_get(&vd_index_ida, 0, minor_to_index(1 << MINORBITS),
                             GFP_KERNEL);
        if (err < 0)
@@ -823,6 +839,14 @@ static int virtblk_probe(struct virtio_device *vdev)
        else
                blk_size = queue_logical_block_size(q);
 
+       if (unlikely(blk_size < SECTOR_SIZE || blk_size > PAGE_SIZE)) {
+               dev_err(&vdev->dev,
+                       "block size is changed unexpectedly, now is %u\n",
+                       blk_size);
+               err = -EINVAL;
+               goto err_cleanup_disk;
+       }
+
        /* Use topology information if available */
        err = virtio_cread_feature(vdev, VIRTIO_BLK_F_TOPOLOGY,
                                   struct virtio_blk_config, physical_block_exp,
@@ -881,6 +905,8 @@ static int virtblk_probe(struct virtio_device *vdev)
        device_add_disk(&vdev->dev, vblk->disk, virtblk_attr_groups);
        return 0;
 
+err_cleanup_disk:
+       blk_cleanup_disk(vblk->disk);
 out_free_tags:
        blk_mq_free_tag_set(&vblk->tag_set);
 out_free_vq:
@@ -983,6 +1009,7 @@ static struct virtio_driver virtio_blk = {
        .driver.name                    = KBUILD_MODNAME,
        .driver.owner                   = THIS_MODULE,
        .id_table                       = id_table,
+       .validate                       = virtblk_validate,
        .probe                          = virtblk_probe,
        .remove                         = virtblk_remove,
        .config_changed                 = virtblk_config_changed,
index bc239a1..5b9ea66 100644 (file)
@@ -682,7 +682,7 @@ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl,
                      struct image_info *img_info);
 void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl);
 int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
-                       struct mhi_chan *mhi_chan, unsigned int flags);
+                       struct mhi_chan *mhi_chan);
 int mhi_init_chan_ctxt(struct mhi_controller *mhi_cntrl,
                       struct mhi_chan *mhi_chan);
 void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,
index 8444823..fc9196f 100644 (file)
@@ -1430,7 +1430,7 @@ exit_unprepare_channel:
 }
 
 int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
-                       struct mhi_chan *mhi_chan, unsigned int flags)
+                       struct mhi_chan *mhi_chan)
 {
        int ret = 0;
        struct device *dev = &mhi_chan->mhi_dev->dev;
@@ -1455,9 +1455,6 @@ int mhi_prepare_channel(struct mhi_controller *mhi_cntrl,
        if (ret)
                goto error_pm_state;
 
-       if (mhi_chan->dir == DMA_FROM_DEVICE)
-               mhi_chan->pre_alloc = !!(flags & MHI_CH_INBOUND_ALLOC_BUFS);
-       
        /* Pre-allocate buffer for xfer ring */
        if (mhi_chan->pre_alloc) {
                int nr_el = get_nr_avail_ring_elements(mhi_cntrl,
@@ -1613,7 +1610,7 @@ void mhi_reset_chan(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan)
 }
 
 /* Move channel to start state */
-int mhi_prepare_for_transfer(struct mhi_device *mhi_dev, unsigned int flags)
+int mhi_prepare_for_transfer(struct mhi_device *mhi_dev)
 {
        int ret, dir;
        struct mhi_controller *mhi_cntrl = mhi_dev->mhi_cntrl;
@@ -1624,7 +1621,7 @@ int mhi_prepare_for_transfer(struct mhi_device *mhi_dev, unsigned int flags)
                if (!mhi_chan)
                        continue;
 
-               ret = mhi_prepare_channel(mhi_cntrl, mhi_chan, flags);
+               ret = mhi_prepare_channel(mhi_cntrl, mhi_chan);
                if (ret)
                        goto error_open_chan;
        }
index 38cb116..148a4dd 100644 (file)
@@ -100,6 +100,7 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = {
  * @cookie: data used by legacy platform callbacks
  * @name: name if available
  * @revision: interconnect target module revision
+ * @reserved: target module is reserved and already in use
  * @enabled: sysc runtime enabled status
  * @needs_resume: runtime resume needed on resume from suspend
  * @child_needs_resume: runtime resume needed for child on resume from suspend
@@ -130,6 +131,7 @@ struct sysc {
        struct ti_sysc_cookie cookie;
        const char *name;
        u32 revision;
+       unsigned int reserved:1;
        unsigned int enabled:1;
        unsigned int needs_resume:1;
        unsigned int child_needs_resume:1;
@@ -2951,6 +2953,8 @@ static int sysc_init_soc(struct sysc *ddata)
                case SOC_3430 ... SOC_3630:
                        sysc_add_disabled(0x48304000);  /* timer12 */
                        break;
+               case SOC_AM3:
+                       sysc_add_disabled(0x48310000);  /* rng */
                default:
                        break;
                }
@@ -3093,7 +3097,9 @@ static int sysc_probe(struct platform_device *pdev)
                return error;
 
        error = sysc_check_active_timer(ddata);
-       if (error)
+       if (error == -ENXIO)
+               ddata->reserved = true;
+       else if (error)
                return error;
 
        error = sysc_get_clocks(ddata);
@@ -3130,11 +3136,15 @@ static int sysc_probe(struct platform_device *pdev)
        sysc_show_registers(ddata);
 
        ddata->dev->type = &sysc_device_type;
-       error = of_platform_populate(ddata->dev->of_node, sysc_match_table,
-                                    pdata ? pdata->auxdata : NULL,
-                                    ddata->dev);
-       if (error)
-               goto err;
+
+       if (!ddata->reserved) {
+               error = of_platform_populate(ddata->dev->of_node,
+                                            sysc_match_table,
+                                            pdata ? pdata->auxdata : NULL,
+                                            ddata->dev);
+               if (error)
+                       goto err;
+       }
 
        INIT_DELAYED_WORK(&ddata->idle_work, ti_sysc_idle);
 
index 2ccdf8a..6e32355 100644 (file)
@@ -254,11 +254,11 @@ static int ftpm_tee_probe(struct device *dev)
        pvt_data->session = sess_arg.session;
 
        /* Allocate dynamic shared memory with fTPM TA */
-       pvt_data->shm = tee_shm_alloc(pvt_data->ctx,
-                                     MAX_COMMAND_SIZE + MAX_RESPONSE_SIZE,
-                                     TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+       pvt_data->shm = tee_shm_alloc_kernel_buf(pvt_data->ctx,
+                                                MAX_COMMAND_SIZE +
+                                                MAX_RESPONSE_SIZE);
        if (IS_ERR(pvt_data->shm)) {
-               dev_err(dev, "%s: tee_shm_alloc failed\n", __func__);
+               dev_err(dev, "%s: tee_shm_alloc_kernel_buf failed\n", __func__);
                rc = -ENOMEM;
                goto out_shm_alloc;
        }
index 496900d..de36f58 100644 (file)
@@ -974,6 +974,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
                               hws[IMX6QDL_CLK_PLL3_USB_OTG]->clk);
        }
 
-       imx_register_uart_clocks(1);
+       imx_register_uart_clocks(2);
 }
 CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
index 51ed640..4ece326 100644 (file)
@@ -357,27 +357,43 @@ static int gdsc_init(struct gdsc *sc)
        if (on < 0)
                return on;
 
-       /*
-        * Votable GDSCs can be ON due to Vote from other masters.
-        * If a Votable GDSC is ON, make sure we have a Vote.
-        */
-       if ((sc->flags & VOTABLE) && on)
-               gdsc_enable(&sc->pd);
+       if (on) {
+               /* The regulator must be on, sync the kernel state */
+               if (sc->rsupply) {
+                       ret = regulator_enable(sc->rsupply);
+                       if (ret < 0)
+                               return ret;
+               }
 
-       /*
-        * Make sure the retain bit is set if the GDSC is already on, otherwise
-        * we end up turning off the GDSC and destroying all the register
-        * contents that we thought we were saving.
-        */
-       if ((sc->flags & RETAIN_FF_ENABLE) && on)
-               gdsc_retain_ff_on(sc);
+               /*
+                * Votable GDSCs can be ON due to Vote from other masters.
+                * If a Votable GDSC is ON, make sure we have a Vote.
+                */
+               if (sc->flags & VOTABLE) {
+                       ret = regmap_update_bits(sc->regmap, sc->gdscr,
+                                                SW_COLLAPSE_MASK, val);
+                       if (ret)
+                               return ret;
+               }
+
+               /* Turn on HW trigger mode if supported */
+               if (sc->flags & HW_CTRL) {
+                       ret = gdsc_hwctrl(sc, true);
+                       if (ret < 0)
+                               return ret;
+               }
 
-       /* If ALWAYS_ON GDSCs are not ON, turn them ON */
-       if (sc->flags & ALWAYS_ON) {
-               if (!on)
-                       gdsc_enable(&sc->pd);
+               /*
+                * Make sure the retain bit is set if the GDSC is already on,
+                * otherwise we end up turning off the GDSC and destroying all
+                * the register contents that we thought we were saving.
+                */
+               if (sc->flags & RETAIN_FF_ENABLE)
+                       gdsc_retain_ff_on(sc);
+       } else if (sc->flags & ALWAYS_ON) {
+               /* If ALWAYS_ON GDSCs are not ON, turn them ON */
+               gdsc_enable(&sc->pd);
                on = true;
-               sc->pd.flags |= GENPD_FLAG_ALWAYS_ON;
        }
 
        if (on || (sc->pwrsts & PWRSTS_RET))
@@ -385,6 +401,8 @@ static int gdsc_init(struct gdsc *sc)
        else
                gdsc_clear_mem_on(sc);
 
+       if (sc->flags & ALWAYS_ON)
+               sc->pd.flags |= GENPD_FLAG_ALWAYS_ON;
        if (!sc->pd.power_off)
                sc->pd.power_off = gdsc_disable;
        if (!sc->pd.power_on)
index 9fb79bd..684d893 100644 (file)
@@ -187,7 +187,7 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
        init.ops = &usb2_clock_sel_clock_ops;
        priv->hw.init = &init;
 
-       ret = devm_clk_hw_register(NULL, &priv->hw);
+       ret = devm_clk_hw_register(dev, &priv->hw);
        if (ret)
                goto pm_put;
 
index 3fc98a3..c10fc33 100644 (file)
@@ -104,7 +104,11 @@ struct armada_37xx_dvfs {
 };
 
 static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
-       {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} },
+       /*
+        * The cpufreq scaling for 1.2 GHz variant of the SOC is currently
+        * unstable because we do not know how to configure it properly.
+        */
+       /* {.cpu_freq_max = 1200*1000*1000, .divider = {1, 2, 4, 6} }, */
        {.cpu_freq_max = 1000*1000*1000, .divider = {1, 2, 4, 5} },
        {.cpu_freq_max = 800*1000*1000,  .divider = {1, 2, 3, 4} },
        {.cpu_freq_max = 600*1000*1000,  .divider = {2, 4, 5, 6} },
index bef7528..231e585 100644 (file)
@@ -139,7 +139,9 @@ static const struct of_device_id blocklist[] __initconst = {
        { .compatible = "qcom,qcs404", },
        { .compatible = "qcom,sc7180", },
        { .compatible = "qcom,sc7280", },
+       { .compatible = "qcom,sc8180x", },
        { .compatible = "qcom,sdm845", },
+       { .compatible = "qcom,sm8150", },
 
        { .compatible = "st,stih407", },
        { .compatible = "st,stih410", },
index ec9a87c..75f818d 100644 (file)
@@ -134,7 +134,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
        }
 
        if (!zalloc_cpumask_var(&opp_shared_cpus, GFP_KERNEL))
-               ret = -ENOMEM;
+               return -ENOMEM;
 
        /* Obtain CPUs that share SCMI performance controls */
        ret = scmi_get_sharing_cpus(cpu_dev, policy->cpus);
index 7b91060..d9262db 100644 (file)
@@ -382,8 +382,8 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
        alt_intercepts = 2 * idx_intercept_sum > cpu_data->total - idx_hit_sum;
        alt_recent = idx_recent_sum > NR_RECENT / 2;
        if (alt_recent || alt_intercepts) {
-               s64 last_enabled_span_ns = duration_ns;
-               int last_enabled_idx = idx;
+               s64 first_suitable_span_ns = duration_ns;
+               int first_suitable_idx = idx;
 
                /*
                 * Look for the deepest idle state whose target residency had
@@ -397,37 +397,51 @@ static int teo_select(struct cpuidle_driver *drv, struct cpuidle_device *dev,
                intercept_sum = 0;
                recent_sum = 0;
 
-               for (i = idx - 1; i >= idx0; i--) {
+               for (i = idx - 1; i >= 0; i--) {
                        struct teo_bin *bin = &cpu_data->state_bins[i];
                        s64 span_ns;
 
                        intercept_sum += bin->intercepts;
                        recent_sum += bin->recent;
 
+                       span_ns = teo_middle_of_bin(i, drv);
+
+                       if ((!alt_recent || 2 * recent_sum > idx_recent_sum) &&
+                           (!alt_intercepts ||
+                            2 * intercept_sum > idx_intercept_sum)) {
+                               if (teo_time_ok(span_ns) &&
+                                   !dev->states_usage[i].disable) {
+                                       idx = i;
+                                       duration_ns = span_ns;
+                               } else {
+                                       /*
+                                        * The current state is too shallow or
+                                        * disabled, so take the first enabled
+                                        * deeper state with suitable time span.
+                                        */
+                                       idx = first_suitable_idx;
+                                       duration_ns = first_suitable_span_ns;
+                               }
+                               break;
+                       }
+
                        if (dev->states_usage[i].disable)
                                continue;
 
-                       span_ns = teo_middle_of_bin(i, drv);
                        if (!teo_time_ok(span_ns)) {
                                /*
-                                * The current state is too shallow, so select
-                                * the first enabled deeper state.
+                                * The current state is too shallow, but if an
+                                * alternative candidate state has been found,
+                                * it may still turn out to be a better choice.
                                 */
-                               duration_ns = last_enabled_span_ns;
-                               idx = last_enabled_idx;
-                               break;
-                       }
+                               if (first_suitable_idx != idx)
+                                       continue;
 
-                       if ((!alt_recent || 2 * recent_sum > idx_recent_sum) &&
-                           (!alt_intercepts ||
-                            2 * intercept_sum > idx_intercept_sum)) {
-                               idx = i;
-                               duration_ns = span_ns;
                                break;
                        }
 
-                       last_enabled_span_ns = span_ns;
-                       last_enabled_idx = i;
+                       first_suitable_span_ns = span_ns;
+                       first_suitable_idx = i;
                }
        }
 
index 5fa6ae9..44736cb 100644 (file)
@@ -313,7 +313,7 @@ long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
                return -ENXIO;
 
        if (nr_pages < 0)
-               return nr_pages;
+               return -EINVAL;
 
        avail = dax_dev->ops->direct_access(dax_dev, pgoff, nr_pages,
                        kaddr, pfn);
index 26482c7..fc708be 100644 (file)
@@ -294,6 +294,14 @@ struct idxd_desc {
        struct idxd_wq *wq;
 };
 
+/*
+ * This is software defined error for the completion status. We overload the error code
+ * that will never appear in completion status and only SWERR register.
+ */
+enum idxd_completion_status {
+       IDXD_COMP_DESC_ABORT = 0xff,
+};
+
 #define confdev_to_idxd(dev) container_of(dev, struct idxd_device, conf_dev)
 #define confdev_to_wq(dev) container_of(dev, struct idxd_wq, conf_dev)
 
@@ -482,4 +490,10 @@ static inline void perfmon_init(void) {}
 static inline void perfmon_exit(void) {}
 #endif
 
+static inline void complete_desc(struct idxd_desc *desc, enum idxd_complete_type reason)
+{
+       idxd_dma_complete_txd(desc, reason);
+       idxd_free_desc(desc->wq, desc);
+}
+
 #endif
index c8ae41d..c0f4c04 100644 (file)
@@ -102,6 +102,8 @@ static int idxd_setup_interrupts(struct idxd_device *idxd)
                spin_lock_init(&idxd->irq_entries[i].list_lock);
        }
 
+       idxd_msix_perm_setup(idxd);
+
        irq_entry = &idxd->irq_entries[0];
        rc = request_threaded_irq(irq_entry->vector, NULL, idxd_misc_thread,
                                  0, "idxd-misc", irq_entry);
@@ -148,7 +150,6 @@ static int idxd_setup_interrupts(struct idxd_device *idxd)
        }
 
        idxd_unmask_error_interrupts(idxd);
-       idxd_msix_perm_setup(idxd);
        return 0;
 
  err_wq_irqs:
@@ -162,6 +163,7 @@ static int idxd_setup_interrupts(struct idxd_device *idxd)
  err_misc_irq:
        /* Disable error interrupt generation */
        idxd_mask_error_interrupts(idxd);
+       idxd_msix_perm_clear(idxd);
  err_irq_entries:
        pci_free_irq_vectors(pdev);
        dev_err(dev, "No usable interrupts\n");
@@ -758,32 +760,40 @@ static void idxd_shutdown(struct pci_dev *pdev)
        for (i = 0; i < msixcnt; i++) {
                irq_entry = &idxd->irq_entries[i];
                synchronize_irq(irq_entry->vector);
-               free_irq(irq_entry->vector, irq_entry);
                if (i == 0)
                        continue;
                idxd_flush_pending_llist(irq_entry);
                idxd_flush_work_list(irq_entry);
        }
-
-       idxd_msix_perm_clear(idxd);
-       idxd_release_int_handles(idxd);
-       pci_free_irq_vectors(pdev);
-       pci_iounmap(pdev, idxd->reg_base);
-       pci_disable_device(pdev);
-       destroy_workqueue(idxd->wq);
+       flush_workqueue(idxd->wq);
 }
 
 static void idxd_remove(struct pci_dev *pdev)
 {
        struct idxd_device *idxd = pci_get_drvdata(pdev);
+       struct idxd_irq_entry *irq_entry;
+       int msixcnt = pci_msix_vec_count(pdev);
+       int i;
 
        dev_dbg(&pdev->dev, "%s called\n", __func__);
        idxd_shutdown(pdev);
        if (device_pasid_enabled(idxd))
                idxd_disable_system_pasid(idxd);
        idxd_unregister_devices(idxd);
-       perfmon_pmu_remove(idxd);
+
+       for (i = 0; i < msixcnt; i++) {
+               irq_entry = &idxd->irq_entries[i];
+               free_irq(irq_entry->vector, irq_entry);
+       }
+       idxd_msix_perm_clear(idxd);
+       idxd_release_int_handles(idxd);
+       pci_free_irq_vectors(pdev);
+       pci_iounmap(pdev, idxd->reg_base);
        iommu_dev_disable_feature(&pdev->dev, IOMMU_DEV_FEAT_SVA);
+       pci_disable_device(pdev);
+       destroy_workqueue(idxd->wq);
+       perfmon_pmu_remove(idxd);
+       device_unregister(&idxd->conf_dev);
 }
 
 static struct pci_driver idxd_pci_driver = {
index ae68e1e..4e3a719 100644 (file)
@@ -245,12 +245,6 @@ static inline bool match_fault(struct idxd_desc *desc, u64 fault_addr)
        return false;
 }
 
-static inline void complete_desc(struct idxd_desc *desc, enum idxd_complete_type reason)
-{
-       idxd_dma_complete_txd(desc, reason);
-       idxd_free_desc(desc->wq, desc);
-}
-
 static int irq_process_pending_llist(struct idxd_irq_entry *irq_entry,
                                     enum irq_work_type wtype,
                                     int *processed, u64 data)
@@ -272,8 +266,16 @@ static int irq_process_pending_llist(struct idxd_irq_entry *irq_entry,
                reason = IDXD_COMPLETE_DEV_FAIL;
 
        llist_for_each_entry_safe(desc, t, head, llnode) {
-               if (desc->completion->status) {
-                       if ((desc->completion->status & DSA_COMP_STATUS_MASK) != DSA_COMP_SUCCESS)
+               u8 status = desc->completion->status & DSA_COMP_STATUS_MASK;
+
+               if (status) {
+                       if (unlikely(status == IDXD_COMP_DESC_ABORT)) {
+                               complete_desc(desc, IDXD_COMPLETE_ABORT);
+                               (*processed)++;
+                               continue;
+                       }
+
+                       if (unlikely(status != DSA_COMP_SUCCESS))
                                match_fault(desc, data);
                        complete_desc(desc, reason);
                        (*processed)++;
@@ -329,7 +331,14 @@ static int irq_process_work_list(struct idxd_irq_entry *irq_entry,
        spin_unlock_irqrestore(&irq_entry->list_lock, flags);
 
        list_for_each_entry(desc, &flist, list) {
-               if ((desc->completion->status & DSA_COMP_STATUS_MASK) != DSA_COMP_SUCCESS)
+               u8 status = desc->completion->status & DSA_COMP_STATUS_MASK;
+
+               if (unlikely(status == IDXD_COMP_DESC_ABORT)) {
+                       complete_desc(desc, IDXD_COMPLETE_ABORT);
+                       continue;
+               }
+
+               if (unlikely(status != DSA_COMP_SUCCESS))
                        match_fault(desc, data);
                complete_desc(desc, reason);
        }
index 19afb62..36c9c1a 100644 (file)
@@ -25,11 +25,10 @@ static struct idxd_desc *__get_desc(struct idxd_wq *wq, int idx, int cpu)
         * Descriptor completion vectors are 1...N for MSIX. We will round
         * robin through the N vectors.
         */
-       wq->vec_ptr = (wq->vec_ptr % idxd->num_wq_irqs) + 1;
+       wq->vec_ptr = desc->vector = (wq->vec_ptr % idxd->num_wq_irqs) + 1;
        if (!idxd->int_handles) {
                desc->hw->int_handle = wq->vec_ptr;
        } else {
-               desc->vector = wq->vec_ptr;
                /*
                 * int_handles are only for descriptor completion. However for device
                 * MSIX enumeration, vec 0 is used for misc interrupts. Therefore even
@@ -88,9 +87,64 @@ void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc)
        sbitmap_queue_clear(&wq->sbq, desc->id, cpu);
 }
 
+static struct idxd_desc *list_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
+                                        struct idxd_desc *desc)
+{
+       struct idxd_desc *d, *n;
+
+       lockdep_assert_held(&ie->list_lock);
+       list_for_each_entry_safe(d, n, &ie->work_list, list) {
+               if (d == desc) {
+                       list_del(&d->list);
+                       return d;
+               }
+       }
+
+       /*
+        * At this point, the desc needs to be aborted is held by the completion
+        * handler where it has taken it off the pending list but has not added to the
+        * work list. It will be cleaned up by the interrupt handler when it sees the
+        * IDXD_COMP_DESC_ABORT for completion status.
+        */
+       return NULL;
+}
+
+static void llist_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
+                            struct idxd_desc *desc)
+{
+       struct idxd_desc *d, *t, *found = NULL;
+       struct llist_node *head;
+       unsigned long flags;
+
+       desc->completion->status = IDXD_COMP_DESC_ABORT;
+       /*
+        * Grab the list lock so it will block the irq thread handler. This allows the
+        * abort code to locate the descriptor need to be aborted.
+        */
+       spin_lock_irqsave(&ie->list_lock, flags);
+       head = llist_del_all(&ie->pending_llist);
+       if (head) {
+               llist_for_each_entry_safe(d, t, head, llnode) {
+                       if (d == desc) {
+                               found = desc;
+                               continue;
+                       }
+                       list_add_tail(&desc->list, &ie->work_list);
+               }
+       }
+
+       if (!found)
+               found = list_abort_desc(wq, ie, desc);
+       spin_unlock_irqrestore(&ie->list_lock, flags);
+
+       if (found)
+               complete_desc(found, IDXD_COMPLETE_ABORT);
+}
+
 int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
 {
        struct idxd_device *idxd = wq->idxd;
+       struct idxd_irq_entry *ie = NULL;
        void __iomem *portal;
        int rc;
 
@@ -108,6 +162,16 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
         * even on UP because the recipient is a device.
         */
        wmb();
+
+       /*
+        * Pending the descriptor to the lockless list for the irq_entry
+        * that we designated the descriptor to.
+        */
+       if (desc->hw->flags & IDXD_OP_FLAG_RCI) {
+               ie = &idxd->irq_entries[desc->vector];
+               llist_add(&desc->llnode, &ie->pending_llist);
+       }
+
        if (wq_dedicated(wq)) {
                iosubmit_cmds512(portal, desc->hw, 1);
        } else {
@@ -118,29 +182,13 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
                 * device is not accepting descriptor at all.
                 */
                rc = enqcmds(portal, desc->hw);
-               if (rc < 0)
+               if (rc < 0) {
+                       if (ie)
+                               llist_abort_desc(wq, ie, desc);
                        return rc;
+               }
        }
 
        percpu_ref_put(&wq->wq_active);
-
-       /*
-        * Pending the descriptor to the lockless list for the irq_entry
-        * that we designated the descriptor to.
-        */
-       if (desc->hw->flags & IDXD_OP_FLAG_RCI) {
-               int vec;
-
-               /*
-                * If the driver is on host kernel, it would be the value
-                * assigned to interrupt handle, which is index for MSIX
-                * vector. If it's guest then can't use the int_handle since
-                * that is the index to IMS for the entire device. The guest
-                * device local index will be used.
-                */
-               vec = !idxd->int_handles ? desc->hw->int_handle : desc->vector;
-               llist_add(&desc->llnode, &idxd->irq_entries[vec].pending_llist);
-       }
-
        return 0;
 }
index 0460d58..bb4df63 100644 (file)
@@ -1744,8 +1744,6 @@ void idxd_unregister_devices(struct idxd_device *idxd)
 
                device_unregister(&group->conf_dev);
        }
-
-       device_unregister(&idxd->conf_dev);
 }
 
 int idxd_register_bus_type(void)
index 7f116bb..2ddc31e 100644 (file)
@@ -812,6 +812,8 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg(
                dma_length += sg_dma_len(sg);
        }
 
+       imxdma_config_write(chan, &imxdmac->config, direction);
+
        switch (imxdmac->word_size) {
        case DMA_SLAVE_BUSWIDTH_4_BYTES:
                if (sg_dma_len(sgl) & 3 || sgl->dma_address & 3)
index ec00b20..ac61ecd 100644 (file)
@@ -67,8 +67,12 @@ static struct dma_chan *of_dma_router_xlate(struct of_phandle_args *dma_spec,
                return NULL;
 
        ofdma_target = of_dma_find_controller(&dma_spec_target);
-       if (!ofdma_target)
-               return NULL;
+       if (!ofdma_target) {
+               ofdma->dma_router->route_free(ofdma->dma_router->dev,
+                                             route_data);
+               chan = ERR_PTR(-EPROBE_DEFER);
+               goto err;
+       }
 
        chan = ofdma_target->of_dma_xlate(&dma_spec_target, ofdma_target);
        if (IS_ERR_OR_NULL(chan)) {
@@ -89,6 +93,7 @@ static struct dma_chan *of_dma_router_xlate(struct of_phandle_args *dma_spec,
                }
        }
 
+err:
        /*
         * Need to put the node back since the ofdma->of_dma_route_allocate
         * has taken it for generating the new, translated dma_spec
index 8f7ceb6..1cc0690 100644 (file)
@@ -855,8 +855,8 @@ static int usb_dmac_probe(struct platform_device *pdev)
 
 error:
        of_dma_controller_free(pdev->dev.of_node);
-       pm_runtime_put(&pdev->dev);
 error_pm:
+       pm_runtime_put(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        return ret;
 }
index f54ecb1..7dd1d3d 100644 (file)
@@ -1200,7 +1200,7 @@ static int stm32_dma_alloc_chan_resources(struct dma_chan *c)
 
        chan->config_init = false;
 
-       ret = pm_runtime_get_sync(dmadev->ddev.dev);
+       ret = pm_runtime_resume_and_get(dmadev->ddev.dev);
        if (ret < 0)
                return ret;
 
@@ -1470,7 +1470,7 @@ static int stm32_dma_suspend(struct device *dev)
        struct stm32_dma_device *dmadev = dev_get_drvdata(dev);
        int id, ret, scr;
 
-       ret = pm_runtime_get_sync(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret < 0)
                return ret;
 
index ef0d055..a421643 100644 (file)
@@ -137,7 +137,7 @@ static void *stm32_dmamux_route_allocate(struct of_phandle_args *dma_spec,
 
        /* Set dma request */
        spin_lock_irqsave(&dmamux->lock, flags);
-       ret = pm_runtime_get_sync(&pdev->dev);
+       ret = pm_runtime_resume_and_get(&pdev->dev);
        if (ret < 0) {
                spin_unlock_irqrestore(&dmamux->lock, flags);
                goto error;
@@ -336,7 +336,7 @@ static int stm32_dmamux_suspend(struct device *dev)
        struct stm32_dmamux_data *stm32_dmamux = platform_get_drvdata(pdev);
        int i, ret;
 
-       ret = pm_runtime_get_sync(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret < 0)
                return ret;
 
@@ -361,7 +361,7 @@ static int stm32_dmamux_resume(struct device *dev)
        if (ret < 0)
                return ret;
 
-       ret = pm_runtime_get_sync(dev);
+       ret = pm_runtime_resume_and_get(dev);
        if (ret < 0)
                return ret;
 
index 16b1965..d6b8a20 100644 (file)
@@ -209,8 +209,8 @@ static int uniphier_xdmac_chan_stop(struct uniphier_xdmac_chan *xc)
        writel(0, xc->reg_ch_base + XDMAC_TSS);
 
        /* wait until transfer is stopped */
-       return readl_poll_timeout(xc->reg_ch_base + XDMAC_STAT, val,
-                                 !(val & XDMAC_STAT_TENF), 100, 1000);
+       return readl_poll_timeout_atomic(xc->reg_ch_base + XDMAC_STAT, val,
+                                        !(val & XDMAC_STAT_TENF), 100, 1000);
 }
 
 /* xc->vc.lock must be held by caller */
index 75c0b8e..4b9530a 100644 (file)
@@ -394,6 +394,7 @@ struct xilinx_dma_tx_descriptor {
  * @genlock: Support genlock mode
  * @err: Channel has errors
  * @idle: Check for channel idle
+ * @terminating: Check for channel being synchronized by user
  * @tasklet: Cleanup work after irq
  * @config: Device configuration info
  * @flush_on_fsync: Flush on Frame sync
@@ -431,6 +432,7 @@ struct xilinx_dma_chan {
        bool genlock;
        bool err;
        bool idle;
+       bool terminating;
        struct tasklet_struct tasklet;
        struct xilinx_vdma_config config;
        bool flush_on_fsync;
@@ -1049,6 +1051,13 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
                /* Run any dependencies, then free the descriptor */
                dma_run_dependencies(&desc->async_tx);
                xilinx_dma_free_tx_descriptor(chan, desc);
+
+               /*
+                * While we ran a callback the user called a terminate function,
+                * which takes care of cleaning up any remaining descriptors
+                */
+               if (chan->terminating)
+                       break;
        }
 
        spin_unlock_irqrestore(&chan->lock, flags);
@@ -1965,6 +1974,8 @@ static dma_cookie_t xilinx_dma_tx_submit(struct dma_async_tx_descriptor *tx)
        if (desc->cyclic)
                chan->cyclic = true;
 
+       chan->terminating = false;
+
        spin_unlock_irqrestore(&chan->lock, flags);
 
        return cookie;
@@ -2436,6 +2447,7 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan)
 
        xilinx_dma_chan_reset(chan);
        /* Remove and free all of the descriptors in the lists */
+       chan->terminating = true;
        xilinx_dma_free_descriptors(chan);
        chan->idle = true;
 
index ed10da5..a5bf4c3 100644 (file)
@@ -212,10 +212,9 @@ static int tee_bnxt_fw_probe(struct device *dev)
 
        pvt_data.dev = dev;
 
-       fw_shm_pool = tee_shm_alloc(pvt_data.ctx, MAX_SHM_MEM_SZ,
-                                   TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+       fw_shm_pool = tee_shm_alloc_kernel_buf(pvt_data.ctx, MAX_SHM_MEM_SZ);
        if (IS_ERR(fw_shm_pool)) {
-               dev_err(pvt_data.dev, "tee_shm_alloc failed\n");
+               dev_err(pvt_data.dev, "tee_shm_alloc_kernel_buf failed\n");
                err = PTR_ERR(fw_shm_pool);
                goto out_sess;
        }
@@ -242,6 +241,14 @@ static int tee_bnxt_fw_remove(struct device *dev)
        return 0;
 }
 
+static void tee_bnxt_fw_shutdown(struct device *dev)
+{
+       tee_shm_free(pvt_data.fw_shm_pool);
+       tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
+       tee_client_close_context(pvt_data.ctx);
+       pvt_data.ctx = NULL;
+}
+
 static const struct tee_client_device_id tee_bnxt_fw_id_table[] = {
        {UUID_INIT(0x6272636D, 0x2019, 0x0716,
                    0x42, 0x43, 0x4D, 0x5F, 0x53, 0x43, 0x48, 0x49)},
@@ -257,6 +264,7 @@ static struct tee_client_driver tee_bnxt_fw_driver = {
                .bus            = &tee_bus_type,
                .probe          = tee_bnxt_fw_probe,
                .remove         = tee_bnxt_fw_remove,
+               .shutdown       = tee_bnxt_fw_shutdown,
        },
 };
 
index 7bf0a7a..2363fee 100644 (file)
@@ -35,15 +35,48 @@ efi_status_t check_platform_features(void)
 }
 
 /*
- * Although relocatable kernels can fix up the misalignment with respect to
- * MIN_KIMG_ALIGN, the resulting virtual text addresses are subtly out of
- * sync with those recorded in the vmlinux when kaslr is disabled but the
- * image required relocation anyway. Therefore retain 2M alignment unless
- * KASLR is in use.
+ * Distro versions of GRUB may ignore the BSS allocation entirely (i.e., fail
+ * to provide space, and fail to zero it). Check for this condition by double
+ * checking that the first and the last byte of the image are covered by the
+ * same EFI memory map entry.
  */
-static u64 min_kimg_align(void)
+static bool check_image_region(u64 base, u64 size)
 {
-       return efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
+       unsigned long map_size, desc_size, buff_size;
+       efi_memory_desc_t *memory_map;
+       struct efi_boot_memmap map;
+       efi_status_t status;
+       bool ret = false;
+       int map_offset;
+
+       map.map =       &memory_map;
+       map.map_size =  &map_size;
+       map.desc_size = &desc_size;
+       map.desc_ver =  NULL;
+       map.key_ptr =   NULL;
+       map.buff_size = &buff_size;
+
+       status = efi_get_memory_map(&map);
+       if (status != EFI_SUCCESS)
+               return false;
+
+       for (map_offset = 0; map_offset < map_size; map_offset += desc_size) {
+               efi_memory_desc_t *md = (void *)memory_map + map_offset;
+               u64 end = md->phys_addr + md->num_pages * EFI_PAGE_SIZE;
+
+               /*
+                * Find the region that covers base, and return whether
+                * it covers base+size bytes.
+                */
+               if (base >= md->phys_addr && base < end) {
+                       ret = (base + size) <= end;
+                       break;
+               }
+       }
+
+       efi_bs_call(free_pool, memory_map);
+
+       return ret;
 }
 
 efi_status_t handle_kernel_image(unsigned long *image_addr,
@@ -56,6 +89,16 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
        unsigned long kernel_size, kernel_memsize = 0;
        u32 phys_seed = 0;
 
+       /*
+        * Although relocatable kernels can fix up the misalignment with
+        * respect to MIN_KIMG_ALIGN, the resulting virtual text addresses are
+        * subtly out of sync with those recorded in the vmlinux when kaslr is
+        * disabled but the image required relocation anyway. Therefore retain
+        * 2M alignment if KASLR was explicitly disabled, even if it was not
+        * going to be activated to begin with.
+        */
+       u64 min_kimg_align = efi_nokaslr ? MIN_KIMG_ALIGN : EFI_KIMG_ALIGN;
+
        if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) {
                if (!efi_nokaslr) {
                        status = efi_get_random_bytes(sizeof(phys_seed),
@@ -76,6 +119,10 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
        if (image->image_base != _text)
                efi_err("FIRMWARE BUG: efi_loaded_image_t::image_base has bogus value\n");
 
+       if (!IS_ALIGNED((u64)_text, EFI_KIMG_ALIGN))
+               efi_err("FIRMWARE BUG: kernel image not aligned on %ldk boundary\n",
+                       EFI_KIMG_ALIGN >> 10);
+
        kernel_size = _edata - _text;
        kernel_memsize = kernel_size + (_end - _edata);
        *reserve_size = kernel_memsize;
@@ -85,14 +132,18 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                 * If KASLR is enabled, and we have some randomness available,
                 * locate the kernel at a randomized offset in physical memory.
                 */
-               status = efi_random_alloc(*reserve_size, min_kimg_align(),
+               status = efi_random_alloc(*reserve_size, min_kimg_align,
                                          reserve_addr, phys_seed);
+               if (status != EFI_SUCCESS)
+                       efi_warn("efi_random_alloc() failed: 0x%lx\n", status);
        } else {
                status = EFI_OUT_OF_RESOURCES;
        }
 
        if (status != EFI_SUCCESS) {
-               if (IS_ALIGNED((u64)_text, min_kimg_align())) {
+               if (!check_image_region((u64)_text, kernel_memsize)) {
+                       efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");
+               } else if (IS_ALIGNED((u64)_text, min_kimg_align)) {
                        /*
                         * Just execute from wherever we were loaded by the
                         * UEFI PE/COFF loader if the alignment is suitable.
@@ -103,7 +154,7 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                }
 
                status = efi_allocate_pages_aligned(*reserve_size, reserve_addr,
-                                                   ULONG_MAX, min_kimg_align());
+                                                   ULONG_MAX, min_kimg_align);
 
                if (status != EFI_SUCCESS) {
                        efi_err("Failed to relocate kernel\n");
index a408df4..724155b 100644 (file)
@@ -30,6 +30,8 @@ static unsigned long get_entry_num_slots(efi_memory_desc_t *md,
 
        region_end = min(md->phys_addr + md->num_pages * EFI_PAGE_SIZE - 1,
                         (u64)ULONG_MAX);
+       if (region_end < size)
+               return 0;
 
        first_slot = round_up(md->phys_addr, align);
        last_slot = round_down(region_end - size + 1, align);
index 4299145..587c82b 100644 (file)
@@ -953,6 +953,8 @@ static int fme_perf_offline_cpu(unsigned int cpu, struct hlist_node *node)
                return 0;
 
        priv->cpu = target;
+       perf_pmu_migrate_context(&priv->pmu, cpu, target);
+
        return 0;
 }
 
index 6cc0d4f..a9ce3b2 100644 (file)
@@ -1040,7 +1040,7 @@ void amdgpu_acpi_detect(void)
  */
 bool amdgpu_acpi_is_s0ix_supported(struct amdgpu_device *adev)
 {
-#if defined(CONFIG_AMD_PMC) || defined(CONFIG_AMD_PMC_MODULE)
+#if IS_ENABLED(CONFIG_AMD_PMC) && IS_ENABLED(CONFIG_SUSPEND)
        if (acpi_gbl_FADT.flags & ACPI_FADT_LOW_POWER_S0) {
                if (adev->flags & AMD_IS_APU)
                        return pm_suspend_target_state == PM_SUSPEND_TO_IDLE;
index 3b5d131..8f53837 100644 (file)
@@ -468,6 +468,46 @@ bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *ade
        return (fw_cap & ATOM_FIRMWARE_CAP_DYNAMIC_BOOT_CFG_ENABLE) ? true : false;
 }
 
+/*
+ * Helper function to query RAS EEPROM address
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Return true if vbios supports ras rom address reporting
+ */
+bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev, uint8_t* i2c_address)
+{
+       struct amdgpu_mode_info *mode_info = &adev->mode_info;
+       int index;
+       u16 data_offset, size;
+       union firmware_info *firmware_info;
+       u8 frev, crev;
+
+       if (i2c_address == NULL)
+               return false;
+
+       *i2c_address = 0;
+
+       index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
+                       firmwareinfo);
+
+       if (amdgpu_atom_parse_data_header(adev->mode_info.atom_context,
+                               index, &size, &frev, &crev, &data_offset)) {
+               /* support firmware_info 3.4 + */
+               if ((frev == 3 && crev >=4) || (frev > 3)) {
+                       firmware_info = (union firmware_info *)
+                               (mode_info->atom_context->bios + data_offset);
+                       *i2c_address = firmware_info->v34.ras_rom_i2c_slave_addr;
+               }
+       }
+
+       if (*i2c_address != 0)
+               return true;
+
+       return false;
+}
+
+
 union smu_info {
        struct atom_smu_info_v3_1 v31;
 };
index 1bbbb19..751248b 100644 (file)
@@ -36,6 +36,7 @@ int amdgpu_atomfirmware_get_clock_info(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_gfx_info(struct amdgpu_device *adev);
 bool amdgpu_atomfirmware_mem_ecc_supported(struct amdgpu_device *adev);
 bool amdgpu_atomfirmware_sram_ecc_supported(struct amdgpu_device *adev);
+bool amdgpu_atomfirmware_ras_rom_addr(struct amdgpu_device *adev, uint8_t* i2c_address);
 bool amdgpu_atomfirmware_mem_training_supported(struct amdgpu_device *adev);
 bool amdgpu_atomfirmware_dynamic_boot_config_supported(struct amdgpu_device *adev);
 int amdgpu_atomfirmware_get_fw_reserved_fb_size(struct amdgpu_device *adev);
index f3fd5ec..f944ed8 100644 (file)
@@ -2777,12 +2777,11 @@ static void amdgpu_device_delay_enable_gfx_off(struct work_struct *work)
        struct amdgpu_device *adev =
                container_of(work, struct amdgpu_device, gfx.gfx_off_delay_work.work);
 
-       mutex_lock(&adev->gfx.gfx_off_mutex);
-       if (!adev->gfx.gfx_off_state && !adev->gfx.gfx_off_req_count) {
-               if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, true))
-                       adev->gfx.gfx_off_state = true;
-       }
-       mutex_unlock(&adev->gfx.gfx_off_mutex);
+       WARN_ON_ONCE(adev->gfx.gfx_off_state);
+       WARN_ON_ONCE(adev->gfx.gfx_off_req_count);
+
+       if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, true))
+               adev->gfx.gfx_off_state = true;
 }
 
 /**
index 43e7b61..ada7bc1 100644 (file)
@@ -299,6 +299,9 @@ int amdgpu_discovery_reg_base_init(struct amdgpu_device *adev)
                                  ip->major, ip->minor,
                                  ip->revision);
 
+                       if (le16_to_cpu(ip->hw_id) == VCN_HWID)
+                               adev->vcn.num_vcn_inst++;
+
                        for (k = 0; k < num_base_address; k++) {
                                /*
                                 * convert the endianness of base addresses in place,
@@ -385,7 +388,7 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
 {
        struct binary_header *bhdr;
        struct harvest_table *harvest_info;
-       int i;
+       int i, vcn_harvest_count = 0;
 
        bhdr = (struct binary_header *)adev->mman.discovery_bin;
        harvest_info = (struct harvest_table *)(adev->mman.discovery_bin +
@@ -397,8 +400,7 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
 
                switch (le32_to_cpu(harvest_info->list[i].hw_id)) {
                case VCN_HWID:
-                       adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
-                       adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
+                       vcn_harvest_count++;
                        break;
                case DMU_HWID:
                        adev->harvest_ip_mask |= AMD_HARVEST_IP_DMU_MASK;
@@ -407,6 +409,10 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev)
                        break;
                }
        }
+       if (vcn_harvest_count == adev->vcn.num_vcn_inst) {
+               adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK;
+               adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK;
+       }
 }
 
 int amdgpu_discovery_get_gfx_info(struct amdgpu_device *adev)
index 361b86b..971c5b8 100644 (file)
@@ -1213,6 +1213,13 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x740F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN|AMD_EXP_HW_SUPPORT},
 
+       /* BEIGE_GOBY */
+       {0x1002, 0x7420, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+       {0x1002, 0x7421, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+       {0x1002, 0x7422, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+       {0x1002, 0x7423, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+       {0x1002, 0x743F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_BEIGE_GOBY},
+
        {0, 0, 0}
 };
 
@@ -1564,6 +1571,8 @@ static int amdgpu_pmops_runtime_suspend(struct device *dev)
                pci_ignore_hotplug(pdev);
                pci_set_power_state(pdev, PCI_D3cold);
                drm_dev->switch_power_state = DRM_SWITCH_POWER_DYNAMIC_OFF;
+       } else if (amdgpu_device_supports_boco(drm_dev)) {
+               /* nothing to do */
        } else if (amdgpu_device_supports_baco(drm_dev)) {
                amdgpu_device_baco_enter(drm_dev);
        }
index a0be077..b4ced45 100644 (file)
@@ -563,24 +563,38 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable)
 
        mutex_lock(&adev->gfx.gfx_off_mutex);
 
-       if (!enable)
-               adev->gfx.gfx_off_req_count++;
-       else if (adev->gfx.gfx_off_req_count > 0)
+       if (enable) {
+               /* If the count is already 0, it means there's an imbalance bug somewhere.
+                * Note that the bug may be in a different caller than the one which triggers the
+                * WARN_ON_ONCE.
+                */
+               if (WARN_ON_ONCE(adev->gfx.gfx_off_req_count == 0))
+                       goto unlock;
+
                adev->gfx.gfx_off_req_count--;
 
-       if (enable && !adev->gfx.gfx_off_state && !adev->gfx.gfx_off_req_count) {
-               schedule_delayed_work(&adev->gfx.gfx_off_delay_work, GFX_OFF_DELAY_ENABLE);
-       } else if (!enable && adev->gfx.gfx_off_state) {
-               if (!amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, false)) {
-                       adev->gfx.gfx_off_state = false;
+               if (adev->gfx.gfx_off_req_count == 0 && !adev->gfx.gfx_off_state)
+                       schedule_delayed_work(&adev->gfx.gfx_off_delay_work, GFX_OFF_DELAY_ENABLE);
+       } else {
+               if (adev->gfx.gfx_off_req_count == 0) {
+                       cancel_delayed_work_sync(&adev->gfx.gfx_off_delay_work);
+
+                       if (adev->gfx.gfx_off_state &&
+                           !amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GFX, false)) {
+                               adev->gfx.gfx_off_state = false;
 
-                       if (adev->gfx.funcs->init_spm_golden) {
-                               dev_dbg(adev->dev, "GFXOFF is disabled, re-init SPM golden settings\n");
-                               amdgpu_gfx_init_spm_golden(adev);
+                               if (adev->gfx.funcs->init_spm_golden) {
+                                       dev_dbg(adev->dev,
+                                               "GFXOFF is disabled, re-init SPM golden settings\n");
+                                       amdgpu_gfx_init_spm_golden(adev);
+                               }
                        }
                }
+
+               adev->gfx.gfx_off_req_count++;
        }
 
+unlock:
        mutex_unlock(&adev->gfx.gfx_off_mutex);
 }
 
index 795fa74..92c8e6e 100644 (file)
@@ -920,11 +920,6 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
                        return -EINVAL;
        }
 
-       /* This assumes only APU display buffers are pinned with (VRAM|GTT).
-        * See function amdgpu_display_supported_domains()
-        */
-       domain = amdgpu_bo_get_preferred_pin_domain(adev, domain);
-
        if (bo->tbo.pin_count) {
                uint32_t mem_type = bo->tbo.resource->mem_type;
                uint32_t mem_flags = bo->tbo.resource->placement;
@@ -949,6 +944,11 @@ int amdgpu_bo_pin_restricted(struct amdgpu_bo *bo, u32 domain,
                return 0;
        }
 
+       /* This assumes only APU display buffers are pinned with (VRAM|GTT).
+        * See function amdgpu_display_supported_domains()
+        */
+       domain = amdgpu_bo_get_preferred_pin_domain(adev, domain);
+
        if (bo->tbo.base.import_attach)
                dma_buf_pin(bo->tbo.base.import_attach);
 
index f40c871..38222de 100644 (file)
@@ -26,6 +26,7 @@
 #include "amdgpu_ras.h"
 #include <linux/bits.h>
 #include "atom.h"
+#include "amdgpu_atomfirmware.h"
 
 #define EEPROM_I2C_TARGET_ADDR_VEGA20          0xA0
 #define EEPROM_I2C_TARGET_ADDR_ARCTURUS                0xA8
@@ -96,6 +97,9 @@ static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
        if (!i2c_addr)
                return false;
 
+       if (amdgpu_atomfirmware_ras_rom_addr(adev, (uint8_t*)i2c_addr))
+               return true;
+
        switch (adev->asic_type) {
        case CHIP_VEGA20:
                *i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20;
index 59e0fef..acfa207 100644 (file)
@@ -54,11 +54,12 @@ static inline void amdgpu_res_first(struct ttm_resource *res,
 {
        struct drm_mm_node *node;
 
-       if (!res) {
+       if (!res || res->mem_type == TTM_PL_SYSTEM) {
                cur->start = start;
                cur->size = size;
                cur->remaining = size;
                cur->node = NULL;
+               WARN_ON(res && start + size > res->num_pages << PAGE_SHIFT);
                return;
        }
 
index 044076e..6a23c68 100644 (file)
@@ -1295,6 +1295,16 @@ static bool is_raven_kicker(struct amdgpu_device *adev)
                return false;
 }
 
+static bool check_if_enlarge_doorbell_range(struct amdgpu_device *adev)
+{
+       if ((adev->asic_type == CHIP_RENOIR) &&
+           (adev->gfx.me_fw_version >= 0x000000a5) &&
+           (adev->gfx.me_feature_version >= 52))
+               return true;
+       else
+               return false;
+}
+
 static void gfx_v9_0_check_if_need_gfxoff(struct amdgpu_device *adev)
 {
        if (gfx_v9_0_should_disable_gfxoff(adev->pdev))
@@ -3675,7 +3685,16 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring)
        if (ring->use_doorbell) {
                WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER,
                                        (adev->doorbell_index.kiq * 2) << 2);
-               WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
+               /* If GC has entered CGPG, ringing doorbell > first page
+                * doesn't wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to
+                * workaround this issue. And this change has to align with firmware
+                * update.
+                */
+               if (check_if_enlarge_doorbell_range(adev))
+                       WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
+                                       (adev->doorbell.size - 4));
+               else
+                       WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
                                        (adev->doorbell_index.userqueue_end * 2) << 2);
        }
 
index c7b364e..e883731 100644 (file)
@@ -3026,6 +3026,14 @@ svm_range_get_attr(struct kfd_process *p, uint64_t start, uint64_t size,
        pr_debug("svms 0x%p [0x%llx 0x%llx] nattr 0x%x\n", &p->svms, start,
                 start + size - 1, nattr);
 
+       /* Flush pending deferred work to avoid racing with deferred actions from
+        * previous memory map changes (e.g. munmap). Concurrent memory map changes
+        * can still race with get_attr because we don't hold the mmap lock. But that
+        * would be a race condition in the application anyway, and undefined
+        * behaviour is acceptable in that case.
+        */
+       flush_work(&p->svms.deferred_list_work);
+
        mmap_read_lock(mm);
        if (!svm_range_is_valid(mm, start, size)) {
                pr_debug("invalid range\n");
index b53f49a..afa96c8 100644 (file)
@@ -1548,6 +1548,7 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
        }
 
        hdr = (const struct dmcub_firmware_header_v1_0 *)adev->dm.dmub_fw->data;
+       adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);
 
        if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
                adev->firmware.ucode[AMDGPU_UCODE_ID_DMCUB].ucode_id =
@@ -1561,7 +1562,6 @@ static int dm_dmub_sw_init(struct amdgpu_device *adev)
                         adev->dm.dmcub_fw_version);
        }
 
-       adev->dm.dmcub_fw_version = le32_to_cpu(hdr->header.ucode_version);
 
        adev->dm.dmub_srv = kzalloc(sizeof(*adev->dm.dmub_srv), GFP_KERNEL);
        dmub_srv = adev->dm.dmub_srv;
@@ -9605,7 +9605,12 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                } else if (amdgpu_freesync_vid_mode && aconnector &&
                           is_freesync_video_mode(&new_crtc_state->mode,
                                                  aconnector)) {
-                       set_freesync_fixed_config(dm_new_crtc_state);
+                       struct drm_display_mode *high_mode;
+
+                       high_mode = get_highest_refresh_rate_mode(aconnector, false);
+                       if (!drm_mode_equal(&new_crtc_state->mode, high_mode)) {
+                               set_freesync_fixed_config(dm_new_crtc_state);
+                       }
                }
 
                ret = dm_atomic_get_state(state, &dm_state);
index 40f617b..4aba0e8 100644 (file)
@@ -584,7 +584,7 @@ static void amdgpu_dm_irq_schedule_work(struct amdgpu_device *adev,
                handler_data = container_of(handler_list->next, struct amdgpu_dm_irq_handler_data, list);
 
                /*allocate a new amdgpu_dm_irq_handler_data*/
-               handler_data_add = kzalloc(sizeof(*handler_data), GFP_KERNEL);
+               handler_data_add = kzalloc(sizeof(*handler_data), GFP_ATOMIC);
                if (!handler_data_add) {
                        DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n");
                        return;
index c6f494f..6185f94 100644 (file)
@@ -66,9 +66,11 @@ int rn_get_active_display_cnt_wa(
        for (i = 0; i < context->stream_count; i++) {
                const struct dc_stream_state *stream = context->streams[i];
 
+               /* Extend the WA to DP for Linux*/
                if (stream->signal == SIGNAL_TYPE_HDMI_TYPE_A ||
                                stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
-                               stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
+                               stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK ||
+                               stream->signal == SIGNAL_TYPE_DISPLAY_PORT)
                        tmds_present = true;
        }
 
index 605e297..a30283f 100644 (file)
@@ -1530,6 +1530,12 @@ void dc_z10_restore(struct dc *dc)
        if (dc->hwss.z10_restore)
                dc->hwss.z10_restore(dc);
 }
+
+void dc_z10_save_init(struct dc *dc)
+{
+       if (dc->hwss.z10_save_init)
+               dc->hwss.z10_save_init(dc);
+}
 #endif
 /*
  * Applies given context to HW and copy it into current context.
index 9fb8c46..a6d0fd2 100644 (file)
@@ -3602,29 +3602,12 @@ static bool dpcd_read_sink_ext_caps(struct dc_link *link)
 bool dp_retrieve_lttpr_cap(struct dc_link *link)
 {
        uint8_t lttpr_dpcd_data[6];
-       bool vbios_lttpr_enable = false;
-       bool vbios_lttpr_interop = false;
-       struct dc_bios *bios = link->dc->ctx->dc_bios;
+       bool vbios_lttpr_enable = link->dc->caps.vbios_lttpr_enable;
+       bool vbios_lttpr_interop = link->dc->caps.vbios_lttpr_aware;
        enum dc_status status = DC_ERROR_UNEXPECTED;
        bool is_lttpr_present = false;
 
        memset(lttpr_dpcd_data, '\0', sizeof(lttpr_dpcd_data));
-       /* Query BIOS to determine if LTTPR functionality is forced on by system */
-       if (bios->funcs->get_lttpr_caps) {
-               enum bp_result bp_query_result;
-               uint8_t is_vbios_lttpr_enable = 0;
-
-               bp_query_result = bios->funcs->get_lttpr_caps(bios, &is_vbios_lttpr_enable);
-               vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
-       }
-
-       if (bios->funcs->get_lttpr_interop) {
-               enum bp_result bp_query_result;
-               uint8_t is_vbios_interop_enabled = 0;
-
-               bp_query_result = bios->funcs->get_lttpr_interop(bios, &is_vbios_interop_enabled);
-               vbios_lttpr_interop = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled;
-       }
 
        /*
         * Logic to determine LTTPR mode
index f2b39ec..cde8ed2 100644 (file)
@@ -47,6 +47,9 @@ int dc_setup_system_context(struct dc *dc, struct dc_phy_addr_space_config *pa_c
                 */
                memcpy(&dc->vm_pa_config, pa_config, sizeof(struct dc_phy_addr_space_config));
                dc->vm_pa_config.valid = true;
+#if defined(CONFIG_DRM_AMD_DC_DCN)
+               dc_z10_save_init(dc);
+#endif
        }
 
        return num_vmids;
index 8dcea8f..21d7828 100644 (file)
@@ -183,6 +183,8 @@ struct dc_caps {
        unsigned int cursor_cache_size;
        struct dc_plane_cap planes[MAX_PLANES];
        struct dc_color_caps color;
+       bool vbios_lttpr_aware;
+       bool vbios_lttpr_enable;
 };
 
 struct dc_bug_wa {
@@ -1336,6 +1338,7 @@ void dc_hardware_release(struct dc *dc);
 bool dc_set_psr_allow_active(struct dc *dc, bool enable);
 #if defined(CONFIG_DRM_AMD_DC_DCN)
 void dc_z10_restore(struct dc *dc);
+void dc_z10_save_init(struct dc *dc);
 #endif
 
 bool dc_enable_dmub_notifications(struct dc *dc);
index 7fa9fc6..f6e747f 100644 (file)
@@ -464,7 +464,7 @@ void optc2_lock_doublebuffer_enable(struct timing_generator *optc)
 
        REG_UPDATE_2(OTG_GLOBAL_CONTROL1,
                        MASTER_UPDATE_LOCK_DB_X,
-                       h_blank_start - 200 - 1,
+                       (h_blank_start - 200 - 1) / optc1->opp_count,
                        MASTER_UPDATE_LOCK_DB_Y,
                        v_blank_start - 1);
 }
index 596c97d..28e15eb 100644 (file)
@@ -1788,7 +1788,6 @@ static bool dcn30_split_stream_for_mpc_or_odm(
                }
                pri_pipe->next_odm_pipe = sec_pipe;
                sec_pipe->prev_odm_pipe = pri_pipe;
-               ASSERT(sec_pipe->top_pipe == NULL);
 
                if (!sec_pipe->top_pipe)
                        sec_pipe->stream_res.opp = pool->opps[pipe_idx];
@@ -2617,6 +2616,26 @@ static bool dcn30_resource_construct(
        dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
        dc->caps.color.mpc.ocsc = 1;
 
+       /* read VBIOS LTTPR caps */
+       {
+               if (ctx->dc_bios->funcs->get_lttpr_caps) {
+                       enum bp_result bp_query_result;
+                       uint8_t is_vbios_lttpr_enable = 0;
+
+                       bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
+                       dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
+               }
+
+               if (ctx->dc_bios->funcs->get_lttpr_interop) {
+                       enum bp_result bp_query_result;
+                       uint8_t is_vbios_interop_enabled = 0;
+
+                       bp_query_result = ctx->dc_bios->funcs->get_lttpr_interop(ctx->dc_bios,
+                                       &is_vbios_interop_enabled);
+                       dc->caps.vbios_lttpr_aware = (bp_query_result == BP_RESULT_OK) && !!is_vbios_interop_enabled;
+               }
+       }
+
        if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
                dc->debug = debug_defaults_drv;
        else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
index 9776d17..912285f 100644 (file)
@@ -1622,106 +1622,12 @@ static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
        dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
 }
 
-static void calculate_wm_set_for_vlevel(
-               int vlevel,
-               struct wm_range_table_entry *table_entry,
-               struct dcn_watermarks *wm_set,
-               struct display_mode_lib *dml,
-               display_e2e_pipe_params_st *pipes,
-               int pipe_cnt)
-{
-       double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
-
-       ASSERT(vlevel < dml->soc.num_states);
-       /* only pipe 0 is read for voltage and dcf/soc clocks */
-       pipes[0].clks_cfg.voltage = vlevel;
-       pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
-       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;
-       wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
-       wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
-       wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
-       wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
-       wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
-       wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
-       dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
-
-}
-
-static void dcn301_calculate_wm_and_dlg(
-               struct dc *dc, struct dc_state *context,
-               display_e2e_pipe_params_st *pipes,
-               int pipe_cnt,
-               int vlevel_req)
-{
-       int i, pipe_idx;
-       int vlevel, vlevel_max;
-       struct wm_range_table_entry *table_entry;
-       struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
-
-       ASSERT(bw_params);
-
-       vlevel_max = bw_params->clk_table.num_entries - 1;
-
-       /* WM Set D */
-       table_entry = &bw_params->wm_table.entries[WM_D];
-       if (table_entry->wm_type == WM_TYPE_RETRAINING)
-               vlevel = 0;
-       else
-               vlevel = vlevel_max;
-       calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
-                                               &context->bw_ctx.dml, pipes, pipe_cnt);
-       /* WM Set C */
-       table_entry = &bw_params->wm_table.entries[WM_C];
-       vlevel = min(max(vlevel_req, 2), vlevel_max);
-       calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
-                                               &context->bw_ctx.dml, pipes, pipe_cnt);
-       /* WM Set B */
-       table_entry = &bw_params->wm_table.entries[WM_B];
-       vlevel = min(max(vlevel_req, 1), vlevel_max);
-       calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
-                                               &context->bw_ctx.dml, pipes, pipe_cnt);
-
-       /* WM Set A */
-       table_entry = &bw_params->wm_table.entries[WM_A];
-       vlevel = min(vlevel_req, vlevel_max);
-       calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
-                                               &context->bw_ctx.dml, pipes, pipe_cnt);
-
-       for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
-               if (!context->res_ctx.pipe_ctx[i].stream)
-                       continue;
-
-               pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
-               pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
-
-               if (dc->config.forced_clocks) {
-                       pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
-                       pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
-               }
-               if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
-                       pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
-               if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
-                       pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
-
-               pipe_idx++;
-       }
-
-       dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
-}
-
 static struct resource_funcs dcn301_res_pool_funcs = {
        .destroy = dcn301_destroy_resource_pool,
        .link_enc_create = dcn301_link_encoder_create,
        .panel_cntl_create = dcn301_panel_cntl_create,
        .validate_bandwidth = dcn30_validate_bandwidth,
-       .calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg,
+       .calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg,
        .update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
        .populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
        .acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
index 833ab13..dc7823d 100644 (file)
@@ -146,8 +146,8 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_03_soc = {
 
                .min_dcfclk = 500.0, /* TODO: set this to actual min DCFCLK */
                .num_states = 1,
-               .sr_exit_time_us = 26.5,
-               .sr_enter_plus_exit_time_us = 31,
+               .sr_exit_time_us = 35.5,
+               .sr_enter_plus_exit_time_us = 40,
                .urgent_latency_us = 4.0,
                .urgent_latency_pixel_data_only_us = 4.0,
                .urgent_latency_pixel_mixed_with_vm_data_us = 4.0,
index 6ac6faf..8a2119d 100644 (file)
@@ -404,6 +404,18 @@ void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx)
                        &pipe_ctx->stream_res.encoder_info_frame);
        }
 }
+void dcn31_z10_save_init(struct dc *dc)
+{
+       union dmub_rb_cmd cmd;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.dcn_restore.header.type = DMUB_CMD__IDLE_OPT;
+       cmd.dcn_restore.header.sub_type = DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT;
+
+       dc_dmub_srv_cmd_queue(dc->ctx->dmub_srv, &cmd);
+       dc_dmub_srv_cmd_execute(dc->ctx->dmub_srv);
+       dc_dmub_srv_wait_idle(dc->ctx->dmub_srv);
+}
 
 void dcn31_z10_restore(struct dc *dc)
 {
index 40dfebe..140435e 100644 (file)
@@ -44,6 +44,7 @@ void dcn31_enable_power_gating_plane(
 void dcn31_update_info_frame(struct pipe_ctx *pipe_ctx);
 
 void dcn31_z10_restore(struct dc *dc);
+void dcn31_z10_save_init(struct dc *dc);
 
 void dcn31_hubp_pg_control(struct dce_hwseq *hws, unsigned int hubp_inst, bool power_on);
 int dcn31_init_sys_ctx(struct dce_hwseq *hws, struct dc *dc, struct dc_phy_addr_space_config *pa_config);
index aaf2dbd..b30d923 100644 (file)
@@ -97,6 +97,7 @@ static const struct hw_sequencer_funcs dcn31_funcs = {
        .set_abm_immediate_disable = dcn21_set_abm_immediate_disable,
        .set_pipe = dcn21_set_pipe,
        .z10_restore = dcn31_z10_restore,
+       .z10_save_init = dcn31_z10_save_init,
        .is_abm_supported = dcn31_is_abm_supported,
        .set_disp_pattern_generator = dcn30_set_disp_pattern_generator,
        .update_visual_confirm_color = dcn20_update_visual_confirm_color,
index 38c010a..cd3248d 100644 (file)
@@ -1968,6 +1968,22 @@ static bool dcn31_resource_construct(
        dc->caps.color.mpc.ogam_rom_caps.hlg = 0;
        dc->caps.color.mpc.ocsc = 1;
 
+       /* read VBIOS LTTPR caps */
+       {
+               if (ctx->dc_bios->funcs->get_lttpr_caps) {
+                       enum bp_result bp_query_result;
+                       uint8_t is_vbios_lttpr_enable = 0;
+
+                       bp_query_result = ctx->dc_bios->funcs->get_lttpr_caps(ctx->dc_bios, &is_vbios_lttpr_enable);
+                       dc->caps.vbios_lttpr_enable = (bp_query_result == BP_RESULT_OK) && !!is_vbios_lttpr_enable;
+               }
+
+               /* interop bit is implicit */
+               {
+                       dc->caps.vbios_lttpr_aware = true;
+               }
+       }
+
        if (dc->ctx->dce_environment == DCE_ENV_PRODUCTION_DRV)
                dc->debug = debug_defaults_drv;
        else if (dc->ctx->dce_environment == DCE_ENV_FPGA_MAXIMUS) {
index 5ab008e..ad5f2ad 100644 (file)
@@ -237,6 +237,7 @@ struct hw_sequencer_funcs {
                        int width, int height, int offset);
 
        void (*z10_restore)(struct dc *dc);
+       void (*z10_save_init)(struct dc *dc);
 
        void (*update_visual_confirm_color)(struct dc *dc,
                        struct pipe_ctx *pipe_ctx,
index 7c4734f..7fafb8d 100644 (file)
@@ -856,6 +856,11 @@ enum dmub_cmd_idle_opt_type {
         * DCN hardware restore.
         */
        DMUB_CMD__IDLE_OPT_DCN_RESTORE = 0,
+
+       /**
+        * DCN hardware save.
+        */
+       DMUB_CMD__IDLE_OPT_DCN_SAVE_INIT = 1
 };
 
 /**
index 973de34..27c7fa3 100644 (file)
@@ -267,11 +267,13 @@ void dmub_dcn31_set_outbox1_rptr(struct dmub_srv *dmub, uint32_t rptr_offset)
 
 bool dmub_dcn31_is_hw_init(struct dmub_srv *dmub)
 {
-       uint32_t is_hw_init;
+       union dmub_fw_boot_status status;
+       uint32_t is_enable;
 
-       REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_hw_init);
+       status.all = REG_READ(DMCUB_SCRATCH0);
+       REG_GET(DMCUB_CNTL, DMCUB_ENABLE, &is_enable);
 
-       return is_hw_init != 0;
+       return is_enable != 0 && status.bits.dal_fw;
 }
 
 bool dmub_dcn31_is_supported(struct dmub_srv *dmub)
index 3811e58..4495545 100644 (file)
@@ -590,7 +590,7 @@ struct atom_firmware_info_v3_4 {
        uint8_t  board_i2c_feature_id;            // enum of atom_board_i2c_feature_id_def
        uint8_t  board_i2c_feature_gpio_id;       // i2c id find in gpio_lut data table gpio_id
        uint8_t  board_i2c_feature_slave_addr;
-       uint8_t  reserved3;
+       uint8_t  ras_rom_i2c_slave_addr;
        uint16_t bootup_mvddq_mv;
        uint16_t bootup_mvpp_mv;
        uint32_t zfbstartaddrin16mb;
index 3fea243..dc91eb6 100644 (file)
@@ -26,7 +26,7 @@
 #include "amdgpu_smu.h"
 
 #define SMU13_DRIVER_IF_VERSION_INV 0xFFFFFFFF
-#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x03
+#define SMU13_DRIVER_IF_VERSION_YELLOW_CARP 0x04
 #define SMU13_DRIVER_IF_VERSION_ALDE 0x07
 
 /* MP Apertures */
index 5627de7..c5e26d6 100644 (file)
@@ -111,7 +111,9 @@ typedef struct {
   uint32_t InWhisperMode        : 1;
   uint32_t spare0               : 1;
   uint32_t ZstateStatus         : 4;
-  uint32_t spare1               :12;
+  uint32_t spare1               : 4;
+  uint32_t DstateFun            : 4;
+  uint32_t DstateDev            : 4;
   // MP1_EXT_SCRATCH2
   uint32_t P2JobHandler         :24;
   uint32_t RsmuPmiP2FinishedCnt : 8;
index 2597910..02e8c6e 100644 (file)
@@ -5127,6 +5127,13 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        return size;
 }
 
+static bool vega10_get_power_profile_mode_quirks(struct pp_hwmgr *hwmgr)
+{
+       struct amdgpu_device *adev = hwmgr->adev;
+
+       return (adev->pdev->device == 0x6860);
+}
+
 static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, uint32_t size)
 {
        struct vega10_hwmgr *data = hwmgr->backend;
@@ -5163,9 +5170,15 @@ static int vega10_set_power_profile_mode(struct pp_hwmgr *hwmgr, long *input, ui
        }
 
 out:
-       smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
+       if (vega10_get_power_profile_mode_quirks(hwmgr))
+               smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
+                                               1 << power_profile_mode,
+                                               NULL);
+       else
+               smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_SetWorkloadMask,
                                                (!power_profile_mode) ? 0 : 1 << (power_profile_mode - 1),
                                                NULL);
+
        hwmgr->power_profile_mode = power_profile_mode;
 
        return 0;
index c751f71..d92dd2c 100644 (file)
@@ -353,8 +353,7 @@ static void sienna_cichlid_check_bxco_support(struct smu_context *smu)
        struct amdgpu_device *adev = smu->adev;
        uint32_t val;
 
-       if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO ||
-           powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_MACO) {
+       if (powerplay_table->platform_caps & SMU_11_0_7_PP_PLATFORM_CAP_BACO) {
                val = RREG32_SOC15(NBIO, 0, mmRCC_BIF_STRAP0);
                smu_baco->platform_support =
                        (val & RCC_BIF_STRAP0__STRAP_PX_CAPABLE_MASK) ? true :
index 18681dc..bcaaa08 100644 (file)
@@ -256,7 +256,7 @@ static int vangogh_tables_init(struct smu_context *smu)
        return 0;
 
 err3_out:
-       kfree(smu_table->clocks_table);
+       kfree(smu_table->watermarks_table);
 err2_out:
        kfree(smu_table->gpu_metrics_table);
 err1_out:
index d299079..5d82891 100644 (file)
@@ -855,8 +855,6 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
        req.request.sequence = req32.request.sequence;
        req.request.signal = req32.request.signal;
        err = drm_ioctl_kernel(file, drm_wait_vblank_ioctl, &req, DRM_UNLOCKED);
-       if (err)
-               return err;
 
        req32.reply.type = req.reply.type;
        req32.reply.sequence = req.reply.sequence;
@@ -865,7 +863,7 @@ static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
        if (copy_to_user(argp, &req32, sizeof(req32)))
                return -EFAULT;
 
-       return 0;
+       return err;
 }
 
 #if defined(CONFIG_X86)
index be716b5..00dade4 100644 (file)
@@ -2463,6 +2463,15 @@ static void intel_ddi_power_up_lanes(struct intel_encoder *encoder,
        }
 }
 
+/* Splitter enable for eDP MSO is limited to certain pipes. */
+static u8 intel_ddi_splitter_pipe_mask(struct drm_i915_private *i915)
+{
+       if (IS_ALDERLAKE_P(i915))
+               return BIT(PIPE_A) | BIT(PIPE_B);
+       else
+               return BIT(PIPE_A);
+}
+
 static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
                                     struct intel_crtc_state *pipe_config)
 {
@@ -2480,8 +2489,7 @@ static void intel_ddi_mso_get_config(struct intel_encoder *encoder,
        if (!pipe_config->splitter.enable)
                return;
 
-       /* Splitter enable is supported for pipe A only. */
-       if (drm_WARN_ON(&i915->drm, pipe != PIPE_A)) {
+       if (drm_WARN_ON(&i915->drm, !(intel_ddi_splitter_pipe_mask(i915) & BIT(pipe)))) {
                pipe_config->splitter.enable = false;
                return;
        }
@@ -2513,10 +2521,6 @@ static void intel_ddi_mso_configure(const struct intel_crtc_state *crtc_state)
                return;
 
        if (crtc_state->splitter.enable) {
-               /* Splitter enable is supported for pipe A only. */
-               if (drm_WARN_ON(&i915->drm, pipe != PIPE_A))
-                       return;
-
                dss1 |= SPLITTER_ENABLE;
                dss1 |= OVERLAP_PIXELS(crtc_state->splitter.pixel_overlap);
                if (crtc_state->splitter.link_count == 2)
@@ -4743,12 +4747,8 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port)
 
                dig_port->hpd_pulse = intel_dp_hpd_pulse;
 
-               /* Splitter enable for eDP MSO is limited to certain pipes. */
-               if (dig_port->dp.mso_link_count) {
-                       encoder->pipe_mask = BIT(PIPE_A);
-                       if (IS_ALDERLAKE_P(dev_priv))
-                               encoder->pipe_mask |= BIT(PIPE_B);
-               }
+               if (dig_port->dp.mso_link_count)
+                       encoder->pipe_mask = intel_ddi_splitter_pipe_mask(dev_priv);
        }
 
        /* In theory we don't need the encoder->type check, but leave it just in
index 2d5d217..0a8a239 100644 (file)
@@ -5746,16 +5746,18 @@ static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state)
 
        switch (crtc_state->pipe_bpp) {
        case 18:
-               val |= PIPEMISC_DITHER_6_BPC;
+               val |= PIPEMISC_6_BPC;
                break;
        case 24:
-               val |= PIPEMISC_DITHER_8_BPC;
+               val |= PIPEMISC_8_BPC;
                break;
        case 30:
-               val |= PIPEMISC_DITHER_10_BPC;
+               val |= PIPEMISC_10_BPC;
                break;
        case 36:
-               val |= PIPEMISC_DITHER_12_BPC;
+               /* Port output 12BPC defined for ADLP+ */
+               if (DISPLAY_VER(dev_priv) > 12)
+                       val |= PIPEMISC_12_BPC_ADLP;
                break;
        default:
                MISSING_CASE(crtc_state->pipe_bpp);
@@ -5808,15 +5810,27 @@ int bdw_get_pipemisc_bpp(struct intel_crtc *crtc)
 
        tmp = intel_de_read(dev_priv, PIPEMISC(crtc->pipe));
 
-       switch (tmp & PIPEMISC_DITHER_BPC_MASK) {
-       case PIPEMISC_DITHER_6_BPC:
+       switch (tmp & PIPEMISC_BPC_MASK) {
+       case PIPEMISC_6_BPC:
                return 18;
-       case PIPEMISC_DITHER_8_BPC:
+       case PIPEMISC_8_BPC:
                return 24;
-       case PIPEMISC_DITHER_10_BPC:
+       case PIPEMISC_10_BPC:
                return 30;
-       case PIPEMISC_DITHER_12_BPC:
-               return 36;
+       /*
+        * PORT OUTPUT 12 BPC defined for ADLP+.
+        *
+        * TODO:
+        * For previous platforms with DSI interface, bits 5:7
+        * are used for storing pipe_bpp irrespective of dithering.
+        * Since the value of 12 BPC is not defined for these bits
+        * on older platforms, need to find a workaround for 12 BPC
+        * MIPI DSI HW readout.
+        */
+       case PIPEMISC_12_BPC_ADLP:
+               if (DISPLAY_VER(dev_priv) > 12)
+                       return 36;
+               fallthrough;
        default:
                MISSING_CASE(tmp);
                return 0;
index 4298ae6..86b7ac7 100644 (file)
@@ -6387,13 +6387,13 @@ void intel_display_power_suspend_late(struct drm_i915_private *i915)
        if (DISPLAY_VER(i915) >= 11 || IS_GEMINILAKE(i915) ||
            IS_BROXTON(i915)) {
                bxt_enable_dc9(i915);
-               /* Tweaked Wa_14010685332:icp,jsp,mcc */
-               if (INTEL_PCH_TYPE(i915) >= PCH_ICP && INTEL_PCH_TYPE(i915) <= PCH_MCC)
-                       intel_de_rmw(i915, SOUTH_CHICKEN1,
-                                    SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);
        } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
                hsw_enable_pc8(i915);
        }
+
+       /* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */
+       if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1)
+               intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, SBCLK_RUN_REFCLK_DIS);
 }
 
 void intel_display_power_resume_early(struct drm_i915_private *i915)
@@ -6402,13 +6402,13 @@ void intel_display_power_resume_early(struct drm_i915_private *i915)
            IS_BROXTON(i915)) {
                gen9_sanitize_dc_state(i915);
                bxt_disable_dc9(i915);
-               /* Tweaked Wa_14010685332:icp,jsp,mcc */
-               if (INTEL_PCH_TYPE(i915) >= PCH_ICP && INTEL_PCH_TYPE(i915) <= PCH_MCC)
-                       intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
-
        } else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) {
                hsw_disable_pc8(i915);
        }
+
+       /* Tweaked Wa_14010685332:cnp,icp,jsp,mcc,tgp,adp */
+       if (INTEL_PCH_TYPE(i915) >= PCH_CNP && INTEL_PCH_TYPE(i915) < PCH_DG1)
+               intel_de_rmw(i915, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
 }
 
 void intel_display_power_suspend(struct drm_i915_private *i915)
index 6cc03b9..862c1df 100644 (file)
@@ -3850,23 +3850,18 @@ static void intel_dp_check_device_service_irq(struct intel_dp *intel_dp)
 
 static void intel_dp_check_link_service_irq(struct intel_dp *intel_dp)
 {
-       struct drm_i915_private *i915 = dp_to_i915(intel_dp);
        u8 val;
 
        if (intel_dp->dpcd[DP_DPCD_REV] < 0x11)
                return;
 
        if (drm_dp_dpcd_readb(&intel_dp->aux,
-                             DP_LINK_SERVICE_IRQ_VECTOR_ESI0, &val) != 1 || !val) {
-               drm_dbg_kms(&i915->drm, "Error in reading link service irq vector\n");
+                             DP_LINK_SERVICE_IRQ_VECTOR_ESI0, &val) != 1 || !val)
                return;
-       }
 
        if (drm_dp_dpcd_writeb(&intel_dp->aux,
-                              DP_LINK_SERVICE_IRQ_VECTOR_ESI0, val) != 1) {
-               drm_dbg_kms(&i915->drm, "Error in writing link service irq vector\n");
+                              DP_LINK_SERVICE_IRQ_VECTOR_ESI0, val) != 1)
                return;
-       }
 
        if (val & HDMI_LINK_STATUS_CHANGED)
                intel_dp_handle_hdmi_link_status_change(intel_dp);
index 08bceae..053a3c2 100644 (file)
@@ -206,7 +206,6 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
 
        return lttpr_count;
 }
-EXPORT_SYMBOL(intel_dp_init_lttpr_and_dprx_caps);
 
 static u8 dp_voltage_max(u8 preemph)
 {
index c4a126c..1257f4f 100644 (file)
@@ -127,6 +127,15 @@ static void intel_timeline_fini(struct rcu_head *rcu)
 
        i915_vma_put(timeline->hwsp_ggtt);
        i915_active_fini(&timeline->active);
+
+       /*
+        * A small race exists between intel_gt_retire_requests_timeout and
+        * intel_timeline_exit which could result in the syncmap not getting
+        * free'd. Rather than work to hard to seal this race, simply cleanup
+        * the syncmap on fini.
+        */
+       i915_syncmap_free(&timeline->sync);
+
        kfree(timeline);
 }
 
index 06024d3..cde0a47 100644 (file)
@@ -3149,6 +3149,7 @@ static int init_bdw_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(_MMIO(0xb100), D_BDW, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0xb10c), D_BDW, F_CMD_ACCESS, NULL, NULL);
        MMIO_D(_MMIO(0xb110), D_BDW);
+       MMIO_D(GEN9_SCRATCH_LNCF1, D_BDW_PLUS);
 
        MMIO_F(_MMIO(0x24d0), 48, F_CMD_ACCESS | F_CMD_WRITE_PATCH, 0, 0,
                D_BDW_PLUS, NULL, force_nonpriv_write);
index b8ac807..f776c47 100644 (file)
@@ -105,6 +105,8 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = {
        {RCS0, COMMON_SLICE_CHICKEN2, 0xffff, true}, /* 0x7014 */
        {RCS0, GEN9_CS_DEBUG_MODE1, 0xffff, false}, /* 0x20ec */
        {RCS0, GEN8_L3SQCREG4, 0, false}, /* 0xb118 */
+       {RCS0, GEN9_SCRATCH1, 0, false}, /* 0xb11c */
+       {RCS0, GEN9_SCRATCH_LNCF1, 0, false}, /* 0xb008 */
        {RCS0, GEN7_HALF_SLICE_CHICKEN1, 0xffff, true}, /* 0xe100 */
        {RCS0, HALF_SLICE_CHICKEN2, 0xffff, true}, /* 0xe180 */
        {RCS0, HALF_SLICE_CHICKEN3, 0xffff, true}, /* 0xe184 */
index 77f1911..3acb0b6 100644 (file)
@@ -138,7 +138,7 @@ void i915_globals_unpark(void)
        atomic_inc(&active);
 }
 
-static void __exit __i915_globals_flush(void)
+static void  __i915_globals_flush(void)
 {
        atomic_inc(&active); /* skip shrinking */
 
@@ -148,7 +148,7 @@ static void __exit __i915_globals_flush(void)
        atomic_dec(&active);
 }
 
-void __exit i915_globals_exit(void)
+void i915_globals_exit(void)
 {
        GEM_BUG_ON(atomic_read(&active));
 
index 35c97c3..9666646 100644 (file)
@@ -727,9 +727,18 @@ static void err_print_gt(struct drm_i915_error_state_buf *m,
        if (GRAPHICS_VER(m->i915) >= 12) {
                int i;
 
-               for (i = 0; i < GEN12_SFC_DONE_MAX; i++)
+               for (i = 0; i < GEN12_SFC_DONE_MAX; i++) {
+                       /*
+                        * SFC_DONE resides in the VD forcewake domain, so it
+                        * only exists if the corresponding VCS engine is
+                        * present.
+                        */
+                       if (!HAS_ENGINE(gt->_gt, _VCS(i * 2)))
+                               continue;
+
                        err_printf(m, "  SFC_DONE[%d]: 0x%08x\n", i,
                                   gt->sfc_done[i]);
+               }
 
                err_printf(m, "  GAM_DONE: 0x%08x\n", gt->gam_done);
        }
@@ -1581,6 +1590,14 @@ static void gt_record_regs(struct intel_gt_coredump *gt)
 
        if (GRAPHICS_VER(i915) >= 12) {
                for (i = 0; i < GEN12_SFC_DONE_MAX; i++) {
+                       /*
+                        * SFC_DONE resides in the VD forcewake domain, so it
+                        * only exists if the corresponding VCS engine is
+                        * present.
+                        */
+                       if (!HAS_ENGINE(gt->_gt, _VCS(i * 2)))
+                               continue;
+
                        gt->sfc_done[i] =
                                intel_uncore_read(uncore, GEN12_SFC_DONE(i));
                }
index c039431..c3816f5 100644 (file)
@@ -3064,24 +3064,6 @@ static void valleyview_irq_reset(struct drm_i915_private *dev_priv)
        spin_unlock_irq(&dev_priv->irq_lock);
 }
 
-static void cnp_display_clock_wa(struct drm_i915_private *dev_priv)
-{
-       struct intel_uncore *uncore = &dev_priv->uncore;
-
-       /*
-        * Wa_14010685332:cnp/cmp,tgp,adp
-        * TODO: Clarify which platforms this applies to
-        * TODO: Figure out if this workaround can be applied in the s0ix suspend/resume handlers as
-        * on earlier platforms and whether the workaround is also needed for runtime suspend/resume
-        */
-       if (INTEL_PCH_TYPE(dev_priv) == PCH_CNP ||
-           (INTEL_PCH_TYPE(dev_priv) >= PCH_TGP && INTEL_PCH_TYPE(dev_priv) < PCH_DG1)) {
-               intel_uncore_rmw(uncore, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS,
-                                SBCLK_RUN_REFCLK_DIS);
-               intel_uncore_rmw(uncore, SOUTH_CHICKEN1, SBCLK_RUN_REFCLK_DIS, 0);
-       }
-}
-
 static void gen8_display_irq_reset(struct drm_i915_private *dev_priv)
 {
        struct intel_uncore *uncore = &dev_priv->uncore;
@@ -3115,7 +3097,6 @@ static void gen8_irq_reset(struct drm_i915_private *dev_priv)
        if (HAS_PCH_SPLIT(dev_priv))
                ibx_irq_reset(dev_priv);
 
-       cnp_display_clock_wa(dev_priv);
 }
 
 static void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
@@ -3159,8 +3140,6 @@ static void gen11_display_irq_reset(struct drm_i915_private *dev_priv)
 
        if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP)
                GEN3_IRQ_RESET(uncore, SDE);
-
-       cnp_display_clock_wa(dev_priv);
 }
 
 static void gen11_irq_reset(struct drm_i915_private *dev_priv)
index 83b500b..2880ec5 100644 (file)
@@ -1195,6 +1195,7 @@ static int __init i915_init(void)
        err = pci_register_driver(&i915_pci_driver);
        if (err) {
                i915_pmu_exit();
+               i915_globals_exit();
                return err;
        }
 
index 94fde5c..476bb3b 100644 (file)
@@ -422,7 +422,7 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg)
 #define   GEN12_HCP_SFC_LOCK_ACK_BIT           REG_BIT(1)
 #define   GEN12_HCP_SFC_USAGE_BIT                      REG_BIT(0)
 
-#define GEN12_SFC_DONE(n)              _MMIO(0x1cc00 + (n) * 0x100)
+#define GEN12_SFC_DONE(n)              _MMIO(0x1cc000 + (n) * 0x1000)
 #define GEN12_SFC_DONE_MAX             4
 
 #define RING_PP_DIR_BASE(base)         _MMIO((base) + 0x228)
@@ -6163,11 +6163,17 @@ enum {
 #define   PIPEMISC_HDR_MODE_PRECISION  (1 << 23) /* icl+ */
 #define   PIPEMISC_OUTPUT_COLORSPACE_YUV  (1 << 11)
 #define   PIPEMISC_PIXEL_ROUNDING_TRUNC        REG_BIT(8) /* tgl+ */
-#define   PIPEMISC_DITHER_BPC_MASK     (7 << 5)
-#define   PIPEMISC_DITHER_8_BPC                (0 << 5)
-#define   PIPEMISC_DITHER_10_BPC       (1 << 5)
-#define   PIPEMISC_DITHER_6_BPC                (2 << 5)
-#define   PIPEMISC_DITHER_12_BPC       (3 << 5)
+/*
+ * For Display < 13, Bits 5-7 of PIPE MISC represent DITHER BPC with
+ * valid values of: 6, 8, 10 BPC.
+ * ADLP+, the bits 5-7 represent PORT OUTPUT BPC with valid values of:
+ * 6, 8, 10, 12 BPC.
+ */
+#define   PIPEMISC_BPC_MASK            (7 << 5)
+#define   PIPEMISC_8_BPC               (0 << 5)
+#define   PIPEMISC_10_BPC              (1 << 5)
+#define   PIPEMISC_6_BPC               (2 << 5)
+#define   PIPEMISC_12_BPC_ADLP         (4 << 5) /* adlp+ */
 #define   PIPEMISC_DITHER_ENABLE       (1 << 4)
 #define   PIPEMISC_DITHER_TYPE_MASK    (3 << 2)
 #define   PIPEMISC_DITHER_TYPE_SP      (0 << 2)
index 8710f55..bd1f9f0 100644 (file)
@@ -683,7 +683,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,
                break;
        }
 
-       ipu_dmfc_config_wait4eot(ipu_plane->dmfc, drm_rect_width(dst));
+       ipu_dmfc_config_wait4eot(ipu_plane->dmfc, ALIGN(drm_rect_width(dst), 8));
 
        width = ipu_src_rect_width(new_state);
        height = drm_rect_height(&new_state->src) >> 16;
index 96ea1a2..f54392e 100644 (file)
@@ -203,6 +203,7 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
        unsigned long status, val, val1;
        int plane_id, dma0_state, dma1_state;
        struct kmb_drm_private *kmb = to_kmb(dev);
+       u32 ctrl = 0;
 
        status = kmb_read_lcd(kmb, LCD_INT_STATUS);
 
@@ -227,6 +228,19 @@ static irqreturn_t handle_lcd_irq(struct drm_device *dev)
                                kmb_clr_bitmask_lcd(kmb, LCD_CONTROL,
                                                    kmb->plane_status[plane_id].ctrl);
 
+                               ctrl = kmb_read_lcd(kmb, LCD_CONTROL);
+                               if (!(ctrl & (LCD_CTRL_VL1_ENABLE |
+                                   LCD_CTRL_VL2_ENABLE |
+                                   LCD_CTRL_GL1_ENABLE |
+                                   LCD_CTRL_GL2_ENABLE))) {
+                                       /* If no LCD layers are using DMA,
+                                        * then disable DMA pipelined AXI read
+                                        * transactions.
+                                        */
+                                       kmb_clr_bitmask_lcd(kmb, LCD_CONTROL,
+                                                           LCD_CTRL_PIPELINE_DMA);
+                               }
+
                                kmb->plane_status[plane_id].disable = false;
                        }
                }
@@ -411,10 +425,10 @@ static const struct drm_driver kmb_driver = {
        .fops = &fops,
        DRM_GEM_CMA_DRIVER_OPS_VMAP,
        .name = "kmb-drm",
-       .desc = "KEEMBAY DISPLAY DRIVER ",
-       .date = "20201008",
-       .major = 1,
-       .minor = 0,
+       .desc = "KEEMBAY DISPLAY DRIVER",
+       .date = DRIVER_DATE,
+       .major = DRIVER_MAJOR,
+       .minor = DRIVER_MINOR,
 };
 
 static int kmb_remove(struct platform_device *pdev)
index 02e8067..ebbaa5f 100644 (file)
 #define KMB_MAX_HEIGHT                 1080 /*Max height in pixels */
 #define KMB_MIN_WIDTH                   1920 /*Max width in pixels */
 #define KMB_MIN_HEIGHT                  1080 /*Max height in pixels */
+
+#define DRIVER_DATE                    "20210223"
+#define DRIVER_MAJOR                   1
+#define DRIVER_MINOR                   1
+
 #define KMB_LCD_DEFAULT_CLK            200000000
 #define KMB_SYS_CLK_MHZ                        500
 
index d5b6195..ecee678 100644 (file)
@@ -427,8 +427,14 @@ static void kmb_plane_atomic_update(struct drm_plane *plane,
 
        kmb_set_bitmask_lcd(kmb, LCD_CONTROL, ctrl);
 
-       /* FIXME no doc on how to set output format,these values are
-        * taken from the Myriadx tests
+       /* Enable pipeline AXI read transactions for the DMA
+        * after setting graphics layers. This must be done
+        * in a separate write cycle.
+        */
+       kmb_set_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
+
+       /* FIXME no doc on how to set output format, these values are taken
+        * from the Myriadx tests
         */
        out_format |= LCD_OUTF_FORMAT_RGB888;
 
@@ -526,6 +532,11 @@ struct kmb_plane *kmb_plane_init(struct drm_device *drm)
                plane->id = i;
        }
 
+       /* Disable pipeline AXI read transactions for the DMA
+        * prior to setting graphics layers
+        */
+       kmb_clr_bitmask_lcd(kmb, LCD_CONTROL, LCD_CTRL_PIPELINE_DMA);
+
        return primary;
 cleanup:
        drmm_kfree(drm, plane);
index 6f4c80b..473f5bb 100644 (file)
@@ -133,6 +133,8 @@ static int mtk_disp_color_probe(struct platform_device *pdev)
 
 static int mtk_disp_color_remove(struct platform_device *pdev)
 {
+       component_del(&pdev->dev, &mtk_disp_color_component_ops);
+
        return 0;
 }
 
index fa9d799..5326989 100644 (file)
@@ -423,6 +423,8 @@ static int mtk_disp_ovl_probe(struct platform_device *pdev)
 
 static int mtk_disp_ovl_remove(struct platform_device *pdev)
 {
+       component_del(&pdev->dev, &mtk_disp_ovl_component_ops);
+
        return 0;
 }
 
index bced555..e94738f 100644 (file)
@@ -605,11 +605,15 @@ static int mtk_dpi_bridge_atomic_check(struct drm_bridge *bridge,
                                       struct drm_crtc_state *crtc_state,
                                       struct drm_connector_state *conn_state)
 {
-       struct mtk_dpi *dpi = bridge->driver_private;
+       struct mtk_dpi *dpi = bridge_to_dpi(bridge);
        unsigned int out_bus_format;
 
        out_bus_format = bridge_state->output_bus_cfg.format;
 
+       if (out_bus_format == MEDIA_BUS_FMT_FIXED)
+               if (dpi->conf->num_output_fmts)
+                       out_bus_format = dpi->conf->output_fmts[0];
+
        dev_dbg(dpi->dev, "input format 0x%04x, output format 0x%04x\n",
                bridge_state->input_bus_cfg.format,
                bridge_state->output_bus_cfg.format);
index 474efb8..735efe7 100644 (file)
@@ -532,13 +532,10 @@ void mtk_drm_crtc_async_update(struct drm_crtc *crtc, struct drm_plane *plane,
                               struct drm_atomic_state *state)
 {
        struct mtk_drm_crtc *mtk_crtc = to_mtk_crtc(crtc);
-       const struct drm_plane_helper_funcs *plane_helper_funcs =
-                       plane->helper_private;
 
        if (!mtk_crtc->enabled)
                return;
 
-       plane_helper_funcs->atomic_update(plane, state);
        mtk_drm_crtc_update_config(mtk_crtc, false);
 }
 
index 75bc00e..50d2056 100644 (file)
@@ -34,6 +34,7 @@
 
 #define DISP_AAL_EN                            0x0000
 #define DISP_AAL_SIZE                          0x0030
+#define DISP_AAL_OUTPUT_SIZE                   0x04d8
 
 #define DISP_DITHER_EN                         0x0000
 #define DITHER_EN                              BIT(0)
@@ -197,6 +198,7 @@ static void mtk_aal_config(struct device *dev, unsigned int w,
        struct mtk_ddp_comp_dev *priv = dev_get_drvdata(dev);
 
        mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_SIZE);
+       mtk_ddp_write(cmdq_pkt, w << 16 | h, &priv->cmdq_reg, priv->regs, DISP_AAL_OUTPUT_SIZE);
 }
 
 static void mtk_aal_gamma_set(struct device *dev, struct drm_crtc_state *state)
index b5582dc..e6dcb34 100644 (file)
@@ -110,6 +110,35 @@ static int mtk_plane_atomic_async_check(struct drm_plane *plane,
                                                   true, true);
 }
 
+static void mtk_plane_update_new_state(struct drm_plane_state *new_state,
+                                      struct mtk_plane_state *mtk_plane_state)
+{
+       struct drm_framebuffer *fb = new_state->fb;
+       struct drm_gem_object *gem;
+       struct mtk_drm_gem_obj *mtk_gem;
+       unsigned int pitch, format;
+       dma_addr_t addr;
+
+       gem = fb->obj[0];
+       mtk_gem = to_mtk_gem_obj(gem);
+       addr = mtk_gem->dma_addr;
+       pitch = fb->pitches[0];
+       format = fb->format->format;
+
+       addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
+       addr += (new_state->src.y1 >> 16) * pitch;
+
+       mtk_plane_state->pending.enable = true;
+       mtk_plane_state->pending.pitch = pitch;
+       mtk_plane_state->pending.format = format;
+       mtk_plane_state->pending.addr = addr;
+       mtk_plane_state->pending.x = new_state->dst.x1;
+       mtk_plane_state->pending.y = new_state->dst.y1;
+       mtk_plane_state->pending.width = drm_rect_width(&new_state->dst);
+       mtk_plane_state->pending.height = drm_rect_height(&new_state->dst);
+       mtk_plane_state->pending.rotation = new_state->rotation;
+}
+
 static void mtk_plane_atomic_async_update(struct drm_plane *plane,
                                          struct drm_atomic_state *state)
 {
@@ -126,8 +155,10 @@ static void mtk_plane_atomic_async_update(struct drm_plane *plane,
        plane->state->src_h = new_state->src_h;
        plane->state->src_w = new_state->src_w;
        swap(plane->state->fb, new_state->fb);
-       new_plane_state->pending.async_dirty = true;
 
+       mtk_plane_update_new_state(new_state, new_plane_state);
+       wmb(); /* Make sure the above parameters are set before update */
+       new_plane_state->pending.async_dirty = true;
        mtk_drm_crtc_async_update(new_state->crtc, plane, state);
 }
 
@@ -189,14 +220,8 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
        struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
                                                                           plane);
        struct mtk_plane_state *mtk_plane_state = to_mtk_plane_state(new_state);
-       struct drm_crtc *crtc = new_state->crtc;
-       struct drm_framebuffer *fb = new_state->fb;
-       struct drm_gem_object *gem;
-       struct mtk_drm_gem_obj *mtk_gem;
-       unsigned int pitch, format;
-       dma_addr_t addr;
 
-       if (!crtc || WARN_ON(!fb))
+       if (!new_state->crtc || WARN_ON(!new_state->fb))
                return;
 
        if (!new_state->visible) {
@@ -204,24 +229,7 @@ static void mtk_plane_atomic_update(struct drm_plane *plane,
                return;
        }
 
-       gem = fb->obj[0];
-       mtk_gem = to_mtk_gem_obj(gem);
-       addr = mtk_gem->dma_addr;
-       pitch = fb->pitches[0];
-       format = fb->format->format;
-
-       addr += (new_state->src.x1 >> 16) * fb->format->cpp[0];
-       addr += (new_state->src.y1 >> 16) * pitch;
-
-       mtk_plane_state->pending.enable = true;
-       mtk_plane_state->pending.pitch = pitch;
-       mtk_plane_state->pending.format = format;
-       mtk_plane_state->pending.addr = addr;
-       mtk_plane_state->pending.x = new_state->dst.x1;
-       mtk_plane_state->pending.y = new_state->dst.y1;
-       mtk_plane_state->pending.width = drm_rect_width(&new_state->dst);
-       mtk_plane_state->pending.height = drm_rect_height(&new_state->dst);
-       mtk_plane_state->pending.rotation = new_state->rotation;
+       mtk_plane_update_new_state(new_state, mtk_plane_state);
        wmb(); /* Make sure the above parameters are set before update */
        mtk_plane_state->pending.dirty = true;
 }
index 446e796..0f3cafa 100644 (file)
 #define VPP_WRAP_OSD3_MATRIX_PRE_OFFSET2 0x3dbc
 #define VPP_WRAP_OSD3_MATRIX_EN_CTRL 0x3dbd
 
+/* osd1 HDR */
+#define OSD1_HDR2_CTRL 0x38a0
+#define OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN       BIT(13)
+#define OSD1_HDR2_CTRL_REG_ONLY_MAT            BIT(16)
+
 /* osd2 scaler */
 #define OSD2_VSC_PHASE_STEP 0x3d00
 #define OSD2_VSC_INI_PHASE 0x3d01
index aede0c6..259f3e6 100644 (file)
@@ -425,9 +425,14 @@ void meson_viu_init(struct meson_drm *priv)
        if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
            meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
                meson_viu_load_matrix(priv);
-       else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
+       else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
                meson_viu_set_g12a_osd1_matrix(priv, RGB709_to_YUV709l_coeff,
                                               true);
+               /* fix green/pink color distortion from vendor u-boot */
+               writel_bits_relaxed(OSD1_HDR2_CTRL_REG_ONLY_MAT |
+                               OSD1_HDR2_CTRL_VDIN0_HDR2_TOP_EN, 0,
+                               priv->io_base + _REG(OSD1_HDR2_CTRL));
+       }
 
        /* Initialize OSD1 fifo control register */
        reg = VIU_OSD_DDR_PRIORITY_URGENT |
index f949767..bcb0310 100644 (file)
@@ -2237,6 +2237,33 @@ nv50_disp_atomic_commit_tail(struct drm_atomic_state *state)
                interlock[NV50_DISP_INTERLOCK_CORE] = 0;
        }
 
+       /* Finish updating head(s)...
+        *
+        * NVD is rather picky about both where window assignments can change,
+        * *and* about certain core and window channel states matching.
+        *
+        * The EFI GOP driver on newer GPUs configures window channels with a
+        * different output format to what we do, and the core channel update
+        * in the assign_windows case above would result in a state mismatch.
+        *
+        * Delay some of the head update until after that point to workaround
+        * the issue.  This only affects the initial modeset.
+        *
+        * TODO: handle this better when adding flexible window mapping
+        */
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
+               struct nv50_head_atom *asyh = nv50_head_atom(new_crtc_state);
+               struct nv50_head *head = nv50_head(crtc);
+
+               NV_ATOMIC(drm, "%s: set %04x (clr %04x)\n", crtc->name,
+                         asyh->set.mask, asyh->clr.mask);
+
+               if (asyh->set.mask) {
+                       nv50_head_flush_set_wndw(head, asyh);
+                       interlock[NV50_DISP_INTERLOCK_CORE] = 1;
+               }
+       }
+
        /* Update plane(s). */
        for_each_new_plane_in_state(state, plane, new_plane_state, i) {
                struct nv50_wndw_atom *asyw = nv50_wndw_atom(new_plane_state);
index ec361d1..d66f972 100644 (file)
@@ -50,11 +50,8 @@ nv50_head_flush_clr(struct nv50_head *head,
 }
 
 void
-nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
+nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom *asyh)
 {
-       if (asyh->set.view   ) head->func->view    (head, asyh);
-       if (asyh->set.mode   ) head->func->mode    (head, asyh);
-       if (asyh->set.core   ) head->func->core_set(head, asyh);
        if (asyh->set.olut   ) {
                asyh->olut.offset = nv50_lut_load(&head->olut,
                                                  asyh->olut.buffer,
@@ -62,6 +59,14 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
                                                  asyh->olut.load);
                head->func->olut_set(head, asyh);
        }
+}
+
+void
+nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
+{
+       if (asyh->set.view   ) head->func->view    (head, asyh);
+       if (asyh->set.mode   ) head->func->mode    (head, asyh);
+       if (asyh->set.core   ) head->func->core_set(head, asyh);
        if (asyh->set.curs   ) head->func->curs_set(head, asyh);
        if (asyh->set.base   ) head->func->base    (head, asyh);
        if (asyh->set.ovly   ) head->func->ovly    (head, asyh);
index dae841d..0bac6be 100644 (file)
@@ -21,6 +21,7 @@ struct nv50_head {
 
 struct nv50_head *nv50_head_create(struct drm_device *, int index);
 void nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh);
+void nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom *asyh);
 void nv50_head_flush_clr(struct nv50_head *head,
                         struct nv50_head_atom *asyh, bool flush);
 
index 0b86c44..59759c4 100644 (file)
@@ -4,7 +4,8 @@
 
 struct nv_device_v0 {
        __u8  version;
-       __u8  pad01[7];
+       __u8  priv;
+       __u8  pad02[6];
        __u64 device;   /* device identifier, ~0 for client default */
 };
 
index ba2c28e..c68cc95 100644 (file)
@@ -61,8 +61,6 @@
 #define NV10_CHANNEL_DMA                              /* cl506b.h */ 0x0000006e
 #define NV17_CHANNEL_DMA                              /* cl506b.h */ 0x0000176e
 #define NV40_CHANNEL_DMA                              /* cl506b.h */ 0x0000406e
-#define NV50_CHANNEL_DMA                              /* cl506e.h */ 0x0000506e
-#define G82_CHANNEL_DMA                               /* cl826e.h */ 0x0000826e
 
 #define NV50_CHANNEL_GPFIFO                           /* cl506f.h */ 0x0000506f
 #define G82_CHANNEL_GPFIFO                            /* cl826f.h */ 0x0000826f
index 347d2c0..5d9395e 100644 (file)
@@ -9,7 +9,6 @@ struct nvif_client {
        const struct nvif_driver *driver;
        u64 version;
        u8 route;
-       bool super;
 };
 
 int  nvif_client_ctor(struct nvif_client *parent, const char *name, u64 device,
index 8e85b93..7a3af05 100644 (file)
@@ -11,7 +11,7 @@ struct nvif_driver {
        void (*fini)(void *priv);
        int (*suspend)(void *priv);
        int (*resume)(void *priv);
-       int (*ioctl)(void *priv, bool super, void *data, u32 size, void **hack);
+       int (*ioctl)(void *priv, void *data, u32 size, void **hack);
        void __iomem *(*map)(void *priv, u64 handle, u32 size);
        void (*unmap)(void *priv, void __iomem *ptr, u32 size);
        bool keep;
index 5d7017f..2f86606 100644 (file)
@@ -13,7 +13,6 @@ struct nvkm_client {
        struct nvkm_client_notify *notify[32];
        struct rb_root objroot;
 
-       bool super;
        void *data;
        int (*ntfy)(const void *, u32, const void *, u32);
 
index 71ed147..f52918a 100644 (file)
@@ -4,5 +4,5 @@
 #include <core/os.h>
 struct nvkm_client;
 
-int nvkm_ioctl(struct nvkm_client *, bool, void *, u32, void **);
+int nvkm_ioctl(struct nvkm_client *, void *, u32, void **);
 #endif
index 0911e73..70e7887 100644 (file)
@@ -15,7 +15,6 @@ struct nvkm_vma {
        u8   refd:3; /* Current page type (index, or NONE for unreferenced). */
        bool used:1; /* Region allocated. */
        bool part:1; /* Region was split from an allocated region by map(). */
-       bool user:1; /* Region user-allocated. */
        bool busy:1; /* Region busy (for temporarily preventing user access). */
        bool mapped:1; /* Region contains valid pages. */
        struct nvkm_memory *memory; /* Memory currently mapped into VMA. */
index b45ec30..4107b70 100644 (file)
@@ -570,11 +570,9 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        }
 
        client->route = NVDRM_OBJECT_ABI16;
-       client->super = true;
        ret = nvif_object_ctor(&chan->chan->user, "abi16Ntfy", info->handle,
                               NV_DMA_IN_MEMORY, &args, sizeof(args),
                               &ntfy->object);
-       client->super = false;
        client->route = NVDRM_OBJECT_NVIF;
        if (ret)
                goto done;
index 4036260..80099ef 100644 (file)
@@ -86,12 +86,6 @@ nouveau_channel_del(struct nouveau_channel **pchan)
        struct nouveau_channel *chan = *pchan;
        if (chan) {
                struct nouveau_cli *cli = (void *)chan->user.client;
-               bool super;
-
-               if (cli) {
-                       super = cli->base.super;
-                       cli->base.super = true;
-               }
 
                if (chan->fence)
                        nouveau_fence(chan->drm)->context_del(chan);
@@ -111,9 +105,6 @@ nouveau_channel_del(struct nouveau_channel **pchan)
                        nouveau_bo_unpin(chan->push.buffer);
                nouveau_bo_ref(NULL, &chan->push.buffer);
                kfree(chan);
-
-               if (cli)
-                       cli->base.super = super;
        }
        *pchan = NULL;
 }
@@ -512,20 +503,16 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
                    struct nouveau_channel **pchan)
 {
        struct nouveau_cli *cli = (void *)device->object.client;
-       bool super;
        int ret;
 
        /* hack until fencenv50 is fixed, and agp access relaxed */
-       super = cli->base.super;
-       cli->base.super = true;
-
        ret = nouveau_channel_ind(drm, device, arg0, priv, pchan);
        if (ret) {
                NV_PRINTK(dbg, cli, "ib channel create, %d\n", ret);
                ret = nouveau_channel_dma(drm, device, pchan);
                if (ret) {
                        NV_PRINTK(dbg, cli, "dma channel create, %d\n", ret);
-                       goto done;
+                       return ret;
                }
        }
 
@@ -533,15 +520,13 @@ nouveau_channel_new(struct nouveau_drm *drm, struct nvif_device *device,
        if (ret) {
                NV_PRINTK(err, cli, "channel failed to initialise, %d\n", ret);
                nouveau_channel_del(pchan);
-               goto done;
+               return ret;
        }
 
        ret = nouveau_svmm_join((*pchan)->vmm->svmm, (*pchan)->inst);
        if (ret)
                nouveau_channel_del(pchan);
 
-done:
-       cli->base.super = super;
        return ret;
 }
 
index a616cf4..ba4cd5f 100644 (file)
@@ -244,6 +244,7 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname,
        ret = nvif_device_ctor(&cli->base.object, "drmDevice", 0, NV_DEVICE,
                               &(struct nv_device_v0) {
                                        .device = ~0,
+                                       .priv = true,
                               }, sizeof(struct nv_device_v0),
                               &cli->device);
        if (ret) {
@@ -1086,8 +1087,6 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv)
        if (ret)
                goto done;
 
-       cli->base.super = false;
-
        fpriv->driver_priv = cli;
 
        mutex_lock(&drm->client.mutex);
index 0de6549..2ca3207 100644 (file)
@@ -41,8 +41,6 @@ nouveau_mem_map(struct nouveau_mem *mem,
                struct gf100_vmm_map_v0 gf100;
        } args;
        u32 argc = 0;
-       bool super;
-       int ret;
 
        switch (vmm->object.oclass) {
        case NVIF_CLASS_VMM_NV04:
@@ -73,12 +71,7 @@ nouveau_mem_map(struct nouveau_mem *mem,
                return -ENOSYS;
        }
 
-       super = vmm->object.client->super;
-       vmm->object.client->super = true;
-       ret = nvif_vmm_map(vmm, vma->addr, mem->mem.size, &args, argc,
-                          &mem->mem, 0);
-       vmm->object.client->super = super;
-       return ret;
+       return nvif_vmm_map(vmm, vma->addr, mem->mem.size, &args, argc, &mem->mem, 0);
 }
 
 void
@@ -99,7 +92,6 @@ nouveau_mem_host(struct ttm_resource *reg, struct ttm_tt *tt)
        struct nouveau_drm *drm = cli->drm;
        struct nvif_mmu *mmu = &cli->mmu;
        struct nvif_mem_ram_v0 args = {};
-       bool super = cli->base.super;
        u8 type;
        int ret;
 
@@ -122,11 +114,9 @@ nouveau_mem_host(struct ttm_resource *reg, struct ttm_tt *tt)
                args.dma = tt->dma_address;
 
        mutex_lock(&drm->master.lock);
-       cli->base.super = true;
        ret = nvif_mem_ctor_type(mmu, "ttmHostMem", cli->mem->oclass, type, PAGE_SHIFT,
                                 reg->num_pages << PAGE_SHIFT,
                                 &args, sizeof(args), &mem->mem);
-       cli->base.super = super;
        mutex_unlock(&drm->master.lock);
        return ret;
 }
@@ -138,12 +128,10 @@ nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page)
        struct nouveau_cli *cli = mem->cli;
        struct nouveau_drm *drm = cli->drm;
        struct nvif_mmu *mmu = &cli->mmu;
-       bool super = cli->base.super;
        u64 size = ALIGN(reg->num_pages << PAGE_SHIFT, 1 << page);
        int ret;
 
        mutex_lock(&drm->master.lock);
-       cli->base.super = true;
        switch (cli->mem->oclass) {
        case NVIF_CLASS_MEM_GF100:
                ret = nvif_mem_ctor_type(mmu, "ttmVram", cli->mem->oclass,
@@ -167,7 +155,6 @@ nouveau_mem_vram(struct ttm_resource *reg, bool contig, u8 page)
                WARN_ON(1);
                break;
        }
-       cli->base.super = super;
        mutex_unlock(&drm->master.lock);
 
        reg->start = mem->mem.addr >> PAGE_SHIFT;
index b3f29b1..52f5793 100644 (file)
@@ -52,9 +52,9 @@ nvkm_client_map(void *priv, u64 handle, u32 size)
 }
 
 static int
-nvkm_client_ioctl(void *priv, bool super, void *data, u32 size, void **hack)
+nvkm_client_ioctl(void *priv, void *data, u32 size, void **hack)
 {
-       return nvkm_ioctl(priv, super, data, size, hack);
+       return nvkm_ioctl(priv, data, size, hack);
 }
 
 static int
index 82b583f..b0c3422 100644 (file)
@@ -237,14 +237,11 @@ void
 nouveau_svmm_invalidate(struct nouveau_svmm *svmm, u64 start, u64 limit)
 {
        if (limit > start) {
-               bool super = svmm->vmm->vmm.object.client->super;
-               svmm->vmm->vmm.object.client->super = true;
                nvif_object_mthd(&svmm->vmm->vmm.object, NVIF_VMM_V0_PFNCLR,
                                 &(struct nvif_vmm_pfnclr_v0) {
                                        .addr = start,
                                        .size = limit - start,
                                 }, sizeof(struct nvif_vmm_pfnclr_v0));
-               svmm->vmm->vmm.object.client->super = super;
        }
 }
 
@@ -634,9 +631,7 @@ static int nouveau_atomic_range_fault(struct nouveau_svmm *svmm,
                NVIF_VMM_PFNMAP_V0_A |
                NVIF_VMM_PFNMAP_V0_HOST;
 
-       svmm->vmm->vmm.object.client->super = true;
        ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, size, NULL);
-       svmm->vmm->vmm.object.client->super = false;
        mutex_unlock(&svmm->mutex);
 
        unlock_page(page);
@@ -702,9 +697,7 @@ static int nouveau_range_fault(struct nouveau_svmm *svmm,
 
        nouveau_hmm_convert_pfn(drm, &range, args);
 
-       svmm->vmm->vmm.object.client->super = true;
        ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, size, NULL);
-       svmm->vmm->vmm.object.client->super = false;
        mutex_unlock(&svmm->mutex);
 
 out:
@@ -928,10 +921,8 @@ nouveau_pfns_map(struct nouveau_svmm *svmm, struct mm_struct *mm,
 
        mutex_lock(&svmm->mutex);
 
-       svmm->vmm->vmm.object.client->super = true;
        ret = nvif_object_ioctl(&svmm->vmm->vmm.object, args, sizeof(*args) +
                                npages * sizeof(args->p.phys[0]), NULL);
-       svmm->vmm->vmm.object.client->super = false;
 
        mutex_unlock(&svmm->mutex);
 }
index 9dc10b1..5da1f4d 100644 (file)
@@ -32,6 +32,9 @@
 #include <nvif/event.h>
 #include <nvif/ioctl.h>
 
+#include <nvif/class.h>
+#include <nvif/cl0080.h>
+
 struct usif_notify_p {
        struct drm_pending_event base;
        struct {
@@ -261,7 +264,7 @@ usif_object_dtor(struct usif_object *object)
 }
 
 static int
-usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
+usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc, bool parent_abi16)
 {
        struct nouveau_cli *cli = nouveau_cli(f);
        struct nvif_client *client = &cli->base;
@@ -271,23 +274,48 @@ usif_object_new(struct drm_file *f, void *data, u32 size, void *argv, u32 argc)
        struct usif_object *object;
        int ret = -ENOSYS;
 
+       if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true)))
+               return ret;
+
+       switch (args->v0.oclass) {
+       case NV_DMA_FROM_MEMORY:
+       case NV_DMA_TO_MEMORY:
+       case NV_DMA_IN_MEMORY:
+               return -EINVAL;
+       case NV_DEVICE: {
+               union {
+                       struct nv_device_v0 v0;
+               } *args = data;
+
+               if ((ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false)))
+                       return ret;
+
+               args->v0.priv = false;
+               break;
+       }
+       default:
+               if (!parent_abi16)
+                       return -EINVAL;
+               break;
+       }
+
        if (!(object = kmalloc(sizeof(*object), GFP_KERNEL)))
                return -ENOMEM;
        list_add(&object->head, &cli->objects);
 
-       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
-               object->route = args->v0.route;
-               object->token = args->v0.token;
-               args->v0.route = NVDRM_OBJECT_USIF;
-               args->v0.token = (unsigned long)(void *)object;
-               ret = nvif_client_ioctl(client, argv, argc);
-               args->v0.token = object->token;
-               args->v0.route = object->route;
+       object->route = args->v0.route;
+       object->token = args->v0.token;
+       args->v0.route = NVDRM_OBJECT_USIF;
+       args->v0.token = (unsigned long)(void *)object;
+       ret = nvif_client_ioctl(client, argv, argc);
+       if (ret) {
+               usif_object_dtor(object);
+               return ret;
        }
 
-       if (ret)
-               usif_object_dtor(object);
-       return ret;
+       args->v0.token = object->token;
+       args->v0.route = object->route;
+       return 0;
 }
 
 int
@@ -301,6 +329,7 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
                struct nvif_ioctl_v0 v0;
        } *argv = data;
        struct usif_object *object;
+       bool abi16 = false;
        u8 owner;
        int ret;
 
@@ -331,11 +360,13 @@ usif_ioctl(struct drm_file *filp, void __user *user, u32 argc)
                        mutex_unlock(&cli->mutex);
                        goto done;
                }
+
+               abi16 = true;
        }
 
        switch (argv->v0.type) {
        case NVIF_IOCTL_V0_NEW:
-               ret = usif_object_new(filp, data, size, argv, argc);
+               ret = usif_object_new(filp, data, size, argv, argc, abi16);
                break;
        case NVIF_IOCTL_V0_NTFY_NEW:
                ret = usif_notify_new(filp, data, size, argv, argc);
index 12644f8..a3264a0 100644 (file)
@@ -32,7 +32,7 @@
 int
 nvif_client_ioctl(struct nvif_client *client, void *data, u32 size)
 {
-       return client->driver->ioctl(client->object.priv, client->super, data, size, NULL);
+       return client->driver->ioctl(client->object.priv, data, size, NULL);
 }
 
 int
@@ -80,7 +80,6 @@ nvif_client_ctor(struct nvif_client *parent, const char *name, u64 device,
        client->object.client = client;
        client->object.handle = ~0;
        client->route = NVIF_IOCTL_V0_ROUTE_NVIF;
-       client->super = true;
        client->driver = parent->driver;
 
        if (ret == 0) {
index 671a5c0..dce1ece 100644 (file)
@@ -44,8 +44,7 @@ nvif_object_ioctl(struct nvif_object *object, void *data, u32 size, void **hack)
        } else
                return -ENOSYS;
 
-       return client->driver->ioctl(client->object.priv, client->super,
-                                    data, size, hack);
+       return client->driver->ioctl(client->object.priv, data, size, hack);
 }
 
 void
index d777df5..735cb68 100644 (file)
@@ -426,8 +426,7 @@ nvkm_ioctl_path(struct nvkm_client *client, u64 handle, u32 type,
 }
 
 int
-nvkm_ioctl(struct nvkm_client *client, bool supervisor,
-          void *data, u32 size, void **hack)
+nvkm_ioctl(struct nvkm_client *client, void *data, u32 size, void **hack)
 {
        struct nvkm_object *object = &client->object;
        union {
@@ -435,7 +434,6 @@ nvkm_ioctl(struct nvkm_client *client, bool supervisor,
        } *args = data;
        int ret = -ENOSYS;
 
-       client->super = supervisor;
        nvif_ioctl(object, "size %d\n", size);
 
        if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) {
index b930f53..93ddf63 100644 (file)
@@ -2624,6 +2624,26 @@ nv174_chipset = {
        .dma      = { 0x00000001, gv100_dma_new },
 };
 
+static const struct nvkm_device_chip
+nv177_chipset = {
+       .name = "GA107",
+       .bar      = { 0x00000001, tu102_bar_new },
+       .bios     = { 0x00000001, nvkm_bios_new },
+       .devinit  = { 0x00000001, ga100_devinit_new },
+       .fb       = { 0x00000001, ga102_fb_new },
+       .gpio     = { 0x00000001, ga102_gpio_new },
+       .i2c      = { 0x00000001, gm200_i2c_new },
+       .imem     = { 0x00000001, nv50_instmem_new },
+       .mc       = { 0x00000001, ga100_mc_new },
+       .mmu      = { 0x00000001, tu102_mmu_new },
+       .pci      = { 0x00000001, gp100_pci_new },
+       .privring = { 0x00000001, gm200_privring_new },
+       .timer    = { 0x00000001, gk20a_timer_new },
+       .top      = { 0x00000001, ga100_top_new },
+       .disp     = { 0x00000001, ga102_disp_new },
+       .dma      = { 0x00000001, gv100_dma_new },
+};
+
 static int
 nvkm_device_event_ctor(struct nvkm_object *object, void *data, u32 size,
                       struct nvkm_notify *notify)
@@ -3049,6 +3069,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x168: device->chip = &nv168_chipset; break;
                case 0x172: device->chip = &nv172_chipset; break;
                case 0x174: device->chip = &nv174_chipset; break;
+               case 0x177: device->chip = &nv177_chipset; break;
                default:
                        if (nvkm_boolopt(device->cfgopt, "NvEnableUnsupportedChipsets", false)) {
                                switch (device->chipset) {
index fea9d8f..f28894f 100644 (file)
@@ -397,7 +397,7 @@ nvkm_udevice_new(const struct nvkm_oclass *oclass, void *data, u32 size,
                return ret;
 
        /* give priviledged clients register access */
-       if (client->super)
+       if (args->v0.priv)
                func = &nvkm_udevice_super;
        else
                func = &nvkm_udevice;
index 55fbfe2..9669472 100644 (file)
@@ -440,7 +440,7 @@ nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps)
        return ret;
 }
 
-static void
+void
 nvkm_dp_disable(struct nvkm_outp *outp, struct nvkm_ior *ior)
 {
        struct nvkm_dp *dp = nvkm_dp(outp);
index 428b3f4..e484d0c 100644 (file)
@@ -32,6 +32,7 @@ struct nvkm_dp {
 
 int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *,
                struct nvkm_outp **);
+void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *);
 
 /* DPCD Receiver Capabilities */
 #define DPCD_RC00_DPCD_REV                                              0x00000
index dffcac2..129982f 100644 (file)
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 #include "outp.h"
+#include "dp.h"
 #include "ior.h"
 
 #include <subdev/bios.h>
@@ -257,6 +258,14 @@ nvkm_outp_init_route(struct nvkm_outp *outp)
        if (!ior->arm.head || ior->arm.proto != proto) {
                OUTP_DBG(outp, "no heads (%x %d %d)", ior->arm.head,
                         ior->arm.proto, proto);
+
+               /* The EFI GOP driver on Ampere can leave unused DP links routed,
+                * which we don't expect.  The DisableLT IED script *should* get
+                * us back to where we need to be.
+                */
+               if (ior->func->route.get && !ior->arm.head && outp->info.type == DCB_OUTPUT_DP)
+                       nvkm_dp_disable(outp, ior);
+
                return;
        }
 
index d20cc06..797131e 100644 (file)
@@ -26,7 +26,6 @@
 #include <core/client.h>
 #include <core/gpuobj.h>
 #include <subdev/fb.h>
-#include <subdev/instmem.h>
 
 #include <nvif/cl0002.h>
 #include <nvif/unpack.h>
@@ -72,11 +71,7 @@ nvkm_dmaobj_ctor(const struct nvkm_dmaobj_func *func, struct nvkm_dma *dma,
        union {
                struct nv_dma_v0 v0;
        } *args = *pdata;
-       struct nvkm_device *device = dma->engine.subdev.device;
-       struct nvkm_client *client = oclass->client;
        struct nvkm_object *parent = oclass->parent;
-       struct nvkm_instmem *instmem = device->imem;
-       struct nvkm_fb *fb = device->fb;
        void *data = *pdata;
        u32 size = *psize;
        int ret = -ENOSYS;
@@ -109,23 +104,13 @@ nvkm_dmaobj_ctor(const struct nvkm_dmaobj_func *func, struct nvkm_dma *dma,
                dmaobj->target = NV_MEM_TARGET_VM;
                break;
        case NV_DMA_V0_TARGET_VRAM:
-               if (!client->super) {
-                       if (dmaobj->limit >= fb->ram->size - instmem->reserved)
-                               return -EACCES;
-                       if (device->card_type >= NV_50)
-                               return -EACCES;
-               }
                dmaobj->target = NV_MEM_TARGET_VRAM;
                break;
        case NV_DMA_V0_TARGET_PCI:
-               if (!client->super)
-                       return -EACCES;
                dmaobj->target = NV_MEM_TARGET_PCI;
                break;
        case NV_DMA_V0_TARGET_PCI_US:
        case NV_DMA_V0_TARGET_AGP:
-               if (!client->super)
-                       return -EACCES;
                dmaobj->target = NV_MEM_TARGET_PCI_NOSNOOP;
                break;
        default:
index 90e9a09..3209eb7 100644 (file)
@@ -27,8 +27,6 @@ nvkm-y += nvkm/engine/fifo/dmanv04.o
 nvkm-y += nvkm/engine/fifo/dmanv10.o
 nvkm-y += nvkm/engine/fifo/dmanv17.o
 nvkm-y += nvkm/engine/fifo/dmanv40.o
-nvkm-y += nvkm/engine/fifo/dmanv50.o
-nvkm-y += nvkm/engine/fifo/dmag84.o
 
 nvkm-y += nvkm/engine/fifo/gpfifonv50.o
 nvkm-y += nvkm/engine/fifo/gpfifog84.o
index af8bdf2..3a95730 100644 (file)
@@ -48,8 +48,6 @@ void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int);
 int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push,
                       const struct nvkm_oclass *, struct nv50_fifo_chan *);
 
-extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass;
 extern const struct nvkm_fifo_chan_oclass nv50_fifo_gpfifo_oclass;
-extern const struct nvkm_fifo_chan_oclass g84_fifo_dma_oclass;
 extern const struct nvkm_fifo_chan_oclass g84_fifo_gpfifo_oclass;
 #endif
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c
deleted file mode 100644 (file)
index fc34cdd..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-#include "channv50.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-
-#include <nvif/class.h>
-#include <nvif/cl826e.h>
-#include <nvif/unpack.h>
-
-static int
-g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
-                void *data, u32 size, struct nvkm_object **pobject)
-{
-       struct nvkm_object *parent = oclass->parent;
-       union {
-               struct g82_channel_dma_v0 v0;
-       } *args = data;
-       struct nv50_fifo *fifo = nv50_fifo(base);
-       struct nv50_fifo_chan *chan;
-       int ret = -ENOSYS;
-
-       nvif_ioctl(parent, "create channel dma size %d\n", size);
-       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
-               nvif_ioctl(parent, "create channel dma vers %d vmm %llx "
-                                  "pushbuf %llx offset %016llx\n",
-                          args->v0.version, args->v0.vmm, args->v0.pushbuf,
-                          args->v0.offset);
-               if (!args->v0.pushbuf)
-                       return -EINVAL;
-       } else
-               return ret;
-
-       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
-               return -ENOMEM;
-       *pobject = &chan->base.object;
-
-       ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
-                                oclass, chan);
-       if (ret)
-               return ret;
-
-       args->v0.chid = chan->base.chid;
-
-       nvkm_kmap(chan->ramfc);
-       nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078);
-       nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
-       nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
-       nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff);
-       nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
-       nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
-       nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
-       nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
-                                    (4 << 24) /* SEARCH_FULL */ |
-                                    (chan->ramht->gpuobj->node->offset >> 4));
-       nvkm_wo32(chan->ramfc, 0x88, chan->cache->addr >> 10);
-       nvkm_wo32(chan->ramfc, 0x98, chan->base.inst->addr >> 12);
-       nvkm_done(chan->ramfc);
-       return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-g84_fifo_dma_oclass = {
-       .base.oclass = G82_CHANNEL_DMA,
-       .base.minver = 0,
-       .base.maxver = 0,
-       .ctor = g84_fifo_dma_new,
-};
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c
deleted file mode 100644 (file)
index 8043718..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2012 Red Hat Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- *
- * Authors: Ben Skeggs
- */
-#include "channv50.h"
-
-#include <core/client.h>
-#include <core/ramht.h>
-
-#include <nvif/class.h>
-#include <nvif/cl506e.h>
-#include <nvif/unpack.h>
-
-static int
-nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass,
-                 void *data, u32 size, struct nvkm_object **pobject)
-{
-       struct nvkm_object *parent = oclass->parent;
-       union {
-               struct nv50_channel_dma_v0 v0;
-       } *args = data;
-       struct nv50_fifo *fifo = nv50_fifo(base);
-       struct nv50_fifo_chan *chan;
-       int ret = -ENOSYS;
-
-       nvif_ioctl(parent, "create channel dma size %d\n", size);
-       if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) {
-               nvif_ioctl(parent, "create channel dma vers %d vmm %llx "
-                                  "pushbuf %llx offset %016llx\n",
-                          args->v0.version, args->v0.vmm, args->v0.pushbuf,
-                          args->v0.offset);
-               if (!args->v0.pushbuf)
-                       return -EINVAL;
-       } else
-               return ret;
-
-       if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL)))
-               return -ENOMEM;
-       *pobject = &chan->base.object;
-
-       ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf,
-                                 oclass, chan);
-       if (ret)
-               return ret;
-
-       args->v0.chid = chan->base.chid;
-
-       nvkm_kmap(chan->ramfc);
-       nvkm_wo32(chan->ramfc, 0x08, lower_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x0c, upper_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x10, lower_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x14, upper_32_bits(args->v0.offset));
-       nvkm_wo32(chan->ramfc, 0x3c, 0x003f6078);
-       nvkm_wo32(chan->ramfc, 0x44, 0x01003fff);
-       nvkm_wo32(chan->ramfc, 0x48, chan->base.push->node->offset >> 4);
-       nvkm_wo32(chan->ramfc, 0x4c, 0xffffffff);
-       nvkm_wo32(chan->ramfc, 0x60, 0x7fffffff);
-       nvkm_wo32(chan->ramfc, 0x78, 0x00000000);
-       nvkm_wo32(chan->ramfc, 0x7c, 0x30000001);
-       nvkm_wo32(chan->ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
-                                    (4 << 24) /* SEARCH_FULL */ |
-                                    (chan->ramht->gpuobj->node->offset >> 4));
-       nvkm_done(chan->ramfc);
-       return 0;
-}
-
-const struct nvkm_fifo_chan_oclass
-nv50_fifo_dma_oclass = {
-       .base.oclass = NV50_CHANNEL_DMA,
-       .base.minver = 0,
-       .base.maxver = 0,
-       .ctor = nv50_fifo_dma_new,
-};
index c0a7d0f..3885c38 100644 (file)
@@ -119,7 +119,6 @@ g84_fifo = {
        .uevent_init = g84_fifo_uevent_init,
        .uevent_fini = g84_fifo_uevent_fini,
        .chan = {
-               &g84_fifo_dma_oclass,
                &g84_fifo_gpfifo_oclass,
                NULL
        },
index b6900a5..ae6c4d8 100644 (file)
@@ -341,8 +341,6 @@ gk104_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                                   "runlist %016llx priv %d\n",
                           args->v0.version, args->v0.vmm, args->v0.ioffset,
                           args->v0.ilength, args->v0.runlist, args->v0.priv);
-               if (args->v0.priv && !oclass->client->super)
-                       return -EINVAL;
                return gk104_fifo_gpfifo_new_(fifo,
                                              &args->v0.runlist,
                                              &args->v0.chid,
index ee4967b..743791c 100644 (file)
@@ -226,8 +226,6 @@ gv100_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                                   "runlist %016llx priv %d\n",
                           args->v0.version, args->v0.vmm, args->v0.ioffset,
                           args->v0.ilength, args->v0.runlist, args->v0.priv);
-               if (args->v0.priv && !oclass->client->super)
-                       return -EINVAL;
                return gv100_fifo_gpfifo_new_(&gv100_fifo_gpfifo, fifo,
                                              &args->v0.runlist,
                                              &args->v0.chid,
index abef7fb..99aafa1 100644 (file)
@@ -65,8 +65,6 @@ tu102_fifo_gpfifo_new(struct gk104_fifo *fifo, const struct nvkm_oclass *oclass,
                                   "runlist %016llx priv %d\n",
                           args->v0.version, args->v0.vmm, args->v0.ioffset,
                           args->v0.ilength, args->v0.runlist, args->v0.priv);
-               if (args->v0.priv && !oclass->client->super)
-                       return -EINVAL;
                return gv100_fifo_gpfifo_new_(&tu102_fifo_gpfifo, fifo,
                                              &args->v0.runlist,
                                              &args->v0.chid,
index be94156..a08742c 100644 (file)
@@ -136,7 +136,6 @@ nv50_fifo = {
        .pause = nv04_fifo_pause,
        .start = nv04_fifo_start,
        .chan = {
-               &nv50_fifo_dma_oclass,
                &nv50_fifo_gpfifo_oclass,
                NULL
        },
index fac2f9a..e530bb8 100644 (file)
@@ -41,7 +41,7 @@ nvkm_umem_search(struct nvkm_client *client, u64 handle)
 
        object = nvkm_object_search(client, handle, &nvkm_umem);
        if (IS_ERR(object)) {
-               if (client->super && client != master) {
+               if (client != master) {
                        spin_lock(&master->lock);
                        list_for_each_entry(umem, &master->umem, head) {
                                if (umem->object.object == handle) {
@@ -53,8 +53,7 @@ nvkm_umem_search(struct nvkm_client *client, u64 handle)
                }
        } else {
                umem = nvkm_umem(object);
-               if (!umem->priv || client->super)
-                       memory = nvkm_memory_ref(umem->memory);
+               memory = nvkm_memory_ref(umem->memory);
        }
 
        return memory ? memory : ERR_PTR(-ENOENT);
@@ -167,7 +166,6 @@ nvkm_umem_new(const struct nvkm_oclass *oclass, void *argv, u32 argc,
        nvkm_object_ctor(&nvkm_umem, oclass, &umem->object);
        umem->mmu = mmu;
        umem->type = mmu->type[type].type;
-       umem->priv = oclass->client->super;
        INIT_LIST_HEAD(&umem->head);
        *pobject = &umem->object;
 
index 85cf692..d56a594 100644 (file)
@@ -8,7 +8,6 @@ struct nvkm_umem {
        struct nvkm_object object;
        struct nvkm_mmu *mmu;
        u8 type:8;
-       bool priv:1;
        bool mappable:1;
        bool io:1;
 
index 0e4b894..6870fda 100644 (file)
@@ -34,7 +34,7 @@ nvkm_ummu_sclass(struct nvkm_object *object, int index,
 {
        struct nvkm_mmu *mmu = nvkm_ummu(object)->mmu;
 
-       if (mmu->func->mem.user.oclass && oclass->client->super) {
+       if (mmu->func->mem.user.oclass) {
                if (index-- == 0) {
                        oclass->base = mmu->func->mem.user;
                        oclass->ctor = nvkm_umem_new;
index c43b824..d6a1f8d 100644 (file)
@@ -45,7 +45,6 @@ nvkm_uvmm_search(struct nvkm_client *client, u64 handle)
 static int
 nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_pfnclr_v0 v0;
        } *args = argv;
@@ -59,9 +58,6 @@ nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
        } else
                return ret;
 
-       if (!client->super)
-               return -ENOENT;
-
        if (size) {
                mutex_lock(&vmm->mutex);
                ret = nvkm_vmm_pfn_unmap(vmm, addr, size);
@@ -74,7 +70,6 @@ nvkm_uvmm_mthd_pfnclr(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 static int
 nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_pfnmap_v0 v0;
        } *args = argv;
@@ -93,9 +88,6 @@ nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
        } else
                return ret;
 
-       if (!client->super)
-               return -ENOENT;
-
        if (size) {
                mutex_lock(&vmm->mutex);
                ret = nvkm_vmm_pfn_map(vmm, page, addr, size, phys);
@@ -108,7 +100,6 @@ nvkm_uvmm_mthd_pfnmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 static int
 nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_unmap_v0 v0;
        } *args = argv;
@@ -130,9 +121,8 @@ nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                goto done;
        }
 
-       if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
-               VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
-                         vma->user, !client->super, vma->busy);
+       if (ret = -ENOENT, vma->busy) {
+               VMM_DEBUG(vmm, "denied %016llx: %d", addr, vma->busy);
                goto done;
        }
 
@@ -181,9 +171,8 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                goto fail;
        }
 
-       if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
-               VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
-                         vma->user, !client->super, vma->busy);
+       if (ret = -ENOENT, vma->busy) {
+               VMM_DEBUG(vmm, "denied %016llx: %d", addr, vma->busy);
                goto fail;
        }
 
@@ -230,7 +219,6 @@ fail:
 static int
 nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_put_v0 v0;
        } *args = argv;
@@ -252,9 +240,8 @@ nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                goto done;
        }
 
-       if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) {
-               VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr,
-                         vma->user, !client->super, vma->busy);
+       if (ret = -ENOENT, vma->busy) {
+               VMM_DEBUG(vmm, "denied %016llx: %d", addr, vma->busy);
                goto done;
        }
 
@@ -268,7 +255,6 @@ done:
 static int
 nvkm_uvmm_mthd_get(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
 {
-       struct nvkm_client *client = uvmm->object.client;
        union {
                struct nvif_vmm_get_v0 v0;
        } *args = argv;
@@ -297,7 +283,6 @@ nvkm_uvmm_mthd_get(struct nvkm_uvmm *uvmm, void *argv, u32 argc)
                return ret;
 
        args->v0.addr = vma->addr;
-       vma->user = !client->super;
        return ret;
 }
 
index 710f3f8..8bf00b3 100644 (file)
@@ -774,7 +774,6 @@ nvkm_vma_tail(struct nvkm_vma *vma, u64 tail)
        new->refd = vma->refd;
        new->used = vma->used;
        new->part = vma->part;
-       new->user = vma->user;
        new->busy = vma->busy;
        new->mapped = vma->mapped;
        list_add(&new->head, &vma->head);
@@ -951,7 +950,7 @@ nvkm_vmm_node_split(struct nvkm_vmm *vmm,
 static void
 nvkm_vma_dump(struct nvkm_vma *vma)
 {
-       printk(KERN_ERR "%016llx %016llx %c%c%c%c%c%c%c%c%c %p\n",
+       printk(KERN_ERR "%016llx %016llx %c%c%c%c%c%c%c%c %p\n",
               vma->addr, (u64)vma->size,
               vma->used ? '-' : 'F',
               vma->mapref ? 'R' : '-',
@@ -959,7 +958,6 @@ nvkm_vma_dump(struct nvkm_vma *vma)
               vma->page != NVKM_VMA_PAGE_NONE ? '0' + vma->page : '-',
               vma->refd != NVKM_VMA_PAGE_NONE ? '0' + vma->refd : '-',
               vma->part ? 'P' : '-',
-              vma->user ? 'U' : '-',
               vma->busy ? 'B' : '-',
               vma->mapped ? 'M' : '-',
               vma->memory);
@@ -1024,7 +1022,6 @@ nvkm_vmm_ctor_managed(struct nvkm_vmm *vmm, u64 addr, u64 size)
        vma->mapref = true;
        vma->sparse = false;
        vma->used = true;
-       vma->user = true;
        nvkm_vmm_node_insert(vmm, vma);
        list_add_tail(&vma->head, &vmm->list);
        return 0;
@@ -1615,7 +1612,6 @@ nvkm_vmm_put_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma)
        vma->page = NVKM_VMA_PAGE_NONE;
        vma->refd = NVKM_VMA_PAGE_NONE;
        vma->used = false;
-       vma->user = false;
        nvkm_vmm_put_region(vmm, vma);
 }
 
index f02abd9..b5e7337 100644 (file)
@@ -534,15 +534,13 @@ int
 gp100_vmm_mthd(struct nvkm_vmm *vmm,
               struct nvkm_client *client, u32 mthd, void *argv, u32 argc)
 {
-       if (client->super) {
-               switch (mthd) {
-               case GP100_VMM_VN_FAULT_REPLAY:
-                       return gp100_vmm_fault_replay(vmm, argv, argc);
-               case GP100_VMM_VN_FAULT_CANCEL:
-                       return gp100_vmm_fault_cancel(vmm, argv, argc);
-               default:
-                       break;
-               }
+       switch (mthd) {
+       case GP100_VMM_VN_FAULT_REPLAY:
+               return gp100_vmm_fault_replay(vmm, argv, argc);
+       case GP100_VMM_VN_FAULT_CANCEL:
+               return gp100_vmm_fault_cancel(vmm, argv, argc);
+       default:
+               break;
        }
        return -EINVAL;
 }
index 74e3b46..2df59b3 100644 (file)
@@ -78,9 +78,7 @@ static int ttm_global_init(void)
 
        ttm_debugfs_root = debugfs_create_dir("ttm", NULL);
        if (IS_ERR(ttm_debugfs_root)) {
-               ret = PTR_ERR(ttm_debugfs_root);
                ttm_debugfs_root = NULL;
-               goto out;
        }
 
        /* Limit the number of pages in the pool to about 50% of the total
index d1cef3b..5652d98 100644 (file)
@@ -492,7 +492,7 @@ struct vmw_private {
        resource_size_t vram_start;
        resource_size_t vram_size;
        resource_size_t prim_bb_mem;
-       void __iomem *rmmio;
+       u32 __iomem *rmmio;
        u32 *fifo_mem;
        resource_size_t fifo_mem_size;
        uint32_t fb_max_width;
index a1c85d1..82b244c 100644 (file)
@@ -585,21 +585,21 @@ static const struct ipu_rgb def_bgra_16 = {
        .bits_per_pixel = 16,
 };
 
-#define Y_OFFSET(pix, x, y)    ((x) + pix->width * (y))
-#define U_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
-                                (pix->width * ((y) / 2) / 2) + (x) / 2)
-#define V_OFFSET(pix, x, y)    ((pix->width * pix->height) +           \
-                                (pix->width * pix->height / 4) +       \
-                                (pix->width * ((y) / 2) / 2) + (x) / 2)
-#define U2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
-                                (pix->width * (y) / 2) + (x) / 2)
-#define V2_OFFSET(pix, x, y)   ((pix->width * pix->height) +           \
-                                (pix->width * pix->height / 2) +       \
-                                (pix->width * (y) / 2) + (x) / 2)
-#define UV_OFFSET(pix, x, y)   ((pix->width * pix->height) +   \
-                                (pix->width * ((y) / 2)) + (x))
-#define UV2_OFFSET(pix, x, y)  ((pix->width * pix->height) +   \
-                                (pix->width * y) + (x))
+#define Y_OFFSET(pix, x, y)    ((x) + pix->bytesperline * (y))
+#define U_OFFSET(pix, x, y)    ((pix->bytesperline * pix->height) +     \
+                                (pix->bytesperline * ((y) / 2) / 2) + (x) / 2)
+#define V_OFFSET(pix, x, y)    ((pix->bytesperline * pix->height) +     \
+                                (pix->bytesperline * pix->height / 4) + \
+                                (pix->bytesperline * ((y) / 2) / 2) + (x) / 2)
+#define U2_OFFSET(pix, x, y)   ((pix->bytesperline * pix->height) +     \
+                                (pix->bytesperline * (y) / 2) + (x) / 2)
+#define V2_OFFSET(pix, x, y)   ((pix->bytesperline * pix->height) +     \
+                                (pix->bytesperline * pix->height / 2) + \
+                                (pix->bytesperline * (y) / 2) + (x) / 2)
+#define UV_OFFSET(pix, x, y)   ((pix->bytesperline * pix->height) +     \
+                                (pix->bytesperline * ((y) / 2)) + (x))
+#define UV2_OFFSET(pix, x, y)  ((pix->bytesperline * pix->height) +     \
+                                (pix->bytesperline * y) + (x))
 
 #define NUM_ALPHA_CHANNELS     7
 
index cceaf69..6304d1d 100644 (file)
@@ -1224,14 +1224,14 @@ static int bcm_iproc_i2c_unreg_slave(struct i2c_client *slave)
 
        disable_irq(iproc_i2c->irq);
 
+       tasklet_kill(&iproc_i2c->slave_rx_tasklet);
+
        /* disable all slave interrupts */
        tmp = iproc_i2c_rd_reg(iproc_i2c, IE_OFFSET);
        tmp &= ~(IE_S_ALL_INTERRUPT_MASK <<
                        IE_S_ALL_INTERRUPT_SHIFT);
        iproc_i2c_wr_reg(iproc_i2c, IE_OFFSET, tmp);
 
-       tasklet_kill(&iproc_i2c->slave_rx_tasklet);
-
        /* Erase the slave address programmed */
        tmp = iproc_i2c_rd_reg(iproc_i2c, S_CFG_SMBUS_ADDR_OFFSET);
        tmp &= ~BIT(S_CFG_EN_NIC_SMB_ADDR3_SHIFT);
index cb64fe6..77f576e 100644 (file)
@@ -141,7 +141,7 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,
        if (count > 8192)
                count = 8192;
 
-       tmp = kmalloc(count, GFP_KERNEL);
+       tmp = kzalloc(count, GFP_KERNEL);
        if (tmp == NULL)
                return -ENOMEM;
 
@@ -150,7 +150,8 @@ static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count,
 
        ret = i2c_master_recv(client, tmp, count);
        if (ret >= 0)
-               ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret;
+               if (copy_to_user(buf, tmp, ret))
+                       ret = -EFAULT;
        kfree(tmp);
        return ret;
 }
index 0e56ace..8d8b1ba 100644 (file)
@@ -231,6 +231,7 @@ config DMARD10
 
 config FXLS8962AF
        tristate
+       depends on I2C || !I2C # cannot be built-in for modular I2C
 
 config FXLS8962AF_I2C
        tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer I2C Driver"
@@ -247,6 +248,7 @@ config FXLS8962AF_I2C
 config FXLS8962AF_SPI
        tristate "NXP FXLS8962AF/FXLS8964AF Accelerometer SPI Driver"
        depends on SPI
+       depends on I2C || !I2C
        select FXLS8962AF
        select REGMAP_SPI
        help
index 078d878..0019f1e 100644 (file)
@@ -637,7 +637,7 @@ static int fxls8962af_i2c_raw_read_errata3(struct fxls8962af_data *data,
                        return ret;
        }
 
-       return ret;
+       return 0;
 }
 
 static int fxls8962af_fifo_transfer(struct fxls8962af_data *data,
index 6ef0960..f9c8385 100644 (file)
@@ -664,8 +664,8 @@ static int palmas_adc_wakeup_configure(struct palmas_gpadc *adc)
 
        adc_period = adc->auto_conversion_period;
        for (i = 0; i < 16; ++i) {
-               if (((1000 * (1 << i)) / 32) < adc_period)
-                       continue;
+               if (((1000 * (1 << i)) / 32) >= adc_period)
+                       break;
        }
        if (i > 0)
                i--;
index 2383eac..a2b83f0 100644 (file)
@@ -568,7 +568,6 @@ static int ti_ads7950_probe(struct spi_device *spi)
        st->ring_xfer.tx_buf = &st->tx_buf[0];
        st->ring_xfer.rx_buf = &st->rx_buf[0];
        /* len will be set later */
-       st->ring_xfer.cs_change = true;
 
        spi_message_add_tail(&st->ring_xfer, &st->ring_msg);
 
index 2a957f1..9e0fce9 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/iio/trigger_consumer.h>
 #include <linux/iio/triggered_buffer.h>
 
+#include <linux/time.h>
+
 #define HDC100X_REG_TEMP                       0x00
 #define HDC100X_REG_HUMIDITY                   0x01
 
@@ -166,7 +168,7 @@ static int hdc100x_get_measurement(struct hdc100x_data *data,
                                   struct iio_chan_spec const *chan)
 {
        struct i2c_client *client = data->client;
-       int delay = data->adc_int_us[chan->address];
+       int delay = data->adc_int_us[chan->address] + 1*USEC_PER_MSEC;
        int ret;
        __be16 val;
 
@@ -316,7 +318,7 @@ static irqreturn_t hdc100x_trigger_handler(int irq, void *p)
        struct iio_dev *indio_dev = pf->indio_dev;
        struct hdc100x_data *data = iio_priv(indio_dev);
        struct i2c_client *client = data->client;
-       int delay = data->adc_int_us[0] + data->adc_int_us[1];
+       int delay = data->adc_int_us[0] + data->adc_int_us[1] + 2*USEC_PER_MSEC;
        int ret;
 
        /* dual read starts at temp register */
index a5b421f..b9a06ca 100644 (file)
@@ -411,12 +411,11 @@ int __adis_initial_startup(struct adis *adis)
        int ret;
 
        /* check if the device has rst pin low */
-       gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_ASIS);
+       gpio = devm_gpiod_get_optional(&adis->spi->dev, "reset", GPIOD_OUT_HIGH);
        if (IS_ERR(gpio))
                return PTR_ERR(gpio);
 
        if (gpio) {
-               gpiod_set_value_cansleep(gpio, 1);
                msleep(10);
                /* bring device out of reset */
                gpiod_set_value_cansleep(gpio, 0);
index 515a7e9..5d3b8b8 100644 (file)
@@ -926,12 +926,25 @@ static int cma_init_ud_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
        return ret;
 }
 
+static int cma_init_conn_qp(struct rdma_id_private *id_priv, struct ib_qp *qp)
+{
+       struct ib_qp_attr qp_attr;
+       int qp_attr_mask, ret;
+
+       qp_attr.qp_state = IB_QPS_INIT;
+       ret = rdma_init_qp_attr(&id_priv->id, &qp_attr, &qp_attr_mask);
+       if (ret)
+               return ret;
+
+       return ib_modify_qp(qp, &qp_attr, qp_attr_mask);
+}
+
 int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
                   struct ib_qp_init_attr *qp_init_attr)
 {
        struct rdma_id_private *id_priv;
        struct ib_qp *qp;
-       int ret = 0;
+       int ret;
 
        id_priv = container_of(id, struct rdma_id_private, id);
        if (id->device != pd->device) {
@@ -948,6 +961,8 @@ int rdma_create_qp(struct rdma_cm_id *id, struct ib_pd *pd,
 
        if (id->qp_type == IB_QPT_UD)
                ret = cma_init_ud_qp(id_priv, qp);
+       else
+               ret = cma_init_conn_qp(id_priv, qp);
        if (ret)
                goto out_destroy;
 
index f782d5e..03e1db5 100644 (file)
@@ -249,6 +249,9 @@ static int UVERBS_HANDLER(UVERBS_METHOD_REG_DMABUF_MR)(
        mr->uobject = uobj;
        atomic_inc(&pd->usecnt);
 
+       rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
+       rdma_restrack_set_name(&mr->res, NULL);
+       rdma_restrack_add(&mr->res);
        uobj->object = mr;
 
        uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_REG_DMABUF_MR_HANDLE);
index 283b6b8..ea0054c 100644 (file)
@@ -1681,6 +1681,7 @@ int bnxt_re_create_srq(struct ib_srq *ib_srq,
        if (nq)
                nq->budget++;
        atomic_inc(&rdev->srq_count);
+       spin_lock_init(&srq->lock);
 
        return 0;
 
index a8688a9..4678bd6 100644 (file)
@@ -1397,7 +1397,6 @@ static int bnxt_re_dev_init(struct bnxt_re_dev *rdev, u8 wqe_mode)
        memset(&rattr, 0, sizeof(rattr));
        rc = bnxt_re_register_netdev(rdev);
        if (rc) {
-               rtnl_unlock();
                ibdev_err(&rdev->ibdev,
                          "Failed to register with netedev: %#x\n", rc);
                return -EINVAL;
index 6c8c910..c7e8d7b 100644 (file)
@@ -967,6 +967,12 @@ int c4iw_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc)
        return !err || err == -ENODATA ? npolled : err;
 }
 
+void c4iw_cq_rem_ref(struct c4iw_cq *chp)
+{
+       if (refcount_dec_and_test(&chp->refcnt))
+               complete(&chp->cq_rel_comp);
+}
+
 int c4iw_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
 {
        struct c4iw_cq *chp;
@@ -976,8 +982,8 @@ int c4iw_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata)
        chp = to_c4iw_cq(ib_cq);
 
        xa_erase_irq(&chp->rhp->cqs, chp->cq.cqid);
-       refcount_dec(&chp->refcnt);
-       wait_event(chp->wait, !refcount_read(&chp->refcnt));
+       c4iw_cq_rem_ref(chp);
+       wait_for_completion(&chp->cq_rel_comp);
 
        ucontext = rdma_udata_to_drv_context(udata, struct c4iw_ucontext,
                                             ibucontext);
@@ -1081,7 +1087,7 @@ int c4iw_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
        spin_lock_init(&chp->lock);
        spin_lock_init(&chp->comp_handler_lock);
        refcount_set(&chp->refcnt, 1);
-       init_waitqueue_head(&chp->wait);
+       init_completion(&chp->cq_rel_comp);
        ret = xa_insert_irq(&rhp->cqs, chp->cq.cqid, chp, GFP_KERNEL);
        if (ret)
                goto err_destroy_cq;
index 7798d09..34211a5 100644 (file)
@@ -213,8 +213,7 @@ void c4iw_ev_dispatch(struct c4iw_dev *dev, struct t4_cqe *err_cqe)
                break;
        }
 done:
-       if (refcount_dec_and_test(&chp->refcnt))
-               wake_up(&chp->wait);
+       c4iw_cq_rem_ref(chp);
        c4iw_qp_rem_ref(&qhp->ibqp);
 out:
        return;
@@ -234,8 +233,7 @@ int c4iw_ev_handler(struct c4iw_dev *dev, u32 qid)
                spin_lock_irqsave(&chp->comp_handler_lock, flag);
                (*chp->ibcq.comp_handler)(&chp->ibcq, chp->ibcq.cq_context);
                spin_unlock_irqrestore(&chp->comp_handler_lock, flag);
-               if (refcount_dec_and_test(&chp->refcnt))
-                       wake_up(&chp->wait);
+               c4iw_cq_rem_ref(chp);
        } else {
                pr_debug("unknown cqid 0x%x\n", qid);
                xa_unlock_irqrestore(&dev->cqs, flag);
index 3883af3..ac5f581 100644 (file)
@@ -428,7 +428,7 @@ struct c4iw_cq {
        spinlock_t lock;
        spinlock_t comp_handler_lock;
        refcount_t refcnt;
-       wait_queue_head_t wait;
+       struct completion cq_rel_comp;
        struct c4iw_wr_wait *wr_waitp;
 };
 
@@ -979,6 +979,7 @@ struct ib_mr *c4iw_reg_user_mr(struct ib_pd *pd, u64 start,
 struct ib_mr *c4iw_get_dma_mr(struct ib_pd *pd, int acc);
 int c4iw_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata);
 int c4iw_destroy_cq(struct ib_cq *ib_cq, struct ib_udata *udata);
+void c4iw_cq_rem_ref(struct c4iw_cq *chp);
 int c4iw_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
                   struct ib_udata *udata);
 int c4iw_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags flags);
index 203e6dd..be4a07b 100644 (file)
@@ -357,6 +357,7 @@ static int efa_enable_msix(struct efa_dev *dev)
        }
 
        if (irq_num != msix_vecs) {
+               efa_disable_msix(dev);
                dev_err(&dev->pdev->dev,
                        "Allocated %d MSI-X (out of %d requested)\n",
                        irq_num, msix_vecs);
index eb15c31..e83dc56 100644 (file)
@@ -3055,6 +3055,7 @@ static void __sdma_process_event(struct sdma_engine *sde,
 static int _extend_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx)
 {
        int i;
+       struct sdma_desc *descp;
 
        /* Handle last descriptor */
        if (unlikely((tx->num_desc == (MAX_DESC - 1)))) {
@@ -3075,12 +3076,10 @@ static int _extend_sdma_tx_descs(struct hfi1_devdata *dd, struct sdma_txreq *tx)
        if (unlikely(tx->num_desc == MAX_DESC))
                goto enomem;
 
-       tx->descp = kmalloc_array(
-                       MAX_DESC,
-                       sizeof(struct sdma_desc),
-                       GFP_ATOMIC);
-       if (!tx->descp)
+       descp = kmalloc_array(MAX_DESC, sizeof(struct sdma_desc), GFP_ATOMIC);
+       if (!descp)
                goto enomem;
+       tx->descp = descp;
 
        /* reserve last descriptor for coalescing */
        tx->desc_limit = MAX_DESC - 1;
index 8f68cc3..84f3f2b 100644 (file)
@@ -213,8 +213,10 @@ int hns_roce_cmd_use_events(struct hns_roce_dev *hr_dev)
 
        hr_cmd->context =
                kcalloc(hr_cmd->max_cmds, sizeof(*hr_cmd->context), GFP_KERNEL);
-       if (!hr_cmd->context)
+       if (!hr_cmd->context) {
+               hr_dev->cmd_mod = 0;
                return -ENOMEM;
+       }
 
        for (i = 0; i < hr_cmd->max_cmds; ++i) {
                hr_cmd->context[i].token = i;
@@ -228,7 +230,6 @@ int hns_roce_cmd_use_events(struct hns_roce_dev *hr_dev)
        spin_lock_init(&hr_cmd->context_lock);
 
        hr_cmd->use_events = 1;
-       down(&hr_cmd->poll_sem);
 
        return 0;
 }
@@ -239,8 +240,6 @@ void hns_roce_cmd_use_polling(struct hns_roce_dev *hr_dev)
 
        kfree(hr_cmd->context);
        hr_cmd->use_events = 0;
-
-       up(&hr_cmd->poll_sem);
 }
 
 struct hns_roce_cmd_mailbox *
index 078a971..cc6eab1 100644 (file)
@@ -873,11 +873,9 @@ int hns_roce_init(struct hns_roce_dev *hr_dev)
 
        if (hr_dev->cmd_mod) {
                ret = hns_roce_cmd_use_events(hr_dev);
-               if (ret) {
+               if (ret)
                        dev_warn(dev,
                                 "Cmd event  mode failed, set back to poll!\n");
-                       hns_roce_cmd_use_polling(hr_dev);
-               }
        }
 
        ret = hns_roce_init_hem(hr_dev);
index dab8828..b6f9c41 100644 (file)
@@ -6,7 +6,7 @@ config INFINIBAND_IRDMA
        depends on PCI
        depends on ICE && I40E
        select GENERIC_ALLOCATOR
-       select CONFIG_AUXILIARY_BUS
+       select AUXILIARY_BUS
        help
          This is an Intel(R) Ethernet Protocol Driver for RDMA driver
          that support E810 (iWARP/RoCE) and X722 (iWARP) network devices.
index 7abeb57..b8e5e37 100644 (file)
@@ -945,7 +945,6 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
        u32 *cqb = NULL;
        void *cqc;
        int cqe_size;
-       unsigned int irqn;
        int eqn;
        int err;
 
@@ -984,7 +983,7 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
                INIT_WORK(&cq->notify_work, notify_soft_wc_handler);
        }
 
-       err = mlx5_vector2eqn(dev->mdev, vector, &eqn, &irqn);
+       err = mlx5_vector2eqn(dev->mdev, vector, &eqn);
        if (err)
                goto err_cqb;
 
@@ -1007,7 +1006,6 @@ int mlx5_ib_create_cq(struct ib_cq *ibcq, const struct ib_cq_init_attr *attr,
                goto err_cqb;
 
        mlx5_ib_dbg(dev, "cqn 0x%x\n", cq->mcq.cqn);
-       cq->mcq.irqn = irqn;
        if (udata)
                cq->mcq.tasklet_ctx.comp = mlx5_ib_cq_comp;
        else
index eb9b0a2..c869b2a 100644 (file)
@@ -975,7 +975,6 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
        struct mlx5_ib_dev *dev;
        int user_vector;
        int dev_eqn;
-       unsigned int irqn;
        int err;
 
        if (uverbs_copy_from(&user_vector, attrs,
@@ -987,7 +986,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_QUERY_EQN)(
                return PTR_ERR(c);
        dev = to_mdev(c->ibucontext.device);
 
-       err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn, &irqn);
+       err = mlx5_vector2eqn(dev->mdev, user_vector, &dev_eqn);
        if (err < 0)
                return err;
 
index 094c976..2507051 100644 (file)
@@ -4454,7 +4454,8 @@ static void mlx5r_mp_remove(struct auxiliary_device *adev)
        mutex_lock(&mlx5_ib_multiport_mutex);
        if (mpi->ibdev)
                mlx5_ib_unbind_slave_port(mpi->ibdev, mpi);
-       list_del(&mpi->list);
+       else
+               list_del(&mpi->list);
        mutex_unlock(&mlx5_ib_multiport_mutex);
        kfree(mpi);
 }
index 3263851..3f1c5a4 100644 (file)
@@ -531,8 +531,8 @@ static void __cache_work_func(struct mlx5_cache_ent *ent)
                 */
                spin_unlock_irq(&ent->lock);
                need_delay = need_resched() || someone_adding(cache) ||
-                            time_after(jiffies,
-                                       READ_ONCE(cache->last_add) + 300 * HZ);
+                            !time_after(jiffies,
+                                        READ_ONCE(cache->last_add) + 300 * HZ);
                spin_lock_irq(&ent->lock);
                if (ent->disabled)
                        goto out;
index 0ea9a5a..1c1d1b5 100644 (file)
@@ -85,7 +85,7 @@ int rxe_mcast_add_grp_elem(struct rxe_dev *rxe, struct rxe_qp *qp,
                goto out;
        }
 
-       elem = rxe_alloc(&rxe->mc_elem_pool);
+       elem = rxe_alloc_locked(&rxe->mc_elem_pool);
        if (!elem) {
                err = -ENOMEM;
                goto out;
index dec9292..5ac27f2 100644 (file)
@@ -259,6 +259,7 @@ static void prepare_ipv4_hdr(struct dst_entry *dst, struct sk_buff *skb,
 
        iph->version    =       IPVERSION;
        iph->ihl        =       sizeof(struct iphdr) >> 2;
+       iph->tot_len    =       htons(skb->len);
        iph->frag_off   =       df;
        iph->protocol   =       proto;
        iph->tos        =       tos;
index 85b8125..72d9539 100644 (file)
@@ -63,7 +63,7 @@ struct rxe_queue *rxe_queue_init(struct rxe_dev *rxe, int *num_elem,
        if (*num_elem < 0)
                goto err1;
 
-       q = kmalloc(sizeof(*q), GFP_KERNEL);
+       q = kzalloc(sizeof(*q), GFP_KERNEL);
        if (!q)
                goto err1;
 
index 3743dc3..360ec67 100644 (file)
@@ -318,7 +318,7 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp)
                pr_warn("%s: invalid num_sge in SRQ entry\n", __func__);
                return RESPST_ERR_MALFORMED_WQE;
        }
-       size = sizeof(wqe) + wqe->dma.num_sge*sizeof(struct rxe_sge);
+       size = sizeof(*wqe) + wqe->dma.num_sge*sizeof(struct rxe_sge);
        memcpy(&qp->resp.srq_wqe, wqe, size);
 
        qp->resp.wqe = &qp->resp.srq_wqe.wqe;
index 8a1e70e..7887941 100644 (file)
@@ -403,7 +403,7 @@ struct icc_path *devm_of_icc_get(struct device *dev, const char *name)
 {
        struct icc_path **ptr, *path;
 
-       ptr = devres_alloc(devm_icc_release, sizeof(**ptr), GFP_KERNEL);
+       ptr = devres_alloc(devm_icc_release, sizeof(*ptr), GFP_KERNEL);
        if (!ptr)
                return ERR_PTR(-ENOMEM);
 
@@ -973,9 +973,14 @@ void icc_node_add(struct icc_node *node, struct icc_provider *provider)
        }
        node->avg_bw = node->init_avg;
        node->peak_bw = node->init_peak;
+
+       if (provider->pre_aggregate)
+               provider->pre_aggregate(node);
+
        if (provider->aggregate)
                provider->aggregate(node, 0, node->init_avg, node->init_peak,
                                    &node->avg_bw, &node->peak_bw);
+
        provider->set(node, node);
        node->avg_bw = 0;
        node->peak_bw = 0;
@@ -1106,6 +1111,8 @@ void icc_sync_state(struct device *dev)
                dev_dbg(p->dev, "interconnect provider is in synced state\n");
                list_for_each_entry(n, &p->nodes, node_list) {
                        if (n->init_avg || n->init_peak) {
+                               n->init_avg = 0;
+                               n->init_peak = 0;
                                aggregate_requests(n);
                                p->set(n, n);
                        }
index bf01d09..f6fae64 100644 (file)
@@ -57,6 +57,11 @@ int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
                        qn->sum_avg[i] += avg_bw;
                        qn->max_peak[i] = max_t(u32, qn->max_peak[i], peak_bw);
                }
+
+               if (node->init_avg || node->init_peak) {
+                       qn->sum_avg[i] = max_t(u64, qn->sum_avg[i], node->init_avg);
+                       qn->max_peak[i] = max_t(u64, qn->max_peak[i], node->init_peak);
+               }
        }
 
        *agg_avg += avg_bw;
@@ -79,7 +84,6 @@ EXPORT_SYMBOL_GPL(qcom_icc_aggregate);
 int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
 {
        struct qcom_icc_provider *qp;
-       struct qcom_icc_node *qn;
        struct icc_node *node;
 
        if (!src)
@@ -88,12 +92,6 @@ int qcom_icc_set(struct icc_node *src, struct icc_node *dst)
                node = src;
 
        qp = to_qcom_provider(node->provider);
-       qn = node->data;
-
-       qn->sum_avg[QCOM_ICC_BUCKET_AMC] = max_t(u64, qn->sum_avg[QCOM_ICC_BUCKET_AMC],
-                                                node->avg_bw);
-       qn->max_peak[QCOM_ICC_BUCKET_AMC] = max_t(u64, qn->max_peak[QCOM_ICC_BUCKET_AMC],
-                                                 node->peak_bw);
 
        qcom_icc_bcm_voter_commit(qp->voter);
 
index 98ba927..6f0df62 100644 (file)
@@ -768,6 +768,7 @@ static void iommu_dma_free_noncontiguous(struct device *dev, size_t size,
        __iommu_dma_unmap(dev, sgt->sgl->dma_address, size);
        __iommu_dma_free_pages(sh->pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
        sg_free_table(&sh->sgt);
+       kfree(sh);
 }
 #endif /* CONFIG_DMA_REMAP */
 
index c6cf44a..9ec374e 100644 (file)
@@ -511,7 +511,7 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
                                 u32 pasid, bool fault_ignore)
 {
        struct pasid_entry *pte;
-       u16 did;
+       u16 did, pgtt;
 
        pte = intel_pasid_get_entry(dev, pasid);
        if (WARN_ON(!pte))
@@ -521,13 +521,19 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
                return;
 
        did = pasid_get_domain_id(pte);
+       pgtt = pasid_pte_get_pgtt(pte);
+
        intel_pasid_clear_entry(dev, pasid, fault_ignore);
 
        if (!ecap_coherent(iommu->ecap))
                clflush_cache_range(pte, sizeof(*pte));
 
        pasid_cache_invalidation_with_pasid(iommu, did, pasid);
-       qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
+
+       if (pgtt == PASID_ENTRY_PGTT_PT || pgtt == PASID_ENTRY_PGTT_FL_ONLY)
+               qi_flush_piotlb(iommu, did, pasid, 0, -1, 0);
+       else
+               iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
 
        /* Device IOTLB doesn't need to be flushed in caching mode. */
        if (!cap_caching_mode(iommu->cap))
index 5ff61c3..c11bc8b 100644 (file)
@@ -99,6 +99,12 @@ static inline bool pasid_pte_is_present(struct pasid_entry *pte)
        return READ_ONCE(pte->val[0]) & PASID_PTE_PRESENT;
 }
 
+/* Get PGTT field of a PASID table entry */
+static inline u16 pasid_pte_get_pgtt(struct pasid_entry *pte)
+{
+       return (u16)((READ_ONCE(pte->val[0]) >> 6) & 0x7);
+}
+
 extern unsigned int intel_pasid_max_id;
 int intel_pasid_alloc_table(struct device *dev);
 void intel_pasid_free_table(struct device *dev);
index 9b0f22b..4b9b3f3 100644 (file)
@@ -675,7 +675,6 @@ static int intel_svm_unbind_mm(struct device *dev, u32 pasid)
                        kfree_rcu(sdev, rcu);
 
                        if (list_empty(&svm->devs)) {
-                               intel_svm_free_pasid(mm);
                                if (svm->notifier.ops) {
                                        mmu_notifier_unregister(&svm->notifier, mm);
                                        /* Clear mm's pasid. */
@@ -690,6 +689,8 @@ static int intel_svm_unbind_mm(struct device *dev, u32 pasid)
                                kfree(svm);
                        }
                }
+               /* Drop a PASID reference and free it if no reference. */
+               intel_svm_free_pasid(mm);
        }
 out:
        return ret;
index 5419c4b..63f0af1 100644 (file)
@@ -924,6 +924,9 @@ void iommu_group_remove_device(struct device *dev)
        struct iommu_group *group = dev->iommu_group;
        struct group_device *tmp_device, *device = NULL;
 
+       if (!group)
+               return;
+
        dev_info(dev, "Removing from iommu group %d\n", group->id);
 
        /* Pre-notify listeners that a device is being removed. */
index 3461b0a..cbfdade 100644 (file)
@@ -89,16 +89,13 @@ static void tpci200_unregister(struct tpci200_board *tpci200)
        free_irq(tpci200->info->pdev->irq, (void *) tpci200);
 
        pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
-       pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
 
        pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
        pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
-       pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
 
        pci_disable_device(tpci200->info->pdev);
-       pci_dev_put(tpci200->info->pdev);
 }
 
 static void tpci200_enable_irq(struct tpci200_board *tpci200,
@@ -257,7 +254,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_disable_pci;
+               goto err_disable_device;
        }
 
        /* Request IO ID INT space (Bar 3) */
@@ -269,7 +266,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_release_ip_space;
+               goto err_ip_interface_bar;
        }
 
        /* Request MEM8 space (Bar 5) */
@@ -280,7 +277,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_release_ioid_int_space;
+               goto err_io_id_int_spaces_bar;
        }
 
        /* Request MEM16 space (Bar 4) */
@@ -291,7 +288,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_release_mem8_space;
+               goto err_mem8_space_bar;
        }
 
        /* Map internal tpci200 driver user space */
@@ -305,7 +302,7 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
                res = -ENOMEM;
-               goto out_release_mem8_space;
+               goto err_mem16_space_bar;
        }
 
        /* Initialize lock that protects interface_regs */
@@ -344,18 +341,22 @@ static int tpci200_register(struct tpci200_board *tpci200)
                        "(bn 0x%X, sn 0x%X) unable to register IRQ !",
                        tpci200->info->pdev->bus->number,
                        tpci200->info->pdev->devfn);
-               goto out_release_ioid_int_space;
+               goto err_interface_regs;
        }
 
        return 0;
 
-out_release_mem8_space:
+err_interface_regs:
+       pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
+err_mem16_space_bar:
+       pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
+err_mem8_space_bar:
        pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
-out_release_ioid_int_space:
+err_io_id_int_spaces_bar:
        pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
-out_release_ip_space:
+err_ip_interface_bar:
        pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
-out_disable_pci:
+err_disable_device:
        pci_disable_device(tpci200->info->pdev);
        return res;
 }
@@ -527,7 +528,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
        if (!tpci200->info) {
                ret = -ENOMEM;
-               goto out_err_info;
+               goto err_tpci200;
        }
 
        pci_dev_get(pdev);
@@ -538,7 +539,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        if (ret) {
                dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
                ret = -EBUSY;
-               goto out_err_pci_request;
+               goto err_tpci200_info;
        }
        tpci200->info->cfg_regs = ioremap(
                        pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
@@ -546,7 +547,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        if (!tpci200->info->cfg_regs) {
                dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
                ret = -EFAULT;
-               goto out_err_ioremap;
+               goto err_request_region;
        }
 
        /* Disable byte swapping for 16 bit IP module access. This will ensure
@@ -569,7 +570,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
        if (ret) {
                dev_err(&pdev->dev, "error during tpci200 install\n");
                ret = -ENODEV;
-               goto out_err_install;
+               goto err_cfg_regs;
        }
 
        /* Register the carrier in the industry pack bus driver */
@@ -581,7 +582,7 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
                dev_err(&pdev->dev,
                        "error registering the carrier on ipack driver\n");
                ret = -EFAULT;
-               goto out_err_bus_register;
+               goto err_tpci200_install;
        }
 
        /* save the bus number given by ipack to logging purpose */
@@ -592,19 +593,16 @@ static int tpci200_pci_probe(struct pci_dev *pdev,
                tpci200_create_device(tpci200, i);
        return 0;
 
-out_err_bus_register:
+err_tpci200_install:
        tpci200_uninstall(tpci200);
-       /* tpci200->info->cfg_regs is unmapped in tpci200_uninstall */
-       tpci200->info->cfg_regs = NULL;
-out_err_install:
-       if (tpci200->info->cfg_regs)
-               iounmap(tpci200->info->cfg_regs);
-out_err_ioremap:
+err_cfg_regs:
+       pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+err_request_region:
        pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
-out_err_pci_request:
-       pci_dev_put(pdev);
+err_tpci200_info:
        kfree(tpci200->info);
-out_err_info:
+       pci_dev_put(pdev);
+err_tpci200:
        kfree(tpci200);
        return ret;
 }
@@ -614,6 +612,12 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200)
        ipack_bus_unregister(tpci200->info->ipack_bus);
        tpci200_uninstall(tpci200);
 
+       pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+
+       pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
+
+       pci_dev_put(tpci200->info->pdev);
+
        kfree(tpci200->info);
        kfree(tpci200);
 }
index 51f2547..3c44c4b 100644 (file)
@@ -474,8 +474,6 @@ static void raid1_end_write_request(struct bio *bio)
                /*
                 * When the device is faulty, it is not necessary to
                 * handle write error.
-                * For failfast, this is the only remaining device,
-                * We need to retry the write without FailFast.
                 */
                if (!test_bit(Faulty, &rdev->flags))
                        set_bit(R1BIO_WriteError, &r1_bio->state);
index 16977e8..07119d7 100644 (file)
@@ -471,12 +471,12 @@ static void raid10_end_write_request(struct bio *bio)
                        /*
                         * When the device is faulty, it is not necessary to
                         * handle write error.
-                        * For failfast, this is the only remaining device,
-                        * We need to retry the write without FailFast.
                         */
                        if (!test_bit(Faulty, &rdev->flags))
                                set_bit(R10BIO_WriteError, &r10_bio->state);
                        else {
+                               /* Fail the request */
+                               set_bit(R10BIO_Degraded, &r10_bio->state);
                                r10_bio->devs[slot].bio = NULL;
                                to_put = bio;
                                dec_rdev = 1;
index 59a36f9..30d29b9 100644 (file)
@@ -226,7 +226,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
 err_free_swnodes:
        software_node_unregister_nodes(sensor->swnodes);
 err_put_adev:
-       acpi_dev_put(sensor->adev);
+       acpi_dev_put(adev);
        return ret;
 }
 
index d333130..c3229d8 100644 (file)
@@ -2018,8 +2018,8 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
                                        continue;
                                }
 
-                               dw_mci_stop_dma(host);
                                send_stop_abort(host, data);
+                               dw_mci_stop_dma(host);
                                state = STATE_SENDING_STOP;
                                break;
                        }
@@ -2043,10 +2043,10 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
                         */
                        if (test_and_clear_bit(EVENT_DATA_ERROR,
                                               &host->pending_events)) {
-                               dw_mci_stop_dma(host);
                                if (!(host->data_status & (SDMMC_INT_DRTO |
                                                           SDMMC_INT_EBE)))
                                        send_stop_abort(host, data);
+                               dw_mci_stop_dma(host);
                                state = STATE_DATA_ERROR;
                                break;
                        }
@@ -2079,10 +2079,10 @@ static void dw_mci_tasklet_func(struct tasklet_struct *t)
                         */
                        if (test_and_clear_bit(EVENT_DATA_ERROR,
                                               &host->pending_events)) {
-                               dw_mci_stop_dma(host);
                                if (!(host->data_status & (SDMMC_INT_DRTO |
                                                           SDMMC_INT_EBE)))
                                        send_stop_abort(host, data);
+                               dw_mci_stop_dma(host);
                                state = STATE_DATA_ERROR;
                                break;
                        }
index 51db30a..fdaa11f 100644 (file)
@@ -479,8 +479,9 @@ static int sdmmc_post_sig_volt_switch(struct mmci_host *host,
        u32 status;
        int ret = 0;
 
-       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180) {
-               spin_lock_irqsave(&host->lock, flags);
+       spin_lock_irqsave(&host->lock, flags);
+       if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_180 &&
+           host->pwr_reg & MCI_STM32_VSWITCHEN) {
                mmci_write_pwrreg(host, host->pwr_reg | MCI_STM32_VSWITCH);
                spin_unlock_irqrestore(&host->lock, flags);
 
@@ -492,9 +493,11 @@ static int sdmmc_post_sig_volt_switch(struct mmci_host *host,
 
                writel_relaxed(MCI_STM32_VSWENDC | MCI_STM32_CKSTOPC,
                               host->base + MMCICLEAR);
+               spin_lock_irqsave(&host->lock, flags);
                mmci_write_pwrreg(host, host->pwr_reg &
                                  ~(MCI_STM32_VSWITCHEN | MCI_STM32_VSWITCH));
        }
+       spin_unlock_irqrestore(&host->lock, flags);
 
        return ret;
 }
index cce390f..032bf85 100644 (file)
@@ -173,6 +173,23 @@ static unsigned int sdhci_iproc_get_max_clock(struct sdhci_host *host)
                return pltfm_host->clock;
 }
 
+/*
+ * There is a known bug on BCM2711's SDHCI core integration where the
+ * controller will hang when the difference between the core clock and the bus
+ * clock is too great. Specifically this can be reproduced under the following
+ * conditions:
+ *
+ *  - No SD card plugged in, polling thread is running, probing cards at
+ *    100 kHz.
+ *  - BCM2711's core clock configured at 500MHz or more
+ *
+ * So we set 200kHz as the minimum clock frequency available for that SoC.
+ */
+static unsigned int sdhci_iproc_bcm2711_get_min_clock(struct sdhci_host *host)
+{
+       return 200000;
+}
+
 static const struct sdhci_ops sdhci_iproc_ops = {
        .set_clock = sdhci_set_clock,
        .get_max_clock = sdhci_iproc_get_max_clock,
@@ -271,6 +288,7 @@ static const struct sdhci_ops sdhci_iproc_bcm2711_ops = {
        .set_clock = sdhci_set_clock,
        .set_power = sdhci_set_power_and_bus_voltage,
        .get_max_clock = sdhci_iproc_get_max_clock,
+       .get_min_clock = sdhci_iproc_bcm2711_get_min_clock,
        .set_bus_width = sdhci_set_bus_width,
        .reset = sdhci_reset,
        .set_uhs_signaling = sdhci_set_uhs_signaling,
index e44b7a6..290a14c 100644 (file)
@@ -2089,6 +2089,23 @@ static void sdhci_msm_cqe_disable(struct mmc_host *mmc, bool recovery)
        sdhci_cqe_disable(mmc, recovery);
 }
 
+static void sdhci_msm_set_timeout(struct sdhci_host *host, struct mmc_command *cmd)
+{
+       u32 count, start = 15;
+
+       __sdhci_set_timeout(host, cmd);
+       count = sdhci_readb(host, SDHCI_TIMEOUT_CONTROL);
+       /*
+        * Update software timeout value if its value is less than hardware data
+        * timeout value. Qcom SoC hardware data timeout value was calculated
+        * using 4 * MCLK * 2^(count + 13). where MCLK = 1 / host->clock.
+        */
+       if (cmd && cmd->data && host->clock > 400000 &&
+           host->clock <= 50000000 &&
+           ((1 << (count + start)) > (10 * host->clock)))
+               host->data_timeout = 22LL * NSEC_PER_SEC;
+}
+
 static const struct cqhci_host_ops sdhci_msm_cqhci_ops = {
        .enable         = sdhci_msm_cqe_enable,
        .disable        = sdhci_msm_cqe_disable,
@@ -2438,6 +2455,7 @@ static const struct sdhci_ops sdhci_msm_ops = {
        .irq    = sdhci_msm_cqe_irq,
        .dump_vendor_regs = sdhci_msm_dump_vendor_regs,
        .set_power = sdhci_set_power_noreg,
+       .set_timeout = sdhci_msm_set_timeout,
 };
 
 static const struct sdhci_pltfm_data sdhci_msm_pdata = {
index 3097e93..a761134 100644 (file)
@@ -119,7 +119,7 @@ static int cfi_use_status_reg(struct cfi_private *cfi)
        struct cfi_pri_amdstd *extp = cfi->cmdset_priv;
        u8 poll_mask = CFI_POLL_STATUS_REG | CFI_POLL_DQ;
 
-       return extp->MinorVersion >= '5' &&
+       return extp && extp->MinorVersion >= '5' &&
                (extp->SoftwareFeatures & poll_mask) == CFI_POLL_STATUS_REG;
 }
 
index efc2003..99400d0 100644 (file)
@@ -229,7 +229,7 @@ static int mchp48l640_write(struct mtd_info *mtd, loff_t to, size_t len,
                woff += ws;
        }
 
-       return ret;
+       return 0;
 }
 
 static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len,
@@ -255,6 +255,7 @@ static int mchp48l640_read_page(struct mtd_info *mtd, loff_t from, size_t len,
        if (!ret)
                *retlen += len;
 
+       kfree(cmd);
        return ret;
 
 fail:
@@ -286,7 +287,7 @@ static int mchp48l640_read(struct mtd_info *mtd, loff_t from, size_t len,
                woff += ws;
        }
 
-       return ret;
+       return 0;
 };
 
 static const struct mchp48_caps mchp48l640_caps = {
index 6ce4bc5..44bea3f 100644 (file)
@@ -419,6 +419,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new)
        if (tr->discard) {
                blk_queue_flag_set(QUEUE_FLAG_DISCARD, new->rq);
                blk_queue_max_discard_sectors(new->rq, UINT_MAX);
+               new->rq->limits.discard_granularity = tr->blksize;
        }
 
        gd->queue = new->rq;
@@ -525,14 +526,10 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
        if (!blktrans_notifier.list.next)
                register_mtd_user(&blktrans_notifier);
 
-
-       mutex_lock(&mtd_table_mutex);
-
        ret = register_blkdev(tr->major, tr->name);
        if (ret < 0) {
                printk(KERN_WARNING "Unable to register %s block device on major %d: %d\n",
                       tr->name, tr->major, ret);
-               mutex_unlock(&mtd_table_mutex);
                return ret;
        }
 
@@ -542,12 +539,12 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr)
        tr->blkshift = ffs(tr->blksize) - 1;
 
        INIT_LIST_HEAD(&tr->devs);
-       list_add(&tr->list, &blktrans_majors);
 
+       mutex_lock(&mtd_table_mutex);
+       list_add(&tr->list, &blktrans_majors);
        mtd_for_each_device(mtd)
                if (mtd->type != MTD_ABSENT)
                        tr->add_mtd(tr, mtd);
-
        mutex_unlock(&mtd_table_mutex);
        return 0;
 }
@@ -564,8 +561,8 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr)
        list_for_each_entry_safe(dev, next, &tr->devs, list)
                tr->remove_dev(dev);
 
-       unregister_blkdev(tr->major, tr->name);
        mutex_unlock(&mtd_table_mutex);
+       unregister_blkdev(tr->major, tr->name);
 
        BUG_ON(!list_empty(&tr->devs));
        return 0;
index b5ccd30..c8fd7f7 100644 (file)
@@ -806,7 +806,9 @@ static ssize_t mtd_otp_size(struct mtd_info *mtd, bool is_user)
 
 err:
        kfree(info);
-       return ret;
+
+       /* ENODATA means there is no OTP region. */
+       return ret == -ENODATA ? 0 : ret;
 }
 
 static struct nvmem_device *mtd_otp_nvmem_register(struct mtd_info *mtd,
index 57a5831..3d6c6e8 100644 (file)
@@ -5228,12 +5228,18 @@ static bool of_get_nand_on_flash_bbt(struct device_node *np)
 static int of_get_nand_secure_regions(struct nand_chip *chip)
 {
        struct device_node *dn = nand_get_flash_node(chip);
+       struct property *prop;
        int nr_elem, i, j;
 
-       nr_elem = of_property_count_elems_of_size(dn, "secure-regions", sizeof(u64));
-       if (!nr_elem)
+       /* Only proceed if the "secure-regions" property is present in DT */
+       prop = of_find_property(dn, "secure-regions", NULL);
+       if (!prop)
                return 0;
 
+       nr_elem = of_property_count_elems_of_size(dn, "secure-regions", sizeof(u64));
+       if (nr_elem <= 0)
+               return nr_elem;
+
        chip->nr_secure_regions = nr_elem / 2;
        chip->secure_regions = kcalloc(chip->nr_secure_regions, sizeof(*chip->secure_regions),
                                       GFP_KERNEL);
index a7ee0af..54e321a 100644 (file)
@@ -71,12 +71,18 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
                family = AF_INET6;
 
        if (bareudp->ethertype == htons(ETH_P_IP)) {
-               struct iphdr *iphdr;
+               __u8 ipversion;
 
-               iphdr = (struct iphdr *)(skb->data + BAREUDP_BASE_HLEN);
-               if (iphdr->version == 4) {
-                       proto = bareudp->ethertype;
-               } else if (bareudp->multi_proto_mode && (iphdr->version == 6)) {
+               if (skb_copy_bits(skb, BAREUDP_BASE_HLEN, &ipversion,
+                                 sizeof(ipversion))) {
+                       bareudp->dev->stats.rx_dropped++;
+                       goto drop;
+               }
+               ipversion >>= 4;
+
+               if (ipversion == 4) {
+                       proto = htons(ETH_P_IP);
+               } else if (ipversion == 6 && bareudp->multi_proto_mode) {
                        proto = htons(ETH_P_IPV6);
                } else {
                        bareudp->dev->stats.rx_dropped++;
index bba2a44..43bca31 100644 (file)
@@ -1164,10 +1164,10 @@ static int m_can_set_bittiming(struct net_device *dev)
                                    FIELD_PREP(TDCR_TDCO_MASK, tdco));
                }
 
-               reg_btp = FIELD_PREP(NBTP_NBRP_MASK, brp) |
-                         FIELD_PREP(NBTP_NSJW_MASK, sjw) |
-                         FIELD_PREP(NBTP_NTSEG1_MASK, tseg1) |
-                         FIELD_PREP(NBTP_NTSEG2_MASK, tseg2);
+               reg_btp |= FIELD_PREP(DBTP_DBRP_MASK, brp) |
+                       FIELD_PREP(DBTP_DSJW_MASK, sjw) |
+                       FIELD_PREP(DBTP_DTSEG1_MASK, tseg1) |
+                       FIELD_PREP(DBTP_DTSEG2_MASK, tseg2);
 
                m_can_write(cdev, M_CAN_DBTP, reg_btp);
        }
index 66fa8b0..95ae740 100644 (file)
@@ -224,8 +224,8 @@ static void esd_usb2_rx_event(struct esd_usb2_net_priv *priv,
        if (id == ESD_EV_CAN_ERROR_EXT) {
                u8 state = msg->msg.rx.data[0];
                u8 ecc = msg->msg.rx.data[1];
-               u8 txerr = msg->msg.rx.data[2];
-               u8 rxerr = msg->msg.rx.data[3];
+               u8 rxerr = msg->msg.rx.data[2];
+               u8 txerr = msg->msg.rx.data[3];
 
                skb = alloc_can_err_skb(priv->netdev, &cf);
                if (skb == NULL) {
index 9fdcc4b..7062db6 100644 (file)
@@ -912,6 +912,7 @@ static int hellcreek_fdb_dump(struct dsa_switch *ds, int port,
 {
        struct hellcreek *hellcreek = ds->priv;
        u16 entries;
+       int ret = 0;
        size_t i;
 
        mutex_lock(&hellcreek->reg_lock);
@@ -943,12 +944,14 @@ static int hellcreek_fdb_dump(struct dsa_switch *ds, int port,
                if (!(entry.portmask & BIT(port)))
                        continue;
 
-               cb(entry.mac, 0, entry.is_static, data);
+               ret = cb(entry.mac, 0, entry.is_static, data);
+               if (ret)
+                       break;
        }
 
        mutex_unlock(&hellcreek->reg_lock);
 
-       return 0;
+       return ret;
 }
 
 static int hellcreek_vlan_filtering(struct dsa_switch *ds, int port,
@@ -1469,9 +1472,6 @@ static void hellcreek_setup_gcl(struct hellcreek *hellcreek, int port,
                u16 data;
                u8 gates;
 
-               cur++;
-               next++;
-
                if (i == schedule->num_entries)
                        gates = initial->gate_mask ^
                                cur->gate_mask;
@@ -1500,6 +1500,9 @@ static void hellcreek_setup_gcl(struct hellcreek *hellcreek, int port,
                        (initial->gate_mask <<
                         TR_GCLCMD_INIT_GATE_STATES_SHIFT);
                hellcreek_write(hellcreek, data, TR_GCLCMD);
+
+               cur++;
+               next++;
        }
 }
 
@@ -1547,7 +1550,7 @@ static bool hellcreek_schedule_startable(struct hellcreek *hellcreek, int port)
        /* Calculate difference to admin base time */
        base_time_ns = ktime_to_ns(hellcreek_port->current_schedule->base_time);
 
-       return base_time_ns - current_ns < (s64)8 * NSEC_PER_SEC;
+       return base_time_ns - current_ns < (s64)4 * NSEC_PER_SEC;
 }
 
 static void hellcreek_start_schedule(struct hellcreek *hellcreek, int port)
index 3443740..d7ce281 100644 (file)
@@ -557,12 +557,12 @@ static int lan9303_alr_make_entry_raw(struct lan9303 *chip, u32 dat0, u32 dat1)
        return 0;
 }
 
-typedef void alr_loop_cb_t(struct lan9303 *chip, u32 dat0, u32 dat1,
-                          int portmap, void *ctx);
+typedef int alr_loop_cb_t(struct lan9303 *chip, u32 dat0, u32 dat1,
+                         int portmap, void *ctx);
 
-static void lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
+static int lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
 {
-       int i;
+       int ret = 0, i;
 
        mutex_lock(&chip->alr_mutex);
        lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD,
@@ -582,13 +582,17 @@ static void lan9303_alr_loop(struct lan9303 *chip, alr_loop_cb_t *cb, void *ctx)
                                                LAN9303_ALR_DAT1_PORT_BITOFFS;
                portmap = alrport_2_portmap[alrport];
 
-               cb(chip, dat0, dat1, portmap, ctx);
+               ret = cb(chip, dat0, dat1, portmap, ctx);
+               if (ret)
+                       break;
 
                lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD,
                                         LAN9303_ALR_CMD_GET_NEXT);
                lan9303_write_switch_reg(chip, LAN9303_SWE_ALR_CMD, 0);
        }
        mutex_unlock(&chip->alr_mutex);
+
+       return ret;
 }
 
 static void alr_reg_to_mac(u32 dat0, u32 dat1, u8 mac[6])
@@ -606,18 +610,20 @@ struct del_port_learned_ctx {
 };
 
 /* Clear learned (non-static) entry on given port */
-static void alr_loop_cb_del_port_learned(struct lan9303 *chip, u32 dat0,
-                                        u32 dat1, int portmap, void *ctx)
+static int alr_loop_cb_del_port_learned(struct lan9303 *chip, u32 dat0,
+                                       u32 dat1, int portmap, void *ctx)
 {
        struct del_port_learned_ctx *del_ctx = ctx;
        int port = del_ctx->port;
 
        if (((BIT(port) & portmap) == 0) || (dat1 & LAN9303_ALR_DAT1_STATIC))
-               return;
+               return 0;
 
        /* learned entries has only one port, we can just delete */
        dat1 &= ~LAN9303_ALR_DAT1_VALID; /* delete entry */
        lan9303_alr_make_entry_raw(chip, dat0, dat1);
+
+       return 0;
 }
 
 struct port_fdb_dump_ctx {
@@ -626,19 +632,19 @@ struct port_fdb_dump_ctx {
        dsa_fdb_dump_cb_t *cb;
 };
 
-static void alr_loop_cb_fdb_port_dump(struct lan9303 *chip, u32 dat0,
-                                     u32 dat1, int portmap, void *ctx)
+static int alr_loop_cb_fdb_port_dump(struct lan9303 *chip, u32 dat0,
+                                    u32 dat1, int portmap, void *ctx)
 {
        struct port_fdb_dump_ctx *dump_ctx = ctx;
        u8 mac[ETH_ALEN];
        bool is_static;
 
        if ((BIT(dump_ctx->port) & portmap) == 0)
-               return;
+               return 0;
 
        alr_reg_to_mac(dat0, dat1, mac);
        is_static = !!(dat1 & LAN9303_ALR_DAT1_STATIC);
-       dump_ctx->cb(mac, 0, is_static, dump_ctx->data);
+       return dump_ctx->cb(mac, 0, is_static, dump_ctx->data);
 }
 
 /* Set a static ALR entry. Delete entry if port_map is zero */
@@ -1210,9 +1216,7 @@ static int lan9303_port_fdb_dump(struct dsa_switch *ds, int port,
        };
 
        dev_dbg(chip->dev, "%s(%d)\n", __func__, port);
-       lan9303_alr_loop(chip, alr_loop_cb_fdb_port_dump, &dump_ctx);
-
-       return 0;
+       return lan9303_alr_loop(chip, alr_loop_cb_fdb_port_dump, &dump_ctx);
 }
 
 static int lan9303_port_mdb_prepare(struct dsa_switch *ds, int port,
index 314ae78..e78026e 100644 (file)
@@ -1404,11 +1404,17 @@ static int gswip_port_fdb_dump(struct dsa_switch *ds, int port,
                addr[1] = mac_bridge.key[2] & 0xff;
                addr[0] = (mac_bridge.key[2] >> 8) & 0xff;
                if (mac_bridge.val[1] & GSWIP_TABLE_MAC_BRIDGE_STATIC) {
-                       if (mac_bridge.val[0] & BIT(port))
-                               cb(addr, 0, true, data);
+                       if (mac_bridge.val[0] & BIT(port)) {
+                               err = cb(addr, 0, true, data);
+                               if (err)
+                                       return err;
+                       }
                } else {
-                       if (((mac_bridge.val[0] & GENMASK(7, 4)) >> 4) == port)
-                               cb(addr, 0, false, data);
+                       if (((mac_bridge.val[0] & GENMASK(7, 4)) >> 4) == port) {
+                               err = cb(addr, 0, false, data);
+                               if (err)
+                                       return err;
+                       }
                }
        }
        return 0;
index 560f684..c5142f8 100644 (file)
@@ -687,8 +687,8 @@ static void ksz8_r_vlan_entries(struct ksz_device *dev, u16 addr)
        shifts = ksz8->shifts;
 
        ksz8_r_table(dev, TABLE_VLAN, addr, &data);
-       addr *= dev->phy_port_cnt;
-       for (i = 0; i < dev->phy_port_cnt; i++) {
+       addr *= 4;
+       for (i = 0; i < 4; i++) {
                dev->vlan_cache[addr + i].table[0] = (u16)data;
                data >>= shifts[VLAN_TABLE];
        }
@@ -702,7 +702,7 @@ static void ksz8_r_vlan_table(struct ksz_device *dev, u16 vid, u16 *vlan)
        u64 buf;
 
        data = (u16 *)&buf;
-       addr = vid / dev->phy_port_cnt;
+       addr = vid / 4;
        index = vid & 3;
        ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
        *vlan = data[index];
@@ -716,7 +716,7 @@ static void ksz8_w_vlan_table(struct ksz_device *dev, u16 vid, u16 vlan)
        u64 buf;
 
        data = (u16 *)&buf;
-       addr = vid / dev->phy_port_cnt;
+       addr = vid / 4;
        index = vid & 3;
        ksz8_r_table(dev, TABLE_VLAN, addr, &buf);
        data[index] = vlan;
@@ -1119,24 +1119,67 @@ static int ksz8_port_vlan_filtering(struct dsa_switch *ds, int port, bool flag,
        if (ksz_is_ksz88x3(dev))
                return -ENOTSUPP;
 
+       /* Discard packets with VID not enabled on the switch */
        ksz_cfg(dev, S_MIRROR_CTRL, SW_VLAN_ENABLE, flag);
 
+       /* Discard packets with VID not enabled on the ingress port */
+       for (port = 0; port < dev->phy_port_cnt; ++port)
+               ksz_port_cfg(dev, port, REG_PORT_CTRL_2, PORT_INGRESS_FILTER,
+                            flag);
+
        return 0;
 }
 
+static void ksz8_port_enable_pvid(struct ksz_device *dev, int port, bool state)
+{
+       if (ksz_is_ksz88x3(dev)) {
+               ksz_cfg(dev, REG_SW_INSERT_SRC_PVID,
+                       0x03 << (4 - 2 * port), state);
+       } else {
+               ksz_pwrite8(dev, port, REG_PORT_CTRL_12, state ? 0x0f : 0x00);
+       }
+}
+
 static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
                              const struct switchdev_obj_port_vlan *vlan,
                              struct netlink_ext_ack *extack)
 {
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        struct ksz_device *dev = ds->priv;
+       struct ksz_port *p = &dev->ports[port];
        u16 data, new_pvid = 0;
        u8 fid, member, valid;
 
        if (ksz_is_ksz88x3(dev))
                return -ENOTSUPP;
 
-       ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
+       /* If a VLAN is added with untagged flag different from the
+        * port's Remove Tag flag, we need to change the latter.
+        * Ignore VID 0, which is always untagged.
+        * Ignore CPU port, which will always be tagged.
+        */
+       if (untagged != p->remove_tag && vlan->vid != 0 &&
+           port != dev->cpu_port) {
+               unsigned int vid;
+
+               /* Reject attempts to add a VLAN that requires the
+                * Remove Tag flag to be changed, unless there are no
+                * other VLANs currently configured.
+                */
+               for (vid = 1; vid < dev->num_vlans; ++vid) {
+                       /* Skip the VID we are going to add or reconfigure */
+                       if (vid == vlan->vid)
+                               continue;
+
+                       ksz8_from_vlan(dev, dev->vlan_cache[vid].table[0],
+                                      &fid, &member, &valid);
+                       if (valid && (member & BIT(port)))
+                               return -EINVAL;
+               }
+
+               ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
+               p->remove_tag = untagged;
+       }
 
        ksz8_r_vlan_table(dev, vlan->vid, &data);
        ksz8_from_vlan(dev, data, &fid, &member, &valid);
@@ -1160,9 +1203,11 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
                u16 vid;
 
                ksz_pread16(dev, port, REG_PORT_CTRL_VID, &vid);
-               vid &= 0xfff;
+               vid &= ~VLAN_VID_MASK;
                vid |= new_pvid;
                ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, vid);
+
+               ksz8_port_enable_pvid(dev, port, true);
        }
 
        return 0;
@@ -1171,9 +1216,8 @@ static int ksz8_port_vlan_add(struct dsa_switch *ds, int port,
 static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
                              const struct switchdev_obj_port_vlan *vlan)
 {
-       bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        struct ksz_device *dev = ds->priv;
-       u16 data, pvid, new_pvid = 0;
+       u16 data, pvid;
        u8 fid, member, valid;
 
        if (ksz_is_ksz88x3(dev))
@@ -1182,8 +1226,6 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
        ksz_pread16(dev, port, REG_PORT_CTRL_VID, &pvid);
        pvid = pvid & 0xFFF;
 
-       ksz_port_cfg(dev, port, P_TAG_CTRL, PORT_REMOVE_TAG, untagged);
-
        ksz8_r_vlan_table(dev, vlan->vid, &data);
        ksz8_from_vlan(dev, data, &fid, &member, &valid);
 
@@ -1195,14 +1237,11 @@ static int ksz8_port_vlan_del(struct dsa_switch *ds, int port,
                valid = 0;
        }
 
-       if (pvid == vlan->vid)
-               new_pvid = 1;
-
        ksz8_to_vlan(dev, fid, member, valid, &data);
        ksz8_w_vlan_table(dev, vlan->vid, data);
 
-       if (new_pvid != pvid)
-               ksz_pwrite16(dev, port, REG_PORT_CTRL_VID, pvid);
+       if (pvid == vlan->vid)
+               ksz8_port_enable_pvid(dev, port, false);
 
        return 0;
 }
@@ -1435,6 +1474,9 @@ static int ksz8_setup(struct dsa_switch *ds)
 
        ksz_cfg(dev, S_MIRROR_CTRL, SW_MIRROR_RX_TX, false);
 
+       if (!ksz_is_ksz88x3(dev))
+               ksz_cfg(dev, REG_SW_CTRL_19, SW_INS_TAG_ENABLE, true);
+
        /* set broadcast storm protection 10% rate */
        regmap_update_bits(dev->regmap[1], S_REPLACE_VID_CTRL,
                           BROADCAST_STORM_RATE,
@@ -1717,6 +1759,16 @@ static int ksz8_switch_init(struct ksz_device *dev)
        /* set the real number of ports */
        dev->ds->num_ports = dev->port_cnt;
 
+       /* We rely on software untagging on the CPU port, so that we
+        * can support both tagged and untagged VLANs
+        */
+       dev->ds->untag_bridge_pvid = true;
+
+       /* VLAN filtering is partly controlled by the global VLAN
+        * Enable flag
+        */
+       dev->ds->vlan_filtering_is_global = true;
+
        return 0;
 }
 
index a323556..6b40bc2 100644 (file)
 #define REG_PORT_4_OUT_RATE_3          0xEE
 #define REG_PORT_5_OUT_RATE_3          0xFE
 
+/* 88x3 specific */
+
+#define REG_SW_INSERT_SRC_PVID         0xC2
+
 /* PME */
 
 #define SW_PME_OUTPUT_ENABLE           BIT(1)
index 2e6bfd3..1597c63 100644 (file)
@@ -27,6 +27,7 @@ struct ksz_port_mib {
 struct ksz_port {
        u16 member;
        u16 vid_member;
+       bool remove_tag;                /* Remove Tag flag set, for ksz8795 only */
        int stp_state;
        struct phy_device phydev;
 
@@ -205,12 +206,8 @@ static inline int ksz_read64(struct ksz_device *dev, u32 reg, u64 *val)
        int ret;
 
        ret = regmap_bulk_read(dev->regmap[2], reg, value, 2);
-       if (!ret) {
-               /* Ick! ToDo: Add 64bit R/W to regmap on 32bit systems */
-               value[0] = swab32(value[0]);
-               value[1] = swab32(value[1]);
-               *val = swab64((u64)*value);
-       }
+       if (!ret)
+               *val = (u64)value[0] << 32 | value[1];
 
        return ret;
 }
index 69f21b7..632f0fc 100644 (file)
@@ -47,6 +47,7 @@ static const struct mt7530_mib_desc mt7530_mib[] = {
        MIB_DESC(2, 0x48, "TxBytes"),
        MIB_DESC(1, 0x60, "RxDrop"),
        MIB_DESC(1, 0x64, "RxFiltering"),
+       MIB_DESC(1, 0x68, "RxUnicast"),
        MIB_DESC(1, 0x6c, "RxMulticast"),
        MIB_DESC(1, 0x70, "RxBroadcast"),
        MIB_DESC(1, 0x74, "RxAlignErr"),
index b1d46dd..6ea0036 100644 (file)
@@ -1277,15 +1277,16 @@ static int mv88e6393x_serdes_port_errata(struct mv88e6xxx_chip *chip, int lane)
        int err;
 
        /* mv88e6393x family errata 4.6:
-        * Cannot clear PwrDn bit on SERDES on port 0 if device is configured
-        * CPU_MGD mode or P0_mode is configured for [x]MII.
-        * Workaround: Set Port0 SERDES register 4.F002 bit 5=0 and bit 15=1.
+        * Cannot clear PwrDn bit on SERDES if device is configured CPU_MGD
+        * mode or P0_mode is configured for [x]MII.
+        * Workaround: Set SERDES register 4.F002 bit 5=0 and bit 15=1.
         *
         * It seems that after this workaround the SERDES is automatically
         * powered up (the bit is cleared), so power it down.
         */
-       if (lane == MV88E6393X_PORT0_LANE) {
-               err = mv88e6390_serdes_read(chip, MV88E6393X_PORT0_LANE,
+       if (lane == MV88E6393X_PORT0_LANE || lane == MV88E6393X_PORT9_LANE ||
+           lane == MV88E6393X_PORT10_LANE) {
+               err = mv88e6390_serdes_read(chip, lane,
                                            MDIO_MMD_PHYXS,
                                            MV88E6393X_SERDES_POC, &reg);
                if (err)
index 6686192..563d8a2 100644 (file)
         AR9331_SW_PORT_STATUS_RX_FLOW_EN | AR9331_SW_PORT_STATUS_TX_FLOW_EN | \
         AR9331_SW_PORT_STATUS_SPEED_M)
 
+#define AR9331_SW_REG_PORT_CTRL(_port)                 (0x104 + (_port) * 0x100)
+#define AR9331_SW_PORT_CTRL_HEAD_EN                    BIT(11)
+#define AR9331_SW_PORT_CTRL_PORT_STATE                 GENMASK(2, 0)
+#define AR9331_SW_PORT_CTRL_PORT_STATE_DISABLED                0
+#define AR9331_SW_PORT_CTRL_PORT_STATE_BLOCKING                1
+#define AR9331_SW_PORT_CTRL_PORT_STATE_LISTENING       2
+#define AR9331_SW_PORT_CTRL_PORT_STATE_LEARNING                3
+#define AR9331_SW_PORT_CTRL_PORT_STATE_FORWARD         4
+
+#define AR9331_SW_REG_PORT_VLAN(_port)                 (0x108 + (_port) * 0x100)
+#define AR9331_SW_PORT_VLAN_8021Q_MODE                 GENMASK(31, 30)
+#define AR9331_SW_8021Q_MODE_SECURE                    3
+#define AR9331_SW_8021Q_MODE_CHECK                     2
+#define AR9331_SW_8021Q_MODE_FALLBACK                  1
+#define AR9331_SW_8021Q_MODE_NONE                      0
+#define AR9331_SW_PORT_VLAN_PORT_VID_MEMBER            GENMASK(25, 16)
+
 /* MIB registers */
 #define AR9331_MIB_COUNTER(x)                  (0x20000 + ((x) * 0x100))
 
@@ -371,12 +388,60 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv)
        return 0;
 }
 
-static int ar9331_sw_setup(struct dsa_switch *ds)
+static int ar9331_sw_setup_port(struct dsa_switch *ds, int port)
 {
        struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
        struct regmap *regmap = priv->regmap;
+       u32 port_mask, port_ctrl, val;
        int ret;
 
+       /* Generate default port settings */
+       port_ctrl = FIELD_PREP(AR9331_SW_PORT_CTRL_PORT_STATE,
+                              AR9331_SW_PORT_CTRL_PORT_STATE_FORWARD);
+
+       if (dsa_is_cpu_port(ds, port)) {
+               /* CPU port should be allowed to communicate with all user
+                * ports.
+                */
+               port_mask = dsa_user_ports(ds);
+               /* Enable Atheros header on CPU port. This will allow us
+                * communicate with each port separately
+                */
+               port_ctrl |= AR9331_SW_PORT_CTRL_HEAD_EN;
+       } else if (dsa_is_user_port(ds, port)) {
+               /* User ports should communicate only with the CPU port.
+                */
+               port_mask = BIT(dsa_upstream_port(ds, port));
+       } else {
+               /* Other ports do not need to communicate at all */
+               port_mask = 0;
+       }
+
+       val = FIELD_PREP(AR9331_SW_PORT_VLAN_8021Q_MODE,
+                        AR9331_SW_8021Q_MODE_NONE) |
+               FIELD_PREP(AR9331_SW_PORT_VLAN_PORT_VID_MEMBER, port_mask);
+
+       ret = regmap_write(regmap, AR9331_SW_REG_PORT_VLAN(port), val);
+       if (ret)
+               goto error;
+
+       ret = regmap_write(regmap, AR9331_SW_REG_PORT_CTRL(port), port_ctrl);
+       if (ret)
+               goto error;
+
+       return 0;
+error:
+       dev_err(priv->dev, "%s: error: %i\n", __func__, ret);
+
+       return ret;
+}
+
+static int ar9331_sw_setup(struct dsa_switch *ds)
+{
+       struct ar9331_sw_priv *priv = (struct ar9331_sw_priv *)ds->priv;
+       struct regmap *regmap = priv->regmap;
+       int ret, i;
+
        ret = ar9331_sw_reset(priv);
        if (ret)
                return ret;
@@ -402,6 +467,12 @@ static int ar9331_sw_setup(struct dsa_switch *ds)
        if (ret)
                goto error;
 
+       for (i = 0; i < ds->num_ports; i++) {
+               ret = ar9331_sw_setup_port(ds, i);
+               if (ret)
+                       goto error;
+       }
+
        ds->configure_vlan_while_not_filtering = false;
 
        return 0;
index 8667c97..49eb0ac 100644 (file)
@@ -1635,7 +1635,9 @@ static int sja1105_fdb_dump(struct dsa_switch *ds, int port,
                /* We need to hide the dsa_8021q VLANs from the user. */
                if (priv->vlan_state == SJA1105_VLAN_UNAWARE)
                        l2_lookup.vlanid = 0;
-               cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
+               rc = cb(macaddr, l2_lookup.vlanid, l2_lookup.lockeds, data);
+               if (rc)
+                       return rc;
        }
        return 0;
 }
@@ -3185,6 +3187,7 @@ static void sja1105_teardown(struct dsa_switch *ds)
        }
 
        sja1105_devlink_teardown(ds);
+       sja1105_mdiobus_unregister(ds);
        sja1105_flower_teardown(ds);
        sja1105_tas_teardown(ds);
        sja1105_ptp_clock_unregister(ds);
index 19aea8f..705d390 100644 (file)
@@ -284,8 +284,7 @@ static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
        struct mii_bus *bus;
        int rc = 0;
 
-       np = of_find_compatible_node(mdio_node, NULL,
-                                    "nxp,sja1110-base-tx-mdio");
+       np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
        if (!np)
                return 0;
 
@@ -339,8 +338,7 @@ static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
        struct mii_bus *bus;
        int rc = 0;
 
-       np = of_find_compatible_node(mdio_node, NULL,
-                                    "nxp,sja1110-base-t1-mdio");
+       np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
        if (!np)
                return 0;
 
index 860c18f..80399c8 100644 (file)
@@ -677,11 +677,13 @@ static int xge_probe(struct platform_device *pdev)
        ret = register_netdev(ndev);
        if (ret) {
                netdev_err(ndev, "Failed to register netdev\n");
-               goto err;
+               goto err_mdio_remove;
        }
 
        return 0;
 
+err_mdio_remove:
+       xge_mdio_remove(ndev);
 err:
        free_netdev(ndev);
 
index 8960658..8a97640 100644 (file)
@@ -72,7 +72,8 @@
 #include "bnxt_debugfs.h"
 
 #define BNXT_TX_TIMEOUT                (5 * HZ)
-#define BNXT_DEF_MSG_ENABLE    (NETIF_MSG_DRV | NETIF_MSG_HW)
+#define BNXT_DEF_MSG_ENABLE    (NETIF_MSG_DRV | NETIF_MSG_HW | \
+                                NETIF_MSG_TX_ERR)
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Broadcom BCM573xx network driver");
@@ -365,6 +366,33 @@ static u16 bnxt_xmit_get_cfa_action(struct sk_buff *skb)
        return md_dst->u.port_info.port_id;
 }
 
+static void bnxt_txr_db_kick(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
+                            u16 prod)
+{
+       bnxt_db_write(bp, &txr->tx_db, prod);
+       txr->kick_pending = 0;
+}
+
+static bool bnxt_txr_netif_try_stop_queue(struct bnxt *bp,
+                                         struct bnxt_tx_ring_info *txr,
+                                         struct netdev_queue *txq)
+{
+       netif_tx_stop_queue(txq);
+
+       /* netif_tx_stop_queue() must be done before checking
+        * tx index in bnxt_tx_avail() below, because in
+        * bnxt_tx_int(), we update tx index before checking for
+        * netif_tx_queue_stopped().
+        */
+       smp_mb();
+       if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh) {
+               netif_tx_wake_queue(txq);
+               return false;
+       }
+
+       return true;
+}
+
 static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct bnxt *bp = netdev_priv(dev);
@@ -384,6 +412,7 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
        i = skb_get_queue_mapping(skb);
        if (unlikely(i >= bp->tx_nr_rings)) {
                dev_kfree_skb_any(skb);
+               atomic_long_inc(&dev->tx_dropped);
                return NETDEV_TX_OK;
        }
 
@@ -393,8 +422,12 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
        free_size = bnxt_tx_avail(bp, txr);
        if (unlikely(free_size < skb_shinfo(skb)->nr_frags + 2)) {
-               netif_tx_stop_queue(txq);
-               return NETDEV_TX_BUSY;
+               /* We must have raced with NAPI cleanup */
+               if (net_ratelimit() && txr->kick_pending)
+                       netif_warn(bp, tx_err, dev,
+                                  "bnxt: ring busy w/ flush pending!\n");
+               if (bnxt_txr_netif_try_stop_queue(bp, txr, txq))
+                       return NETDEV_TX_BUSY;
        }
 
        length = skb->len;
@@ -426,7 +459,10 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 
                if (ptp && ptp->tx_tstamp_en && !skb_is_gso(skb) &&
                    atomic_dec_if_positive(&ptp->tx_avail) >= 0) {
-                       if (!bnxt_ptp_parse(skb, &ptp->tx_seqid)) {
+                       if (!bnxt_ptp_parse(skb, &ptp->tx_seqid,
+                                           &ptp->tx_hdr_off)) {
+                               if (vlan_tag_flags)
+                                       ptp->tx_hdr_off += VLAN_HLEN;
                                lflags |= cpu_to_le32(TX_BD_FLAGS_STAMP);
                                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
                        } else {
@@ -514,21 +550,16 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
 normal_tx:
        if (length < BNXT_MIN_PKT_SIZE) {
                pad = BNXT_MIN_PKT_SIZE - length;
-               if (skb_pad(skb, pad)) {
+               if (skb_pad(skb, pad))
                        /* SKB already freed. */
-                       tx_buf->skb = NULL;
-                       return NETDEV_TX_OK;
-               }
+                       goto tx_kick_pending;
                length = BNXT_MIN_PKT_SIZE;
        }
 
        mapping = dma_map_single(&pdev->dev, skb->data, len, DMA_TO_DEVICE);
 
-       if (unlikely(dma_mapping_error(&pdev->dev, mapping))) {
-               dev_kfree_skb_any(skb);
-               tx_buf->skb = NULL;
-               return NETDEV_TX_OK;
-       }
+       if (unlikely(dma_mapping_error(&pdev->dev, mapping)))
+               goto tx_free;
 
        dma_unmap_addr_set(tx_buf, mapping, mapping);
        flags = (len << TX_BD_LEN_SHIFT) | TX_BD_TYPE_LONG_TX_BD |
@@ -615,24 +646,17 @@ normal_tx:
        txr->tx_prod = prod;
 
        if (!netdev_xmit_more() || netif_xmit_stopped(txq))
-               bnxt_db_write(bp, &txr->tx_db, prod);
+               bnxt_txr_db_kick(bp, txr, prod);
+       else
+               txr->kick_pending = 1;
 
 tx_done:
 
        if (unlikely(bnxt_tx_avail(bp, txr) <= MAX_SKB_FRAGS + 1)) {
                if (netdev_xmit_more() && !tx_buf->is_push)
-                       bnxt_db_write(bp, &txr->tx_db, prod);
-
-               netif_tx_stop_queue(txq);
+                       bnxt_txr_db_kick(bp, txr, prod);
 
-               /* netif_tx_stop_queue() must be done before checking
-                * tx index in bnxt_tx_avail() below, because in
-                * bnxt_tx_int(), we update tx index before checking for
-                * netif_tx_queue_stopped().
-                */
-               smp_mb();
-               if (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)
-                       netif_tx_wake_queue(txq);
+               bnxt_txr_netif_try_stop_queue(bp, txr, txq);
        }
        return NETDEV_TX_OK;
 
@@ -645,7 +669,6 @@ tx_dma_error:
        /* start back at beginning and unmap skb */
        prod = txr->tx_prod;
        tx_buf = &txr->tx_buf_ring[prod];
-       tx_buf->skb = NULL;
        dma_unmap_single(&pdev->dev, dma_unmap_addr(tx_buf, mapping),
                         skb_headlen(skb), PCI_DMA_TODEVICE);
        prod = NEXT_TX(prod);
@@ -659,7 +682,13 @@ tx_dma_error:
                               PCI_DMA_TODEVICE);
        }
 
+tx_free:
        dev_kfree_skb_any(skb);
+tx_kick_pending:
+       if (txr->kick_pending)
+               bnxt_txr_db_kick(bp, txr, txr->tx_prod);
+       txr->tx_buf_ring[txr->tx_prod].skb = NULL;
+       atomic_long_inc(&dev->tx_dropped);
        return NETDEV_TX_OK;
 }
 
@@ -729,14 +758,9 @@ next_tx_int:
        smp_mb();
 
        if (unlikely(netif_tx_queue_stopped(txq)) &&
-           (bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh)) {
-               __netif_tx_lock(txq, smp_processor_id());
-               if (netif_tx_queue_stopped(txq) &&
-                   bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh &&
-                   txr->dev_state != BNXT_DEV_STATE_CLOSING)
-                       netif_tx_wake_queue(txq);
-               __netif_tx_unlock(txq);
-       }
+           bnxt_tx_avail(bp, txr) > bp->tx_wake_thresh &&
+           READ_ONCE(txr->dev_state) != BNXT_DEV_STATE_CLOSING)
+               netif_tx_wake_queue(txq);
 }
 
 static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
@@ -1764,6 +1788,10 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
        if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
                return -EBUSY;
 
+       /* The valid test of the entry must be done first before
+        * reading any further.
+        */
+       dma_rmb();
        prod = rxr->rx_prod;
 
        if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP) {
@@ -1986,6 +2014,10 @@ static int bnxt_force_rx_discard(struct bnxt *bp,
        if (!RX_CMP_VALID(rxcmp1, tmp_raw_cons))
                return -EBUSY;
 
+       /* The valid test of the entry must be done first before
+        * reading any further.
+        */
+       dma_rmb();
        cmp_type = RX_CMP_TYPE(rxcmp);
        if (cmp_type == CMP_TYPE_RX_L2_CMP) {
                rxcmp1->rx_cmp_cfa_code_errors_v2 |=
@@ -2451,6 +2483,10 @@ static int bnxt_poll_nitroa0(struct napi_struct *napi, int budget)
                if (!TX_CMP_VALID(txcmp, raw_cons))
                        break;
 
+               /* The valid test of the entry must be done first before
+                * reading any further.
+                */
+               dma_rmb();
                if ((TX_CMP_TYPE(txcmp) & 0x30) == 0x10) {
                        tmp_raw_cons = NEXT_RAW_CMP(raw_cons);
                        cp_cons = RING_CMP(tmp_raw_cons);
@@ -9125,10 +9161,9 @@ static void bnxt_disable_napi(struct bnxt *bp)
        for (i = 0; i < bp->cp_nr_rings; i++) {
                struct bnxt_cp_ring_info *cpr = &bp->bnapi[i]->cp_ring;
 
+               napi_disable(&bp->bnapi[i]->napi);
                if (bp->bnapi[i]->rx_ring)
                        cancel_work_sync(&cpr->dim.work);
-
-               napi_disable(&bp->bnapi[i]->napi);
        }
 }
 
@@ -9162,9 +9197,11 @@ void bnxt_tx_disable(struct bnxt *bp)
        if (bp->tx_ring) {
                for (i = 0; i < bp->tx_nr_rings; i++) {
                        txr = &bp->tx_ring[i];
-                       txr->dev_state = BNXT_DEV_STATE_CLOSING;
+                       WRITE_ONCE(txr->dev_state, BNXT_DEV_STATE_CLOSING);
                }
        }
+       /* Make sure napi polls see @dev_state change */
+       synchronize_net();
        /* Drop carrier first to prevent TX timeout */
        netif_carrier_off(bp->dev);
        /* Stop all TX queues */
@@ -9178,8 +9215,10 @@ void bnxt_tx_enable(struct bnxt *bp)
 
        for (i = 0; i < bp->tx_nr_rings; i++) {
                txr = &bp->tx_ring[i];
-               txr->dev_state = 0;
+               WRITE_ONCE(txr->dev_state, 0);
        }
+       /* Make sure napi polls see @dev_state change */
+       synchronize_net();
        netif_tx_wake_all_queues(bp->dev);
        if (bp->link_info.link_up)
                netif_carrier_on(bp->dev);
@@ -10765,6 +10804,9 @@ static bool bnxt_rfs_supported(struct bnxt *bp)
                        return true;
                return false;
        }
+       /* 212 firmware is broken for aRFS */
+       if (BNXT_FW_MAJ(bp) == 212)
+               return false;
        if (BNXT_PF(bp) && !BNXT_CHIP_TYPE_NITRO_A0(bp))
                return true;
        if (bp->flags & BNXT_FLAG_NEW_RSS_CAP)
index bcf8d00..ba4e0fc 100644 (file)
@@ -786,6 +786,7 @@ struct bnxt_tx_ring_info {
        u16                     tx_prod;
        u16                     tx_cons;
        u16                     txq_index;
+       u8                      kick_pending;
        struct bnxt_db_info     tx_db;
 
        struct tx_bd            *tx_desc_ring[MAX_TX_PAGES];
index 3fc6781..94d07a9 100644 (file)
@@ -368,6 +368,7 @@ struct cmd_nums {
        #define HWRM_FUNC_PTP_TS_QUERY                    0x19fUL
        #define HWRM_FUNC_PTP_EXT_CFG                     0x1a0UL
        #define HWRM_FUNC_PTP_EXT_QCFG                    0x1a1UL
+       #define HWRM_FUNC_KEY_CTX_ALLOC                   0x1a2UL
        #define HWRM_SELFTEST_QLIST                       0x200UL
        #define HWRM_SELFTEST_EXEC                        0x201UL
        #define HWRM_SELFTEST_IRQ                         0x202UL
@@ -531,8 +532,8 @@ struct hwrm_err_output {
 #define HWRM_VERSION_MAJOR 1
 #define HWRM_VERSION_MINOR 10
 #define HWRM_VERSION_UPDATE 2
-#define HWRM_VERSION_RSVD 47
-#define HWRM_VERSION_STR "1.10.2.47"
+#define HWRM_VERSION_RSVD 52
+#define HWRM_VERSION_STR "1.10.2.52"
 
 /* hwrm_ver_get_input (size:192b/24B) */
 struct hwrm_ver_get_input {
@@ -585,6 +586,7 @@ struct hwrm_ver_get_output {
        #define VER_GET_RESP_DEV_CAPS_CFG_CFA_ADV_FLOW_MGNT_SUPPORTED              0x1000UL
        #define VER_GET_RESP_DEV_CAPS_CFG_CFA_TFLIB_SUPPORTED                      0x2000UL
        #define VER_GET_RESP_DEV_CAPS_CFG_CFA_TRUFLOW_SUPPORTED                    0x4000UL
+       #define VER_GET_RESP_DEV_CAPS_CFG_SECURE_BOOT_CAPABLE                      0x8000UL
        u8      roce_fw_maj_8b;
        u8      roce_fw_min_8b;
        u8      roce_fw_bld_8b;
@@ -886,7 +888,8 @@ struct hwrm_async_event_cmpl_reset_notify {
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_EXCEPTION_FATAL        (0x2UL << 8)
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_EXCEPTION_NON_FATAL    (0x3UL << 8)
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FAST_RESET                (0x4UL << 8)
-       #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_LAST                     ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FAST_RESET
+       #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_ACTIVATION             (0x5UL << 8)
+       #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_LAST                     ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_REASON_CODE_FW_ACTIVATION
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_DELAY_IN_100MS_TICKS_MASK           0xffff0000UL
        #define ASYNC_EVENT_CMPL_RESET_NOTIFY_EVENT_DATA1_DELAY_IN_100MS_TICKS_SFT            16
 };
@@ -1236,13 +1239,14 @@ struct hwrm_async_event_cmpl_error_report_base {
        u8      timestamp_lo;
        __le16  timestamp_hi;
        __le32  event_data1;
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK          0xffUL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT           0
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_RESERVED        0x0UL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_PAUSE_STORM     0x1UL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL  0x2UL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_NVM             0x3UL
-       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_LAST           ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_NVM
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_MASK                   0xffUL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_SFT                    0
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_RESERVED                 0x0UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_PAUSE_STORM              0x1UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_INVALID_SIGNAL           0x2UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_NVM                      0x3UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD  0x4UL
+       #define ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_LAST                    ASYNC_EVENT_CMPL_ERROR_REPORT_BASE_EVENT_DATA1_ERROR_TYPE_DOORBELL_DROP_THRESHOLD
 };
 
 /* hwrm_async_event_cmpl_error_report_pause_storm (size:128b/16B) */
@@ -1446,6 +1450,8 @@ struct hwrm_func_vf_cfg_input {
        #define FUNC_VF_CFG_REQ_ENABLES_NUM_VNICS            0x200UL
        #define FUNC_VF_CFG_REQ_ENABLES_NUM_STAT_CTXS        0x400UL
        #define FUNC_VF_CFG_REQ_ENABLES_NUM_HW_RING_GRPS     0x800UL
+       #define FUNC_VF_CFG_REQ_ENABLES_NUM_TX_KEY_CTXS      0x1000UL
+       #define FUNC_VF_CFG_REQ_ENABLES_NUM_RX_KEY_CTXS      0x2000UL
        __le16  mtu;
        __le16  guest_vlan;
        __le16  async_event_cr;
@@ -1469,7 +1475,8 @@ struct hwrm_func_vf_cfg_input {
        __le16  num_vnics;
        __le16  num_stat_ctxs;
        __le16  num_hw_ring_grps;
-       u8      unused_0[4];
+       __le16  num_tx_key_ctxs;
+       __le16  num_rx_key_ctxs;
 };
 
 /* hwrm_func_vf_cfg_output (size:128b/16B) */
@@ -1493,7 +1500,7 @@ struct hwrm_func_qcaps_input {
        u8      unused_0[6];
 };
 
-/* hwrm_func_qcaps_output (size:704b/88B) */
+/* hwrm_func_qcaps_output (size:768b/96B) */
 struct hwrm_func_qcaps_output {
        __le16  error_code;
        __le16  req_type;
@@ -1587,7 +1594,8 @@ struct hwrm_func_qcaps_output {
        #define FUNC_QCAPS_RESP_MPC_CHNLS_CAP_TE_CFA      0x4UL
        #define FUNC_QCAPS_RESP_MPC_CHNLS_CAP_RE_CFA      0x8UL
        #define FUNC_QCAPS_RESP_MPC_CHNLS_CAP_PRIMATE     0x10UL
-       u8      unused_1;
+       __le16  max_key_ctxs_alloc;
+       u8      unused_1[7];
        u8      valid;
 };
 
@@ -1602,7 +1610,7 @@ struct hwrm_func_qcfg_input {
        u8      unused_0[6];
 };
 
-/* hwrm_func_qcfg_output (size:832b/104B) */
+/* hwrm_func_qcfg_output (size:896b/112B) */
 struct hwrm_func_qcfg_output {
        __le16  error_code;
        __le16  req_type;
@@ -1749,11 +1757,13 @@ struct hwrm_func_qcfg_output {
        #define FUNC_QCFG_RESP_PARTITION_MAX_BW_BW_VALUE_UNIT_PERCENT1_100  (0x1UL << 29)
        #define FUNC_QCFG_RESP_PARTITION_MAX_BW_BW_VALUE_UNIT_LAST         FUNC_QCFG_RESP_PARTITION_MAX_BW_BW_VALUE_UNIT_PERCENT1_100
        __le16  host_mtu;
-       u8      unused_3;
+       __le16  alloc_tx_key_ctxs;
+       __le16  alloc_rx_key_ctxs;
+       u8      unused_3[5];
        u8      valid;
 };
 
-/* hwrm_func_cfg_input (size:832b/104B) */
+/* hwrm_func_cfg_input (size:896b/112B) */
 struct hwrm_func_cfg_input {
        __le16  req_type;
        __le16  cmpl_ring;
@@ -1820,6 +1830,8 @@ struct hwrm_func_cfg_input {
        #define FUNC_CFG_REQ_ENABLES_PARTITION_MAX_BW         0x8000000UL
        #define FUNC_CFG_REQ_ENABLES_TPID                     0x10000000UL
        #define FUNC_CFG_REQ_ENABLES_HOST_MTU                 0x20000000UL
+       #define FUNC_CFG_REQ_ENABLES_TX_KEY_CTXS              0x40000000UL
+       #define FUNC_CFG_REQ_ENABLES_RX_KEY_CTXS              0x80000000UL
        __le16  admin_mtu;
        __le16  mru;
        __le16  num_rsscos_ctxs;
@@ -1929,6 +1941,9 @@ struct hwrm_func_cfg_input {
        #define FUNC_CFG_REQ_PARTITION_MAX_BW_BW_VALUE_UNIT_LAST         FUNC_CFG_REQ_PARTITION_MAX_BW_BW_VALUE_UNIT_PERCENT1_100
        __be16  tpid;
        __le16  host_mtu;
+       __le16  num_tx_key_ctxs;
+       __le16  num_rx_key_ctxs;
+       u8      unused_0[4];
 };
 
 /* hwrm_func_cfg_output (size:128b/16B) */
@@ -2099,6 +2114,7 @@ struct hwrm_func_drv_rgtr_input {
        #define FUNC_DRV_RGTR_REQ_FLAGS_MASTER_SUPPORT                   0x40UL
        #define FUNC_DRV_RGTR_REQ_FLAGS_FAST_RESET_SUPPORT               0x80UL
        #define FUNC_DRV_RGTR_REQ_FLAGS_RSS_STRICT_HASH_TYPE_SUPPORT     0x100UL
+       #define FUNC_DRV_RGTR_REQ_FLAGS_NPAR_1_2_SUPPORT                 0x200UL
        __le32  enables;
        #define FUNC_DRV_RGTR_REQ_ENABLES_OS_TYPE             0x1UL
        #define FUNC_DRV_RGTR_REQ_ENABLES_VER                 0x2UL
@@ -2268,7 +2284,7 @@ struct hwrm_func_resource_qcaps_input {
        u8      unused_0[6];
 };
 
-/* hwrm_func_resource_qcaps_output (size:448b/56B) */
+/* hwrm_func_resource_qcaps_output (size:512b/64B) */
 struct hwrm_func_resource_qcaps_output {
        __le16  error_code;
        __le16  req_type;
@@ -2300,11 +2316,15 @@ struct hwrm_func_resource_qcaps_output {
        __le16  max_tx_scheduler_inputs;
        __le16  flags;
        #define FUNC_RESOURCE_QCAPS_RESP_FLAGS_MIN_GUARANTEED     0x1UL
+       __le16  min_tx_key_ctxs;
+       __le16  max_tx_key_ctxs;
+       __le16  min_rx_key_ctxs;
+       __le16  max_rx_key_ctxs;
        u8      unused_0[5];
        u8      valid;
 };
 
-/* hwrm_func_vf_resource_cfg_input (size:448b/56B) */
+/* hwrm_func_vf_resource_cfg_input (size:512b/64B) */
 struct hwrm_func_vf_resource_cfg_input {
        __le16  req_type;
        __le16  cmpl_ring;
@@ -2331,6 +2351,10 @@ struct hwrm_func_vf_resource_cfg_input {
        __le16  max_hw_ring_grps;
        __le16  flags;
        #define FUNC_VF_RESOURCE_CFG_REQ_FLAGS_MIN_GUARANTEED     0x1UL
+       __le16  min_tx_key_ctxs;
+       __le16  max_tx_key_ctxs;
+       __le16  min_rx_key_ctxs;
+       __le16  max_rx_key_ctxs;
        u8      unused_0[2];
 };
 
@@ -2348,7 +2372,9 @@ struct hwrm_func_vf_resource_cfg_output {
        __le16  reserved_vnics;
        __le16  reserved_stat_ctx;
        __le16  reserved_hw_ring_grps;
-       u8      unused_0[7];
+       __le16  reserved_tx_key_ctxs;
+       __le16  reserved_rx_key_ctxs;
+       u8      unused_0[3];
        u8      valid;
 };
 
@@ -4220,7 +4246,7 @@ struct hwrm_port_lpbk_clr_stats_output {
        u8      valid;
 };
 
-/* hwrm_port_ts_query_input (size:256b/32B) */
+/* hwrm_port_ts_query_input (size:320b/40B) */
 struct hwrm_port_ts_query_input {
        __le16  req_type;
        __le16  cmpl_ring;
@@ -4238,8 +4264,11 @@ struct hwrm_port_ts_query_input {
        __le16  enables;
        #define PORT_TS_QUERY_REQ_ENABLES_TS_REQ_TIMEOUT     0x1UL
        #define PORT_TS_QUERY_REQ_ENABLES_PTP_SEQ_ID         0x2UL
+       #define PORT_TS_QUERY_REQ_ENABLES_PTP_HDR_OFFSET     0x4UL
        __le16  ts_req_timeout;
        __le32  ptp_seq_id;
+       __le16  ptp_hdr_offset;
+       u8      unused_1[6];
 };
 
 /* hwrm_port_ts_query_output (size:192b/24B) */
@@ -8172,6 +8201,7 @@ struct hwrm_fw_reset_input {
        u8      host_idx;
        u8      flags;
        #define FW_RESET_REQ_FLAGS_RESET_GRACEFUL     0x1UL
+       #define FW_RESET_REQ_FLAGS_FW_ACTIVATION      0x2UL
        u8      unused_0[4];
 };
 
@@ -8952,7 +8982,7 @@ struct hwrm_nvm_get_dir_info_output {
        u8      valid;
 };
 
-/* hwrm_nvm_write_input (size:384b/48B) */
+/* hwrm_nvm_write_input (size:448b/56B) */
 struct hwrm_nvm_write_input {
        __le16  req_type;
        __le16  cmpl_ring;
@@ -8968,7 +8998,11 @@ struct hwrm_nvm_write_input {
        __le16  option;
        __le16  flags;
        #define NVM_WRITE_REQ_FLAGS_KEEP_ORIG_ACTIVE_IMG     0x1UL
+       #define NVM_WRITE_REQ_FLAGS_BATCH_MODE               0x2UL
+       #define NVM_WRITE_REQ_FLAGS_BATCH_LAST               0x4UL
        __le32  dir_item_length;
+       __le32  offset;
+       __le32  len;
        __le32  unused_0;
 };
 
index ec381c2..81f40ab 100644 (file)
@@ -20,7 +20,7 @@
 #include "bnxt.h"
 #include "bnxt_ptp.h"
 
-int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id)
+int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off)
 {
        unsigned int ptp_class;
        struct ptp_header *hdr;
@@ -34,6 +34,7 @@ int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id)
                if (!hdr)
                        return -EINVAL;
 
+               *hdr_off = (u8 *)hdr - skb->data;
                *seq_id  = ntohs(hdr->sequence_id);
                return 0;
        default:
@@ -91,6 +92,7 @@ static int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts)
            PORT_TS_QUERY_REQ_FLAGS_PATH_TX) {
                req.enables = cpu_to_le16(BNXT_PTP_QTS_TX_ENABLES);
                req.ptp_seq_id = cpu_to_le32(bp->ptp_cfg->tx_seqid);
+               req.ptp_hdr_offset = cpu_to_le16(bp->ptp_cfg->tx_hdr_off);
                req.ts_req_timeout = cpu_to_le16(BNXT_PTP_QTS_TIMEOUT);
        }
        mutex_lock(&bp->hwrm_cmd_lock);
index 254ba7b..524f1c2 100644 (file)
@@ -10,8 +10,8 @@
 #ifndef BNXT_PTP_H
 #define BNXT_PTP_H
 
-#define BNXT_PTP_GRC_WIN       5
-#define BNXT_PTP_GRC_WIN_BASE  0x5000
+#define BNXT_PTP_GRC_WIN       6
+#define BNXT_PTP_GRC_WIN_BASE  0x6000
 
 #define BNXT_MAX_PHC_DRIFT     31000000
 #define BNXT_LO_TIMER_MASK     0x0000ffffffffUL
@@ -19,7 +19,8 @@
 
 #define BNXT_PTP_QTS_TIMEOUT   1000
 #define BNXT_PTP_QTS_TX_ENABLES        (PORT_TS_QUERY_REQ_ENABLES_PTP_SEQ_ID | \
-                                PORT_TS_QUERY_REQ_ENABLES_TS_REQ_TIMEOUT)
+                                PORT_TS_QUERY_REQ_ENABLES_TS_REQ_TIMEOUT | \
+                                PORT_TS_QUERY_REQ_ENABLES_PTP_HDR_OFFSET)
 
 struct bnxt_ptp_cfg {
        struct ptp_clock_info   ptp_info;
@@ -37,6 +38,7 @@ struct bnxt_ptp_cfg {
        #define BNXT_PHC_OVERFLOW_PERIOD        (19 * 3600 * HZ)
 
        u16                     tx_seqid;
+       u16                     tx_hdr_off;
        struct bnxt             *bp;
        atomic_t                tx_avail;
 #define BNXT_MAX_TX_TS 1
@@ -74,7 +76,7 @@ do {                                          \
        ((dst) = READ_ONCE(src))
 #endif
 
-int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id);
+int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off);
 int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr);
 int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr);
 int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb);
index 5c368a9..c2e1f16 100644 (file)
@@ -275,6 +275,12 @@ void gem_ptp_rxstamp(struct macb *bp, struct sk_buff *skb,
 
        if (GEM_BFEXT(DMA_RXVALID, desc->addr)) {
                desc_ptp = macb_ptp_desc(bp, desc);
+               /* Unlikely but check */
+               if (!desc_ptp) {
+                       dev_warn_ratelimited(&bp->pdev->dev,
+                                            "Timestamp not supported in BD\n");
+                       return;
+               }
                gem_hw_timestamp(bp, desc_ptp->ts_1, desc_ptp->ts_2, &ts);
                memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
                shhwtstamps->hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
@@ -307,8 +313,11 @@ int gem_ptp_txstamp(struct macb_queue *queue, struct sk_buff *skb,
        if (CIRC_SPACE(head, tail, PTP_TS_BUFFER_SIZE) == 0)
                return -ENOMEM;
 
-       skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
        desc_ptp = macb_ptp_desc(queue->bp, desc);
+       /* Unlikely but check */
+       if (!desc_ptp)
+               return -EINVAL;
+       skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
        tx_timestamp = &queue->tx_timestamps[head];
        tx_timestamp->skb = skb;
        /* ensure ts_1/ts_2 is loaded after ctrl (TX_USED check) */
index dbf9a0e..710cb00 100644 (file)
@@ -5068,6 +5068,7 @@ static int adap_init0(struct adapter *adap, int vpd_skip)
                ret = -ENOMEM;
                goto bye;
        }
+       bitmap_zero(adap->sge.blocked_fl, adap->sge.egr_sz);
 #endif
 
        params[0] = FW_PARAM_PFVF(CLIP_START);
@@ -6788,13 +6789,11 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        setup_memwin(adapter);
        err = adap_init0(adapter, 0);
-#ifdef CONFIG_DEBUG_FS
-       bitmap_zero(adapter->sge.blocked_fl, adapter->sge.egr_sz);
-#endif
-       setup_memwin_rdma(adapter);
        if (err)
                goto out_unmap_bar;
 
+       setup_memwin_rdma(adapter);
+
        /* configure SGE_STAT_CFG_A to read WC stats */
        if (!is_t4(adapter->params.chip))
                t4_write_reg(adapter, SGE_STAT_CFG_A, STATSOURCE_T5_V(7) |
index 68b7864..98cc013 100644 (file)
@@ -3038,26 +3038,30 @@ static int dpaa2_switch_port_init(struct ethsw_port_priv *port_priv, u16 port)
        return err;
 }
 
-static void dpaa2_switch_takedown(struct fsl_mc_device *sw_dev)
+static void dpaa2_switch_ctrl_if_teardown(struct ethsw_core *ethsw)
+{
+       dpsw_ctrl_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle);
+       dpaa2_switch_free_dpio(ethsw);
+       dpaa2_switch_destroy_rings(ethsw);
+       dpaa2_switch_drain_bp(ethsw);
+       dpaa2_switch_free_dpbp(ethsw);
+}
+
+static void dpaa2_switch_teardown(struct fsl_mc_device *sw_dev)
 {
        struct device *dev = &sw_dev->dev;
        struct ethsw_core *ethsw = dev_get_drvdata(dev);
        int err;
 
+       dpaa2_switch_ctrl_if_teardown(ethsw);
+
+       destroy_workqueue(ethsw->workqueue);
+
        err = dpsw_close(ethsw->mc_io, 0, ethsw->dpsw_handle);
        if (err)
                dev_warn(dev, "dpsw_close err %d\n", err);
 }
 
-static void dpaa2_switch_ctrl_if_teardown(struct ethsw_core *ethsw)
-{
-       dpsw_ctrl_if_disable(ethsw->mc_io, 0, ethsw->dpsw_handle);
-       dpaa2_switch_free_dpio(ethsw);
-       dpaa2_switch_destroy_rings(ethsw);
-       dpaa2_switch_drain_bp(ethsw);
-       dpaa2_switch_free_dpbp(ethsw);
-}
-
 static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
 {
        struct ethsw_port_priv *port_priv;
@@ -3068,8 +3072,6 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
        dev = &sw_dev->dev;
        ethsw = dev_get_drvdata(dev);
 
-       dpaa2_switch_ctrl_if_teardown(ethsw);
-
        dpaa2_switch_teardown_irqs(sw_dev);
 
        dpsw_disable(ethsw->mc_io, 0, ethsw->dpsw_handle);
@@ -3084,9 +3086,7 @@ static int dpaa2_switch_remove(struct fsl_mc_device *sw_dev)
        kfree(ethsw->acls);
        kfree(ethsw->ports);
 
-       dpaa2_switch_takedown(sw_dev);
-
-       destroy_workqueue(ethsw->workqueue);
+       dpaa2_switch_teardown(sw_dev);
 
        fsl_mc_portal_free(ethsw->mc_io);
 
@@ -3199,7 +3199,7 @@ static int dpaa2_switch_probe(struct fsl_mc_device *sw_dev)
                               GFP_KERNEL);
        if (!(ethsw->ports)) {
                err = -ENOMEM;
-               goto err_takedown;
+               goto err_teardown;
        }
 
        ethsw->fdbs = kcalloc(ethsw->sw_attr.num_ifs, sizeof(*ethsw->fdbs),
@@ -3270,8 +3270,8 @@ err_free_fdbs:
 err_free_ports:
        kfree(ethsw->ports);
 
-err_takedown:
-       dpaa2_switch_takedown(sw_dev);
+err_teardown:
+       dpaa2_switch_teardown(sw_dev);
 
 err_free_cmdport:
        fsl_mc_portal_free(ethsw->mc_io);
index 5325230..80461ab 100644 (file)
@@ -938,20 +938,19 @@ static int hns3_dbg_dev_info(struct hnae3_handle *h, char *buf, int len)
        return 0;
 }
 
-static int hns3_dbg_get_cmd_index(struct hnae3_handle *handle,
-                                 const unsigned char *name, u32 *index)
+static int hns3_dbg_get_cmd_index(struct hns3_dbg_data *dbg_data, u32 *index)
 {
        u32 i;
 
        for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) {
-               if (!strncmp(name, hns3_dbg_cmd[i].name,
-                            strlen(hns3_dbg_cmd[i].name))) {
+               if (hns3_dbg_cmd[i].cmd == dbg_data->cmd) {
                        *index = i;
                        return 0;
                }
        }
 
-       dev_err(&handle->pdev->dev, "unknown command(%s)\n", name);
+       dev_err(&dbg_data->handle->pdev->dev, "unknown command(%d)\n",
+               dbg_data->cmd);
        return -EINVAL;
 }
 
@@ -1019,8 +1018,7 @@ static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
        u32 index;
        int ret;
 
-       ret = hns3_dbg_get_cmd_index(handle, filp->f_path.dentry->d_iname,
-                                    &index);
+       ret = hns3_dbg_get_cmd_index(dbg_data, &index);
        if (ret)
                return ret;
 
@@ -1090,6 +1088,7 @@ static int hns3_dbg_bd_file_init(struct hnae3_handle *handle, u32 cmd)
                char name[HNS3_DBG_FILE_NAME_LEN];
 
                data[i].handle = handle;
+               data[i].cmd = hns3_dbg_cmd[cmd].cmd;
                data[i].qid = i;
                sprintf(name, "%s%u", hns3_dbg_cmd[cmd].name, i);
                debugfs_create_file(name, 0400, entry_dir, &data[i],
@@ -1110,6 +1109,7 @@ hns3_dbg_common_file_init(struct hnae3_handle *handle, u32 cmd)
                return -ENOMEM;
 
        data->handle = handle;
+       data->cmd = hns3_dbg_cmd[cmd].cmd;
        entry_dir = hns3_dbg_dentry[hns3_dbg_cmd[cmd].dentry].dentry;
        debugfs_create_file(hns3_dbg_cmd[cmd].name, 0400, entry_dir,
                            data, &hns3_dbg_fops);
index f3766ff..bd88010 100644 (file)
@@ -22,6 +22,7 @@ struct hns3_dbg_item {
 
 struct hns3_dbg_data {
        struct hnae3_handle *handle;
+       enum hnae3_dbg_cmd cmd;
        u16 qid;
 };
 
index 887297e..eb748aa 100644 (file)
@@ -573,9 +573,13 @@ static void hclge_cmd_uninit_regs(struct hclge_hw *hw)
 
 void hclge_cmd_uninit(struct hclge_dev *hdev)
 {
+       set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
+       /* wait to ensure that the firmware completes the possible left
+        * over commands.
+        */
+       msleep(HCLGE_CMDQ_CLEAR_WAIT_TIME);
        spin_lock_bh(&hdev->hw.cmq.csq.lock);
        spin_lock(&hdev->hw.cmq.crq.lock);
-       set_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state);
        hclge_cmd_uninit_regs(&hdev->hw);
        spin_unlock(&hdev->hw.cmq.crq.lock);
        spin_unlock_bh(&hdev->hw.cmq.csq.lock);
index 18bde77..ac70d49 100644 (file)
@@ -9,6 +9,7 @@
 #include "hnae3.h"
 
 #define HCLGE_CMDQ_TX_TIMEOUT          30000
+#define HCLGE_CMDQ_CLEAR_WAIT_TIME     200
 #define HCLGE_DESC_DATA_LEN            6
 
 struct hclge_dev;
@@ -270,6 +271,9 @@ enum hclge_opcode_type {
        /* Led command */
        HCLGE_OPC_LED_STATUS_CFG        = 0xB000,
 
+       /* clear hardware resource command */
+       HCLGE_OPC_CLEAR_HW_RESOURCE     = 0x700B,
+
        /* NCL config command */
        HCLGE_OPC_QUERY_NCL_CONFIG      = 0x7011,
 
index 5bf5db9..39f56f2 100644 (file)
@@ -255,21 +255,12 @@ static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
        u64 requests[HNAE3_MAX_TC], indications[HNAE3_MAX_TC];
        struct hclge_vport *vport = hclge_get_vport(h);
        struct hclge_dev *hdev = vport->back;
-       u8 i, j, pfc_map, *prio_tc;
        int ret;
+       u8 i;
 
        memset(pfc, 0, sizeof(*pfc));
        pfc->pfc_cap = hdev->pfc_max;
-       prio_tc = hdev->tm_info.prio_tc;
-       pfc_map = hdev->tm_info.hw_pfc_map;
-
-       /* Pfc setting is based on TC */
-       for (i = 0; i < hdev->tm_info.num_tc; i++) {
-               for (j = 0; j < HNAE3_MAX_USER_PRIO; j++) {
-                       if ((prio_tc[j] == i) && (pfc_map & BIT(i)))
-                               pfc->pfc_en |= BIT(j);
-               }
-       }
+       pfc->pfc_en = hdev->tm_info.pfc_en;
 
        ret = hclge_pfc_tx_stats_get(hdev, requests);
        if (ret)
index ebeaf12..03ae122 100644 (file)
@@ -1550,6 +1550,7 @@ static int hclge_configure(struct hclge_dev *hdev)
        hdev->tm_info.hw_pfc_map = 0;
        hdev->wanted_umv_size = cfg.umv_space;
        hdev->tx_spare_buf_size = cfg.tx_spare_buf_size;
+       hdev->gro_en = true;
        if (cfg.vlan_fliter_cap == HCLGE_VLAN_FLTR_CAN_MDF)
                set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps);
 
@@ -1618,7 +1619,7 @@ static int hclge_config_tso(struct hclge_dev *hdev, u16 tso_mss_min,
        return hclge_cmd_send(&hdev->hw, &desc, 1);
 }
 
-static int hclge_config_gro(struct hclge_dev *hdev, bool en)
+static int hclge_config_gro(struct hclge_dev *hdev)
 {
        struct hclge_cfg_gro_status_cmd *req;
        struct hclge_desc desc;
@@ -1630,7 +1631,7 @@ static int hclge_config_gro(struct hclge_dev *hdev, bool en)
        hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_GRO_GENERIC_CONFIG, false);
        req = (struct hclge_cfg_gro_status_cmd *)desc.data;
 
-       req->gro_en = en ? 1 : 0;
+       req->gro_en = hdev->gro_en ? 1 : 0;
 
        ret = hclge_cmd_send(&hdev->hw, &desc, 1);
        if (ret)
@@ -2952,12 +2953,12 @@ static void hclge_update_link_status(struct hclge_dev *hdev)
        }
 
        if (state != hdev->hw.mac.link) {
+               hdev->hw.mac.link = state;
                client->ops->link_status_change(handle, state);
                hclge_config_mac_tnl_int(hdev, state);
                if (rclient && rclient->ops->link_status_change)
                        rclient->ops->link_status_change(rhandle, state);
 
-               hdev->hw.mac.link = state;
                hclge_push_link_status(hdev);
        }
 
@@ -10073,7 +10074,11 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
 static void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
                                       bool writen_to_tbl)
 {
-       struct hclge_vport_vlan_cfg *vlan;
+       struct hclge_vport_vlan_cfg *vlan, *tmp;
+
+       list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node)
+               if (vlan->vlan_id == vlan_id)
+                       return;
 
        vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
        if (!vlan)
@@ -11443,6 +11448,28 @@ static void hclge_clear_resetting_state(struct hclge_dev *hdev)
        }
 }
 
+static int hclge_clear_hw_resource(struct hclge_dev *hdev)
+{
+       struct hclge_desc desc;
+       int ret;
+
+       hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_CLEAR_HW_RESOURCE, false);
+
+       ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+       /* This new command is only supported by new firmware, it will
+        * fail with older firmware. Error value -EOPNOSUPP can only be
+        * returned by older firmware running this command, to keep code
+        * backward compatible we will override this value and return
+        * success.
+        */
+       if (ret && ret != -EOPNOTSUPP) {
+               dev_err(&hdev->pdev->dev,
+                       "failed to clear hw resource, ret = %d\n", ret);
+               return ret;
+       }
+       return 0;
+}
+
 static void hclge_init_rxd_adv_layout(struct hclge_dev *hdev)
 {
        if (hnae3_ae_dev_rxd_adv_layout_supported(hdev->ae_dev))
@@ -11492,6 +11519,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
        if (ret)
                goto err_cmd_uninit;
 
+       ret  = hclge_clear_hw_resource(hdev);
+       if (ret)
+               goto err_cmd_uninit;
+
        ret = hclge_get_cap(hdev);
        if (ret)
                goto err_cmd_uninit;
@@ -11556,7 +11587,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
                goto err_mdiobus_unreg;
        }
 
-       ret = hclge_config_gro(hdev, true);
+       ret = hclge_config_gro(hdev);
        if (ret)
                goto err_mdiobus_unreg;
 
@@ -11937,7 +11968,7 @@ static int hclge_reset_ae_dev(struct hnae3_ae_dev *ae_dev)
                return ret;
        }
 
-       ret = hclge_config_gro(hdev, true);
+       ret = hclge_config_gro(hdev);
        if (ret)
                return ret;
 
@@ -12671,8 +12702,15 @@ static int hclge_gro_en(struct hnae3_handle *handle, bool enable)
 {
        struct hclge_vport *vport = hclge_get_vport(handle);
        struct hclge_dev *hdev = vport->back;
+       bool gro_en_old = hdev->gro_en;
+       int ret;
 
-       return hclge_config_gro(hdev, enable);
+       hdev->gro_en = enable;
+       ret = hclge_config_gro(hdev);
+       if (ret)
+               hdev->gro_en = gro_en_old;
+
+       return ret;
 }
 
 static void hclge_sync_promisc_mode(struct hclge_dev *hdev)
index 3d33524..e446b83 100644 (file)
@@ -927,6 +927,7 @@ struct hclge_dev {
        unsigned long fd_bmap[BITS_TO_LONGS(MAX_FD_FILTER_NUM)];
        enum HCLGE_FD_ACTIVE_RULE_TYPE fd_active_type;
        u8 fd_en;
+       bool gro_en;
 
        u16 wanted_umv_size;
        /* max available unicast mac vlan space */
index bd19a2d..d9ddb0a 100644 (file)
@@ -507,12 +507,17 @@ static void hclgevf_cmd_uninit_regs(struct hclgevf_hw *hw)
 
 void hclgevf_cmd_uninit(struct hclgevf_dev *hdev)
 {
+       set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
+       /* wait to ensure that the firmware completes the possible left
+        * over commands.
+        */
+       msleep(HCLGEVF_CMDQ_CLEAR_WAIT_TIME);
        spin_lock_bh(&hdev->hw.cmq.csq.lock);
        spin_lock(&hdev->hw.cmq.crq.lock);
-       set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
        hclgevf_cmd_uninit_regs(&hdev->hw);
        spin_unlock(&hdev->hw.cmq.crq.lock);
        spin_unlock_bh(&hdev->hw.cmq.csq.lock);
+
        hclgevf_free_cmd_desc(&hdev->hw.cmq.csq);
        hclgevf_free_cmd_desc(&hdev->hw.cmq.crq);
 }
index 202feb7..5b82177 100644 (file)
@@ -8,6 +8,7 @@
 #include "hnae3.h"
 
 #define HCLGEVF_CMDQ_TX_TIMEOUT                30000
+#define HCLGEVF_CMDQ_CLEAR_WAIT_TIME   200
 #define HCLGEVF_CMDQ_RX_INVLD_B                0
 #define HCLGEVF_CMDQ_RX_OUTVLD_B       1
 
index 8784d61..9386547 100644 (file)
@@ -506,10 +506,10 @@ void hclgevf_update_link_status(struct hclgevf_dev *hdev, int link_state)
        link_state =
                test_bit(HCLGEVF_STATE_DOWN, &hdev->state) ? 0 : link_state;
        if (link_state != hdev->hw.mac.link) {
+               hdev->hw.mac.link = link_state;
                client->ops->link_status_change(handle, !!link_state);
                if (rclient && rclient->ops->link_status_change)
                        rclient->ops->link_status_change(rhandle, !!link_state);
-               hdev->hw.mac.link = link_state;
        }
 
        clear_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state);
@@ -2487,6 +2487,8 @@ static int hclgevf_configure(struct hclgevf_dev *hdev)
 {
        int ret;
 
+       hdev->gro_en = true;
+
        ret = hclgevf_get_basic_info(hdev);
        if (ret)
                return ret;
@@ -2549,7 +2551,7 @@ static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
        return 0;
 }
 
-static int hclgevf_config_gro(struct hclgevf_dev *hdev, bool en)
+static int hclgevf_config_gro(struct hclgevf_dev *hdev)
 {
        struct hclgevf_cfg_gro_status_cmd *req;
        struct hclgevf_desc desc;
@@ -2562,7 +2564,7 @@ static int hclgevf_config_gro(struct hclgevf_dev *hdev, bool en)
                                     false);
        req = (struct hclgevf_cfg_gro_status_cmd *)desc.data;
 
-       req->gro_en = en ? 1 : 0;
+       req->gro_en = hdev->gro_en ? 1 : 0;
 
        ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
        if (ret)
@@ -3308,7 +3310,7 @@ static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
                return ret;
        }
 
-       ret = hclgevf_config_gro(hdev, true);
+       ret = hclgevf_config_gro(hdev);
        if (ret)
                return ret;
 
@@ -3389,7 +3391,7 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
        if (ret)
                goto err_config;
 
-       ret = hclgevf_config_gro(hdev, true);
+       ret = hclgevf_config_gro(hdev);
        if (ret)
                goto err_config;
 
@@ -3638,8 +3640,15 @@ void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed,
 static int hclgevf_gro_en(struct hnae3_handle *handle, bool enable)
 {
        struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
+       bool gro_en_old = hdev->gro_en;
+       int ret;
 
-       return hclgevf_config_gro(hdev, enable);
+       hdev->gro_en = enable;
+       ret = hclgevf_config_gro(hdev);
+       if (ret)
+               hdev->gro_en = gro_en_old;
+
+       return ret;
 }
 
 static void hclgevf_get_media_type(struct hnae3_handle *handle, u8 *media_type,
index d7d0284..e8013be 100644 (file)
@@ -310,6 +310,8 @@ struct hclgevf_dev {
        u16 *vector_status;
        int *vector_irq;
 
+       bool gro_en;
+
        unsigned long vlan_del_fail_bmap[BITS_TO_LONGS(VLAN_N_VID)];
 
        struct hclgevf_mac_table_cfg mac_table;
index 772b2f8..b339b9b 100644 (file)
@@ -323,8 +323,8 @@ void hclgevf_mbx_async_handler(struct hclgevf_dev *hdev)
                        flag = (u8)msg_q[5];
 
                        /* update upper layer with new link link status */
-                       hclgevf_update_link_status(hdev, link_status);
                        hclgevf_update_speed_duplex(hdev, speed, duplex);
+                       hclgevf_update_link_status(hdev, link_status);
 
                        if (flag & HCLGE_MBX_PUSH_LINK_STATUS_EN)
                                set_bit(HCLGEVF_STATE_PF_PUSH_LINK_STATUS,
index cf7b388..a80336c 100644 (file)
@@ -1006,6 +1006,8 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
 {
        u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) |
            link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND;
+       u16 max_ltr_enc_d = 0;  /* maximum LTR decoded by platform */
+       u16 lat_enc_d = 0;      /* latency decoded */
        u16 lat_enc = 0;        /* latency encoded */
 
        if (link) {
@@ -1059,7 +1061,17 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
                                     E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop);
                max_ltr_enc = max_t(u16, max_snoop, max_nosnoop);
 
-               if (lat_enc > max_ltr_enc)
+               lat_enc_d = (lat_enc & E1000_LTRV_VALUE_MASK) *
+                            (1U << (E1000_LTRV_SCALE_FACTOR *
+                            ((lat_enc & E1000_LTRV_SCALE_MASK)
+                            >> E1000_LTRV_SCALE_SHIFT)));
+
+               max_ltr_enc_d = (max_ltr_enc & E1000_LTRV_VALUE_MASK) *
+                                (1U << (E1000_LTRV_SCALE_FACTOR *
+                                ((max_ltr_enc & E1000_LTRV_SCALE_MASK)
+                                >> E1000_LTRV_SCALE_SHIFT)));
+
+               if (lat_enc_d > max_ltr_enc_d)
                        lat_enc = max_ltr_enc;
        }
 
@@ -4115,13 +4127,17 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
                return ret_val;
 
        if (!(data & valid_csum_mask)) {
-               data |= valid_csum_mask;
-               ret_val = e1000_write_nvm(hw, word, 1, &data);
-               if (ret_val)
-                       return ret_val;
-               ret_val = e1000e_update_nvm_checksum(hw);
-               if (ret_val)
-                       return ret_val;
+               e_dbg("NVM Checksum Invalid\n");
+
+               if (hw->mac.type < e1000_pch_cnp) {
+                       data |= valid_csum_mask;
+                       ret_val = e1000_write_nvm(hw, word, 1, &data);
+                       if (ret_val)
+                               return ret_val;
+                       ret_val = e1000e_update_nvm_checksum(hw);
+                       if (ret_val)
+                               return ret_val;
+               }
        }
 
        return e1000e_validate_nvm_checksum_generic(hw);
index 1502895..e757896 100644 (file)
 
 /* Latency Tolerance Reporting */
 #define E1000_LTRV                     0x000F8
+#define E1000_LTRV_VALUE_MASK          0x000003FF
 #define E1000_LTRV_SCALE_MAX           5
 #define E1000_LTRV_SCALE_FACTOR                5
+#define E1000_LTRV_SCALE_SHIFT         10
+#define E1000_LTRV_SCALE_MASK          0x00001C00
 #define E1000_LTRV_REQ_SHIFT           15
 #define E1000_LTRV_NOSNOOP_SHIFT       16
 #define E1000_LTRV_SEND                        (1 << 30)
index 3f25bd8..10a83e5 100644 (file)
@@ -3663,8 +3663,7 @@ u16 i40e_lan_select_queue(struct net_device *netdev,
 
        /* is DCB enabled at all? */
        if (vsi->tc_config.numtc == 1)
-               return i40e_swdcb_skb_tx_hash(netdev, skb,
-                                             netdev->real_num_tx_queues);
+               return netdev_pick_tx(netdev, skb, sb_dev);
 
        prio = skb->priority;
        hw = &vsi->back->hw;
index e8bd041..90793b3 100644 (file)
@@ -136,6 +136,7 @@ struct iavf_q_vector {
 struct iavf_mac_filter {
        struct list_head list;
        u8 macaddr[ETH_ALEN];
+       bool is_new_mac;        /* filter is new, wait for PF decision */
        bool remove;            /* filter needs to be removed */
        bool add;               /* filter needs to be added */
 };
index 44bafed..606a01c 100644 (file)
@@ -751,6 +751,7 @@ struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
 
                list_add_tail(&f->list, &adapter->mac_filter_list);
                f->add = true;
+               f->is_new_mac = true;
                adapter->aq_required |= IAVF_FLAG_AQ_ADD_MAC_FILTER;
        } else {
                f->remove = false;
@@ -1506,11 +1507,6 @@ static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter)
        set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
 
        iavf_map_rings_to_vectors(adapter);
-
-       if (RSS_AQ(adapter))
-               adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS;
-       else
-               err = iavf_init_rss(adapter);
 err:
        return err;
 }
@@ -2200,6 +2196,14 @@ continue_reset:
                        goto reset_err;
        }
 
+       if (RSS_AQ(adapter)) {
+               adapter->aq_required |= IAVF_FLAG_AQ_CONFIGURE_RSS;
+       } else {
+               err = iavf_init_rss(adapter);
+               if (err)
+                       goto reset_err;
+       }
+
        adapter->aq_required |= IAVF_FLAG_AQ_GET_CONFIG;
        adapter->aq_required |= IAVF_FLAG_AQ_MAP_VECTORS;
 
index 0eab3c4..3c73596 100644 (file)
@@ -540,6 +540,47 @@ void iavf_del_ether_addrs(struct iavf_adapter *adapter)
        kfree(veal);
 }
 
+/**
+ * iavf_mac_add_ok
+ * @adapter: adapter structure
+ *
+ * Submit list of filters based on PF response.
+ **/
+static void iavf_mac_add_ok(struct iavf_adapter *adapter)
+{
+       struct iavf_mac_filter *f, *ftmp;
+
+       spin_lock_bh(&adapter->mac_vlan_list_lock);
+       list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+               f->is_new_mac = false;
+       }
+       spin_unlock_bh(&adapter->mac_vlan_list_lock);
+}
+
+/**
+ * iavf_mac_add_reject
+ * @adapter: adapter structure
+ *
+ * Remove filters from list based on PF response.
+ **/
+static void iavf_mac_add_reject(struct iavf_adapter *adapter)
+{
+       struct net_device *netdev = adapter->netdev;
+       struct iavf_mac_filter *f, *ftmp;
+
+       spin_lock_bh(&adapter->mac_vlan_list_lock);
+       list_for_each_entry_safe(f, ftmp, &adapter->mac_filter_list, list) {
+               if (f->remove && ether_addr_equal(f->macaddr, netdev->dev_addr))
+                       f->remove = false;
+
+               if (f->is_new_mac) {
+                       list_del(&f->list);
+                       kfree(f);
+               }
+       }
+       spin_unlock_bh(&adapter->mac_vlan_list_lock);
+}
+
 /**
  * iavf_add_vlans
  * @adapter: adapter structure
@@ -1492,6 +1533,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                case VIRTCHNL_OP_ADD_ETH_ADDR:
                        dev_err(&adapter->pdev->dev, "Failed to add MAC filter, error %s\n",
                                iavf_stat_str(&adapter->hw, v_retval));
+                       iavf_mac_add_reject(adapter);
                        /* restore administratively set MAC address */
                        ether_addr_copy(adapter->hw.mac.addr, netdev->dev_addr);
                        break;
@@ -1639,10 +1681,11 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                }
        }
        switch (v_opcode) {
-       case VIRTCHNL_OP_ADD_ETH_ADDR: {
+       case VIRTCHNL_OP_ADD_ETH_ADDR:
+               if (!v_retval)
+                       iavf_mac_add_ok(adapter);
                if (!ether_addr_equal(netdev->dev_addr, adapter->hw.mac.addr))
                        ether_addr_copy(netdev->dev_addr, adapter->hw.mac.addr);
-               }
                break;
        case VIRTCHNL_OP_GET_STATS: {
                struct iavf_eth_stats *stats =
index a450343..eadcb99 100644 (file)
@@ -234,6 +234,7 @@ enum ice_pf_state {
        ICE_VFLR_EVENT_PENDING,
        ICE_FLTR_OVERFLOW_PROMISC,
        ICE_VF_DIS,
+       ICE_VF_DEINIT_IN_PROGRESS,
        ICE_CFG_BUSY,
        ICE_SERVICE_SCHED,
        ICE_SERVICE_DIS,
index 91b545a..7fe6e8e 100644 (file)
@@ -42,7 +42,9 @@ static int ice_info_pba(struct ice_pf *pf, struct ice_info_ctx *ctx)
 
        status = ice_read_pba_string(hw, (u8 *)ctx->buf, sizeof(ctx->buf));
        if (status)
-               return -EIO;
+               /* We failed to locate the PBA, so just skip this entry */
+               dev_dbg(ice_pf_to_dev(pf), "Failed to read Product Board Assembly string, status %s\n",
+                       ice_stat_str(status));
 
        return 0;
 }
index ef8d181..fe2ded7 100644 (file)
@@ -191,6 +191,14 @@ static int ice_add_mac_to_unsync_list(struct net_device *netdev, const u8 *addr)
        struct ice_netdev_priv *np = netdev_priv(netdev);
        struct ice_vsi *vsi = np->vsi;
 
+       /* Under some circumstances, we might receive a request to delete our
+        * own device address from our uc list. Because we store the device
+        * address in the VSI's MAC filter list, we need to ignore such
+        * requests and not delete our device address from this list.
+        */
+       if (ether_addr_equal(addr, netdev->dev_addr))
+               return 0;
+
        if (ice_fltr_add_mac_to_list(vsi, &vsi->tmp_unsync_list, addr,
                                     ICE_FWD_TO_VSI))
                return -EINVAL;
@@ -4194,6 +4202,11 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
        struct ice_hw *hw;
        int i, err;
 
+       if (pdev->is_virtfn) {
+               dev_err(dev, "can't probe a virtual function\n");
+               return -EINVAL;
+       }
+
        /* this driver uses devres, see
         * Documentation/driver-api/driver-model/devres.rst
         */
@@ -5119,7 +5132,7 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
                return -EADDRNOTAVAIL;
 
        if (ether_addr_equal(netdev->dev_addr, mac)) {
-               netdev_warn(netdev, "already using mac %pM\n", mac);
+               netdev_dbg(netdev, "already using mac %pM\n", mac);
                return 0;
        }
 
@@ -5130,6 +5143,7 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
                return -EBUSY;
        }
 
+       netif_addr_lock_bh(netdev);
        /* Clean up old MAC filter. Not an error if old filter doesn't exist */
        status = ice_fltr_remove_mac(vsi, netdev->dev_addr, ICE_FWD_TO_VSI);
        if (status && status != ICE_ERR_DOES_NOT_EXIST) {
@@ -5139,30 +5153,28 @@ static int ice_set_mac_address(struct net_device *netdev, void *pi)
 
        /* Add filter for new MAC. If filter exists, return success */
        status = ice_fltr_add_mac(vsi, mac, ICE_FWD_TO_VSI);
-       if (status == ICE_ERR_ALREADY_EXISTS) {
+       if (status == ICE_ERR_ALREADY_EXISTS)
                /* Although this MAC filter is already present in hardware it's
                 * possible in some cases (e.g. bonding) that dev_addr was
                 * modified outside of the driver and needs to be restored back
                 * to this value.
                 */
-               memcpy(netdev->dev_addr, mac, netdev->addr_len);
                netdev_dbg(netdev, "filter for MAC %pM already exists\n", mac);
-               return 0;
-       }
-
-       /* error if the new filter addition failed */
-       if (status)
+       else if (status)
+               /* error if the new filter addition failed */
                err = -EADDRNOTAVAIL;
 
 err_update_filters:
        if (err) {
                netdev_err(netdev, "can't set MAC %pM. filter update failed\n",
                           mac);
+               netif_addr_unlock_bh(netdev);
                return err;
        }
 
        /* change the netdev's MAC address */
        memcpy(netdev->dev_addr, mac, netdev->addr_len);
+       netif_addr_unlock_bh(netdev);
        netdev_dbg(vsi->netdev, "updated MAC address to %pM\n",
                   netdev->dev_addr);
 
index 5d5207b..9e3ddb9 100644 (file)
@@ -656,7 +656,7 @@ static int ice_ptp_cfg_clkout(struct ice_pf *pf, unsigned int chan,
         * maintaining phase
         */
        if (start_time < current_time)
-               start_time = div64_u64(current_time + NSEC_PER_MSEC - 1,
+               start_time = div64_u64(current_time + NSEC_PER_SEC - 1,
                                       NSEC_PER_SEC) * NSEC_PER_SEC + phase;
 
        start_time -= E810_OUT_PROP_DELAY_NS;
index 2826570..e93430a 100644 (file)
@@ -615,6 +615,8 @@ void ice_free_vfs(struct ice_pf *pf)
        struct ice_hw *hw = &pf->hw;
        unsigned int tmp, i;
 
+       set_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state);
+
        if (!pf->vf)
                return;
 
@@ -680,6 +682,7 @@ void ice_free_vfs(struct ice_pf *pf)
                                i);
 
        clear_bit(ICE_VF_DIS, pf->state);
+       clear_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state);
        clear_bit(ICE_FLAG_SRIOV_ENA, pf->flags);
 }
 
@@ -4415,6 +4418,10 @@ void ice_vc_process_vf_msg(struct ice_pf *pf, struct ice_rq_event_info *event)
        struct device *dev;
        int err = 0;
 
+       /* if de-init is underway, don't process messages from VF */
+       if (test_bit(ICE_VF_DEINIT_IN_PROGRESS, pf->state))
+               return;
+
        dev = ice_pf_to_dev(pf);
        if (ice_validate_vf_id(pf, vf_id)) {
                err = -EINVAL;
index e29aadb..ed2d66b 100644 (file)
@@ -149,6 +149,9 @@ static void igc_release_hw_control(struct igc_adapter *adapter)
        struct igc_hw *hw = &adapter->hw;
        u32 ctrl_ext;
 
+       if (!pci_device_is_present(adapter->pdev))
+               return;
+
        /* Let firmware take over control of h/w */
        ctrl_ext = rd32(IGC_CTRL_EXT);
        wr32(IGC_CTRL_EXT,
@@ -4449,26 +4452,29 @@ void igc_down(struct igc_adapter *adapter)
 
        igc_ptp_suspend(adapter);
 
-       /* disable receives in the hardware */
-       rctl = rd32(IGC_RCTL);
-       wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);
-       /* flush and sleep below */
-
+       if (pci_device_is_present(adapter->pdev)) {
+               /* disable receives in the hardware */
+               rctl = rd32(IGC_RCTL);
+               wr32(IGC_RCTL, rctl & ~IGC_RCTL_EN);
+               /* flush and sleep below */
+       }
        /* set trans_start so we don't get spurious watchdogs during reset */
        netif_trans_update(netdev);
 
        netif_carrier_off(netdev);
        netif_tx_stop_all_queues(netdev);
 
-       /* disable transmits in the hardware */
-       tctl = rd32(IGC_TCTL);
-       tctl &= ~IGC_TCTL_EN;
-       wr32(IGC_TCTL, tctl);
-       /* flush both disables and wait for them to finish */
-       wrfl();
-       usleep_range(10000, 20000);
+       if (pci_device_is_present(adapter->pdev)) {
+               /* disable transmits in the hardware */
+               tctl = rd32(IGC_TCTL);
+               tctl &= ~IGC_TCTL_EN;
+               wr32(IGC_TCTL, tctl);
+               /* flush both disables and wait for them to finish */
+               wrfl();
+               usleep_range(10000, 20000);
 
-       igc_irq_disable(adapter);
+               igc_irq_disable(adapter);
+       }
 
        adapter->flags &= ~IGC_FLAG_NEED_LINK_UPDATE;
 
@@ -5489,7 +5495,7 @@ static bool validate_schedule(struct igc_adapter *adapter,
                if (e->command != TC_TAPRIO_CMD_SET_GATES)
                        return false;
 
-               for (i = 0; i < IGC_MAX_TX_QUEUES; i++) {
+               for (i = 0; i < adapter->num_tx_queues; i++) {
                        if (e->gate_mask & BIT(i))
                                queue_uses[i]++;
 
@@ -5546,7 +5552,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 
                end_time += e->interval;
 
-               for (i = 0; i < IGC_MAX_TX_QUEUES; i++) {
+               for (i = 0; i < adapter->num_tx_queues; i++) {
                        struct igc_ring *ring = adapter->tx_ring[i];
 
                        if (!(e->gate_mask & BIT(i)))
index 69617d2..4ae19c6 100644 (file)
@@ -849,7 +849,8 @@ void igc_ptp_suspend(struct igc_adapter *adapter)
        adapter->ptp_tx_skb = NULL;
        clear_bit_unlock(__IGC_PTP_TX_IN_PROGRESS, &adapter->state);
 
-       igc_ptp_time_save(adapter);
+       if (pci_device_is_present(adapter->pdev))
+               igc_ptp_time_save(adapter);
 }
 
 /**
index 96dd1a4..b1d22e4 100644 (file)
@@ -52,8 +52,11 @@ static int ixgbe_xsk_pool_enable(struct ixgbe_adapter *adapter,
 
                /* Kick start the NAPI context so that receiving will start */
                err = ixgbe_xsk_wakeup(adapter->netdev, qid, XDP_WAKEUP_RX);
-               if (err)
+               if (err) {
+                       clear_bit(qid, adapter->af_xdp_zc_qps);
+                       xsk_pool_dma_unmap(pool, IXGBE_RX_DMA_ATTR);
                        return err;
+               }
        }
 
        return 0;
index 76a7777..de32e5b 100644 (file)
 #define        MVNETA_VLAN_PRIO_TO_RXQ                  0x2440
 #define      MVNETA_VLAN_PRIO_RXQ_MAP(prio, rxq) ((rxq) << ((prio) * 3))
 #define MVNETA_PORT_STATUS                       0x2444
-#define      MVNETA_TX_IN_PRGRS                  BIT(1)
+#define      MVNETA_TX_IN_PRGRS                  BIT(0)
 #define      MVNETA_TX_FIFO_EMPTY                BIT(8)
 #define MVNETA_RX_MIN_FRAME_SIZE                 0x247c
 /* Only exists on Armada XP and Armada 370 */
index b9fbc9f..cf8acab 100644 (file)
@@ -938,7 +938,7 @@ enum mvpp22_ptp_packet_format {
 #define MVPP2_BM_COOKIE_POOL_OFFS      8
 #define MVPP2_BM_COOKIE_CPU_OFFS       24
 
-#define MVPP2_BM_SHORT_FRAME_SIZE      704     /* frame size 128 */
+#define MVPP2_BM_SHORT_FRAME_SIZE      736     /* frame size 128 */
 #define MVPP2_BM_LONG_FRAME_SIZE       2240    /* frame size 1664 */
 #define MVPP2_BM_JUMBO_FRAME_SIZE      10432   /* frame size 9856 */
 /* BM short pool packet size
index 0b3e8f2..9a30916 100644 (file)
@@ -748,7 +748,7 @@ static void
 prestera_fdb_offload_notify(struct prestera_port *port,
                            struct switchdev_notifier_fdb_info *info)
 {
-       struct switchdev_notifier_fdb_info send_info;
+       struct switchdev_notifier_fdb_info send_info = {};
 
        send_info.addr = info->addr;
        send_info.vid = info->vid;
@@ -1123,7 +1123,7 @@ static int prestera_switchdev_blk_event(struct notifier_block *unused,
 static void prestera_fdb_event(struct prestera_switch *sw,
                               struct prestera_event *evt, void *arg)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
        struct net_device *dev = NULL;
        struct prestera_port *port;
        struct prestera_lag *lag;
index df3e493..360e093 100644 (file)
@@ -134,6 +134,7 @@ int mlx5_core_create_cq(struct mlx5_core_dev *dev, struct mlx5_core_cq *cq,
                              cq->cqn);
 
        cq->uar = dev->priv.uar;
+       cq->irqn = eq->core.irqn;
 
        return 0;
 
index 01a1d02..3f8a980 100644 (file)
@@ -1019,12 +1019,19 @@ int mlx5_fw_tracer_init(struct mlx5_fw_tracer *tracer)
        MLX5_NB_INIT(&tracer->nb, fw_tracer_event, DEVICE_TRACER);
        mlx5_eq_notifier_register(dev, &tracer->nb);
 
-       mlx5_fw_tracer_start(tracer);
-
+       err = mlx5_fw_tracer_start(tracer);
+       if (err) {
+               mlx5_core_warn(dev, "FWTracer: Failed to start tracer %d\n", err);
+               goto err_notifier_unregister;
+       }
        return 0;
 
+err_notifier_unregister:
+       mlx5_eq_notifier_unregister(dev, &tracer->nb);
+       mlx5_core_destroy_mkey(dev, &tracer->buff.mkey);
 err_dealloc_pd:
        mlx5_core_dealloc_pd(dev, tracer->buff.pdn);
+       cancel_work_sync(&tracer->read_fw_strings_work);
        return err;
 }
 
index 8f79f04..1e2d117 100644 (file)
@@ -124,6 +124,11 @@ static int mlx5e_route_lookup_ipv4_get(struct mlx5e_priv *priv,
        if (IS_ERR(rt))
                return PTR_ERR(rt);
 
+       if (rt->rt_type != RTN_UNICAST) {
+               ret = -ENETUNREACH;
+               goto err_rt_release;
+       }
+
        if (mlx5_lag_is_multipath(mdev) && rt->rt_gw_family != AF_INET) {
                ret = -ENETUNREACH;
                goto err_rt_release;
index 37c4408..24f919e 100644 (file)
@@ -1535,15 +1535,9 @@ static int mlx5e_alloc_cq_common(struct mlx5e_priv *priv,
 {
        struct mlx5_core_dev *mdev = priv->mdev;
        struct mlx5_core_cq *mcq = &cq->mcq;
-       int eqn_not_used;
-       unsigned int irqn;
        int err;
        u32 i;
 
-       err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn);
-       if (err)
-               return err;
-
        err = mlx5_cqwq_create(mdev, &param->wq, param->cqc, &cq->wq,
                               &cq->wq_ctrl);
        if (err)
@@ -1557,7 +1551,6 @@ static int mlx5e_alloc_cq_common(struct mlx5e_priv *priv,
        mcq->vector     = param->eq_ix;
        mcq->comp       = mlx5e_completion_event;
        mcq->event      = mlx5e_cq_error_event;
-       mcq->irqn       = irqn;
 
        for (i = 0; i < mlx5_cqwq_get_size(&cq->wq); i++) {
                struct mlx5_cqe64 *cqe = mlx5_cqwq_get_wqe(&cq->wq, i);
@@ -1605,11 +1598,10 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)
        void *in;
        void *cqc;
        int inlen;
-       unsigned int irqn_not_used;
        int eqn;
        int err;
 
-       err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used);
+       err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn);
        if (err)
                return err;
 
@@ -1891,30 +1883,30 @@ static int mlx5e_open_queues(struct mlx5e_channel *c,
        if (err)
                goto err_close_icosq;
 
+       err = mlx5e_open_rxq_rq(c, params, &cparam->rq);
+       if (err)
+               goto err_close_sqs;
+
        if (c->xdp) {
                err = mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, NULL,
                                       &c->rq_xdpsq, false);
                if (err)
-                       goto err_close_sqs;
+                       goto err_close_rq;
        }
 
-       err = mlx5e_open_rxq_rq(c, params, &cparam->rq);
-       if (err)
-               goto err_close_xdp_sq;
-
        err = mlx5e_open_xdpsq(c, params, &cparam->xdp_sq, NULL, &c->xdpsq, true);
        if (err)
-               goto err_close_rq;
+               goto err_close_xdp_sq;
 
        return 0;
 
-err_close_rq:
-       mlx5e_close_rq(&c->rq);
-
 err_close_xdp_sq:
        if (c->xdp)
                mlx5e_close_xdpsq(&c->rq_xdpsq);
 
+err_close_rq:
+       mlx5e_close_rq(&c->rq);
+
 err_close_sqs:
        mlx5e_close_sqs(c);
 
@@ -1949,9 +1941,9 @@ err_close_async_icosq_cq:
 static void mlx5e_close_queues(struct mlx5e_channel *c)
 {
        mlx5e_close_xdpsq(&c->xdpsq);
-       mlx5e_close_rq(&c->rq);
        if (c->xdp)
                mlx5e_close_xdpsq(&c->rq_xdpsq);
+       mlx5e_close_rq(&c->rq);
        mlx5e_close_sqs(c);
        mlx5e_close_icosq(&c->icosq);
        mlx5e_close_icosq(&c->async_icosq);
@@ -1983,9 +1975,8 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
        struct mlx5e_channel *c;
        unsigned int irq;
        int err;
-       int eqn;
 
-       err = mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq);
+       err = mlx5_vector2irqn(priv->mdev, ix, &irq);
        if (err)
                return err;
 
index 6e074cc..605c8ec 100644 (file)
@@ -855,8 +855,8 @@ clean:
        return err;
 }
 
-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
-                   unsigned int *irqn)
+static int vector2eqnirqn(struct mlx5_core_dev *dev, int vector, int *eqn,
+                         unsigned int *irqn)
 {
        struct mlx5_eq_table *table = dev->priv.eq_table;
        struct mlx5_eq_comp *eq, *n;
@@ -865,8 +865,10 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
 
        list_for_each_entry_safe(eq, n, &table->comp_eqs_list, list) {
                if (i++ == vector) {
-                       *eqn = eq->core.eqn;
-                       *irqn = eq->core.irqn;
+                       if (irqn)
+                               *irqn = eq->core.irqn;
+                       if (eqn)
+                               *eqn = eq->core.eqn;
                        err = 0;
                        break;
                }
@@ -874,8 +876,18 @@ int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
 
        return err;
 }
+
+int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn)
+{
+       return vector2eqnirqn(dev, vector, eqn, NULL);
+}
 EXPORT_SYMBOL(mlx5_vector2eqn);
 
+int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn)
+{
+       return vector2eqnirqn(dev, vector, NULL, irqn);
+}
+
 unsigned int mlx5_comp_vectors_count(struct mlx5_core_dev *dev)
 {
        return dev->priv.eq_table->num_comp_eqs;
index a6e1d4f..69a3630 100644 (file)
@@ -69,7 +69,7 @@ static void
 mlx5_esw_bridge_fdb_offload_notify(struct net_device *dev, const unsigned char *addr, u16 vid,
                                   unsigned long val)
 {
-       struct switchdev_notifier_fdb_info send_info;
+       struct switchdev_notifier_fdb_info send_info = {};
 
        send_info.addr = addr;
        send_info.vid = vid;
@@ -579,7 +579,7 @@ static struct mlx5_esw_bridge *mlx5_esw_bridge_create(int ifindex,
        xa_init(&bridge->vports);
        bridge->ifindex = ifindex;
        bridge->refcnt = 1;
-       bridge->ageing_time = BR_DEFAULT_AGEING_TIME;
+       bridge->ageing_time = clock_t_to_jiffies(BR_DEFAULT_AGEING_TIME);
        list_add(&bridge->list, &br_offloads->bridges);
 
        return bridge;
@@ -1006,7 +1006,7 @@ int mlx5_esw_bridge_ageing_time_set(unsigned long ageing_time, struct mlx5_eswit
        if (!vport->bridge)
                return -EINVAL;
 
-       vport->bridge->ageing_time = ageing_time;
+       vport->bridge->ageing_time = clock_t_to_jiffies(ageing_time);
        return 0;
 }
 
index 794012c..d3ad78a 100644 (file)
@@ -501,6 +501,7 @@ err_sampler:
 err_offload_rule:
        mlx5_esw_vporttbl_put(esw, &per_vport_tbl_attr);
 err_default_tbl:
+       kfree(sample_flow);
        return ERR_PTR(err);
 }
 
index 011e766..3bb71a1 100644 (file)
@@ -48,6 +48,7 @@
 #include "lib/fs_chains.h"
 #include "en_tc.h"
 #include "en/mapping.h"
+#include "devlink.h"
 
 #define mlx5_esw_for_each_rep(esw, i, rep) \
        xa_for_each(&((esw)->offloads.vport_reps), i, rep)
@@ -3001,12 +3002,19 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
        if (cur_mlx5_mode == mlx5_mode)
                goto unlock;
 
-       if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV)
+       if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
+               if (mlx5_devlink_trap_get_num_active(esw->dev)) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "Can't change mode while devlink traps are active");
+                       err = -EOPNOTSUPP;
+                       goto unlock;
+               }
                err = esw_offloads_start(esw, extack);
-       else if (mode == DEVLINK_ESWITCH_MODE_LEGACY)
+       } else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) {
                err = esw_offloads_stop(esw, extack);
-       else
+       } else {
                err = -EINVAL;
+       }
 
 unlock:
        mlx5_esw_unlock(esw);
index bd66ab2..d5da4ab 100644 (file)
@@ -417,7 +417,6 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
        struct mlx5_wq_param wqp;
        struct mlx5_cqe64 *cqe;
        int inlen, err, eqn;
-       unsigned int irqn;
        void *cqc, *in;
        __be64 *pas;
        u32 i;
@@ -446,7 +445,7 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
                goto err_cqwq;
        }
 
-       err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn, &irqn);
+       err = mlx5_vector2eqn(mdev, smp_processor_id(), &eqn);
        if (err) {
                kvfree(in);
                goto err_cqwq;
@@ -476,7 +475,6 @@ static int mlx5_fpga_conn_create_cq(struct mlx5_fpga_conn *conn, int cq_size)
        *conn->cq.mcq.arm_db    = 0;
        conn->cq.mcq.vector     = 0;
        conn->cq.mcq.comp       = mlx5_fpga_conn_cq_complete;
-       conn->cq.mcq.irqn       = irqn;
        conn->cq.mcq.uar        = fdev->conn_res.uar;
        tasklet_setup(&conn->cq.tasklet, mlx5_fpga_conn_cq_tasklet);
 
index 624cede..d3d628b 100644 (file)
@@ -104,4 +104,6 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev);
 struct cpu_rmap *mlx5_eq_table_get_rmap(struct mlx5_core_dev *dev);
 #endif
 
+int mlx5_vector2irqn(struct mlx5_core_dev *dev, int vector, unsigned int *irqn);
+
 #endif
index eb1b316..c84ad87 100644 (file)
@@ -1784,16 +1784,14 @@ static int __init init(void)
        if (err)
                goto err_sf;
 
-#ifdef CONFIG_MLX5_CORE_EN
        err = mlx5e_init();
-       if (err) {
-               pci_unregister_driver(&mlx5_core_driver);
-               goto err_debug;
-       }
-#endif
+       if (err)
+               goto err_en;
 
        return 0;
 
+err_en:
+       mlx5_sf_driver_unregister();
 err_sf:
        pci_unregister_driver(&mlx5_core_driver);
 err_debug:
@@ -1803,9 +1801,7 @@ err_debug:
 
 static void __exit cleanup(void)
 {
-#ifdef CONFIG_MLX5_CORE_EN
        mlx5e_cleanup();
-#endif
        mlx5_sf_driver_unregister();
        pci_unregister_driver(&mlx5_core_driver);
        mlx5_unregister_debugfs();
index 343807a..da365b8 100644 (file)
@@ -206,8 +206,13 @@ int mlx5_firmware_flash(struct mlx5_core_dev *dev, const struct firmware *fw,
 int mlx5_fw_version_query(struct mlx5_core_dev *dev,
                          u32 *running_ver, u32 *stored_ver);
 
+#ifdef CONFIG_MLX5_CORE_EN
 int mlx5e_init(void);
 void mlx5e_cleanup(void);
+#else
+static inline int mlx5e_init(void){ return 0; }
+static inline void mlx5e_cleanup(void){}
+#endif
 
 static inline bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev)
 {
index b25f764..3465b36 100644 (file)
@@ -214,6 +214,7 @@ static struct mlx5_irq *irq_request(struct mlx5_irq_pool *pool, int i)
                err = -ENOMEM;
                goto err_cpumask;
        }
+       irq->pool = pool;
        kref_init(&irq->kref);
        irq->index = i;
        err = xa_err(xa_store(&pool->irqs, irq->index, irq, GFP_KERNEL));
@@ -222,7 +223,6 @@ static struct mlx5_irq *irq_request(struct mlx5_irq_pool *pool, int i)
                              irq->index, err);
                goto err_xa;
        }
-       irq->pool = pool;
        return irq;
 err_xa:
        free_cpumask_var(irq->mask);
@@ -251,8 +251,11 @@ int mlx5_irq_attach_nb(struct mlx5_irq *irq, struct notifier_block *nb)
 
 int mlx5_irq_detach_nb(struct mlx5_irq *irq, struct notifier_block *nb)
 {
+       int err = 0;
+
+       err = atomic_notifier_chain_unregister(&irq->nh, nb);
        irq_put(irq);
-       return atomic_notifier_chain_unregister(&irq->nh, nb);
+       return err;
 }
 
 struct cpumask *mlx5_irq_get_affinity_mask(struct mlx5_irq *irq)
@@ -437,6 +440,7 @@ irq_pool_alloc(struct mlx5_core_dev *dev, int start, int size, char *name,
        if (!pool)
                return ERR_PTR(-ENOMEM);
        pool->dev = dev;
+       mutex_init(&pool->lock);
        xa_init_flags(&pool->irqs, XA_FLAGS_ALLOC);
        pool->xa_num_irqs.min = start;
        pool->xa_num_irqs.max = start + size - 1;
@@ -445,7 +449,6 @@ irq_pool_alloc(struct mlx5_core_dev *dev, int start, int size, char *name,
                         name);
        pool->min_threshold = min_threshold * MLX5_EQ_REFS_PER_IRQ;
        pool->max_threshold = max_threshold * MLX5_EQ_REFS_PER_IRQ;
-       mutex_init(&pool->lock);
        mlx5_core_dbg(dev, "pool->name = %s, pool->size = %d, pool->start = %d",
                      name, size, start);
        return pool;
@@ -459,6 +462,7 @@ static void irq_pool_free(struct mlx5_irq_pool *pool)
        xa_for_each(&pool->irqs, index, irq)
                irq_release(&irq->kref);
        xa_destroy(&pool->irqs);
+       mutex_destroy(&pool->lock);
        kvfree(pool);
 }
 
index 12cf323..9df0e73 100644 (file)
@@ -749,7 +749,6 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
        struct mlx5_cqe64 *cqe;
        struct mlx5dr_cq *cq;
        int inlen, err, eqn;
-       unsigned int irqn;
        void *cqc, *in;
        __be64 *pas;
        int vector;
@@ -782,7 +781,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
                goto err_cqwq;
 
        vector = raw_smp_processor_id() % mlx5_comp_vectors_count(mdev);
-       err = mlx5_vector2eqn(mdev, vector, &eqn, &irqn);
+       err = mlx5_vector2eqn(mdev, vector, &eqn);
        if (err) {
                kvfree(in);
                goto err_cqwq;
@@ -818,7 +817,6 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
        *cq->mcq.arm_db = cpu_to_be32(2 << 28);
 
        cq->mcq.vector = 0;
-       cq->mcq.irqn = irqn;
        cq->mcq.uar = uar;
 
        return cq;
index f1950e4..e4dd4ee 100644 (file)
@@ -352,6 +352,7 @@ static void dr_ste_v0_set_rx_decap(u8 *hw_ste_p)
 {
        MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action,
                 DR_STE_TUNL_ACTION_DECAP);
+       MLX5_SET(ste_rx_steering_mult, hw_ste_p, fail_on_error, 1);
 }
 
 static void dr_ste_v0_set_rx_pop_vlan(u8 *hw_ste_p)
@@ -365,6 +366,7 @@ static void dr_ste_v0_set_rx_decap_l3(u8 *hw_ste_p, bool vlan)
        MLX5_SET(ste_rx_steering_mult, hw_ste_p, tunneling_action,
                 DR_STE_TUNL_ACTION_L3_DECAP);
        MLX5_SET(ste_modify_packet, hw_ste_p, action_description, vlan ? 1 : 0);
+       MLX5_SET(ste_rx_steering_mult, hw_ste_p, fail_on_error, 1);
 }
 
 static void dr_ste_v0_set_rewrite_actions(u8 *hw_ste_p, u16 num_of_actions,
index 7e221ef..f69cbb3 100644 (file)
@@ -9079,7 +9079,7 @@ mlxsw_sp_rif_fid_fid_get(struct mlxsw_sp_rif *rif,
 
 static void mlxsw_sp_rif_fid_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
        struct net_device *dev;
 
        dev = br_fdb_find_port(rif->dev, mac, 0);
@@ -9127,8 +9127,8 @@ mlxsw_sp_rif_vlan_fid_get(struct mlxsw_sp_rif *rif,
 
 static void mlxsw_sp_rif_vlan_fdb_del(struct mlxsw_sp_rif *rif, const char *mac)
 {
+       struct switchdev_notifier_fdb_info info = {};
        u16 vid = mlxsw_sp_fid_8021q_vid(rif->fid);
-       struct switchdev_notifier_fdb_info info;
        struct net_device *br_dev;
        struct net_device *dev;
 
index c5ef9aa..8f90cd3 100644 (file)
@@ -2508,7 +2508,7 @@ mlxsw_sp_fdb_call_notifiers(enum switchdev_notifier_type type,
                            const char *mac, u16 vid,
                            struct net_device *dev, bool offloaded)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = mac;
        info.vid = vid;
index 0443f66..9a8e4f2 100644 (file)
@@ -277,7 +277,7 @@ static void sparx5_fdb_call_notifiers(enum switchdev_notifier_type type,
                                      const char *mac, u16 vid,
                                      struct net_device *dev, bool offloaded)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = mac;
        info.vid = vid;
index adfb978..2948d73 100644 (file)
@@ -1334,6 +1334,7 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot)
                        struct net_device *bond = ocelot_port->bond;
 
                        mask = ocelot_get_bridge_fwd_mask(ocelot, bridge);
+                       mask |= cpu_fwd_mask;
                        mask &= ~BIT(port);
                        if (bond) {
                                mask &= ~ocelot_get_bond_mask(ocelot, bond,
index ea4e834..7390fa3 100644 (file)
@@ -21,7 +21,7 @@ u32 __ocelot_read_ix(struct ocelot *ocelot, u32 reg, u32 offset)
                    ocelot->map[target][reg & REG_MASK] + offset, &val);
        return val;
 }
-EXPORT_SYMBOL(__ocelot_read_ix);
+EXPORT_SYMBOL_GPL(__ocelot_read_ix);
 
 void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset)
 {
@@ -32,7 +32,7 @@ void __ocelot_write_ix(struct ocelot *ocelot, u32 val, u32 reg, u32 offset)
        regmap_write(ocelot->targets[target],
                     ocelot->map[target][reg & REG_MASK] + offset, val);
 }
-EXPORT_SYMBOL(__ocelot_write_ix);
+EXPORT_SYMBOL_GPL(__ocelot_write_ix);
 
 void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
                     u32 offset)
@@ -45,7 +45,7 @@ void __ocelot_rmw_ix(struct ocelot *ocelot, u32 val, u32 mask, u32 reg,
                           ocelot->map[target][reg & REG_MASK] + offset,
                           mask, val);
 }
-EXPORT_SYMBOL(__ocelot_rmw_ix);
+EXPORT_SYMBOL_GPL(__ocelot_rmw_ix);
 
 u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
 {
@@ -58,7 +58,7 @@ u32 ocelot_port_readl(struct ocelot_port *port, u32 reg)
        regmap_read(port->target, ocelot->map[target][reg & REG_MASK], &val);
        return val;
 }
-EXPORT_SYMBOL(ocelot_port_readl);
+EXPORT_SYMBOL_GPL(ocelot_port_readl);
 
 void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
 {
@@ -69,7 +69,7 @@ void ocelot_port_writel(struct ocelot_port *port, u32 val, u32 reg)
 
        regmap_write(port->target, ocelot->map[target][reg & REG_MASK], val);
 }
-EXPORT_SYMBOL(ocelot_port_writel);
+EXPORT_SYMBOL_GPL(ocelot_port_writel);
 
 void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask, u32 reg)
 {
@@ -77,7 +77,7 @@ void ocelot_port_rmwl(struct ocelot_port *port, u32 val, u32 mask, u32 reg)
 
        ocelot_port_writel(port, (cur & (~mask)) | val, reg);
 }
-EXPORT_SYMBOL(ocelot_port_rmwl);
+EXPORT_SYMBOL_GPL(ocelot_port_rmwl);
 
 u32 __ocelot_target_read_ix(struct ocelot *ocelot, enum ocelot_target target,
                            u32 reg, u32 offset)
@@ -128,7 +128,7 @@ int ocelot_regfields_init(struct ocelot *ocelot,
 
        return 0;
 }
-EXPORT_SYMBOL(ocelot_regfields_init);
+EXPORT_SYMBOL_GPL(ocelot_regfields_init);
 
 static struct regmap_config ocelot_regmap_config = {
        .reg_bits       = 32,
@@ -148,4 +148,4 @@ struct regmap *ocelot_regmap_init(struct ocelot *ocelot, struct resource *res)
 
        return devm_regmap_init_mmio(ocelot->dev, regs, &ocelot_regmap_config);
 }
-EXPORT_SYMBOL(ocelot_regmap_init);
+EXPORT_SYMBOL_GPL(ocelot_regmap_init);
index 02a4610..c46a7f7 100644 (file)
@@ -327,6 +327,9 @@ static int qed_ll2_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        unsigned long flags;
        int rc = -EINVAL;
 
+       if (!p_ll2_conn)
+               return rc;
+
        spin_lock_irqsave(&p_tx->lock, flags);
        if (p_tx->b_completing_packet) {
                rc = -EBUSY;
@@ -500,7 +503,16 @@ static int qed_ll2_rxq_completion(struct qed_hwfn *p_hwfn, void *cookie)
        unsigned long flags = 0;
        int rc = 0;
 
+       if (!p_ll2_conn)
+               return rc;
+
        spin_lock_irqsave(&p_rx->lock, flags);
+
+       if (!QED_LL2_RX_REGISTERED(p_ll2_conn)) {
+               spin_unlock_irqrestore(&p_rx->lock, flags);
+               return 0;
+       }
+
        cq_new_idx = le16_to_cpu(*p_rx->p_fw_cons);
        cq_old_idx = qed_chain_get_cons_idx(&p_rx->rcq_chain);
 
@@ -821,6 +833,9 @@ static int qed_ll2_lb_rxq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        struct qed_ll2_info *p_ll2_conn = (struct qed_ll2_info *)p_cookie;
        int rc;
 
+       if (!p_ll2_conn)
+               return 0;
+
        if (!QED_LL2_RX_REGISTERED(p_ll2_conn))
                return 0;
 
@@ -844,6 +859,9 @@ static int qed_ll2_lb_txq_completion(struct qed_hwfn *p_hwfn, void *p_cookie)
        u16 new_idx = 0, num_bds = 0;
        int rc;
 
+       if (!p_ll2_conn)
+               return 0;
+
        if (!QED_LL2_TX_REGISTERED(p_ll2_conn))
                return 0;
 
@@ -1728,6 +1746,8 @@ int qed_ll2_post_rx_buffer(void *cxt,
        if (!p_ll2_conn)
                return -EINVAL;
        p_rx = &p_ll2_conn->rx_queue;
+       if (!p_rx->set_prod_addr)
+               return -EIO;
 
        spin_lock_irqsave(&p_rx->lock, flags);
        if (!list_empty(&p_rx->free_descq))
index 5bd58c6..6bb9ec9 100644 (file)
@@ -616,7 +616,12 @@ static int qed_enable_msix(struct qed_dev *cdev,
                        rc = cnt;
        }
 
-       if (rc > 0) {
+       /* For VFs, we should return with an error in case we didn't get the
+        * exact number of msix vectors as we requested.
+        * Not doing that will lead to a crash when starting queues for
+        * this VF.
+        */
+       if ((IS_PF(cdev) && rc > 0) || (IS_VF(cdev) && rc == cnt)) {
                /* MSI-x configuration was achieved */
                int_params->out.int_mode = QED_INT_MODE_MSIX;
                int_params->out.num_vectors = rc;
index da864d1..4f4b792 100644 (file)
@@ -1285,8 +1285,7 @@ qed_rdma_create_qp(void *rdma_cxt,
 
        if (!rdma_cxt || !in_params || !out_params ||
            !p_hwfn->p_rdma_info->active) {
-               DP_ERR(p_hwfn->cdev,
-                      "qed roce create qp failed due to NULL entry (rdma_cxt=%p, in=%p, out=%p, roce_info=?\n",
+               pr_err("qed roce create qp failed due to NULL entry (rdma_cxt=%p, in=%p, out=%p, roce_info=?\n",
                       rdma_cxt, in_params, out_params);
                return NULL;
        }
index 7c6064b..1c7f9ed 100644 (file)
@@ -1874,6 +1874,7 @@ static void qede_sync_free_irqs(struct qede_dev *edev)
        }
 
        edev->int_info.used_cnt = 0;
+       edev->int_info.msix_cnt = 0;
 }
 
 static int qede_req_msix_irqs(struct qede_dev *edev)
@@ -2427,7 +2428,6 @@ static int qede_load(struct qede_dev *edev, enum qede_load_mode mode,
        goto out;
 err4:
        qede_sync_free_irqs(edev);
-       memset(&edev->int_info.msix_cnt, 0, sizeof(struct qed_int_info));
 err3:
        qede_napi_disable_remove(edev);
 err2:
index d8882d0..d51bac7 100644 (file)
@@ -3156,8 +3156,10 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
 
                indirect_addr = QLC_83XX_FLASH_DIRECT_DATA(addr);
                ret = QLCRD32(adapter, indirect_addr, &err);
-               if (err == -EIO)
+               if (err == -EIO) {
+                       qlcnic_83xx_unlock_flash(adapter);
                        return err;
+               }
 
                word = ret;
                *(u32 *)p_data  = word;
index c7af5bc..4d8e337 100644 (file)
@@ -3502,12 +3502,16 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp)
        RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
        RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
 
+       /* The default value is 0x13. Change it to 0x2f */
+       rtl_csi_access_enable(tp, 0x2f);
+
        rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
 
        /* disable EEE */
        rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
 
        rtl_pcie_state_l2l3_disable(tp);
+       rtl_hw_aspm_clkreq_enable(tp, true);
 }
 
 DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)
index a466336..1f06b92 100644 (file)
@@ -2715,7 +2715,7 @@ static void
 rocker_fdb_offload_notify(struct rocker_port *rocker_port,
                          struct switchdev_notifier_fdb_info *recv_info)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = recv_info->addr;
        info.vid = recv_info->vid;
index 967a634..e33a9d2 100644 (file)
@@ -1822,7 +1822,7 @@ static void ofdpa_port_fdb_learn_work(struct work_struct *work)
                container_of(work, struct ofdpa_fdb_learn_work, work);
        bool removing = (lw->flags & OFDPA_OP_FLAG_REMOVE);
        bool learned = (lw->flags & OFDPA_OP_FLAG_LEARNED);
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = lw->addr;
        info.vid = lw->vid;
index 280ac01..ed81701 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/delay.h>
 #include <linux/mfd/syscon.h>
 #include <linux/regmap.h>
-#include <linux/pm_runtime.h>
 
 #include "stmmac_platform.h"
 
@@ -1529,9 +1528,6 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
                return ret;
        }
 
-       pm_runtime_enable(dev);
-       pm_runtime_get_sync(dev);
-
        if (bsp_priv->integrated_phy)
                rk_gmac_integrated_phy_powerup(bsp_priv);
 
@@ -1540,14 +1536,9 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
 
 static void rk_gmac_powerdown(struct rk_priv_data *gmac)
 {
-       struct device *dev = &gmac->pdev->dev;
-
        if (gmac->integrated_phy)
                rk_gmac_integrated_phy_powerdown(gmac);
 
-       pm_runtime_put_sync(dev);
-       pm_runtime_disable(dev);
-
        phy_power_on(gmac, false);
        gmac_clk_enable(gmac, false);
 }
index fcdb1d2..43eead7 100644 (file)
@@ -339,9 +339,9 @@ static inline bool stmmac_xdp_is_enabled(struct stmmac_priv *priv)
 static inline unsigned int stmmac_rx_offset(struct stmmac_priv *priv)
 {
        if (stmmac_xdp_is_enabled(priv))
-               return XDP_PACKET_HEADROOM + NET_IP_ALIGN;
+               return XDP_PACKET_HEADROOM;
 
-       return NET_SKB_PAD + NET_IP_ALIGN;
+       return 0;
 }
 
 void stmmac_disable_rx_queue(struct stmmac_priv *priv, u32 queue);
index 7b8404a..fa90bcd 100644 (file)
@@ -4914,6 +4914,10 @@ read_again:
 
                prefetch(np);
 
+               /* Ensure a valid XSK buffer before proceed */
+               if (!buf->xdp)
+                       break;
+
                if (priv->extend_desc)
                        stmmac_rx_extended_status(priv, &priv->dev->stats,
                                                  &priv->xstats,
@@ -4934,10 +4938,6 @@ read_again:
                        continue;
                }
 
-               /* Ensure a valid XSK buffer before proceed */
-               if (!buf->xdp)
-                       break;
-
                /* XSK pool expects RX frame 1:1 mapped to XSK buffer */
                if (likely(status & rx_not_ls)) {
                        xsk_buff_free(buf->xdp);
index 4f3b643..8160087 100644 (file)
@@ -884,11 +884,13 @@ static int tc_setup_taprio(struct stmmac_priv *priv,
        return 0;
 
 disable:
-       mutex_lock(&priv->plat->est->lock);
-       priv->plat->est->enable = false;
-       stmmac_est_configure(priv, priv->ioaddr, priv->plat->est,
-                            priv->plat->clk_ptp_rate);
-       mutex_unlock(&priv->plat->est->lock);
+       if (priv->plat->est) {
+               mutex_lock(&priv->plat->est->lock);
+               priv->plat->est->enable = false;
+               stmmac_est_configure(priv, priv->ioaddr, priv->plat->est,
+                                    priv->plat->clk_ptp_rate);
+               mutex_unlock(&priv->plat->est->lock);
+       }
 
        priv->plat->fpe_cfg->enable = false;
        stmmac_fpe_configure(priv, priv->ioaddr,
index 105821b..2a616c6 100644 (file)
@@ -34,18 +34,18 @@ static int stmmac_xdp_enable_pool(struct stmmac_priv *priv,
        need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
 
        if (need_update) {
-               stmmac_disable_rx_queue(priv, queue);
-               stmmac_disable_tx_queue(priv, queue);
                napi_disable(&ch->rx_napi);
                napi_disable(&ch->tx_napi);
+               stmmac_disable_rx_queue(priv, queue);
+               stmmac_disable_tx_queue(priv, queue);
        }
 
        set_bit(queue, priv->af_xdp_zc_qps);
 
        if (need_update) {
-               napi_enable(&ch->rxtx_napi);
                stmmac_enable_rx_queue(priv, queue);
                stmmac_enable_tx_queue(priv, queue);
+               napi_enable(&ch->rxtx_napi);
 
                err = stmmac_xsk_wakeup(priv->dev, queue, XDP_WAKEUP_RX);
                if (err)
@@ -72,10 +72,10 @@ static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
        need_update = netif_running(priv->dev) && stmmac_xdp_is_enabled(priv);
 
        if (need_update) {
+               napi_disable(&ch->rxtx_napi);
                stmmac_disable_rx_queue(priv, queue);
                stmmac_disable_tx_queue(priv, queue);
                synchronize_rcu();
-               napi_disable(&ch->rxtx_napi);
        }
 
        xsk_pool_dma_unmap(pool, STMMAC_RX_DMA_ATTR);
@@ -83,10 +83,10 @@ static int stmmac_xdp_disable_pool(struct stmmac_priv *priv, u16 queue)
        clear_bit(queue, priv->af_xdp_zc_qps);
 
        if (need_update) {
-               napi_enable(&ch->rx_napi);
-               napi_enable(&ch->tx_napi);
                stmmac_enable_rx_queue(priv, queue);
                stmmac_enable_tx_queue(priv, queue);
+               napi_enable(&ch->rx_napi);
+               napi_enable(&ch->tx_napi);
        }
 
        return 0;
index 9c29b36..599708a 100644 (file)
@@ -358,7 +358,7 @@ static int am65_cpsw_port_obj_del(struct net_device *ndev, const void *ctx,
 static void am65_cpsw_fdb_offload_notify(struct net_device *ndev,
                                         struct switchdev_notifier_fdb_info *rcv)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = rcv->addr;
        info.vid = rcv->vid;
index 57d279f..d1d0200 100644 (file)
@@ -920,7 +920,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
        struct cpdma_chan *txch;
        int ret, q_idx;
 
-       if (skb_padto(skb, CPSW_MIN_PACKET_SIZE)) {
+       if (skb_put_padto(skb, READ_ONCE(priv->tx_packet_min))) {
                cpsw_err(priv, tx_err, "packet pad failed\n");
                ndev->stats.tx_dropped++;
                return NET_XMIT_DROP;
@@ -1100,7 +1100,7 @@ static int cpsw_ndo_xdp_xmit(struct net_device *ndev, int n,
 
        for (i = 0; i < n; i++) {
                xdpf = frames[i];
-               if (xdpf->len < CPSW_MIN_PACKET_SIZE)
+               if (xdpf->len < READ_ONCE(priv->tx_packet_min))
                        break;
 
                if (cpsw_xdp_tx_frame(priv, xdpf, NULL, priv->emac_port))
@@ -1389,6 +1389,7 @@ static int cpsw_create_ports(struct cpsw_common *cpsw)
                priv->dev  = dev;
                priv->msg_enable = netif_msg_init(debug_level, CPSW_DEBUG);
                priv->emac_port = i + 1;
+               priv->tx_packet_min = CPSW_MIN_PACKET_SIZE;
 
                if (is_valid_ether_addr(slave_data->mac_addr)) {
                        ether_addr_copy(priv->mac_addr, slave_data->mac_addr);
@@ -1686,6 +1687,7 @@ static int cpsw_dl_switch_mode_set(struct devlink *dl, u32 id,
 
                        priv = netdev_priv(sl_ndev);
                        slave->port_vlan = vlan;
+                       WRITE_ONCE(priv->tx_packet_min, CPSW_MIN_PACKET_SIZE_VLAN);
                        if (netif_running(sl_ndev))
                                cpsw_port_add_switch_def_ale_entries(priv,
                                                                     slave);
@@ -1714,6 +1716,7 @@ static int cpsw_dl_switch_mode_set(struct devlink *dl, u32 id,
 
                        priv = netdev_priv(slave->ndev);
                        slave->port_vlan = slave->data->dual_emac_res_vlan;
+                       WRITE_ONCE(priv->tx_packet_min, CPSW_MIN_PACKET_SIZE);
                        cpsw_port_add_dual_emac_def_ale_entries(priv, slave);
                }
 
index a323bea..2951fb7 100644 (file)
@@ -89,7 +89,8 @@ do {                                                          \
 
 #define CPSW_POLL_WEIGHT       64
 #define CPSW_RX_VLAN_ENCAP_HDR_SIZE            4
-#define CPSW_MIN_PACKET_SIZE   (VLAN_ETH_ZLEN)
+#define CPSW_MIN_PACKET_SIZE_VLAN      (VLAN_ETH_ZLEN)
+#define CPSW_MIN_PACKET_SIZE   (ETH_ZLEN)
 #define CPSW_MAX_PACKET_SIZE   (VLAN_ETH_FRAME_LEN +\
                                 ETH_FCS_LEN +\
                                 CPSW_RX_VLAN_ENCAP_HDR_SIZE)
@@ -380,6 +381,7 @@ struct cpsw_priv {
        u32 emac_port;
        struct cpsw_common *cpsw;
        int offload_fwd_mark;
+       u32 tx_packet_min;
 };
 
 #define ndev_to_cpsw(ndev) (((struct cpsw_priv *)netdev_priv(ndev))->cpsw)
index f7fb6e1..a7d97d4 100644 (file)
@@ -368,7 +368,7 @@ static int cpsw_port_obj_del(struct net_device *ndev, const void *ctx,
 static void cpsw_fdb_offload_notify(struct net_device *ndev,
                                    struct switchdev_notifier_fdb_info *rcv)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        info.addr = rcv->addr;
        info.vid = rcv->vid;
index fcf3af7..8fe8887 100644 (file)
@@ -827,6 +827,12 @@ static void decode_data(struct sixpack *sp, unsigned char inbyte)
                return;
        }
 
+       if (sp->rx_count_cooked + 2 >= sizeof(sp->cooked_buf)) {
+               pr_err("6pack: cooked buffer overrun, data loss\n");
+               sp->rx_count = 0;
+               return;
+       }
+
        buf = sp->raw_buf;
        sp->cooked_buf[sp->rx_count_cooked++] =
                buf[0] | ((buf[1] << 2) & 0xc0);
index ebc976b..8caa61e 100644 (file)
@@ -418,7 +418,7 @@ static int hwsim_new_edge_nl(struct sk_buff *msg, struct genl_info *info)
        struct hwsim_edge *e;
        u32 v0, v1;
 
-       if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
+       if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] ||
            !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
                return -EINVAL;
 
@@ -528,14 +528,14 @@ static int hwsim_set_edge_lqi(struct sk_buff *msg, struct genl_info *info)
        u32 v0, v1;
        u8 lqi;
 
-       if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] &&
+       if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] ||
            !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE])
                return -EINVAL;
 
        if (nla_parse_nested_deprecated(edge_attrs, MAC802154_HWSIM_EDGE_ATTR_MAX, info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE], hwsim_edge_policy, NULL))
                return -EINVAL;
 
-       if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] &&
+       if (!edge_attrs[MAC802154_HWSIM_EDGE_ATTR_ENDPOINT_ID] ||
            !edge_attrs[MAC802154_HWSIM_EDGE_ATTR_LQI])
                return -EINVAL;
 
index 110e4ee..ebd001f 100644 (file)
@@ -82,6 +82,17 @@ out:
 
 static int parent_count;
 
+static void mdio_mux_uninit_children(struct mdio_mux_parent_bus *pb)
+{
+       struct mdio_mux_child_bus *cb = pb->children;
+
+       while (cb) {
+               mdiobus_unregister(cb->mii_bus);
+               mdiobus_free(cb->mii_bus);
+               cb = cb->next;
+       }
+}
+
 int mdio_mux_init(struct device *dev,
                  struct device_node *mux_node,
                  int (*switch_fn)(int cur, int desired, void *data),
@@ -144,7 +155,7 @@ int mdio_mux_init(struct device *dev,
                cb = devm_kzalloc(dev, sizeof(*cb), GFP_KERNEL);
                if (!cb) {
                        ret_val = -ENOMEM;
-                       continue;
+                       goto err_loop;
                }
                cb->bus_number = v;
                cb->parent = pb;
@@ -152,8 +163,7 @@ int mdio_mux_init(struct device *dev,
                cb->mii_bus = mdiobus_alloc();
                if (!cb->mii_bus) {
                        ret_val = -ENOMEM;
-                       devm_kfree(dev, cb);
-                       continue;
+                       goto err_loop;
                }
                cb->mii_bus->priv = cb;
 
@@ -165,11 +175,15 @@ int mdio_mux_init(struct device *dev,
                cb->mii_bus->write = mdio_mux_write;
                r = of_mdiobus_register(cb->mii_bus, child_bus_node);
                if (r) {
+                       mdiobus_free(cb->mii_bus);
+                       if (r == -EPROBE_DEFER) {
+                               ret_val = r;
+                               goto err_loop;
+                       }
+                       devm_kfree(dev, cb);
                        dev_err(dev,
                                "Error: Failed to register MDIO bus for child %pOF\n",
                                child_bus_node);
-                       mdiobus_free(cb->mii_bus);
-                       devm_kfree(dev, cb);
                } else {
                        cb->next = pb->children;
                        pb->children = cb;
@@ -181,7 +195,10 @@ int mdio_mux_init(struct device *dev,
        }
 
        dev_err(dev, "Error: No acceptable child buses found\n");
-       devm_kfree(dev, pb);
+
+err_loop:
+       mdio_mux_uninit_children(pb);
+       of_node_put(child_bus_node);
 err_pb_kz:
        put_device(&parent_bus->dev);
 err_parent_bus:
@@ -193,14 +210,8 @@ EXPORT_SYMBOL_GPL(mdio_mux_init);
 void mdio_mux_uninit(void *mux_handle)
 {
        struct mdio_mux_parent_bus *pb = mux_handle;
-       struct mdio_mux_child_bus *cb = pb->children;
-
-       while (cb) {
-               mdiobus_unregister(cb->mii_bus);
-               mdiobus_free(cb->mii_bus);
-               cb = cb->next;
-       }
 
+       mdio_mux_uninit_children(pb);
        put_device(&pb->mii_bus->dev);
 }
 EXPORT_SYMBOL_GPL(mdio_mux_uninit);
index 11be6bc..e60e38c 100644 (file)
@@ -335,7 +335,7 @@ static int mhi_net_newlink(void *ctxt, struct net_device *ndev, u32 if_id,
        u64_stats_init(&mhi_netdev->stats.tx_syncp);
 
        /* Start MHI channels */
-       err = mhi_prepare_for_transfer(mhi_dev, 0);
+       err = mhi_prepare_for_transfer(mhi_dev);
        if (err)
                goto out_err;
 
index 63fda3f..4bd6133 100644 (file)
@@ -1089,7 +1089,7 @@ struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
 
        xpcs = kzalloc(sizeof(*xpcs), GFP_KERNEL);
        if (!xpcs)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        xpcs->mdiodev = mdiodev;
 
index 11ff335..b7a5ae2 100644 (file)
@@ -81,6 +81,8 @@ static struct phy_driver mtk_gephy_driver[] = {
                 */
                .config_intr    = genphy_no_config_intr,
                .handle_interrupt = genphy_handle_interrupt_no_ack,
+               .suspend        = genphy_suspend,
+               .resume         = genphy_resume,
                .read_page      = mtk_gephy_read_page,
                .write_page     = mtk_gephy_write_page,
        },
@@ -93,6 +95,8 @@ static struct phy_driver mtk_gephy_driver[] = {
                 */
                .config_intr    = genphy_no_config_intr,
                .handle_interrupt = genphy_handle_interrupt_no_ack,
+               .suspend        = genphy_suspend,
+               .resume         = genphy_resume,
                .read_page      = mtk_gephy_read_page,
                .write_page     = mtk_gephy_write_page,
        },
index 53bdd67..5c928f8 100644 (file)
@@ -1760,8 +1760,6 @@ static struct phy_driver ksphy_driver[] = {
        .name           = "Micrel KSZ87XX Switch",
        /* PHY_BASIC_FEATURES */
        .config_init    = kszphy_config_init,
-       .config_aneg    = ksz8873mll_config_aneg,
-       .read_status    = ksz8873mll_read_status,
        .match_phy_device = ksz8795_match_phy_device,
        .suspend        = genphy_suspend,
        .resume         = genphy_resume,
index 930e49e..7a099c3 100644 (file)
@@ -284,7 +284,7 @@ static struct channel *ppp_find_channel(struct ppp_net *pn, int unit);
 static int ppp_connect_channel(struct channel *pch, int unit);
 static int ppp_disconnect_channel(struct channel *pch);
 static void ppp_destroy_channel(struct channel *pch);
-static int unit_get(struct idr *p, void *ptr);
+static int unit_get(struct idr *p, void *ptr, int min);
 static int unit_set(struct idr *p, void *ptr, int n);
 static void unit_put(struct idr *p, int n);
 static void *unit_find(struct idr *p, int n);
@@ -1155,9 +1155,20 @@ static int ppp_unit_register(struct ppp *ppp, int unit, bool ifname_is_set)
        mutex_lock(&pn->all_ppp_mutex);
 
        if (unit < 0) {
-               ret = unit_get(&pn->units_idr, ppp);
+               ret = unit_get(&pn->units_idr, ppp, 0);
                if (ret < 0)
                        goto err;
+               if (!ifname_is_set) {
+                       while (1) {
+                               snprintf(ppp->dev->name, IFNAMSIZ, "ppp%i", ret);
+                               if (!__dev_get_by_name(ppp->ppp_net, ppp->dev->name))
+                                       break;
+                               unit_put(&pn->units_idr, ret);
+                               ret = unit_get(&pn->units_idr, ppp, ret + 1);
+                               if (ret < 0)
+                                       goto err;
+                       }
+               }
        } else {
                /* Caller asked for a specific unit number. Fail with -EEXIST
                 * if unavailable. For backward compatibility, return -EEXIST
@@ -1306,7 +1317,7 @@ static int ppp_nl_newlink(struct net *src_net, struct net_device *dev,
         * the PPP unit identifer as suffix (i.e. ppp<unit_id>). This allows
         * userspace to infer the device name using to the PPPIOCGUNIT ioctl.
         */
-       if (!tb[IFLA_IFNAME])
+       if (!tb[IFLA_IFNAME] || !nla_len(tb[IFLA_IFNAME]) || !*(char *)nla_data(tb[IFLA_IFNAME]))
                conf.ifname_is_set = false;
 
        err = ppp_dev_configure(src_net, dev, &conf);
@@ -3552,9 +3563,9 @@ static int unit_set(struct idr *p, void *ptr, int n)
 }
 
 /* get new free unit number and associate pointer with it */
-static int unit_get(struct idr *p, void *ptr)
+static int unit_get(struct idr *p, void *ptr, int min)
 {
-       return idr_alloc(p, ptr, 0, 0, GFP_KERNEL);
+       return idr_alloc(p, ptr, min, 0, GFP_KERNEL);
 }
 
 /* put unit number back to a pool */
index e1994a2..2a1e31d 100644 (file)
@@ -184,6 +184,7 @@ struct asix_common_private {
        struct phy_device *phydev;
        u16 phy_addr;
        char phy_name[20];
+       bool embd_phy;
 };
 
 extern const struct driver_info ax88172a_info;
index ac92bc5..38cda59 100644 (file)
@@ -63,6 +63,29 @@ void asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
                               value, index, data, size);
 }
 
+static int asix_check_host_enable(struct usbnet *dev, int in_pm)
+{
+       int i, ret;
+       u8 smsr;
+
+       for (i = 0; i < 30; ++i) {
+               ret = asix_set_sw_mii(dev, in_pm);
+               if (ret == -ENODEV || ret == -ETIMEDOUT)
+                       break;
+               usleep_range(1000, 1100);
+               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
+                                   0, 0, 1, &smsr, in_pm);
+               if (ret == -ENODEV)
+                       break;
+               else if (ret < 0)
+                       continue;
+               else if (smsr & AX_HOST_EN)
+                       break;
+       }
+
+       return ret;
+}
+
 static void reset_asix_rx_fixup_info(struct asix_rx_fixup_info *rx)
 {
        /* Reset the variables that have a lifetime outside of
@@ -467,19 +490,11 @@ int asix_mdio_read(struct net_device *netdev, int phy_id, int loc)
 {
        struct usbnet *dev = netdev_priv(netdev);
        __le16 res;
-       u8 smsr;
-       int i = 0;
        int ret;
 
        mutex_lock(&dev->phy_mutex);
-       do {
-               ret = asix_set_sw_mii(dev, 0);
-               if (ret == -ENODEV || ret == -ETIMEDOUT)
-                       break;
-               usleep_range(1000, 1100);
-               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-                                   0, 0, 1, &smsr, 0);
-       } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+       ret = asix_check_host_enable(dev, 0);
        if (ret == -ENODEV || ret == -ETIMEDOUT) {
                mutex_unlock(&dev->phy_mutex);
                return ret;
@@ -505,23 +520,14 @@ static int __asix_mdio_write(struct net_device *netdev, int phy_id, int loc,
 {
        struct usbnet *dev = netdev_priv(netdev);
        __le16 res = cpu_to_le16(val);
-       u8 smsr;
-       int i = 0;
        int ret;
 
        netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
                        phy_id, loc, val);
 
        mutex_lock(&dev->phy_mutex);
-       do {
-               ret = asix_set_sw_mii(dev, 0);
-               if (ret == -ENODEV)
-                       break;
-               usleep_range(1000, 1100);
-               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-                                   0, 0, 1, &smsr, 0);
-       } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
 
+       ret = asix_check_host_enable(dev, 0);
        if (ret == -ENODEV)
                goto out;
 
@@ -561,19 +567,11 @@ int asix_mdio_read_nopm(struct net_device *netdev, int phy_id, int loc)
 {
        struct usbnet *dev = netdev_priv(netdev);
        __le16 res;
-       u8 smsr;
-       int i = 0;
        int ret;
 
        mutex_lock(&dev->phy_mutex);
-       do {
-               ret = asix_set_sw_mii(dev, 1);
-               if (ret == -ENODEV || ret == -ETIMEDOUT)
-                       break;
-               usleep_range(1000, 1100);
-               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-                                   0, 0, 1, &smsr, 1);
-       } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+       ret = asix_check_host_enable(dev, 1);
        if (ret == -ENODEV || ret == -ETIMEDOUT) {
                mutex_unlock(&dev->phy_mutex);
                return ret;
@@ -595,22 +593,14 @@ asix_mdio_write_nopm(struct net_device *netdev, int phy_id, int loc, int val)
 {
        struct usbnet *dev = netdev_priv(netdev);
        __le16 res = cpu_to_le16(val);
-       u8 smsr;
-       int i = 0;
        int ret;
 
        netdev_dbg(dev->net, "asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
                        phy_id, loc, val);
 
        mutex_lock(&dev->phy_mutex);
-       do {
-               ret = asix_set_sw_mii(dev, 1);
-               if (ret == -ENODEV)
-                       break;
-               usleep_range(1000, 1100);
-               ret = asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG,
-                                   0, 0, 1, &smsr, 1);
-       } while (!(smsr & AX_HOST_EN) && (i++ < 30) && (ret != -ENODEV));
+
+       ret = asix_check_host_enable(dev, 1);
        if (ret == -ENODEV) {
                mutex_unlock(&dev->phy_mutex);
                return;
index 2c11521..dc87e8c 100644 (file)
@@ -354,24 +354,23 @@ out:
 static int ax88772_hw_reset(struct usbnet *dev, int in_pm)
 {
        struct asix_data *data = (struct asix_data *)&dev->data;
-       int ret, embd_phy;
+       struct asix_common_private *priv = dev->driver_priv;
        u16 rx_ctl;
+       int ret;
 
        ret = asix_write_gpio(dev, AX_GPIO_RSE | AX_GPIO_GPO_2 |
                              AX_GPIO_GPO2EN, 5, in_pm);
        if (ret < 0)
                goto out;
 
-       embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
-
-       ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy,
+       ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, priv->embd_phy,
                             0, 0, NULL, in_pm);
        if (ret < 0) {
                netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
                goto out;
        }
 
-       if (embd_phy) {
+       if (priv->embd_phy) {
                ret = asix_sw_reset(dev, AX_SWRESET_IPPD, in_pm);
                if (ret < 0)
                        goto out;
@@ -449,17 +448,16 @@ out:
 static int ax88772a_hw_reset(struct usbnet *dev, int in_pm)
 {
        struct asix_data *data = (struct asix_data *)&dev->data;
-       int ret, embd_phy;
+       struct asix_common_private *priv = dev->driver_priv;
        u16 rx_ctl, phy14h, phy15h, phy16h;
        u8 chipcode = 0;
+       int ret;
 
        ret = asix_write_gpio(dev, AX_GPIO_RSE, 5, in_pm);
        if (ret < 0)
                goto out;
 
-       embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0);
-
-       ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, embd_phy |
+       ret = asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT, priv->embd_phy |
                             AX_PHYSEL_SSEN, 0, 0, NULL, in_pm);
        if (ret < 0) {
                netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret);
@@ -683,12 +681,6 @@ static int ax88772_init_phy(struct usbnet *dev)
        struct asix_common_private *priv = dev->driver_priv;
        int ret;
 
-       ret = asix_read_phy_addr(dev, true);
-       if (ret < 0)
-               return ret;
-
-       priv->phy_addr = ret;
-
        snprintf(priv->phy_name, sizeof(priv->phy_name), PHY_ID_FMT,
                 priv->mdio->id, priv->phy_addr);
 
@@ -716,6 +708,12 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        int ret, i;
        u32 phyid;
 
+       priv = devm_kzalloc(&dev->udev->dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       dev->driver_priv = priv;
+
        usbnet_get_endpoints(dev, intf);
 
        /* Maybe the boot loader passed the MAC address via device tree */
@@ -751,6 +749,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->net->needed_headroom = 4; /* cf asix_tx_fixup() */
        dev->net->needed_tailroom = 4; /* cf asix_tx_fixup() */
 
+       ret = asix_read_phy_addr(dev, true);
+       if (ret < 0)
+               return ret;
+
+       priv->phy_addr = ret;
+       priv->embd_phy = ((priv->phy_addr & 0x1f) == 0x10);
+
        asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
        chipcode &= AX_CHIPCODE_MASK;
 
@@ -773,12 +778,6 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
                dev->rx_urb_size = 2048;
        }
 
-       priv = devm_kzalloc(&dev->udev->dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       dev->driver_priv = priv;
-
        priv->presvd_phy_bmcr = 0;
        priv->presvd_phy_advertise = 0;
        if (chipcode == AX_AX88772_CHIPCODE) {
@@ -817,6 +816,12 @@ static void ax88772_unbind(struct usbnet *dev, struct usb_interface *intf)
        asix_rx_fixup_common_free(dev->driver_priv);
 }
 
+static void ax88178_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+       asix_rx_fixup_common_free(dev->driver_priv);
+       kfree(dev->driver_priv);
+}
+
 static const struct ethtool_ops ax88178_ethtool_ops = {
        .get_drvinfo            = asix_get_drvinfo,
        .get_link               = asix_get_link,
@@ -1225,7 +1230,7 @@ static const struct driver_info ax88772b_info = {
 static const struct driver_info ax88178_info = {
        .description = "ASIX AX88178 USB 2.0 Ethernet",
        .bind = ax88178_bind,
-       .unbind = ax88772_unbind,
+       .unbind = ax88178_unbind,
        .status = asix_status,
        .link_reset = ax88178_link_reset,
        .reset = ax88178_reset,
index 652e9fc..9f9dd0d 100644 (file)
@@ -446,7 +446,7 @@ static int enable_net_traffic(struct net_device *dev, struct usb_device *usb)
                write_mii_word(pegasus, 0, 0x1b, &auxmode);
        }
 
-       return 0;
+       return ret;
 fail:
        netif_dbg(pegasus, drv, pegasus->net, "%s failed\n", __func__);
        return ret;
@@ -835,7 +835,7 @@ static int pegasus_open(struct net_device *net)
        if (!pegasus->rx_skb)
                goto exit;
 
-       res = set_registers(pegasus, EthID, 6, net->dev_addr);
+       set_registers(pegasus, EthID, 6, net->dev_addr);
 
        usb_fill_bulk_urb(pegasus->rx_urb, pegasus->usb,
                          usb_rcvbulkpipe(pegasus->usb, 1),
index e09b107..7983237 100644 (file)
@@ -3955,17 +3955,28 @@ static void rtl_clear_bp(struct r8152 *tp, u16 type)
        case RTL_VER_06:
                ocp_write_byte(tp, type, PLA_BP_EN, 0);
                break;
+       case RTL_VER_14:
+               ocp_write_word(tp, type, USB_BP2_EN, 0);
+
+               ocp_write_word(tp, type, USB_BP_8, 0);
+               ocp_write_word(tp, type, USB_BP_9, 0);
+               ocp_write_word(tp, type, USB_BP_10, 0);
+               ocp_write_word(tp, type, USB_BP_11, 0);
+               ocp_write_word(tp, type, USB_BP_12, 0);
+               ocp_write_word(tp, type, USB_BP_13, 0);
+               ocp_write_word(tp, type, USB_BP_14, 0);
+               ocp_write_word(tp, type, USB_BP_15, 0);
+               break;
        case RTL_VER_08:
        case RTL_VER_09:
        case RTL_VER_10:
        case RTL_VER_11:
        case RTL_VER_12:
        case RTL_VER_13:
-       case RTL_VER_14:
        case RTL_VER_15:
        default:
                if (type == MCU_TYPE_USB) {
-                       ocp_write_byte(tp, MCU_TYPE_USB, USB_BP2_EN, 0);
+                       ocp_write_word(tp, MCU_TYPE_USB, USB_BP2_EN, 0);
 
                        ocp_write_word(tp, MCU_TYPE_USB, USB_BP_8, 0);
                        ocp_write_word(tp, MCU_TYPE_USB, USB_BP_9, 0);
@@ -4331,7 +4342,6 @@ static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac)
                case RTL_VER_11:
                case RTL_VER_12:
                case RTL_VER_13:
-               case RTL_VER_14:
                case RTL_VER_15:
                        fw_reg = 0xf800;
                        bp_ba_addr = PLA_BP_BA;
@@ -4339,6 +4349,13 @@ static bool rtl8152_is_fw_mac_ok(struct r8152 *tp, struct fw_mac *mac)
                        bp_start = PLA_BP_0;
                        max_bp = 8;
                        break;
+               case RTL_VER_14:
+                       fw_reg = 0xf800;
+                       bp_ba_addr = PLA_BP_BA;
+                       bp_en_addr = USB_BP2_EN;
+                       bp_start = PLA_BP_0;
+                       max_bp = 16;
+                       break;
                default:
                        goto out;
                }
index 56c3f85..eee4936 100644 (file)
@@ -63,7 +63,7 @@ static const unsigned long guest_offloads[] = {
        VIRTIO_NET_F_GUEST_CSUM
 };
 
-#define GUEST_OFFLOAD_LRO_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
+#define GUEST_OFFLOAD_GRO_HW_MASK ((1ULL << VIRTIO_NET_F_GUEST_TSO4) | \
                                (1ULL << VIRTIO_NET_F_GUEST_TSO6) | \
                                (1ULL << VIRTIO_NET_F_GUEST_ECN)  | \
                                (1ULL << VIRTIO_NET_F_GUEST_UFO))
@@ -2515,7 +2515,7 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
                virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) ||
                virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO) ||
                virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))) {
-               NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO/CSUM, disable LRO/CSUM first");
+               NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing GRO_HW/CSUM, disable GRO_HW/CSUM first");
                return -EOPNOTSUPP;
        }
 
@@ -2646,15 +2646,15 @@ static int virtnet_set_features(struct net_device *dev,
        u64 offloads;
        int err;
 
-       if ((dev->features ^ features) & NETIF_F_LRO) {
+       if ((dev->features ^ features) & NETIF_F_GRO_HW) {
                if (vi->xdp_enabled)
                        return -EBUSY;
 
-               if (features & NETIF_F_LRO)
+               if (features & NETIF_F_GRO_HW)
                        offloads = vi->guest_offloads_capable;
                else
                        offloads = vi->guest_offloads_capable &
-                                  ~GUEST_OFFLOAD_LRO_MASK;
+                                  ~GUEST_OFFLOAD_GRO_HW_MASK;
 
                err = virtnet_set_guest_offloads(vi, offloads);
                if (err)
@@ -3134,9 +3134,9 @@ static int virtnet_probe(struct virtio_device *vdev)
                dev->features |= NETIF_F_RXCSUM;
        if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
            virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6))
-               dev->features |= NETIF_F_LRO;
+               dev->features |= NETIF_F_GRO_HW;
        if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_GUEST_OFFLOADS))
-               dev->hw_features |= NETIF_F_LRO;
+               dev->hw_features |= NETIF_F_GRO_HW;
 
        dev->vlan_features = dev->features;
 
index 2b1b944..8bbe2a7 100644 (file)
@@ -1367,6 +1367,8 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
        bool need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr);
        bool is_ndisc = ipv6_ndisc_frame(skb);
 
+       nf_reset_ct(skb);
+
        /* loopback, multicast & non-ND link-local traffic; do not push through
         * packet taps again. Reset pkt_type for upper layers to process skb.
         * For strict packets with a source LLA, determine the dst using the
@@ -1429,6 +1431,8 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
        skb->skb_iif = vrf_dev->ifindex;
        IPCB(skb)->flags |= IPSKB_L3SLAVE;
 
+       nf_reset_ct(skb);
+
        if (ipv4_is_multicast(ip_hdr(skb)->daddr))
                goto out;
 
index 2403490..b4b1f75 100644 (file)
@@ -37,6 +37,7 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
        u32 sha1 = 0;
        u16 mac_type = 0, rf_id = 0;
        u8 *pnvm_data = NULL, *tmp;
+       bool hw_match = false;
        u32 size = 0;
        int ret;
 
@@ -83,6 +84,9 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
                                break;
                        }
 
+                       if (hw_match)
+                               break;
+
                        mac_type = le16_to_cpup((__le16 *)data);
                        rf_id = le16_to_cpup((__le16 *)(data + sizeof(__le16)));
 
@@ -90,15 +94,9 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
                                     "Got IWL_UCODE_TLV_HW_TYPE mac_type 0x%0x rf_id 0x%0x\n",
                                     mac_type, rf_id);
 
-                       if (mac_type != CSR_HW_REV_TYPE(trans->hw_rev) ||
-                           rf_id != CSR_HW_RFID_TYPE(trans->hw_rf_id)) {
-                               IWL_DEBUG_FW(trans,
-                                            "HW mismatch, skipping PNVM section, mac_type 0x%0x, rf_id 0x%0x.\n",
-                                            CSR_HW_REV_TYPE(trans->hw_rev), trans->hw_rf_id);
-                               ret = -ENOENT;
-                               goto out;
-                       }
-
+                       if (mac_type == CSR_HW_REV_TYPE(trans->hw_rev) &&
+                           rf_id == CSR_HW_RFID_TYPE(trans->hw_rf_id))
+                               hw_match = true;
                        break;
                case IWL_UCODE_TLV_SEC_RT: {
                        struct iwl_pnvm_section *section = (void *)data;
@@ -149,6 +147,15 @@ static int iwl_pnvm_handle_section(struct iwl_trans *trans, const u8 *data,
        }
 
 done:
+       if (!hw_match) {
+               IWL_DEBUG_FW(trans,
+                            "HW mismatch, skipping PNVM section (need mac_type 0x%x rf_id 0x%x)\n",
+                            CSR_HW_REV_TYPE(trans->hw_rev),
+                            CSR_HW_RFID_TYPE(trans->hw_rf_id));
+               ret = -ENOENT;
+               goto out;
+       }
+
        if (!size) {
                IWL_DEBUG_FW(trans, "Empty PNVM, skipping.\n");
                ret = -ENOENT;
index 16baee3..0b8a0cd 100644 (file)
@@ -1110,12 +1110,80 @@ static const struct iwl_dev_info iwl_dev_info_table[] = {
                      IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_NO_CDB,
                      iwl_cfg_bz_a0_mr_a0, iwl_ax211_name),
 
+/* SoF with JF2 */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
+
+/* SoF with JF */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
+
 /* So with GF */
        _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
                      IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
                      IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY,
                      IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB,
-                     iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name)
+                     iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name),
+
+/* So with JF2 */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9560_name),
+
+/* So with JF */
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_160_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9461_name),
+       _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+                     IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY,
+                     IWL_CFG_RF_TYPE_JF1, IWL_CFG_RF_ID_JF1_DIV,
+                     IWL_CFG_NO_160, IWL_CFG_CORES_BT, IWL_CFG_NO_CDB,
+                     iwlax210_2ax_cfg_so_jf_b0, iwl9462_name)
 
 #endif /* CONFIG_IWLMVM */
 };
index 863aa18..4396077 100644 (file)
@@ -111,7 +111,7 @@ mt7915_mcu_get_cipher(int cipher)
        case WLAN_CIPHER_SUITE_SMS4:
                return MCU_CIPHER_WAPI;
        default:
-               return MT_CIPHER_NONE;
+               return MCU_CIPHER_NONE;
        }
 }
 
index edd3ba3..e68a562 100644 (file)
@@ -1073,7 +1073,8 @@ enum {
 };
 
 enum mcu_cipher_type {
-       MCU_CIPHER_WEP40 = 1,
+       MCU_CIPHER_NONE = 0,
+       MCU_CIPHER_WEP40,
        MCU_CIPHER_WEP104,
        MCU_CIPHER_WEP128,
        MCU_CIPHER_TKIP,
index cd690c6..9fbaacc 100644 (file)
@@ -111,7 +111,7 @@ mt7921_mcu_get_cipher(int cipher)
        case WLAN_CIPHER_SUITE_SMS4:
                return MCU_CIPHER_WAPI;
        default:
-               return MT_CIPHER_NONE;
+               return MCU_CIPHER_NONE;
        }
 }
 
index d76cf8f..de3c091 100644 (file)
@@ -199,7 +199,8 @@ struct sta_rec_sec {
 } __packed;
 
 enum mcu_cipher_type {
-       MCU_CIPHER_WEP40 = 1,
+       MCU_CIPHER_NONE = 0,
+       MCU_CIPHER_WEP40,
        MCU_CIPHER_WEP104,
        MCU_CIPHER_WEP128,
        MCU_CIPHER_TKIP,
index 804e6c4..519361e 100644 (file)
@@ -64,10 +64,9 @@ static struct ipc_chnl_cfg modem_cfg[] = {
 
 int ipc_chnl_cfg_get(struct ipc_chnl_cfg *chnl_cfg, int index)
 {
-       int array_size = ARRAY_SIZE(modem_cfg);
-
-       if (index >= array_size) {
-               pr_err("index: %d and array_size %d", index, array_size);
+       if (index >= ARRAY_SIZE(modem_cfg)) {
+               pr_err("index: %d and array size %zu", index,
+                      ARRAY_SIZE(modem_cfg));
                return -ECHRNG;
        }
 
index 1e18420..e4d0f69 100644 (file)
@@ -41,14 +41,14 @@ struct mhi_wwan_dev {
 /* Increment RX budget and schedule RX refill if necessary */
 static void mhi_wwan_rx_budget_inc(struct mhi_wwan_dev *mhiwwan)
 {
-       spin_lock(&mhiwwan->rx_lock);
+       spin_lock_bh(&mhiwwan->rx_lock);
 
        mhiwwan->rx_budget++;
 
        if (test_bit(MHI_WWAN_RX_REFILL, &mhiwwan->flags))
                schedule_work(&mhiwwan->rx_refill);
 
-       spin_unlock(&mhiwwan->rx_lock);
+       spin_unlock_bh(&mhiwwan->rx_lock);
 }
 
 /* Decrement RX budget if non-zero and return true on success */
@@ -56,7 +56,7 @@ static bool mhi_wwan_rx_budget_dec(struct mhi_wwan_dev *mhiwwan)
 {
        bool ret = false;
 
-       spin_lock(&mhiwwan->rx_lock);
+       spin_lock_bh(&mhiwwan->rx_lock);
 
        if (mhiwwan->rx_budget) {
                mhiwwan->rx_budget--;
@@ -64,7 +64,7 @@ static bool mhi_wwan_rx_budget_dec(struct mhi_wwan_dev *mhiwwan)
                        ret = true;
        }
 
-       spin_unlock(&mhiwwan->rx_lock);
+       spin_unlock_bh(&mhiwwan->rx_lock);
 
        return ret;
 }
@@ -110,7 +110,7 @@ static int mhi_wwan_ctrl_start(struct wwan_port *port)
        int ret;
 
        /* Start mhi device's channel(s) */
-       ret = mhi_prepare_for_transfer(mhiwwan->mhi_dev, 0);
+       ret = mhi_prepare_for_transfer(mhiwwan->mhi_dev);
        if (ret)
                return ret;
 
@@ -130,9 +130,9 @@ static void mhi_wwan_ctrl_stop(struct wwan_port *port)
 {
        struct mhi_wwan_dev *mhiwwan = wwan_port_get_drvdata(port);
 
-       spin_lock(&mhiwwan->rx_lock);
+       spin_lock_bh(&mhiwwan->rx_lock);
        clear_bit(MHI_WWAN_RX_REFILL, &mhiwwan->flags);
-       spin_unlock(&mhiwwan->rx_lock);
+       spin_unlock_bh(&mhiwwan->rx_lock);
 
        cancel_work_sync(&mhiwwan->rx_refill);
 
index 674a81d..35ece98 100644 (file)
@@ -164,11 +164,14 @@ static struct wwan_device *wwan_create_dev(struct device *parent)
                goto done_unlock;
 
        id = ida_alloc(&wwan_dev_ids, GFP_KERNEL);
-       if (id < 0)
+       if (id < 0) {
+               wwandev = ERR_PTR(id);
                goto done_unlock;
+       }
 
        wwandev = kzalloc(sizeof(*wwandev), GFP_KERNEL);
        if (!wwandev) {
+               wwandev = ERR_PTR(-ENOMEM);
                ida_free(&wwan_dev_ids, id);
                goto done_unlock;
        }
@@ -182,7 +185,8 @@ static struct wwan_device *wwan_create_dev(struct device *parent)
        err = device_register(&wwandev->dev);
        if (err) {
                put_device(&wwandev->dev);
-               wwandev = NULL;
+               wwandev = ERR_PTR(err);
+               goto done_unlock;
        }
 
 done_unlock:
@@ -1014,8 +1018,8 @@ int wwan_register_ops(struct device *parent, const struct wwan_ops *ops,
                return -EINVAL;
 
        wwandev = wwan_create_dev(parent);
-       if (!wwandev)
-               return -ENOMEM;
+       if (IS_ERR(wwandev))
+               return PTR_ERR(wwandev);
 
        if (WARN_ON(wwandev->ops)) {
                wwan_remove_dev(wwandev);
index 2403b71..7454782 100644 (file)
@@ -2527,7 +2527,7 @@ static void deactivate_labels(void *region)
 
 static int init_active_labels(struct nd_region *nd_region)
 {
-       int i;
+       int i, rc = 0;
 
        for (i = 0; i < nd_region->ndr_mappings; i++) {
                struct nd_mapping *nd_mapping = &nd_region->mapping[i];
@@ -2546,13 +2546,14 @@ static int init_active_labels(struct nd_region *nd_region)
                        else if (test_bit(NDD_LABELING, &nvdimm->flags))
                                /* fail, labels needed to disambiguate dpa */;
                        else
-                               return 0;
+                               continue;
 
                        dev_err(&nd_region->dev, "%s: is %s, failing probe\n",
                                        dev_name(&nd_mapping->nvdimm->dev),
                                        test_bit(NDD_LOCKED, &nvdimm->flags)
                                        ? "locked" : "disabled");
-                       return -ENXIO;
+                       rc = -ENXIO;
+                       goto out;
                }
                nd_mapping->ndd = ndd;
                atomic_inc(&nvdimm->busy);
@@ -2586,13 +2587,17 @@ static int init_active_labels(struct nd_region *nd_region)
                        break;
        }
 
-       if (i < nd_region->ndr_mappings) {
+       if (i < nd_region->ndr_mappings)
+               rc = -ENOMEM;
+
+out:
+       if (rc) {
                deactivate_labels(nd_region);
-               return -ENOMEM;
+               return rc;
        }
 
        return devm_add_action_or_reset(&nd_region->dev, deactivate_labels,
-                       nd_region);
+                                       nd_region);
 }
 
 int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
index b335c07..04b4691 100644 (file)
@@ -893,6 +893,10 @@ static int _set_required_opps(struct device *dev,
        if (!required_opp_tables)
                return 0;
 
+       /* required-opps not fully initialized yet */
+       if (lazy_linking_pending(opp_table))
+               return -EBUSY;
+
        /*
         * We only support genpd's OPPs in the "required-opps" for now, as we
         * don't know much about other use cases. Error out if the required OPP
@@ -903,10 +907,6 @@ static int _set_required_opps(struct device *dev,
                return -ENOENT;
        }
 
-       /* required-opps not fully initialized yet */
-       if (lazy_linking_pending(opp_table))
-               return -EBUSY;
-
        /* Single genpd case */
        if (!genpd_virt_devs)
                return _set_required_opp(dev, dev, opp, 0);
@@ -1856,9 +1856,6 @@ void dev_pm_opp_put_supported_hw(struct opp_table *opp_table)
        if (unlikely(!opp_table))
                return;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        kfree(opp_table->supported_hw);
        opp_table->supported_hw = NULL;
        opp_table->supported_hw_count = 0;
@@ -1944,9 +1941,6 @@ void dev_pm_opp_put_prop_name(struct opp_table *opp_table)
        if (unlikely(!opp_table))
                return;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        kfree(opp_table->prop_name);
        opp_table->prop_name = NULL;
 
@@ -2056,9 +2050,6 @@ void dev_pm_opp_put_regulators(struct opp_table *opp_table)
        if (!opp_table->regulators)
                goto put_opp_table;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        if (opp_table->enabled) {
                for (i = opp_table->regulator_count - 1; i >= 0; i--)
                        regulator_disable(opp_table->regulators[i]);
@@ -2178,9 +2169,6 @@ void dev_pm_opp_put_clkname(struct opp_table *opp_table)
        if (unlikely(!opp_table))
                return;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        clk_put(opp_table->clk);
        opp_table->clk = ERR_PTR(-EINVAL);
 
@@ -2279,9 +2267,6 @@ void dev_pm_opp_unregister_set_opp_helper(struct opp_table *opp_table)
        if (unlikely(!opp_table))
                return;
 
-       /* Make sure there are no concurrent readers while updating opp_table */
-       WARN_ON(!list_empty(&opp_table->opp_list));
-
        opp_table->set_opp = NULL;
 
        mutex_lock(&opp_table->lock);
index d298e38..67f2e07 100644 (file)
@@ -964,8 +964,9 @@ static int _of_add_opp_table_v2(struct device *dev, struct opp_table *opp_table)
                }
        }
 
-       /* There should be one of more OPP defined */
-       if (WARN_ON(!count)) {
+       /* There should be one or more OPPs defined */
+       if (!count) {
+               dev_err(dev, "%s: no supported OPPs", __func__);
                ret = -ENOENT;
                goto remove_static_opp;
        }
index 896a45b..654ac4a 100644 (file)
@@ -145,7 +145,7 @@ static int ixp4xx_pci_check_master_abort(struct ixp4xx_pci *p)
        return 0;
 }
 
-static int ixp4xx_pci_read(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 *data)
+static int ixp4xx_pci_read_indirect(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 *data)
 {
        ixp4xx_writel(p, IXP4XX_PCI_NP_AD, addr);
 
@@ -170,7 +170,7 @@ static int ixp4xx_pci_read(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 *data)
        return ixp4xx_pci_check_master_abort(p);
 }
 
-static int ixp4xx_pci_write(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 data)
+static int ixp4xx_pci_write_indirect(struct ixp4xx_pci *p, u32 addr, u32 cmd, u32 data)
 {
        ixp4xx_writel(p, IXP4XX_PCI_NP_AD, addr);
 
@@ -308,7 +308,7 @@ static int ixp4xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
        dev_dbg(p->dev, "read_config from %d size %d dev %d:%d:%d address: %08x cmd: %08x\n",
                where, size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn), addr, cmd);
 
-       ret = ixp4xx_pci_read(p, addr, cmd, &val);
+       ret = ixp4xx_pci_read_indirect(p, addr, cmd, &val);
        if (ret)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -356,7 +356,7 @@ static int ixp4xx_pci_write_config(struct pci_bus *bus,  unsigned int devfn,
        dev_dbg(p->dev, "write_config_byte %#x to %d size %d dev %d:%d:%d addr: %08x cmd %08x\n",
                value, where, size, bus_num, PCI_SLOT(devfn), PCI_FUNC(devfn), addr, cmd);
 
-       ret = ixp4xx_pci_write(p, addr, cmd, val);
+       ret = ixp4xx_pci_write_indirect(p, addr, cmd, val);
        if (ret)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
index 9232255..3a9f4f8 100644 (file)
@@ -143,24 +143,25 @@ static inline __attribute_const__ u32 msi_mask(unsigned x)
  * reliably as devices without an INTx disable bit will then generate a
  * level IRQ which will never be cleared.
  */
-u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
+void __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
-       u32 mask_bits = desc->masked;
+       raw_spinlock_t *lock = &desc->dev->msi_lock;
+       unsigned long flags;
 
        if (pci_msi_ignore_mask || !desc->msi_attrib.maskbit)
-               return 0;
+               return;
 
-       mask_bits &= ~mask;
-       mask_bits |= flag;
+       raw_spin_lock_irqsave(lock, flags);
+       desc->masked &= ~mask;
+       desc->masked |= flag;
        pci_write_config_dword(msi_desc_to_pci_dev(desc), desc->mask_pos,
-                              mask_bits);
-
-       return mask_bits;
+                              desc->masked);
+       raw_spin_unlock_irqrestore(lock, flags);
 }
 
 static void msi_mask_irq(struct msi_desc *desc, u32 mask, u32 flag)
 {
-       desc->masked = __pci_msi_desc_mask_irq(desc, mask, flag);
+       __pci_msi_desc_mask_irq(desc, mask, flag);
 }
 
 static void __iomem *pci_msix_desc_addr(struct msi_desc *desc)
@@ -289,13 +290,31 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
                /* Don't touch the hardware now */
        } else if (entry->msi_attrib.is_msix) {
                void __iomem *base = pci_msix_desc_addr(entry);
+               bool unmasked = !(entry->masked & PCI_MSIX_ENTRY_CTRL_MASKBIT);
 
                if (!base)
                        goto skip;
 
+               /*
+                * The specification mandates that the entry is masked
+                * when the message is modified:
+                *
+                * "If software changes the Address or Data value of an
+                * entry while the entry is unmasked, the result is
+                * undefined."
+                */
+               if (unmasked)
+                       __pci_msix_desc_mask_irq(entry, PCI_MSIX_ENTRY_CTRL_MASKBIT);
+
                writel(msg->address_lo, base + PCI_MSIX_ENTRY_LOWER_ADDR);
                writel(msg->address_hi, base + PCI_MSIX_ENTRY_UPPER_ADDR);
                writel(msg->data, base + PCI_MSIX_ENTRY_DATA);
+
+               if (unmasked)
+                       __pci_msix_desc_mask_irq(entry, 0);
+
+               /* Ensure that the writes are visible in the device */
+               readl(base + PCI_MSIX_ENTRY_DATA);
        } else {
                int pos = dev->msi_cap;
                u16 msgctl;
@@ -316,6 +335,8 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
                        pci_write_config_word(dev, pos + PCI_MSI_DATA_32,
                                              msg->data);
                }
+               /* Ensure that the writes are visible in the device */
+               pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl);
        }
 
 skip:
@@ -636,21 +657,21 @@ static int msi_capability_init(struct pci_dev *dev, int nvec,
        /* Configure MSI capability structure */
        ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI);
        if (ret) {
-               msi_mask_irq(entry, mask, ~mask);
+               msi_mask_irq(entry, mask, 0);
                free_msi_irqs(dev);
                return ret;
        }
 
        ret = msi_verify_entries(dev);
        if (ret) {
-               msi_mask_irq(entry, mask, ~mask);
+               msi_mask_irq(entry, mask, 0);
                free_msi_irqs(dev);
                return ret;
        }
 
        ret = populate_msi_sysfs(dev);
        if (ret) {
-               msi_mask_irq(entry, mask, ~mask);
+               msi_mask_irq(entry, mask, 0);
                free_msi_irqs(dev);
                return ret;
        }
@@ -691,6 +712,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
 {
        struct irq_affinity_desc *curmsk, *masks = NULL;
        struct msi_desc *entry;
+       void __iomem *addr;
        int ret, i;
        int vec_count = pci_msix_vec_count(dev);
 
@@ -711,6 +733,7 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
 
                entry->msi_attrib.is_msix       = 1;
                entry->msi_attrib.is_64         = 1;
+
                if (entries)
                        entry->msi_attrib.entry_nr = entries[i].entry;
                else
@@ -722,6 +745,10 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
                entry->msi_attrib.default_irq   = dev->irq;
                entry->mask_base                = base;
 
+               addr = pci_msix_desc_addr(entry);
+               if (addr)
+                       entry->masked = readl(addr + PCI_MSIX_ENTRY_VECTOR_CTRL);
+
                list_add_tail(&entry->list, dev_to_msi_list(&dev->dev));
                if (masks)
                        curmsk++;
@@ -732,26 +759,28 @@ out:
        return ret;
 }
 
-static void msix_program_entries(struct pci_dev *dev,
-                                struct msix_entry *entries)
+static void msix_update_entries(struct pci_dev *dev, struct msix_entry *entries)
 {
        struct msi_desc *entry;
-       int i = 0;
-       void __iomem *desc_addr;
 
        for_each_pci_msi_entry(entry, dev) {
-               if (entries)
-                       entries[i++].vector = entry->irq;
+               if (entries) {
+                       entries->vector = entry->irq;
+                       entries++;
+               }
+       }
+}
 
-               desc_addr = pci_msix_desc_addr(entry);
-               if (desc_addr)
-                       entry->masked = readl(desc_addr +
-                                             PCI_MSIX_ENTRY_VECTOR_CTRL);
-               else
-                       entry->masked = 0;
+static void msix_mask_all(void __iomem *base, int tsize)
+{
+       u32 ctrl = PCI_MSIX_ENTRY_CTRL_MASKBIT;
+       int i;
 
-               msix_mask_irq(entry, 1);
-       }
+       if (pci_msi_ignore_mask)
+               return;
+
+       for (i = 0; i < tsize; i++, base += PCI_MSIX_ENTRY_SIZE)
+               writel(ctrl, base + PCI_MSIX_ENTRY_VECTOR_CTRL);
 }
 
 /**
@@ -768,22 +797,33 @@ static void msix_program_entries(struct pci_dev *dev,
 static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
                                int nvec, struct irq_affinity *affd)
 {
-       int ret;
-       u16 control;
        void __iomem *base;
+       int ret, tsize;
+       u16 control;
 
-       /* Ensure MSI-X is disabled while it is set up */
-       pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
+       /*
+        * Some devices require MSI-X to be enabled before the MSI-X
+        * registers can be accessed.  Mask all the vectors to prevent
+        * interrupts coming in before they're fully set up.
+        */
+       pci_msix_clear_and_set_ctrl(dev, 0, PCI_MSIX_FLAGS_MASKALL |
+                                   PCI_MSIX_FLAGS_ENABLE);
 
        pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control);
        /* Request & Map MSI-X table region */
-       base = msix_map_region(dev, msix_table_size(control));
-       if (!base)
-               return -ENOMEM;
+       tsize = msix_table_size(control);
+       base = msix_map_region(dev, tsize);
+       if (!base) {
+               ret = -ENOMEM;
+               goto out_disable;
+       }
+
+       /* Ensure that all table entries are masked. */
+       msix_mask_all(base, tsize);
 
        ret = msix_setup_entries(dev, base, entries, nvec, affd);
        if (ret)
-               return ret;
+               goto out_disable;
 
        ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX);
        if (ret)
@@ -794,15 +834,7 @@ static int msix_capability_init(struct pci_dev *dev, struct msix_entry *entries,
        if (ret)
                goto out_free;
 
-       /*
-        * Some devices require MSI-X to be enabled before we can touch the
-        * MSI-X registers.  We need to mask all the vectors to prevent
-        * interrupts coming in before they're fully set up.
-        */
-       pci_msix_clear_and_set_ctrl(dev, 0,
-                               PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE);
-
-       msix_program_entries(dev, entries);
+       msix_update_entries(dev, entries);
 
        ret = populate_msi_sysfs(dev);
        if (ret)
@@ -836,6 +868,9 @@ out_avail:
 out_free:
        free_msi_irqs(dev);
 
+out_disable:
+       pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
+
        return ret;
 }
 
@@ -930,8 +965,7 @@ static void pci_msi_shutdown(struct pci_dev *dev)
 
        /* Return the device with MSI unmasked as initial states */
        mask = msi_mask(desc->msi_attrib.multi_cap);
-       /* Keep cached state to be restored */
-       __pci_msi_desc_mask_irq(desc, mask, ~mask);
+       msi_mask_irq(desc, mask, 0);
 
        /* Restore dev->irq to its default pin-assertion IRQ */
        dev->irq = desc->msi_attrib.default_irq;
@@ -1016,10 +1050,8 @@ static void pci_msix_shutdown(struct pci_dev *dev)
        }
 
        /* Return the device with MSI-X masked as initial states */
-       for_each_pci_msi_entry(entry, dev) {
-               /* Keep cached states to be restored */
+       for_each_pci_msi_entry(entry, dev)
                __pci_msix_desc_mask_irq(entry, 1);
-       }
 
        pci_msix_clear_and_set_ctrl(dev, PCI_MSIX_FLAGS_ENABLE, 0);
        pci_intx_for_msi(dev, 1);
index 5d63df7..7bbf267 100644 (file)
@@ -978,7 +978,7 @@ void pci_create_legacy_files(struct pci_bus *b)
        b->legacy_mem->size = 1024*1024;
        b->legacy_mem->attr.mode = 0600;
        b->legacy_mem->mmap = pci_mmap_legacy_mem;
-       b->legacy_io->mapping = iomem_get_mapping();
+       b->legacy_mem->mapping = iomem_get_mapping();
        pci_adjust_legacy_attr(b, pci_mmap_mem);
        error = device_create_bin_file(&b->dev, b->legacy_mem);
        if (error)
index 6d74386..ab3de15 100644 (file)
@@ -1900,6 +1900,7 @@ static void quirk_ryzen_xhci_d3hot(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e0, quirk_ryzen_xhci_d3hot);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x15e1, quirk_ryzen_xhci_d3hot);
+DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, 0x1639, quirk_ryzen_xhci_d3hot);
 
 #ifdef CONFIG_X86_IO_APIC
 static int dmi_disable_ioapicreroute(const struct dmi_system_id *d)
index 3e4ef2b..0bcd195 100644 (file)
@@ -701,32 +701,32 @@ static const struct pinctrl_pin_desc tglh_pins[] = {
 
 static const struct intel_padgroup tglh_community0_gpps[] = {
        TGL_GPP(0, 0, 24, 0),                           /* GPP_A */
-       TGL_GPP(1, 25, 44, 128),                        /* GPP_R */
-       TGL_GPP(2, 45, 70, 32),                         /* GPP_B */
-       TGL_GPP(3, 71, 78, INTEL_GPIO_BASE_NOMAP),      /* vGPIO_0 */
+       TGL_GPP(1, 25, 44, 32),                         /* GPP_R */
+       TGL_GPP(2, 45, 70, 64),                         /* GPP_B */
+       TGL_GPP(3, 71, 78, 96),                         /* vGPIO_0 */
 };
 
 static const struct intel_padgroup tglh_community1_gpps[] = {
-       TGL_GPP(0, 79, 104, 96),                        /* GPP_D */
-       TGL_GPP(1, 105, 128, 64),                       /* GPP_C */
-       TGL_GPP(2, 129, 136, 160),                      /* GPP_S */
-       TGL_GPP(3, 137, 153, 192),                      /* GPP_G */
-       TGL_GPP(4, 154, 180, 224),                      /* vGPIO */
+       TGL_GPP(0, 79, 104, 128),                       /* GPP_D */
+       TGL_GPP(1, 105, 128, 160),                      /* GPP_C */
+       TGL_GPP(2, 129, 136, 192),                      /* GPP_S */
+       TGL_GPP(3, 137, 153, 224),                      /* GPP_G */
+       TGL_GPP(4, 154, 180, 256),                      /* vGPIO */
 };
 
 static const struct intel_padgroup tglh_community3_gpps[] = {
-       TGL_GPP(0, 181, 193, 256),                      /* GPP_E */
-       TGL_GPP(1, 194, 217, 288),                      /* GPP_F */
+       TGL_GPP(0, 181, 193, 288),                      /* GPP_E */
+       TGL_GPP(1, 194, 217, 320),                      /* GPP_F */
 };
 
 static const struct intel_padgroup tglh_community4_gpps[] = {
-       TGL_GPP(0, 218, 241, 320),                      /* GPP_H */
+       TGL_GPP(0, 218, 241, 352),                      /* GPP_H */
        TGL_GPP(1, 242, 251, 384),                      /* GPP_J */
-       TGL_GPP(2, 252, 266, 352),                      /* GPP_K */
+       TGL_GPP(2, 252, 266, 416),                      /* GPP_K */
 };
 
 static const struct intel_padgroup tglh_community5_gpps[] = {
-       TGL_GPP(0, 267, 281, 416),                      /* GPP_I */
+       TGL_GPP(0, 267, 281, 448),                      /* GPP_I */
        TGL_GPP(1, 282, 290, INTEL_GPIO_BASE_NOMAP),    /* JTAG */
 };
 
index 5b3b048..45ebdeb 100644 (file)
@@ -925,12 +925,10 @@ int mtk_pinconf_adv_pull_set(struct mtk_pinctrl *hw,
                        err = hw->soc->bias_set(hw, desc, pullup);
                        if (err)
                                return err;
-               } else if (hw->soc->bias_set_combo) {
-                       err = hw->soc->bias_set_combo(hw, desc, pullup, arg);
-                       if (err)
-                               return err;
                } else {
-                       return -ENOTSUPP;
+                       err = mtk_pinconf_bias_set_rev1(hw, desc, pullup);
+                       if (err)
+                               err = mtk_pinconf_bias_set(hw, desc, pullup);
                }
        }
 
index a76be6c..5b76474 100644 (file)
@@ -444,8 +444,7 @@ static int amd_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
        unsigned long flags;
        struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
        struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
-       u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3) |
-                       BIT(WAKE_CNTRL_OFF_S4);
+       u32 wake_mask = BIT(WAKE_CNTRL_OFF_S0I3) | BIT(WAKE_CNTRL_OFF_S3);
 
        raw_spin_lock_irqsave(&gpio_dev->lock, flags);
        pin_reg = readl(gpio_dev->base + (d->hwirq)*4);
index f831526..49e3268 100644 (file)
@@ -950,23 +950,37 @@ static int k210_fpioa_probe(struct platform_device *pdev)
                return ret;
 
        pdata->pclk = devm_clk_get_optional(dev, "pclk");
-       if (!IS_ERR(pdata->pclk))
-               clk_prepare_enable(pdata->pclk);
+       if (!IS_ERR(pdata->pclk)) {
+               ret = clk_prepare_enable(pdata->pclk);
+               if (ret)
+                       goto disable_clk;
+       }
 
        pdata->sysctl_map =
                syscon_regmap_lookup_by_phandle_args(np,
                                                "canaan,k210-sysctl-power",
                                                1, &pdata->power_offset);
-       if (IS_ERR(pdata->sysctl_map))
-               return PTR_ERR(pdata->sysctl_map);
+       if (IS_ERR(pdata->sysctl_map)) {
+               ret = PTR_ERR(pdata->sysctl_map);
+               goto disable_pclk;
+       }
 
        k210_fpioa_init_ties(pdata);
 
        pdata->pctl = pinctrl_register(&k210_pinctrl_desc, dev, (void *)pdata);
-       if (IS_ERR(pdata->pctl))
-               return PTR_ERR(pdata->pctl);
+       if (IS_ERR(pdata->pctl)) {
+               ret = PTR_ERR(pdata->pctl);
+               goto disable_pclk;
+       }
 
        return 0;
+
+disable_pclk:
+       clk_disable_unprepare(pdata->pclk);
+disable_clk:
+       clk_disable_unprepare(pdata->clk);
+
+       return ret;
 }
 
 static const struct of_device_id k210_fpioa_dt_ids[] = {
index 2f51b4f..cad4e60 100644 (file)
@@ -13,7 +13,7 @@ config PINCTRL_MSM
 
 config PINCTRL_APQ8064
        tristate "Qualcomm APQ8064 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -21,7 +21,7 @@ config PINCTRL_APQ8064
 
 config PINCTRL_APQ8084
        tristate "Qualcomm APQ8084 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -29,7 +29,7 @@ config PINCTRL_APQ8084
 
 config PINCTRL_IPQ4019
        tristate "Qualcomm IPQ4019 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -37,7 +37,7 @@ config PINCTRL_IPQ4019
 
 config PINCTRL_IPQ8064
        tristate "Qualcomm IPQ8064 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -45,7 +45,7 @@ config PINCTRL_IPQ8064
 
 config PINCTRL_IPQ8074
        tristate "Qualcomm Technologies, Inc. IPQ8074 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for
@@ -55,7 +55,7 @@ config PINCTRL_IPQ8074
 
 config PINCTRL_IPQ6018
        tristate "Qualcomm Technologies, Inc. IPQ6018 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for
@@ -65,7 +65,7 @@ config PINCTRL_IPQ6018
 
 config PINCTRL_MSM8226
        tristate "Qualcomm 8226 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -74,7 +74,7 @@ config PINCTRL_MSM8226
 
 config PINCTRL_MSM8660
        tristate "Qualcomm 8660 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -82,7 +82,7 @@ config PINCTRL_MSM8660
 
 config PINCTRL_MSM8960
        tristate "Qualcomm 8960 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -90,7 +90,7 @@ config PINCTRL_MSM8960
 
 config PINCTRL_MDM9615
        tristate "Qualcomm 9615 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -98,7 +98,7 @@ config PINCTRL_MDM9615
 
 config PINCTRL_MSM8X74
        tristate "Qualcomm 8x74 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -106,7 +106,7 @@ config PINCTRL_MSM8X74
 
 config PINCTRL_MSM8916
        tristate "Qualcomm 8916 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -114,7 +114,7 @@ config PINCTRL_MSM8916
 
 config PINCTRL_MSM8953
        tristate "Qualcomm 8953 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -124,7 +124,7 @@ config PINCTRL_MSM8953
 
 config PINCTRL_MSM8976
        tristate "Qualcomm 8976 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -134,7 +134,7 @@ config PINCTRL_MSM8976
 
 config PINCTRL_MSM8994
        tristate "Qualcomm 8994 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -143,7 +143,7 @@ config PINCTRL_MSM8994
 
 config PINCTRL_MSM8996
        tristate "Qualcomm MSM8996 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -151,7 +151,7 @@ config PINCTRL_MSM8996
 
 config PINCTRL_MSM8998
        tristate "Qualcomm MSM8998 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -159,7 +159,7 @@ config PINCTRL_MSM8998
 
 config PINCTRL_QCS404
        tristate "Qualcomm QCS404 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -167,7 +167,7 @@ config PINCTRL_QCS404
 
 config PINCTRL_QDF2XXX
        tristate "Qualcomm Technologies QDF2xxx pin controller driver"
-       depends on GPIOLIB && ACPI
+       depends on ACPI
        depends on PINCTRL_MSM
        help
          This is the GPIO driver for the TLMM block found on the
@@ -175,7 +175,7 @@ config PINCTRL_QDF2XXX
 
 config PINCTRL_QCOM_SPMI_PMIC
        tristate "Qualcomm SPMI PMIC pin controller driver"
-       depends on GPIOLIB && OF && SPMI
+       depends on OF && SPMI
        select REGMAP_SPMI
        select PINMUX
        select PINCONF
@@ -190,7 +190,7 @@ config PINCTRL_QCOM_SPMI_PMIC
 
 config PINCTRL_QCOM_SSBI_PMIC
        tristate "Qualcomm SSBI PMIC pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        select PINMUX
        select PINCONF
        select GENERIC_PINCONF
@@ -204,7 +204,7 @@ config PINCTRL_QCOM_SSBI_PMIC
 
 config PINCTRL_SC7180
        tristate "Qualcomm Technologies Inc SC7180 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -213,7 +213,7 @@ config PINCTRL_SC7180
 
 config PINCTRL_SC7280
        tristate "Qualcomm Technologies Inc SC7280 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -222,7 +222,7 @@ config PINCTRL_SC7280
 
 config PINCTRL_SC8180X
        tristate "Qualcomm Technologies Inc SC8180x pin controller driver"
-       depends on GPIOLIB && (OF || ACPI)
+       depends on (OF || ACPI)
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -231,7 +231,7 @@ config PINCTRL_SC8180X
 
 config PINCTRL_SDM660
        tristate "Qualcomm Technologies Inc SDM660 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -240,7 +240,7 @@ config PINCTRL_SDM660
 
 config PINCTRL_SDM845
        tristate "Qualcomm Technologies Inc SDM845 pin controller driver"
-       depends on GPIOLIB && (OF || ACPI)
+       depends on (OF || ACPI)
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -249,7 +249,7 @@ config PINCTRL_SDM845
 
 config PINCTRL_SDX55
        tristate "Qualcomm Technologies Inc SDX55 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -258,7 +258,7 @@ config PINCTRL_SDX55
 
 config PINCTRL_SM6125
        tristate "Qualcomm Technologies Inc SM6125 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -267,7 +267,7 @@ config PINCTRL_SM6125
 
 config PINCTRL_SM8150
        tristate "Qualcomm Technologies Inc SM8150 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
         This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -276,7 +276,7 @@ config PINCTRL_SM8150
 
 config PINCTRL_SM8250
        tristate "Qualcomm Technologies Inc SM8250 pin controller driver"
-       depends on GPIOLIB && OF
+       depends on OF
        depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
@@ -285,8 +285,7 @@ config PINCTRL_SM8250
 
 config PINCTRL_SM8350
        tristate "Qualcomm Technologies Inc SM8350 pin controller driver"
-       depends on GPIOLIB && OF
-       select PINCTRL_MSM
+       depends on PINCTRL_MSM
        help
          This is the pinctrl, pinmux, pinconf and gpiolib driver for the
          Qualcomm Technologies Inc TLMM block found on the Qualcomm
index dc8d39a..9c7679c 100644 (file)
@@ -1219,10 +1219,12 @@ static int sunxi_pinctrl_build_state(struct platform_device *pdev)
        }
 
        /*
-        * We suppose that we won't have any more functions than pins,
-        * we'll reallocate that later anyway
+        * Find an upper bound for the maximum number of functions: in
+        * the worst case we have gpio_in, gpio_out, irq and up to four
+        * special functions per pin, plus one entry for the sentinel.
+        * We'll reallocate that later anyway.
         */
-       pctl->functions = kcalloc(pctl->ngroups,
+       pctl->functions = kcalloc(4 * pctl->ngroups + 4,
                                  sizeof(*pctl->functions),
                                  GFP_KERNEL);
        if (!pctl->functions)
index 7d385c3..d12db6c 100644 (file)
@@ -508,6 +508,7 @@ config THINKPAD_ACPI
        depends on RFKILL || RFKILL = n
        depends on ACPI_VIDEO || ACPI_VIDEO = n
        depends on BACKLIGHT_CLASS_DEVICE
+       depends on I2C
        select ACPI_PLATFORM_PROFILE
        select HWMON
        select NVRAM
@@ -691,6 +692,7 @@ config INTEL_HID_EVENT
        tristate "INTEL HID Event"
        depends on ACPI
        depends on INPUT
+       depends on I2C
        select INPUT_SPARSEKMAP
        help
          This driver provides support for the Intel HID Event hotkey interface.
@@ -742,6 +744,7 @@ config INTEL_VBTN
        tristate "INTEL VIRTUAL BUTTON"
        depends on ACPI
        depends on INPUT
+       depends on I2C
        select INPUT_SPARSEKMAP
        help
          This driver provides support for the Intel Virtual Button interface.
index 0cb927f..a81dc4b 100644 (file)
@@ -41,6 +41,10 @@ static int wapf = -1;
 module_param(wapf, uint, 0444);
 MODULE_PARM_DESC(wapf, "WAPF value");
 
+static int tablet_mode_sw = -1;
+module_param(tablet_mode_sw, uint, 0444);
+MODULE_PARM_DESC(tablet_mode_sw, "Tablet mode detect: -1:auto 0:disable 1:kbd-dock 2:lid-flip");
+
 static struct quirk_entry *quirks;
 
 static bool asus_q500a_i8042_filter(unsigned char data, unsigned char str,
@@ -458,6 +462,15 @@ static const struct dmi_system_id asus_quirks[] = {
                },
                .driver_data = &quirk_asus_use_lid_flip_devid,
        },
+       {
+               .callback = dmi_matched,
+               .ident = "ASUS TP200s / E205SA",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "E205SA"),
+               },
+               .driver_data = &quirk_asus_use_lid_flip_devid,
+       },
        {},
 };
 
@@ -477,6 +490,21 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver)
        else
                wapf = quirks->wapf;
 
+       switch (tablet_mode_sw) {
+       case 0:
+               quirks->use_kbd_dock_devid = false;
+               quirks->use_lid_flip_devid = false;
+               break;
+       case 1:
+               quirks->use_kbd_dock_devid = true;
+               quirks->use_lid_flip_devid = false;
+               break;
+       case 2:
+               quirks->use_kbd_dock_devid = false;
+               quirks->use_lid_flip_devid = true;
+               break;
+       }
+
        if (quirks->i8042_filter) {
                ret = i8042_install_filter(quirks->i8042_filter);
                if (ret) {
diff --git a/drivers/platform/x86/dual_accel_detect.h b/drivers/platform/x86/dual_accel_detect.h
new file mode 100644 (file)
index 0000000..a9eae17
--- /dev/null
@@ -0,0 +1,76 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Helper code to detect 360 degree hinges (yoga) style 2-in-1 devices using 2 accelerometers
+ * to allow the OS to determine the angle between the display and the base of the device.
+ *
+ * On Windows these are read by a special HingeAngleService process which calls undocumented
+ * ACPI methods, to let the firmware know if the 2-in-1 is in tablet- or laptop-mode.
+ * The firmware may use this to disable the kbd and touchpad to avoid spurious input in
+ * tablet-mode as well as to report SW_TABLET_MODE info to the OS.
+ *
+ * Since Linux does not call these undocumented methods, the SW_TABLET_MODE info reported
+ * by various drivers/platform/x86 drivers is incorrect. These drivers use the detection
+ * code in this file to disable SW_TABLET_MODE reporting to avoid reporting broken info
+ * (instead userspace can derive the status itself by directly reading the 2 accels).
+ */
+
+#include <linux/acpi.h>
+#include <linux/i2c.h>
+
+static int dual_accel_i2c_resource_count(struct acpi_resource *ares, void *data)
+{
+       struct acpi_resource_i2c_serialbus *sb;
+       int *count = data;
+
+       if (i2c_acpi_get_i2c_resource(ares, &sb))
+               *count = *count + 1;
+
+       return 1;
+}
+
+static int dual_accel_i2c_client_count(struct acpi_device *adev)
+{
+       int ret, count = 0;
+       LIST_HEAD(r);
+
+       ret = acpi_dev_get_resources(adev, &r, dual_accel_i2c_resource_count, &count);
+       if (ret < 0)
+               return ret;
+
+       acpi_dev_free_resource_list(&r);
+       return count;
+}
+
+static bool dual_accel_detect_bosc0200(void)
+{
+       struct acpi_device *adev;
+       int count;
+
+       adev = acpi_dev_get_first_match_dev("BOSC0200", NULL, -1);
+       if (!adev)
+               return false;
+
+       count = dual_accel_i2c_client_count(adev);
+
+       acpi_dev_put(adev);
+
+       return count == 2;
+}
+
+static bool dual_accel_detect(void)
+{
+       /* Systems which use a pair of accels with KIOX010A / KIOX020A ACPI ids */
+       if (acpi_dev_present("KIOX010A", NULL, -1) &&
+           acpi_dev_present("KIOX020A", NULL, -1))
+               return true;
+
+       /* Systems which use a single DUAL250E ACPI device to model 2 accels */
+       if (acpi_dev_present("DUAL250E", NULL, -1))
+               return true;
+
+       /* Systems which use a single BOSC0200 ACPI device to model 2 accels */
+       if (dual_accel_detect_bosc0200())
+               return true;
+
+       return false;
+}
index fbb224a..7f3a03f 100644 (file)
@@ -140,6 +140,7 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev)
        }}
 
 static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B450M S2H V2"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE V2"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"),
@@ -147,6 +148,7 @@ static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 GAMING X"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 I AORUS PRO WIFI"),
        DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 UD"),
        { }
index e5fbe01..2e4e97a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
+#include "dual_accel_detect.h"
 
 /* When NOT in tablet mode, VGBS returns with the flag 0x40 */
 #define TABLET_MODE_FLAG BIT(6)
@@ -122,6 +123,7 @@ struct intel_hid_priv {
        struct input_dev *array;
        struct input_dev *switches;
        bool wakeup_mode;
+       bool dual_accel;
 };
 
 #define HID_EVENT_FILTER_UUID  "eeec56b3-4442-408f-a792-4edd4d758054"
@@ -451,22 +453,9 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
         * SW_TABLET_MODE report, in these cases we enable support when receiving
         * the first event instead of during driver setup.
         *
-        * Some 360 degree hinges (yoga) style 2-in-1 devices use 2 accelerometers
-        * to allow the OS to determine the angle between the display and the base
-        * of the device. On Windows these are read by a special HingeAngleService
-        * process which calls an ACPI DSM (Device Specific Method) on the
-        * ACPI KIOX010A device node for the sensor in the display, to let the
-        * firmware know if the 2-in-1 is in tablet- or laptop-mode so that it can
-        * disable the kbd and touchpad to avoid spurious input in tablet-mode.
-        *
-        * The linux kxcjk1013 driver calls the DSM for this once at probe time
-        * to ensure that the builtin kbd and touchpad work. On some devices this
-        * causes a "spurious" 0xcd event on the intel-hid ACPI dev. In this case
-        * there is not a functional tablet-mode switch, so we should not register
-        * the tablet-mode switch device.
+        * See dual_accel_detect.h for more info on the dual_accel check.
         */
-       if (!priv->switches && (event == 0xcc || event == 0xcd) &&
-           !acpi_dev_present("KIOX010A", NULL, -1)) {
+       if (!priv->switches && !priv->dual_accel && (event == 0xcc || event == 0xcd)) {
                dev_info(&device->dev, "switch event received, enable switches supports\n");
                err = intel_hid_switches_setup(device);
                if (err)
@@ -607,6 +596,8 @@ static int intel_hid_probe(struct platform_device *device)
                return -ENOMEM;
        dev_set_drvdata(&device->dev, priv);
 
+       priv->dual_accel = dual_accel_detect();
+
        err = intel_hid_input_setup(device);
        if (err) {
                pr_err("Failed to setup Intel HID hotkeys\n");
index 888a764..3091664 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/suspend.h>
+#include "dual_accel_detect.h"
 
 /* Returned when NOT in tablet mode on some HP Stream x360 11 models */
 #define VGBS_TABLET_MODE_FLAG_ALT      0x10
@@ -66,6 +67,7 @@ static const struct key_entry intel_vbtn_switchmap[] = {
 struct intel_vbtn_priv {
        struct input_dev *buttons_dev;
        struct input_dev *switches_dev;
+       bool dual_accel;
        bool has_buttons;
        bool has_switches;
        bool wakeup_mode;
@@ -160,6 +162,10 @@ static void notify_handler(acpi_handle handle, u32 event, void *context)
                input_dev = priv->buttons_dev;
        } else if ((ke = sparse_keymap_entry_from_scancode(priv->switches_dev, event))) {
                if (!priv->has_switches) {
+                       /* See dual_accel_detect.h for more info */
+                       if (priv->dual_accel)
+                               return;
+
                        dev_info(&device->dev, "Registering Intel Virtual Switches input-dev after receiving a switch event\n");
                        ret = input_register_device(priv->switches_dev);
                        if (ret)
@@ -248,11 +254,15 @@ static const struct dmi_system_id dmi_switches_allow_list[] = {
        {} /* Array terminator */
 };
 
-static bool intel_vbtn_has_switches(acpi_handle handle)
+static bool intel_vbtn_has_switches(acpi_handle handle, bool dual_accel)
 {
        unsigned long long vgbs;
        acpi_status status;
 
+       /* See dual_accel_detect.h for more info */
+       if (dual_accel)
+               return false;
+
        if (!dmi_check_system(dmi_switches_allow_list))
                return false;
 
@@ -263,13 +273,14 @@ static bool intel_vbtn_has_switches(acpi_handle handle)
 static int intel_vbtn_probe(struct platform_device *device)
 {
        acpi_handle handle = ACPI_HANDLE(&device->dev);
-       bool has_buttons, has_switches;
+       bool dual_accel, has_buttons, has_switches;
        struct intel_vbtn_priv *priv;
        acpi_status status;
        int err;
 
+       dual_accel = dual_accel_detect();
        has_buttons = acpi_has_method(handle, "VBDL");
-       has_switches = intel_vbtn_has_switches(handle);
+       has_switches = intel_vbtn_has_switches(handle, dual_accel);
 
        if (!has_buttons && !has_switches) {
                dev_warn(&device->dev, "failed to read Intel Virtual Button driver\n");
@@ -281,6 +292,7 @@ static int intel_vbtn_probe(struct platform_device *device)
                return -ENOMEM;
        dev_set_drvdata(&device->dev, priv);
 
+       priv->dual_accel = dual_accel;
        priv->has_buttons = has_buttons;
        priv->has_switches = has_switches;
 
index c37349f..d063d91 100644 (file)
@@ -94,6 +94,7 @@ 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),
+               {} /* Terminating entry */
        }
 };
 
@@ -123,6 +124,7 @@ static struct gpiod_lookup_table gpios_key_table = {
        .table = {
                GPIO_LOOKUP_IDX(AMD_FCH_GPIO_DRIVER_NAME, APU2_GPIO_LINE_MODESW,
                                NULL, 0, GPIO_ACTIVE_LOW),
+               {} /* Terminating entry */
        }
 };
 
index 603156a..50ff04c 100644 (file)
@@ -73,6 +73,7 @@
 #include <linux/uaccess.h>
 #include <acpi/battery.h>
 #include <acpi/video.h>
+#include "dual_accel_detect.h"
 
 /* ThinkPad CMOS commands */
 #define TP_CMOS_VOLUME_DOWN    0
@@ -3232,7 +3233,7 @@ static int hotkey_init_tablet_mode(void)
                 * the laptop/tent/tablet mode to the EC. The bmc150 iio driver
                 * does not support this, so skip the hotkey on these models.
                 */
-               if (has_tablet_mode && !acpi_dev_present("BOSC0200", "1", -1))
+               if (has_tablet_mode && !dual_accel_detect())
                        tp_features.hotkey_tablet = TP_HOTKEY_TABLET_USES_GMMS;
                type = "GMMS";
        } else if (acpi_evalf(hkey_handle, &res, "MHKG", "qd")) {
index 8c20e52..e085c25 100644 (file)
@@ -90,7 +90,8 @@ config PTP_1588_CLOCK_INES
 config PTP_1588_CLOCK_PCH
        tristate "Intel PCH EG20T as PTP clock"
        depends on X86_32 || COMPILE_TEST
-       depends on HAS_IOMEM && NET
+       depends on HAS_IOMEM && PCI
+       depends on NET
        imply PTP_1588_CLOCK
        help
          This driver adds support for using the PCH EG20T as a PTP
index b3d96b7..41b92dc 100644 (file)
@@ -154,7 +154,7 @@ static int unregister_vclock(struct device *dev, void *data)
        struct ptp_clock *ptp = dev_get_drvdata(dev);
        struct ptp_clock_info *info = ptp->info;
        struct ptp_vclock *vclock;
-       u8 *num = data;
+       u32 *num = data;
 
        vclock = info_to_vclock(info);
        dev_info(dev->parent, "delete virtual clock ptp%d\n",
index 328f70f..5656cac 100644 (file)
@@ -116,7 +116,7 @@ config RESET_LPC18XX
 
 config RESET_MCHP_SPARX5
        bool "Microchip Sparx5 reset driver"
-       depends on HAS_IOMEM || COMPILE_TEST
+       depends on ARCH_SPARX5 || COMPILE_TEST
        default y if SPARX5_SWITCH
        select MFD_SYSCON
        help
index daa425e..59dc0ff 100644 (file)
@@ -53,7 +53,8 @@ static int zynqmp_reset_status(struct reset_controller_dev *rcdev,
                               unsigned long id)
 {
        struct zynqmp_reset_data *priv = to_zynqmp_reset_data(rcdev);
-       int val, err;
+       int err;
+       u32 val;
 
        err = zynqmp_pm_reset_get_status(priv->data->reset_id + id, &val);
        if (err)
index 0de1a46..fb5d815 100644 (file)
@@ -1004,15 +1004,23 @@ static unsigned char dasd_eckd_path_access(void *conf_data, int conf_len)
 static void dasd_eckd_store_conf_data(struct dasd_device *device,
                                      struct dasd_conf_data *conf_data, int chp)
 {
+       struct dasd_eckd_private *private = device->private;
        struct channel_path_desc_fmt0 *chp_desc;
        struct subchannel_id sch_id;
+       void *cdp;
 
-       ccw_device_get_schid(device->cdev, &sch_id);
        /*
         * path handling and read_conf allocate data
         * free it before replacing the pointer
+        * also replace the old private->conf_data pointer
+        * with the new one if this points to the same data
         */
-       kfree(device->path[chp].conf_data);
+       cdp = device->path[chp].conf_data;
+       if (private->conf_data == cdp) {
+               private->conf_data = (void *)conf_data;
+               dasd_eckd_identify_conf_parts(private);
+       }
+       ccw_device_get_schid(device->cdev, &sch_id);
        device->path[chp].conf_data = conf_data;
        device->path[chp].cssid = sch_id.cssid;
        device->path[chp].ssid = sch_id.ssid;
@@ -1020,6 +1028,7 @@ static void dasd_eckd_store_conf_data(struct dasd_device *device,
        if (chp_desc)
                device->path[chp].chpid = chp_desc->chpid;
        kfree(chp_desc);
+       kfree(cdp);
 }
 
 static void dasd_eckd_clear_conf_data(struct dasd_device *device)
index 2abf86c..d7cdd9c 100644 (file)
@@ -279,7 +279,7 @@ static void qeth_l2_set_pnso_mode(struct qeth_card *card,
 
 static void qeth_l2_dev2br_fdb_flush(struct qeth_card *card)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
 
        QETH_CARD_TEXT(card, 2, "fdbflush");
 
@@ -679,7 +679,7 @@ static void qeth_l2_dev2br_fdb_notify(struct qeth_card *card, u8 code,
                                      struct net_if_token *token,
                                      struct mac_addr_lnid *addr_lnid)
 {
-       struct switchdev_notifier_fdb_info info;
+       struct switchdev_notifier_fdb_info info = {};
        u8 ntfy_mac[ETH_ALEN];
 
        ether_addr_copy(ntfy_mac, addr_lnid->mac);
index 5983e05..e29523a 100644 (file)
@@ -13193,6 +13193,8 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        if (!phba)
                return -ENOMEM;
 
+       INIT_LIST_HEAD(&phba->poll_list);
+
        /* Perform generic PCI device enabling operation */
        error = lpfc_enable_pci_dev(phba);
        if (error)
@@ -13327,7 +13329,6 @@ lpfc_pci_probe_one_s4(struct pci_dev *pdev, const struct pci_device_id *pid)
        /* Enable RAS FW log support */
        lpfc_sli4_ras_setup(phba);
 
-       INIT_LIST_HEAD(&phba->poll_list);
        timer_setup(&phba->cpuhp_poll_timer, lpfc_sli4_poll_hbtimer, 0);
        cpuhp_state_add_instance_nocalls(lpfc_cpuhp_state, &phba->cpuhp);
 
index 19b1c0c..cf4a3a2 100644 (file)
@@ -7851,7 +7851,7 @@ _base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc)
                        return r;
        }
 
-       rc = _base_static_config_pages(ioc);
+       r = _base_static_config_pages(ioc);
        if (r)
                return r;
 
index ae9bfc6..c0d3111 100644 (file)
@@ -808,12 +808,15 @@ store_state_field(struct device *dev, struct device_attribute *attr,
        ret = scsi_device_set_state(sdev, state);
        /*
         * If the device state changes to SDEV_RUNNING, we need to
-        * rescan the device to revalidate it, and run the queue to
-        * avoid I/O hang.
+        * run the queue to avoid I/O hang, and rescan the device
+        * to revalidate it. Running the queue first is necessary
+        * because another thread may be waiting inside
+        * blk_mq_freeze_queue_wait() and because that call may be
+        * waiting for pending I/O to finish.
         */
        if (ret == 0 && state == SDEV_RUNNING) {
-               scsi_rescan_device(dev);
                blk_mq_run_hw_queues(sdev->request_queue, true);
+               scsi_rescan_device(dev);
        }
        mutex_unlock(&sdev->state_mutex);
 
index 328bb96..37506b3 100644 (file)
@@ -1199,14 +1199,24 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device,
                vstor_packet->vm_srb.sense_info_length);
 
        if (vstor_packet->vm_srb.scsi_status != 0 ||
-           vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS)
-               storvsc_log(device, STORVSC_LOGGING_ERROR,
+           vstor_packet->vm_srb.srb_status != SRB_STATUS_SUCCESS) {
+
+               /*
+                * Log TEST_UNIT_READY errors only as warnings. Hyper-V can
+                * return errors when detecting devices using TEST_UNIT_READY,
+                * and logging these as errors produces unhelpful noise.
+                */
+               int loglevel = (stor_pkt->vm_srb.cdb[0] == TEST_UNIT_READY) ?
+                       STORVSC_LOGGING_WARN : STORVSC_LOGGING_ERROR;
+
+               storvsc_log(device, loglevel,
                        "tag#%d cmd 0x%x status: scsi 0x%x srb 0x%x hv 0x%x\n",
                        request->cmd->request->tag,
                        stor_pkt->vm_srb.cdb[0],
                        vstor_packet->vm_srb.scsi_status,
                        vstor_packet->vm_srb.srb_status,
                        vstor_packet->status);
+       }
 
        if (vstor_packet->vm_srb.scsi_status == SAM_STAT_CHECK_CONDITION &&
            (vstor_packet->vm_srb.srb_status & SRB_STATUS_AUTOSENSE_VALID))
index f2b5d34..e5ae262 100644 (file)
@@ -66,7 +66,7 @@ int slim_alloc_txn_tid(struct slim_controller *ctrl, struct slim_msg_txn *txn)
        int ret = 0;
 
        spin_lock_irqsave(&ctrl->txn_lock, flags);
-       ret = idr_alloc_cyclic(&ctrl->tid_idr, txn, 0,
+       ret = idr_alloc_cyclic(&ctrl->tid_idr, txn, 1,
                                SLIM_MAX_TIDS, GFP_ATOMIC);
        if (ret < 0) {
                spin_unlock_irqrestore(&ctrl->txn_lock, flags);
@@ -131,7 +131,8 @@ int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
                        goto slim_xfer_err;
                }
        }
-
+       /* Initialize tid to invalid value */
+       txn->tid = 0;
        need_tid = slim_tid_txn(txn->mt, txn->mc);
 
        if (need_tid) {
@@ -163,7 +164,7 @@ int slim_do_transfer(struct slim_controller *ctrl, struct slim_msg_txn *txn)
                        txn->mt, txn->mc, txn->la, ret);
 
 slim_xfer_err:
-       if (!clk_pause_msg && (!need_tid  || ret == -ETIMEDOUT)) {
+       if (!clk_pause_msg && (txn->tid == 0  || ret == -ETIMEDOUT)) {
                /*
                 * remove runtime-pm vote if this was TX only, or
                 * if there was error during this transaction
index c054e83..7040293 100644 (file)
@@ -618,7 +618,7 @@ static void qcom_slim_ngd_rx(struct qcom_slim_ngd_ctrl *ctrl, u8 *buf)
                (mc == SLIM_USR_MC_GENERIC_ACK &&
                 mt == SLIM_MSG_MT_SRC_REFERRED_USER)) {
                slim_msg_response(&ctrl->ctrl, &buf[4], buf[3], len - 4);
-               pm_runtime_mark_last_busy(ctrl->dev);
+               pm_runtime_mark_last_busy(ctrl->ctrl.dev);
        }
 }
 
@@ -1080,7 +1080,8 @@ static void qcom_slim_ngd_setup(struct qcom_slim_ngd_ctrl *ctrl)
 {
        u32 cfg = readl_relaxed(ctrl->ngd->base);
 
-       if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN)
+       if (ctrl->state == QCOM_SLIM_NGD_CTRL_DOWN ||
+               ctrl->state == QCOM_SLIM_NGD_CTRL_ASLEEP)
                qcom_slim_ngd_init_dma(ctrl);
 
        /* By default enable message queues */
@@ -1131,6 +1132,7 @@ static int qcom_slim_ngd_power_up(struct qcom_slim_ngd_ctrl *ctrl)
                        dev_info(ctrl->dev, "Subsys restart: ADSP active framer\n");
                        return 0;
                }
+               qcom_slim_ngd_setup(ctrl);
                return 0;
        }
 
@@ -1257,13 +1259,14 @@ static int qcom_slim_ngd_enable(struct qcom_slim_ngd_ctrl *ctrl, bool enable)
                }
                /* controller state should be in sync with framework state */
                complete(&ctrl->qmi.qmi_comp);
-               if (!pm_runtime_enabled(ctrl->dev) ||
-                               !pm_runtime_suspended(ctrl->dev))
-                       qcom_slim_ngd_runtime_resume(ctrl->dev);
+               if (!pm_runtime_enabled(ctrl->ctrl.dev) ||
+                        !pm_runtime_suspended(ctrl->ctrl.dev))
+                       qcom_slim_ngd_runtime_resume(ctrl->ctrl.dev);
                else
-                       pm_runtime_resume(ctrl->dev);
-               pm_runtime_mark_last_busy(ctrl->dev);
-               pm_runtime_put(ctrl->dev);
+                       pm_runtime_resume(ctrl->ctrl.dev);
+
+               pm_runtime_mark_last_busy(ctrl->ctrl.dev);
+               pm_runtime_put(ctrl->ctrl.dev);
 
                ret = slim_register_controller(&ctrl->ctrl);
                if (ret) {
@@ -1389,7 +1392,7 @@ static int qcom_slim_ngd_ssr_pdr_notify(struct qcom_slim_ngd_ctrl *ctrl,
                /* Make sure the last dma xfer is finished */
                mutex_lock(&ctrl->tx_lock);
                if (ctrl->state != QCOM_SLIM_NGD_CTRL_DOWN) {
-                       pm_runtime_get_noresume(ctrl->dev);
+                       pm_runtime_get_noresume(ctrl->ctrl.dev);
                        ctrl->state = QCOM_SLIM_NGD_CTRL_DOWN;
                        qcom_slim_ngd_down(ctrl);
                        qcom_slim_ngd_exit_dma(ctrl);
@@ -1617,6 +1620,7 @@ static int __maybe_unused qcom_slim_ngd_runtime_suspend(struct device *dev)
        struct qcom_slim_ngd_ctrl *ctrl = dev_get_drvdata(dev);
        int ret = 0;
 
+       qcom_slim_ngd_exit_dma(ctrl);
        if (!ctrl->qmi.handle)
                return 0;
 
index f678e4d..a05e9fb 100644 (file)
@@ -13,7 +13,7 @@ obj-$(CONFIG_MACH_DOVE)               += dove/
 obj-y                          += fsl/
 obj-$(CONFIG_ARCH_GEMINI)      += gemini/
 obj-y                          += imx/
-obj-$(CONFIG_ARCH_IXP4XX)      += ixp4xx/
+obj-y                          += ixp4xx/
 obj-$(CONFIG_SOC_XWAY)         += lantiq/
 obj-$(CONFIG_LITEX_SOC_CONTROLLER) += litex/
 obj-y                          += mediatek/
index 3f711c1..bbae3d3 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/signal.h>
 #include <linux/device.h>
 #include <linux/spinlock.h>
+#include <linux/platform_device.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <soc/fsl/qe/qe.h>
@@ -53,8 +54,8 @@ struct qe_ic {
        struct irq_chip hc_irq;
 
        /* VIRQ numbers of QE high/low irqs */
-       unsigned int virq_high;
-       unsigned int virq_low;
+       int virq_high;
+       int virq_low;
 };
 
 /*
@@ -404,42 +405,40 @@ static void qe_ic_cascade_muxed_mpic(struct irq_desc *desc)
        chip->irq_eoi(&desc->irq_data);
 }
 
-static void __init qe_ic_init(struct device_node *node)
+static int qe_ic_init(struct platform_device *pdev)
 {
+       struct device *dev = &pdev->dev;
        void (*low_handler)(struct irq_desc *desc);
        void (*high_handler)(struct irq_desc *desc);
        struct qe_ic *qe_ic;
-       struct resource res;
-       u32 ret;
+       struct resource *res;
+       struct device_node *node = pdev->dev.of_node;
 
-       ret = of_address_to_resource(node, 0, &res);
-       if (ret)
-               return;
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(dev, "no memory resource defined\n");
+               return -ENODEV;
+       }
 
-       qe_ic = kzalloc(sizeof(*qe_ic), GFP_KERNEL);
+       qe_ic = devm_kzalloc(dev, sizeof(*qe_ic), GFP_KERNEL);
        if (qe_ic == NULL)
-               return;
+               return -ENOMEM;
 
-       qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS,
-                                              &qe_ic_host_ops, qe_ic);
-       if (qe_ic->irqhost == NULL) {
-               kfree(qe_ic);
-               return;
+       qe_ic->regs = devm_ioremap(dev, res->start, resource_size(res));
+       if (qe_ic->regs == NULL) {
+               dev_err(dev, "failed to ioremap() registers\n");
+               return -ENODEV;
        }
 
-       qe_ic->regs = ioremap(res.start, resource_size(&res));
-
        qe_ic->hc_irq = qe_ic_irq_chip;
 
-       qe_ic->virq_high = irq_of_parse_and_map(node, 0);
-       qe_ic->virq_low = irq_of_parse_and_map(node, 1);
+       qe_ic->virq_high = platform_get_irq(pdev, 0);
+       qe_ic->virq_low = platform_get_irq(pdev, 1);
 
-       if (!qe_ic->virq_low) {
-               printk(KERN_ERR "Failed to map QE_IC low IRQ\n");
-               kfree(qe_ic);
-               return;
-       }
-       if (qe_ic->virq_high != qe_ic->virq_low) {
+       if (qe_ic->virq_low <= 0)
+               return -ENODEV;
+
+       if (qe_ic->virq_high > 0 && qe_ic->virq_high != qe_ic->virq_low) {
                low_handler = qe_ic_cascade_low;
                high_handler = qe_ic_cascade_high;
        } else {
@@ -447,29 +446,42 @@ static void __init qe_ic_init(struct device_node *node)
                high_handler = NULL;
        }
 
+       qe_ic->irqhost = irq_domain_add_linear(node, NR_QE_IC_INTS,
+                                              &qe_ic_host_ops, qe_ic);
+       if (qe_ic->irqhost == NULL) {
+               dev_err(dev, "failed to add irq domain\n");
+               return -ENODEV;
+       }
+
        qe_ic_write(qe_ic->regs, QEIC_CICR, 0);
 
        irq_set_handler_data(qe_ic->virq_low, qe_ic);
        irq_set_chained_handler(qe_ic->virq_low, low_handler);
 
-       if (qe_ic->virq_high && qe_ic->virq_high != qe_ic->virq_low) {
+       if (high_handler) {
                irq_set_handler_data(qe_ic->virq_high, qe_ic);
                irq_set_chained_handler(qe_ic->virq_high, high_handler);
        }
+       return 0;
 }
+static const struct of_device_id qe_ic_ids[] = {
+       { .compatible = "fsl,qe-ic"},
+       { .type = "qeic"},
+       {},
+};
 
-static int __init qe_ic_of_init(void)
+static struct platform_driver qe_ic_driver =
 {
-       struct device_node *np;
+       .driver = {
+               .name           = "qe-ic",
+               .of_match_table = qe_ic_ids,
+       },
+       .probe  = qe_ic_init,
+};
 
-       np = of_find_compatible_node(NULL, NULL, "fsl,qe-ic");
-       if (!np) {
-               np = of_find_node_by_type(NULL, "qeic");
-               if (!np)
-                       return -ENODEV;
-       }
-       qe_ic_init(np);
-       of_node_put(np);
+static int __init qe_ic_of_init(void)
+{
+       platform_driver_register(&qe_ic_driver);
        return 0;
 }
 subsys_initcall(qe_ic_of_init);
index 071e144..cc57a38 100644 (file)
@@ -5,8 +5,6 @@
 
 #include <linux/init.h>
 #include <linux/io.h>
-#include <linux/module.h>
-#include <linux/nvmem-consumer.h>
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/sys_soc.h>
@@ -31,7 +29,7 @@
 
 struct imx8_soc_data {
        char *name;
-       u32 (*soc_revision)(struct device *dev);
+       u32 (*soc_revision)(void);
 };
 
 static u64 soc_uid;
@@ -52,7 +50,7 @@ static u32 imx8mq_soc_revision_from_atf(void)
 static inline u32 imx8mq_soc_revision_from_atf(void) { return 0; };
 #endif
 
-static u32 __init imx8mq_soc_revision(struct device *dev)
+static u32 __init imx8mq_soc_revision(void)
 {
        struct device_node *np;
        void __iomem *ocotp_base;
@@ -77,20 +75,9 @@ static u32 __init imx8mq_soc_revision(struct device *dev)
                        rev = REV_B1;
        }
 
-       if (dev) {
-               int ret;
-
-               ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid);
-               if (ret) {
-                       iounmap(ocotp_base);
-                       of_node_put(np);
-                       return ret;
-               }
-       } else {
-               soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
-               soc_uid <<= 32;
-               soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
-       }
+       soc_uid = readl_relaxed(ocotp_base + OCOTP_UID_HIGH);
+       soc_uid <<= 32;
+       soc_uid |= readl_relaxed(ocotp_base + OCOTP_UID_LOW);
 
        iounmap(ocotp_base);
        of_node_put(np);
@@ -120,7 +107,7 @@ static void __init imx8mm_soc_uid(void)
        of_node_put(np);
 }
 
-static u32 __init imx8mm_soc_revision(struct device *dev)
+static u32 __init imx8mm_soc_revision(void)
 {
        struct device_node *np;
        void __iomem *anatop_base;
@@ -138,15 +125,7 @@ static u32 __init imx8mm_soc_revision(struct device *dev)
        iounmap(anatop_base);
        of_node_put(np);
 
-       if (dev) {
-               int ret;
-
-               ret = nvmem_cell_read_u64(dev, "soc_unique_id", &soc_uid);
-               if (ret)
-                       return ret;
-       } else {
-               imx8mm_soc_uid();
-       }
+       imx8mm_soc_uid();
 
        return rev;
 }
@@ -171,7 +150,7 @@ static const struct imx8_soc_data imx8mp_soc_data = {
        .soc_revision = imx8mm_soc_revision,
 };
 
-static __maybe_unused const struct of_device_id imx8_machine_match[] = {
+static __maybe_unused const struct of_device_id imx8_soc_match[] = {
        { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, },
        { .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, },
        { .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, },
@@ -179,20 +158,12 @@ static __maybe_unused const struct of_device_id imx8_machine_match[] = {
        { }
 };
 
-static __maybe_unused const struct of_device_id imx8_soc_match[] = {
-       { .compatible = "fsl,imx8mq-soc", .data = &imx8mq_soc_data, },
-       { .compatible = "fsl,imx8mm-soc", .data = &imx8mm_soc_data, },
-       { .compatible = "fsl,imx8mn-soc", .data = &imx8mn_soc_data, },
-       { .compatible = "fsl,imx8mp-soc", .data = &imx8mp_soc_data, },
-       { }
-};
-
 #define imx8_revision(soc_rev) \
        soc_rev ? \
        kasprintf(GFP_KERNEL, "%d.%d", (soc_rev >> 4) & 0xf,  soc_rev & 0xf) : \
        "unknown"
 
-static int imx8_soc_info(struct platform_device *pdev)
+static int __init imx8_soc_init(void)
 {
        struct soc_device_attribute *soc_dev_attr;
        struct soc_device *soc_dev;
@@ -211,10 +182,7 @@ static int imx8_soc_info(struct platform_device *pdev)
        if (ret)
                goto free_soc;
 
-       if (pdev)
-               id = of_match_node(imx8_soc_match, pdev->dev.of_node);
-       else
-               id = of_match_node(imx8_machine_match, of_root);
+       id = of_match_node(imx8_soc_match, of_root);
        if (!id) {
                ret = -ENODEV;
                goto free_soc;
@@ -223,16 +191,8 @@ static int imx8_soc_info(struct platform_device *pdev)
        data = id->data;
        if (data) {
                soc_dev_attr->soc_id = data->name;
-               if (data->soc_revision) {
-                       if (pdev) {
-                               soc_rev = data->soc_revision(&pdev->dev);
-                               ret = soc_rev;
-                               if (ret < 0)
-                                       goto free_soc;
-                       } else {
-                               soc_rev = data->soc_revision(NULL);
-                       }
-               }
+               if (data->soc_revision)
+                       soc_rev = data->soc_revision();
        }
 
        soc_dev_attr->revision = imx8_revision(soc_rev);
@@ -270,24 +230,4 @@ free_soc:
        kfree(soc_dev_attr);
        return ret;
 }
-
-/* Retain device_initcall is for backward compatibility with DTS. */
-static int __init imx8_soc_init(void)
-{
-       if (of_find_matching_node_and_match(NULL, imx8_soc_match, NULL))
-               return 0;
-
-       return imx8_soc_info(NULL);
-}
 device_initcall(imx8_soc_init);
-
-static struct platform_driver imx8_soc_info_driver = {
-       .probe = imx8_soc_info,
-       .driver = {
-               .name = "imx8_soc_info",
-               .of_match_table = imx8_soc_match,
-       },
-};
-
-module_platform_driver(imx8_soc_info_driver);
-MODULE_LICENSE("GPL v2");
index 7bd1935..f490c4c 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/soc/ixp4xx/npe.h>
-#include <mach/hardware.h>
 #include <linux/soc/ixp4xx/cpu.h>
 
 #define DEBUG_MSG                      0
@@ -694,8 +693,8 @@ static int ixp4xx_npe_probe(struct platform_device *pdev)
 
                if (!(ixp4xx_read_feature_bits() &
                      (IXP4XX_FEATURE_RESET_NPEA << i))) {
-                       dev_info(dev, "NPE%d at 0x%08x-0x%08x not available\n",
-                                i, res->start, res->end);
+                       dev_info(dev, "NPE%d at %pR not available\n",
+                                i, res);
                        continue; /* NPE already disabled or not present */
                }
                npe->regs = devm_ioremap_resource(dev, res);
@@ -703,13 +702,12 @@ static int ixp4xx_npe_probe(struct platform_device *pdev)
                        return PTR_ERR(npe->regs);
 
                if (npe_reset(npe)) {
-                       dev_info(dev, "NPE%d at 0x%08x-0x%08x does not reset\n",
-                                i, res->start, res->end);
+                       dev_info(dev, "NPE%d at %pR does not reset\n",
+                                i, res);
                        continue;
                }
                npe->valid = 1;
-               dev_info(dev, "NPE%d at 0x%08x-0x%08x registered\n",
-                        i, res->start, res->end);
+               dev_info(dev, "NPE%d at %pR registered\n", i, res);
                found++;
        }
 
index 7149510..9154c70 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/soc/ixp4xx/qmgr.h>
-#include <mach/hardware.h>
 #include <linux/soc/ixp4xx/cpu.h>
 
 static struct qmgr_regs __iomem *qmgr_regs;
@@ -147,12 +146,12 @@ static irqreturn_t qmgr_irq1_a0(int irq, void *pdev)
        /* ACK - it may clear any bits so don't rely on it */
        __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[0]);
 
-       en_bitmap = qmgr_regs->irqen[0];
+       en_bitmap = __raw_readl(&qmgr_regs->irqen[0]);
        while (en_bitmap) {
                i = __fls(en_bitmap); /* number of the last "low" queue */
                en_bitmap &= ~BIT(i);
-               src = qmgr_regs->irqsrc[i >> 3];
-               stat = qmgr_regs->stat1[i >> 3];
+               src = __raw_readl(&qmgr_regs->irqsrc[i >> 3]);
+               stat = __raw_readl(&qmgr_regs->stat1[i >> 3]);
                if (src & 4) /* the IRQ condition is inverted */
                        stat = ~stat;
                if (stat & BIT(src & 3)) {
@@ -172,7 +171,8 @@ static irqreturn_t qmgr_irq2_a0(int irq, void *pdev)
        /* ACK - it may clear any bits so don't rely on it */
        __raw_writel(0xFFFFFFFF, &qmgr_regs->irqstat[1]);
 
-       req_bitmap = qmgr_regs->irqen[1] & qmgr_regs->statne_h;
+       req_bitmap = __raw_readl(&qmgr_regs->irqen[1]) &
+                    __raw_readl(&qmgr_regs->statne_h);
        while (req_bitmap) {
                i = __fls(req_bitmap); /* number of the last "high" queue */
                req_bitmap &= ~BIT(i);
index 20ace65..8b53ed1 100644 (file)
@@ -15,7 +15,7 @@ config ARCH_TEGRA_2x_SOC
        select PL310_ERRATA_769419 if CACHE_L2X0
        select SOC_TEGRA_FLOWCTRL
        select SOC_TEGRA_PMC
-       select SOC_TEGRA20_VOLTAGE_COUPLER
+       select SOC_TEGRA20_VOLTAGE_COUPLER if REGULATOR
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra AP20 and T20 processors, based on the
@@ -29,7 +29,7 @@ config ARCH_TEGRA_3x_SOC
        select PL310_ERRATA_769419 if CACHE_L2X0
        select SOC_TEGRA_FLOWCTRL
        select SOC_TEGRA_PMC
-       select SOC_TEGRA30_VOLTAGE_COUPLER
+       select SOC_TEGRA30_VOLTAGE_COUPLER if REGULATOR
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T30 processor family, based on the
@@ -155,7 +155,9 @@ config SOC_TEGRA_POWERGATE_BPMP
 config SOC_TEGRA20_VOLTAGE_COUPLER
        bool "Voltage scaling support for Tegra20 SoCs"
        depends on ARCH_TEGRA_2x_SOC || COMPILE_TEST
+       depends on REGULATOR
 
 config SOC_TEGRA30_VOLTAGE_COUPLER
        bool "Voltage scaling support for Tegra30 SoCs"
        depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST
+       depends on REGULATOR
index a2de235..101cc71 100644 (file)
@@ -325,7 +325,15 @@ static int cqspi_set_protocol(struct cqspi_flash_pdata *f_pdata,
        f_pdata->inst_width = CQSPI_INST_TYPE_SINGLE;
        f_pdata->addr_width = CQSPI_INST_TYPE_SINGLE;
        f_pdata->data_width = CQSPI_INST_TYPE_SINGLE;
-       f_pdata->dtr = op->data.dtr && op->cmd.dtr && op->addr.dtr;
+
+       /*
+        * For an op to be DTR, cmd phase along with every other non-empty
+        * phase should have dtr field set to 1. If an op phase has zero
+        * nbytes, ignore its dtr field; otherwise, check its dtr field.
+        */
+       f_pdata->dtr = op->cmd.dtr &&
+                      (!op->addr.nbytes || op->addr.dtr) &&
+                      (!op->data.nbytes || op->data.dtr);
 
        switch (op->data.buswidth) {
        case 0:
@@ -1228,8 +1236,15 @@ static bool cqspi_supports_mem_op(struct spi_mem *mem,
 {
        bool all_true, all_false;
 
-       all_true = op->cmd.dtr && op->addr.dtr && op->dummy.dtr &&
-                  op->data.dtr;
+       /*
+        * op->dummy.dtr is required for converting nbytes into ncycles.
+        * Also, don't check the dtr field of the op phase having zero nbytes.
+        */
+       all_true = op->cmd.dtr &&
+                  (!op->addr.nbytes || op->addr.dtr) &&
+                  (!op->dummy.nbytes || op->dummy.dtr) &&
+                  (!op->data.nbytes || op->data.dtr);
+
        all_false = !op->cmd.dtr && !op->addr.dtr && !op->dummy.dtr &&
                    !op->data.dtr;
 
index 4aee3db..fa68e98 100644 (file)
@@ -505,7 +505,9 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
                                      struct spi_message *msg)
 {
        struct spi_device *spi = msg->spi;
+       struct spi_transfer *xfer;
        u32 ctrl = MX51_ECSPI_CTRL_ENABLE;
+       u32 min_speed_hz = ~0U;
        u32 testreg, delay;
        u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
 
@@ -577,9 +579,21 @@ static int mx51_ecspi_prepare_message(struct spi_imx_data *spi_imx,
         * be asserted before the SCLK polarity changes, which would disrupt
         * the SPI communication as the device on the other end would consider
         * the change of SCLK polarity as a clock tick already.
+        *
+        * Because spi_imx->spi_bus_clk is only set in bitbang prepare_message
+        * callback, iterate over all the transfers in spi_message, find the
+        * one with lowest bus frequency, and use that bus frequency for the
+        * delay calculation. In case all transfers have speed_hz == 0, then
+        * min_speed_hz is ~0 and the resulting delay is zero.
         */
-       delay = (2 * 1000000) / spi_imx->spi_bus_clk;
-       if (likely(delay < 10)) /* SCLK is faster than 100 kHz */
+       list_for_each_entry(xfer, &msg->transfers, transfer_list) {
+               if (!xfer->speed_hz)
+                       continue;
+               min_speed_hz = min(xfer->speed_hz, min_speed_hz);
+       }
+
+       delay = (2 * 1000000) / min_speed_hz;
+       if (likely(delay < 10)) /* SCLK is faster than 200 kHz */
                udelay(delay);
        else                    /* SCLK is _very_ slow */
                usleep_range(delay, delay + 10);
index b2c4621..c208efe 100644 (file)
@@ -785,6 +785,8 @@ static int meson_spicc_remove(struct platform_device *pdev)
        clk_disable_unprepare(spicc->core);
        clk_disable_unprepare(spicc->pclk);
 
+       spi_master_put(spicc->master);
+
        return 0;
 }
 
index 68dca8c..7914255 100644 (file)
@@ -426,24 +426,15 @@ static int mtk_spi_fifo_transfer(struct spi_master *master,
        mtk_spi_prepare_transfer(master, xfer);
        mtk_spi_setup_packet(master);
 
-       cnt = xfer->len / 4;
-       if (xfer->tx_buf)
+       if (xfer->tx_buf) {
+               cnt = xfer->len / 4;
                iowrite32_rep(mdata->base + SPI_TX_DATA_REG, xfer->tx_buf, cnt);
-
-       if (xfer->rx_buf)
-               ioread32_rep(mdata->base + SPI_RX_DATA_REG, xfer->rx_buf, cnt);
-
-       remainder = xfer->len % 4;
-       if (remainder > 0) {
-               reg_val = 0;
-               if (xfer->tx_buf) {
+               remainder = xfer->len % 4;
+               if (remainder > 0) {
+                       reg_val = 0;
                        memcpy(&reg_val, xfer->tx_buf + (cnt * 4), remainder);
                        writel(reg_val, mdata->base + SPI_TX_DATA_REG);
                }
-               if (xfer->rx_buf) {
-                       reg_val = readl(mdata->base + SPI_RX_DATA_REG);
-                       memcpy(xfer->rx_buf + (cnt * 4), &reg_val, remainder);
-               }
        }
 
        mtk_spi_enable_transfer(master);
index 37dfc6e..9708b78 100644 (file)
@@ -167,10 +167,17 @@ err_put_ctlr:
        return ret;
 }
 
+static const struct spi_device_id spi_mux_id[] = {
+       { "spi-mux" },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, spi_mux_id);
+
 static const struct of_device_id spi_mux_of_match[] = {
        { .compatible = "spi-mux" },
        { }
 };
+MODULE_DEVICE_TABLE(of, spi_mux_of_match);
 
 static struct spi_driver spi_mux_driver = {
        .probe  = spi_mux_probe,
@@ -178,6 +185,7 @@ static struct spi_driver spi_mux_driver = {
                .name   = "spi-mux",
                .of_match_table = spi_mux_of_match,
        },
+       .id_table = spi_mux_id,
 };
 
 module_spi_driver(spi_mux_driver);
index c991811..e4dc593 100644 (file)
@@ -58,6 +58,10 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf)
        const struct spi_device *spi = to_spi_device(dev);
        int len;
 
+       len = of_device_modalias(dev, buf, PAGE_SIZE);
+       if (len != -ENODEV)
+               return len;
+
        len = acpi_device_modalias(dev, buf, PAGE_SIZE - 1);
        if (len != -ENODEV)
                return len;
diff --git a/drivers/staging/media/av7110/audio.h b/drivers/staging/media/av7110/audio.h
deleted file mode 100644 (file)
index 2f869da..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
-/*
- * audio.h - DEPRECATED MPEG-TS audio decoder API
- *
- * NOTE: should not be used on future drivers
- *
- * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
- *                  & Marcus Metzler <marcus@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- */
-
-#ifndef _DVBAUDIO_H_
-#define _DVBAUDIO_H_
-
-#include <linux/types.h>
-
-typedef enum {
-       AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
-       AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */
-} audio_stream_source_t;
-
-
-typedef enum {
-       AUDIO_STOPPED,      /* Device is stopped */
-       AUDIO_PLAYING,      /* Device is currently playing */
-       AUDIO_PAUSED        /* Device is paused */
-} audio_play_state_t;
-
-
-typedef enum {
-       AUDIO_STEREO,
-       AUDIO_MONO_LEFT,
-       AUDIO_MONO_RIGHT,
-       AUDIO_MONO,
-       AUDIO_STEREO_SWAPPED
-} audio_channel_select_t;
-
-
-typedef struct audio_mixer {
-       unsigned int volume_left;
-       unsigned int volume_right;
-  /* what else do we need? bass, pass-through, ... */
-} audio_mixer_t;
-
-
-typedef struct audio_status {
-       int                    AV_sync_state;  /* sync audio and video? */
-       int                    mute_state;     /* audio is muted */
-       audio_play_state_t     play_state;     /* current playback state */
-       audio_stream_source_t  stream_source;  /* current stream source */
-       audio_channel_select_t channel_select; /* currently selected channel */
-       int                    bypass_mode;    /* pass on audio data to */
-       audio_mixer_t          mixer_state;    /* current mixer state */
-} audio_status_t;                              /* separate decoder hardware */
-
-
-/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */
-#define AUDIO_CAP_DTS    1
-#define AUDIO_CAP_LPCM   2
-#define AUDIO_CAP_MP1    4
-#define AUDIO_CAP_MP2    8
-#define AUDIO_CAP_MP3   16
-#define AUDIO_CAP_AAC   32
-#define AUDIO_CAP_OGG   64
-#define AUDIO_CAP_SDDS 128
-#define AUDIO_CAP_AC3  256
-
-#define AUDIO_STOP                 _IO('o', 1)
-#define AUDIO_PLAY                 _IO('o', 2)
-#define AUDIO_PAUSE                _IO('o', 3)
-#define AUDIO_CONTINUE             _IO('o', 4)
-#define AUDIO_SELECT_SOURCE        _IO('o', 5)
-#define AUDIO_SET_MUTE             _IO('o', 6)
-#define AUDIO_SET_AV_SYNC          _IO('o', 7)
-#define AUDIO_SET_BYPASS_MODE      _IO('o', 8)
-#define AUDIO_CHANNEL_SELECT       _IO('o', 9)
-#define AUDIO_GET_STATUS           _IOR('o', 10, audio_status_t)
-
-#define AUDIO_GET_CAPABILITIES     _IOR('o', 11, unsigned int)
-#define AUDIO_CLEAR_BUFFER         _IO('o',  12)
-#define AUDIO_SET_ID               _IO('o', 13)
-#define AUDIO_SET_MIXER            _IOW('o', 14, audio_mixer_t)
-#define AUDIO_SET_STREAMTYPE       _IO('o', 15)
-#define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20)
-
-#endif /* _DVBAUDIO_H_ */
index b8e8fc8..809d938 100644 (file)
@@ -9,12 +9,11 @@
 #include <linux/input.h>
 #include <linux/time.h>
 
-#include "video.h"
-#include "audio.h"
-#include "osd.h"
-
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
 #include <linux/dvb/dmx.h>
 #include <linux/dvb/ca.h>
+#include <linux/dvb/osd.h>
 #include <linux/dvb/net.h>
 #include <linux/mutex.h>
 
diff --git a/drivers/staging/media/av7110/osd.h b/drivers/staging/media/av7110/osd.h
deleted file mode 100644 (file)
index 858997c..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
-/*
- * osd.h - DEPRECATED On Screen Display API
- *
- * NOTE: should not be used on future drivers
- *
- * Copyright (C) 2001 Ralph  Metzler <ralph@convergence.de>
- *                  & Marcus Metzler <marcus@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Lesser Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- */
-
-#ifndef _DVBOSD_H_
-#define _DVBOSD_H_
-
-#include <linux/compiler.h>
-
-typedef enum {
-       /* All functions return -2 on "not open" */
-       OSD_Close = 1,  /* () */
-       /*
-        * Disables OSD and releases the buffers
-        * returns 0 on success
-        */
-       OSD_Open,       /* (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) */
-       /*
-        * Opens OSD with this size and bit depth
-        * returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
-        */
-       OSD_Show,       /* () */
-       /*
-        * enables OSD mode
-        * returns 0 on success
-        */
-       OSD_Hide,       /* () */
-       /*
-        * disables OSD mode
-        * returns 0 on success
-        */
-       OSD_Clear,      /* () */
-       /*
-        * Sets all pixel to color 0
-        * returns 0 on success
-        */
-       OSD_Fill,       /* (color) */
-       /*
-        * Sets all pixel to color <col>
-        * returns 0 on success
-        */
-       OSD_SetColor,   /* (color,R{x0},G{y0},B{x1},opacity{y1}) */
-       /*
-        * set palette entry <num> to <r,g,b>, <mix> and <trans> apply
-        * R,G,B: 0..255
-        * R=Red, G=Green, B=Blue
-        * opacity=0:      pixel opacity 0% (only video pixel shows)
-        * opacity=1..254: pixel opacity as specified in header
-        * opacity=255:    pixel opacity 100% (only OSD pixel shows)
-        * returns 0 on success, -1 on error
-        */
-       OSD_SetPalette, /* (firstcolor{color},lastcolor{x0},data) */
-       /*
-        * Set a number of entries in the palette
-        * sets the entries "firstcolor" through "lastcolor" from the array "data"
-        * data has 4 byte for each color:
-        * R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
-        */
-       OSD_SetTrans,   /* (transparency{color}) */
-       /*
-        * Sets transparency of mixed pixel (0..15)
-        * returns 0 on success
-        */
-       OSD_SetPixel,   /* (x0,y0,color) */
-       /*
-        * sets pixel <x>,<y> to color number <col>
-        * returns 0 on success, -1 on error
-        */
-       OSD_GetPixel,   /* (x0,y0) */
-       /* returns color number of pixel <x>,<y>,  or -1 */
-       OSD_SetRow,     /* (x0,y0,x1,data) */
-       /*
-        * fills pixels x0,y through  x1,y with the content of data[]
-        * returns 0 on success, -1 on clipping all pixel (no pixel drawn)
-        */
-       OSD_SetBlock,   /* (x0,y0,x1,y1,increment{color},data) */
-       /*
-        * fills pixels x0,y0 through  x1,y1 with the content of data[]
-        * inc contains the width of one line in the data block,
-        * inc<=0 uses blockwidth as linewidth
-        * returns 0 on success, -1 on clipping all pixel
-        */
-       OSD_FillRow,    /* (x0,y0,x1,color) */
-       /*
-        * fills pixels x0,y through  x1,y with the color <col>
-        * returns 0 on success, -1 on clipping all pixel
-        */
-       OSD_FillBlock,  /* (x0,y0,x1,y1,color) */
-       /*
-        * fills pixels x0,y0 through  x1,y1 with the color <col>
-        * returns 0 on success, -1 on clipping all pixel
-        */
-       OSD_Line,       /* (x0,y0,x1,y1,color) */
-       /*
-        * draw a line from x0,y0 to x1,y1 with the color <col>
-        * returns 0 on success
-        */
-       OSD_Query,      /* (x0,y0,x1,y1,xasp{color}}), yasp=11 */
-       /*
-        * fills parameters with the picture dimensions and the pixel aspect ratio
-        * returns 0 on success
-        */
-       OSD_Test,       /* () */
-       /*
-        * draws a test picture. for debugging purposes only
-        * returns 0 on success
-        * TODO: remove "test" in final version
-        */
-       OSD_Text,       /* (x0,y0,size,color,text) */
-       OSD_SetWindow,  /* (x0) set window with number 0<x0<8 as current */
-       OSD_MoveWindow, /* move current window to (x0, y0) */
-       OSD_OpenRaw,    /* Open other types of OSD windows */
-} OSD_Command;
-
-typedef struct osd_cmd_s {
-       OSD_Command cmd;
-       int x0;
-       int y0;
-       int x1;
-       int y1;
-       int color;
-       void __user *data;
-} osd_cmd_t;
-
-/* OSD_OpenRaw: set 'color' to desired window type */
-typedef enum {
-       OSD_BITMAP1,           /* 1 bit bitmap */
-       OSD_BITMAP2,           /* 2 bit bitmap */
-       OSD_BITMAP4,           /* 4 bit bitmap */
-       OSD_BITMAP8,           /* 8 bit bitmap */
-       OSD_BITMAP1HR,         /* 1 Bit bitmap half resolution */
-       OSD_BITMAP2HR,         /* 2 bit bitmap half resolution */
-       OSD_BITMAP4HR,         /* 4 bit bitmap half resolution */
-       OSD_BITMAP8HR,         /* 8 bit bitmap half resolution */
-       OSD_YCRCB422,          /* 4:2:2 YCRCB Graphic Display */
-       OSD_YCRCB444,          /* 4:4:4 YCRCB Graphic Display */
-       OSD_YCRCB444HR,        /* 4:4:4 YCRCB graphic half resolution */
-       OSD_VIDEOTSIZE,        /* True Size Normal MPEG Video Display */
-       OSD_VIDEOHSIZE,        /* MPEG Video Display Half Resolution */
-       OSD_VIDEOQSIZE,        /* MPEG Video Display Quarter Resolution */
-       OSD_VIDEODSIZE,        /* MPEG Video Display Double Resolution */
-       OSD_VIDEOTHSIZE,       /* True Size MPEG Video Display Half Resolution */
-       OSD_VIDEOTQSIZE,       /* True Size MPEG Video Display Quarter Resolution*/
-       OSD_VIDEOTDSIZE,       /* True Size MPEG Video Display Double Resolution */
-       OSD_VIDEONSIZE,        /* Full Size MPEG Video Display */
-       OSD_CURSOR             /* Cursor */
-} osd_raw_window_t;
-
-typedef struct osd_cap_s {
-       int  cmd;
-#define OSD_CAP_MEMSIZE         1  /* memory size */
-       long val;
-} osd_cap_t;
-
-
-#define OSD_SEND_CMD            _IOW('o', 160, osd_cmd_t)
-#define OSD_GET_CAPABILITY      _IOR('o', 161, osd_cap_t)
-
-#endif
diff --git a/drivers/staging/media/av7110/video.h b/drivers/staging/media/av7110/video.h
deleted file mode 100644 (file)
index 179f1ec..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
-/*
- * video.h - DEPRECATED MPEG-TS video decoder API
- *
- * NOTE: should not be used on future drivers
- *
- * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
- *                  & Ralph  Metzler <ralph@convergence.de>
- *                    for convergence integrated media GmbH
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * as published by the Free Software Foundation; either version 2.1
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- *
- */
-
-#ifndef _UAPI_DVBVIDEO_H_
-#define _UAPI_DVBVIDEO_H_
-
-#include <linux/types.h>
-#ifndef __KERNEL__
-#include <time.h>
-#endif
-
-typedef enum {
-       VIDEO_FORMAT_4_3,     /* Select 4:3 format */
-       VIDEO_FORMAT_16_9,    /* Select 16:9 format. */
-       VIDEO_FORMAT_221_1    /* 2.21:1 */
-} video_format_t;
-
-
-typedef enum {
-       VIDEO_PAN_SCAN,       /* use pan and scan format */
-       VIDEO_LETTER_BOX,     /* use letterbox format */
-       VIDEO_CENTER_CUT_OUT  /* use center cut out format */
-} video_displayformat_t;
-
-typedef struct {
-       int w;
-       int h;
-       video_format_t aspect_ratio;
-} video_size_t;
-
-typedef enum {
-       VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
-       VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
-                              comes from the user through the write
-                              system call */
-} video_stream_source_t;
-
-
-typedef enum {
-       VIDEO_STOPPED, /* Video is stopped */
-       VIDEO_PLAYING, /* Video is currently playing */
-       VIDEO_FREEZED  /* Video is freezed */
-} video_play_state_t;
-
-
-/* Decoder commands */
-#define VIDEO_CMD_PLAY        (0)
-#define VIDEO_CMD_STOP        (1)
-#define VIDEO_CMD_FREEZE      (2)
-#define VIDEO_CMD_CONTINUE    (3)
-
-/* Flags for VIDEO_CMD_FREEZE */
-#define VIDEO_CMD_FREEZE_TO_BLACK      (1 << 0)
-
-/* Flags for VIDEO_CMD_STOP */
-#define VIDEO_CMD_STOP_TO_BLACK                (1 << 0)
-#define VIDEO_CMD_STOP_IMMEDIATELY     (1 << 1)
-
-/* Play input formats: */
-/* The decoder has no special format requirements */
-#define VIDEO_PLAY_FMT_NONE         (0)
-/* The decoder requires full GOPs */
-#define VIDEO_PLAY_FMT_GOP          (1)
-
-/* The structure must be zeroed before use by the application
-   This ensures it can be extended safely in the future. */
-struct video_command {
-       __u32 cmd;
-       __u32 flags;
-       union {
-               struct {
-                       __u64 pts;
-               } stop;
-
-               struct {
-                       /* 0 or 1000 specifies normal speed,
-                          1 specifies forward single stepping,
-                          -1 specifies backward single stepping,
-                          >1: playback at speed/1000 of the normal speed,
-                          <-1: reverse playback at (-speed/1000) of the normal speed. */
-                       __s32 speed;
-                       __u32 format;
-               } play;
-
-               struct {
-                       __u32 data[16];
-               } raw;
-       };
-};
-
-/* FIELD_UNKNOWN can be used if the hardware does not know whether
-   the Vsync is for an odd, even or progressive (i.e. non-interlaced)
-   field. */
-#define VIDEO_VSYNC_FIELD_UNKNOWN      (0)
-#define VIDEO_VSYNC_FIELD_ODD          (1)
-#define VIDEO_VSYNC_FIELD_EVEN         (2)
-#define VIDEO_VSYNC_FIELD_PROGRESSIVE  (3)
-
-struct video_event {
-       __s32 type;
-#define VIDEO_EVENT_SIZE_CHANGED       1
-#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
-#define VIDEO_EVENT_DECODER_STOPPED    3
-#define VIDEO_EVENT_VSYNC              4
-       /* unused, make sure to use atomic time for y2038 if it ever gets used */
-       long timestamp;
-       union {
-               video_size_t size;
-               unsigned int frame_rate;        /* in frames per 1000sec */
-               unsigned char vsync_field;      /* unknown/odd/even/progressive */
-       } u;
-};
-
-
-struct video_status {
-       int                   video_blank;   /* blank video on freeze? */
-       video_play_state_t    play_state;    /* current state of playback */
-       video_stream_source_t stream_source; /* current source (demux/memory) */
-       video_format_t        video_format;  /* current aspect ratio of stream*/
-       video_displayformat_t display_format;/* selected cropping mode */
-};
-
-
-struct video_still_picture {
-       char __user *iFrame;        /* pointer to a single iframe in memory */
-       __s32 size;
-};
-
-
-typedef __u16 video_attributes_t;
-/*   bits: descr. */
-/*   15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
-/*   13-12 TV system (0=525/60, 1=625/50) */
-/*   11-10 Aspect ratio (0=4:3, 3=16:9) */
-/*    9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */
-/*    7    line 21-1 data present in GOP (1=yes, 0=no) */
-/*    6    line 21-2 data present in GOP (1=yes, 0=no) */
-/*    5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */
-/*    2    source letterboxed (1=yes, 0=no) */
-/*    0    film/camera mode (0=
- *camera, 1=film (625/50 only)) */
-
-
-/* bit definitions for capabilities: */
-/* can the hardware decode MPEG1 and/or MPEG2? */
-#define VIDEO_CAP_MPEG1   1
-#define VIDEO_CAP_MPEG2   2
-/* can you send a system and/or program stream to video device?
-   (you still have to open the video and the audio device but only
-    send the stream to the video device) */
-#define VIDEO_CAP_SYS     4
-#define VIDEO_CAP_PROG    8
-/* can the driver also handle SPU, NAVI and CSS encoded data?
-   (CSS API is not present yet) */
-#define VIDEO_CAP_SPU    16
-#define VIDEO_CAP_NAVI   32
-#define VIDEO_CAP_CSS    64
-
-
-#define VIDEO_STOP                 _IO('o', 21)
-#define VIDEO_PLAY                 _IO('o', 22)
-#define VIDEO_FREEZE               _IO('o', 23)
-#define VIDEO_CONTINUE             _IO('o', 24)
-#define VIDEO_SELECT_SOURCE        _IO('o', 25)
-#define VIDEO_SET_BLANK            _IO('o', 26)
-#define VIDEO_GET_STATUS           _IOR('o', 27, struct video_status)
-#define VIDEO_GET_EVENT            _IOR('o', 28, struct video_event)
-#define VIDEO_SET_DISPLAY_FORMAT   _IO('o', 29)
-#define VIDEO_STILLPICTURE         _IOW('o', 30, struct video_still_picture)
-#define VIDEO_FAST_FORWARD         _IO('o', 31)
-#define VIDEO_SLOWMOTION           _IO('o', 32)
-#define VIDEO_GET_CAPABILITIES     _IOR('o', 33, unsigned int)
-#define VIDEO_CLEAR_BUFFER         _IO('o',  34)
-#define VIDEO_SET_STREAMTYPE       _IO('o', 36)
-#define VIDEO_SET_FORMAT           _IO('o', 37)
-#define VIDEO_GET_SIZE             _IOR('o', 55, video_size_t)
-
-/**
- * VIDEO_GET_PTS
- *
- * Read the 33 bit presentation time stamp as defined
- * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
- *
- * The PTS should belong to the currently played
- * frame if possible, but may also be a value close to it
- * like the PTS of the last decoded frame or the last PTS
- * extracted by the PES parser.
- */
-#define VIDEO_GET_PTS              _IOR('o', 57, __u64)
-
-/* Read the number of displayed frames since the decoder was started */
-#define VIDEO_GET_FRAME_COUNT     _IOR('o', 58, __u64)
-
-#define VIDEO_COMMAND             _IOWR('o', 59, struct video_command)
-#define VIDEO_TRY_COMMAND         _IOWR('o', 60, struct video_command)
-
-#endif /* _UAPI_DVBVIDEO_H_ */
index 691030e..f9bdf4e 100644 (file)
@@ -422,7 +422,6 @@ static void mt7621_pcie_init_ports(struct mt7621_pcie *pcie)
                        dev_err(dev, "pcie%d no card, disable it (RST & CLK)\n",
                                slot);
                        mt7621_control_assert(port);
-                       clk_disable_unprepare(port->clk);
                        port->enabled = false;
 
                        if (slot == 0) {
index 2297427..4eff3fd 100644 (file)
 #define FWBUFF_ALIGN_SZ 512
 #define MAX_DUMP_FWSZ (48 * 1024)
 
+static void rtl871x_load_fw_fail(struct _adapter *adapter)
+{
+       struct usb_device *udev = adapter->dvobjpriv.pusbdev;
+       struct device *dev = &udev->dev;
+       struct device *parent = dev->parent;
+
+       complete(&adapter->rtl8712_fw_ready);
+
+       dev_err(&udev->dev, "r8712u: Firmware request failed\n");
+
+       if (parent)
+               device_lock(parent);
+
+       device_release_driver(dev);
+
+       if (parent)
+               device_unlock(parent);
+}
+
 static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
 {
        struct _adapter *adapter = context;
 
        if (!firmware) {
-               struct usb_device *udev = adapter->dvobjpriv.pusbdev;
-               struct usb_interface *usb_intf = adapter->pusb_intf;
-
-               dev_err(&udev->dev, "r8712u: Firmware request failed\n");
-               usb_put_dev(udev);
-               usb_set_intfdata(usb_intf, NULL);
-               r8712_free_drv_sw(adapter);
-               adapter->dvobj_deinit(adapter);
-               complete(&adapter->rtl8712_fw_ready);
-               free_netdev(adapter->pnetdev);
+               rtl871x_load_fw_fail(adapter);
                return;
        }
        adapter->fw = firmware;
index 5901026..d5fc902 100644 (file)
@@ -1820,3 +1820,11 @@ void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction)
                break;
        }
 }
+
+void r8712_flush_led_works(struct _adapter *padapter)
+{
+       struct led_priv *pledpriv = &padapter->ledpriv;
+
+       flush_work(&pledpriv->SwLed0.BlinkWorkItem);
+       flush_work(&pledpriv->SwLed1.BlinkWorkItem);
+}
index ee19c87..2f07681 100644 (file)
@@ -112,6 +112,7 @@ struct led_priv {
 void r8712_InitSwLeds(struct _adapter *padapter);
 void r8712_DeInitSwLeds(struct _adapter *padapter);
 void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction);
+void r8712_flush_led_works(struct _adapter *padapter);
 
 #endif
 
index 23cff43..cd6d9ff 100644 (file)
@@ -224,3 +224,11 @@ void r8712_unregister_cmd_alive(struct _adapter *padapter)
        }
        mutex_unlock(&pwrctrl->mutex_lock);
 }
+
+void r8712_flush_rwctrl_works(struct _adapter *padapter)
+{
+       struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
+
+       flush_work(&pwrctrl->SetPSModeWorkItem);
+       flush_work(&pwrctrl->rpwm_workitem);
+}
index bf6623c..b35b9c7 100644 (file)
@@ -108,5 +108,6 @@ void r8712_cpwm_int_hdl(struct _adapter *padapter,
 void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode,
                        uint smart_ps);
 void r8712_set_rpwm(struct _adapter *padapter, u8 val8);
+void r8712_flush_rwctrl_works(struct _adapter *padapter);
 
 #endif  /* __RTL871X_PWRCTRL_H_ */
index 2434b13..505ebeb 100644 (file)
@@ -591,35 +591,30 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf)
 {
        struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
        struct usb_device *udev = interface_to_usbdev(pusb_intf);
+       struct _adapter *padapter = netdev_priv(pnetdev);
+
+       /* never exit with a firmware callback pending */
+       wait_for_completion(&padapter->rtl8712_fw_ready);
+       usb_set_intfdata(pusb_intf, NULL);
+       release_firmware(padapter->fw);
+       if (drvpriv.drv_registered)
+               padapter->surprise_removed = true;
+       if (pnetdev->reg_state != NETREG_UNINITIALIZED)
+               unregister_netdev(pnetdev); /* will call netdev_close() */
+       r8712_flush_rwctrl_works(padapter);
+       r8712_flush_led_works(padapter);
+       udelay(1);
+       /* Stop driver mlme relation timer */
+       r8712_stop_drv_timers(padapter);
+       r871x_dev_unload(padapter);
+       r8712_free_drv_sw(padapter);
+       free_netdev(pnetdev);
+
+       /* decrease the reference count of the usb device structure
+        * when disconnect
+        */
+       usb_put_dev(udev);
 
-       if (pnetdev) {
-               struct _adapter *padapter = netdev_priv(pnetdev);
-
-               /* never exit with a firmware callback pending */
-               wait_for_completion(&padapter->rtl8712_fw_ready);
-               pnetdev = usb_get_intfdata(pusb_intf);
-               usb_set_intfdata(pusb_intf, NULL);
-               if (!pnetdev)
-                       goto firmware_load_fail;
-               release_firmware(padapter->fw);
-               if (drvpriv.drv_registered)
-                       padapter->surprise_removed = true;
-               if (pnetdev->reg_state != NETREG_UNINITIALIZED)
-                       unregister_netdev(pnetdev); /* will call netdev_close() */
-               flush_scheduled_work();
-               udelay(1);
-               /* Stop driver mlme relation timer */
-               r8712_stop_drv_timers(padapter);
-               r871x_dev_unload(padapter);
-               r8712_free_drv_sw(padapter);
-               free_netdev(pnetdev);
-
-               /* decrease the reference count of the usb device structure
-                * when disconnect
-                */
-               usb_put_dev(udev);
-       }
-firmware_load_fail:
        /* If we didn't unplug usb dongle and remove/insert module, driver
         * fails on sitesurvey for the first time when device is up.
         * Reset usb port for sitesurvey fail issue.
index a884673..7eae820 100644 (file)
@@ -5,6 +5,7 @@ config RTL8723BS
        depends on m
        select WIRELESS_EXT
        select WEXT_PRIV
+       select CRYPTO_LIB_ARC4
        help
        This option enables support for RTL8723BS SDIO drivers, such as
        the wifi found on the 1st gen Intel Compute Stick, the CHIP
index 2dd251c..a545832 100644 (file)
@@ -909,6 +909,8 @@ void sd_int_dpc(struct adapter *adapter)
                                } else {
                                        rtw_c2h_wk_cmd(adapter, (u8 *)c2h_evt);
                                }
+                       } else {
+                               kfree(c2h_evt);
                        }
                } else {
                        /* Error handling for malloc fail */
index 6e6eb83..945f03d 100644 (file)
@@ -184,7 +184,7 @@ static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
        struct optee_msg_arg *ma;
 
        shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
-                           TEE_SHM_MAPPED);
+                           TEE_SHM_MAPPED | TEE_SHM_PRIV);
        if (IS_ERR(shm))
                return shm;
 
@@ -416,11 +416,13 @@ void optee_enable_shm_cache(struct optee *optee)
 }
 
 /**
- * optee_disable_shm_cache() - Disables caching of some shared memory allocation
- *                           in OP-TEE
+ * __optee_disable_shm_cache() - Disables caching of some shared memory
+ *                               allocation in OP-TEE
  * @optee:     main service struct
+ * @is_mapped: true if the cached shared memory addresses were mapped by this
+ *             kernel, are safe to dereference, and should be freed
  */
-void optee_disable_shm_cache(struct optee *optee)
+static void __optee_disable_shm_cache(struct optee *optee, bool is_mapped)
 {
        struct optee_call_waiter w;
 
@@ -439,6 +441,13 @@ void optee_disable_shm_cache(struct optee *optee)
                if (res.result.status == OPTEE_SMC_RETURN_OK) {
                        struct tee_shm *shm;
 
+                       /*
+                        * Shared memory references that were not mapped by
+                        * this kernel must be ignored to prevent a crash.
+                        */
+                       if (!is_mapped)
+                               continue;
+
                        shm = reg_pair_to_ptr(res.result.shm_upper32,
                                              res.result.shm_lower32);
                        tee_shm_free(shm);
@@ -449,6 +458,27 @@ void optee_disable_shm_cache(struct optee *optee)
        optee_cq_wait_final(&optee->call_queue, &w);
 }
 
+/**
+ * optee_disable_shm_cache() - Disables caching of mapped shared memory
+ *                             allocations in OP-TEE
+ * @optee:     main service struct
+ */
+void optee_disable_shm_cache(struct optee *optee)
+{
+       return __optee_disable_shm_cache(optee, true);
+}
+
+/**
+ * optee_disable_unmapped_shm_cache() - Disables caching of shared memory
+ *                                      allocations in OP-TEE which are not
+ *                                      currently mapped
+ * @optee:     main service struct
+ */
+void optee_disable_unmapped_shm_cache(struct optee *optee)
+{
+       return __optee_disable_shm_cache(optee, false);
+}
+
 #define PAGELIST_ENTRIES_PER_PAGE                              \
        ((OPTEE_MSG_NONCONTIG_PAGE_SIZE / sizeof(u64)) - 1)
 
index ddb8f9e..5ce13b0 100644 (file)
@@ -6,6 +6,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/arm-smccc.h>
+#include <linux/crash_dump.h>
 #include <linux/errno.h>
 #include <linux/io.h>
 #include <linux/module.h>
@@ -277,7 +278,8 @@ static void optee_release(struct tee_context *ctx)
        if (!ctxdata)
                return;
 
-       shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED);
+       shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg),
+                           TEE_SHM_MAPPED | TEE_SHM_PRIV);
        if (!IS_ERR(shm)) {
                arg = tee_shm_get_va(shm, 0);
                /*
@@ -572,6 +574,13 @@ static optee_invoke_fn *get_invoke_func(struct device *dev)
        return ERR_PTR(-EINVAL);
 }
 
+/* optee_remove - Device Removal Routine
+ * @pdev: platform device information struct
+ *
+ * optee_remove is called by platform subsystem to alert the driver
+ * that it should release the device
+ */
+
 static int optee_remove(struct platform_device *pdev)
 {
        struct optee *optee = platform_get_drvdata(pdev);
@@ -602,6 +611,18 @@ static int optee_remove(struct platform_device *pdev)
        return 0;
 }
 
+/* optee_shutdown - Device Removal Routine
+ * @pdev: platform device information struct
+ *
+ * platform_shutdown is called by the platform subsystem to alert
+ * the driver that a shutdown, reboot, or kexec is happening and
+ * device must be disabled.
+ */
+static void optee_shutdown(struct platform_device *pdev)
+{
+       optee_disable_shm_cache(platform_get_drvdata(pdev));
+}
+
 static int optee_probe(struct platform_device *pdev)
 {
        optee_invoke_fn *invoke_fn;
@@ -612,6 +633,16 @@ static int optee_probe(struct platform_device *pdev)
        u32 sec_caps;
        int rc;
 
+       /*
+        * The kernel may have crashed at the same time that all available
+        * secure world threads were suspended and we cannot reschedule the
+        * suspended threads without access to the crashed kernel's wait_queue.
+        * Therefore, we cannot reliably initialize the OP-TEE driver in the
+        * kdump kernel.
+        */
+       if (is_kdump_kernel())
+               return -ENODEV;
+
        invoke_fn = get_invoke_func(&pdev->dev);
        if (IS_ERR(invoke_fn))
                return PTR_ERR(invoke_fn);
@@ -686,6 +717,15 @@ static int optee_probe(struct platform_device *pdev)
        optee->memremaped_shm = memremaped_shm;
        optee->pool = pool;
 
+       /*
+        * Ensure that there are no pre-existing shm objects before enabling
+        * the shm cache so that there's no chance of receiving an invalid
+        * address during shutdown. This could occur, for example, if we're
+        * kexec booting from an older kernel that did not properly cleanup the
+        * shm cache.
+        */
+       optee_disable_unmapped_shm_cache(optee);
+
        optee_enable_shm_cache(optee);
 
        if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM)
@@ -728,6 +768,7 @@ MODULE_DEVICE_TABLE(of, optee_dt_match);
 static struct platform_driver optee_driver = {
        .probe  = optee_probe,
        .remove = optee_remove,
+       .shutdown = optee_shutdown,
        .driver = {
                .name = "optee",
                .of_match_table = optee_dt_match,
index e25b216..dbdd367 100644 (file)
@@ -159,6 +159,7 @@ int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);
 
 void optee_enable_shm_cache(struct optee *optee);
 void optee_disable_shm_cache(struct optee *optee);
+void optee_disable_unmapped_shm_cache(struct optee *optee);
 
 int optee_shm_register(struct tee_context *ctx, struct tee_shm *shm,
                       struct page **pages, size_t num_pages,
index 1849180..efbaff7 100644 (file)
@@ -314,7 +314,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
                shm = cmd_alloc_suppl(ctx, sz);
                break;
        case OPTEE_RPC_SHM_TYPE_KERNEL:
-               shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
+               shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
                break;
        default:
                arg->ret = TEEC_ERROR_BAD_PARAMETERS;
@@ -502,7 +502,8 @@ void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param,
 
        switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
        case OPTEE_SMC_RPC_FUNC_ALLOC:
-               shm = tee_shm_alloc(ctx, param->a1, TEE_SHM_MAPPED);
+               shm = tee_shm_alloc(ctx, param->a1,
+                                   TEE_SHM_MAPPED | TEE_SHM_PRIV);
                if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
                        reg_pair_from_64(&param->a1, &param->a2, pa);
                        reg_pair_from_64(&param->a4, &param->a5,
index d767eeb..c41a9a5 100644 (file)
@@ -27,13 +27,19 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
        shm->paddr = page_to_phys(page);
        shm->size = PAGE_SIZE << order;
 
-       if (shm->flags & TEE_SHM_DMA_BUF) {
+       /*
+        * Shared memory private to the OP-TEE driver doesn't need
+        * to be registered with OP-TEE.
+        */
+       if (!(shm->flags & TEE_SHM_PRIV)) {
                unsigned int nr_pages = 1 << order, i;
                struct page **pages;
 
                pages = kcalloc(nr_pages, sizeof(pages), GFP_KERNEL);
-               if (!pages)
-                       return -ENOMEM;
+               if (!pages) {
+                       rc = -ENOMEM;
+                       goto err;
+               }
 
                for (i = 0; i < nr_pages; i++) {
                        pages[i] = page;
@@ -44,15 +50,21 @@ static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
                rc = optee_shm_register(shm->ctx, shm, pages, nr_pages,
                                        (unsigned long)shm->kaddr);
                kfree(pages);
+               if (rc)
+                       goto err;
        }
 
+       return 0;
+
+err:
+       __free_pages(page, order);
        return rc;
 }
 
 static void pool_op_free(struct tee_shm_pool_mgr *poolm,
                         struct tee_shm *shm)
 {
-       if (shm->flags & TEE_SHM_DMA_BUF)
+       if (!(shm->flags & TEE_SHM_PRIV))
                optee_shm_unregister(shm->ctx, shm);
 
        free_pages((unsigned long)shm->kaddr, get_order(shm->size));
index 00472f5..8a9384a 100644 (file)
@@ -117,7 +117,7 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
                return ERR_PTR(-EINVAL);
        }
 
-       if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF))) {
+       if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) {
                dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
                return ERR_PTR(-EINVAL);
        }
@@ -193,6 +193,24 @@ err_dev_put:
 }
 EXPORT_SYMBOL_GPL(tee_shm_alloc);
 
+/**
+ * tee_shm_alloc_kernel_buf() - Allocate shared memory for kernel buffer
+ * @ctx:       Context that allocates the shared memory
+ * @size:      Requested size of shared memory
+ *
+ * The returned memory registered in secure world and is suitable to be
+ * passed as a memory buffer in parameter argument to
+ * tee_client_invoke_func(). The memory allocated is later freed with a
+ * call to tee_shm_free().
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
+{
+       return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED);
+}
+EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
+
 struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
                                 size_t length, u32 flags)
 {
index 83b1ef3..10d6b22 100644 (file)
@@ -1875,18 +1875,6 @@ static struct attribute *switch_attrs[] = {
        NULL,
 };
 
-static bool has_port(const struct tb_switch *sw, enum tb_port_type type)
-{
-       const struct tb_port *port;
-
-       tb_switch_for_each_port(sw, port) {
-               if (!port->disabled && port->config.type == type)
-                       return true;
-       }
-
-       return false;
-}
-
 static umode_t switch_attr_is_visible(struct kobject *kobj,
                                      struct attribute *attr, int n)
 {
@@ -1895,8 +1883,7 @@ static umode_t switch_attr_is_visible(struct kobject *kobj,
 
        if (attr == &dev_attr_authorized.attr) {
                if (sw->tb->security_level == TB_SECURITY_NOPCIE ||
-                   sw->tb->security_level == TB_SECURITY_DPONLY ||
-                   !has_port(sw, TB_TYPE_PCIE_UP))
+                   sw->tb->security_level == TB_SECURITY_DPONLY)
                        return 0;
        } else if (attr == &dev_attr_device.attr) {
                if (!sw->device)
index 4caab87..2350fb3 100644 (file)
@@ -329,6 +329,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
 {
        struct uart_8250_port *up = up_to_u8250p(port);
        unsigned int iir, lsr;
+       unsigned long flags;
        unsigned int space, count;
 
        iir = serial_port_in(port, UART_IIR);
@@ -336,7 +337,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
        if (iir & UART_IIR_NO_INT)
                return 0;
 
-       spin_lock(&port->lock);
+       spin_lock_irqsave(&port->lock, flags);
 
        lsr = serial_port_in(port, UART_LSR);
 
@@ -370,7 +371,7 @@ static int aspeed_vuart_handle_irq(struct uart_port *port)
        if (lsr & UART_LSR_THRE)
                serial8250_tx_chars(up);
 
-       uart_unlock_and_check_sysrq(port);
+       uart_unlock_and_check_sysrq_irqrestore(port, flags);
 
        return 1;
 }
index 4e75d2e..fc65a22 100644 (file)
@@ -30,10 +30,11 @@ struct fsl8250_data {
 int fsl8250_handle_irq(struct uart_port *port)
 {
        unsigned char lsr, orig_lsr;
+       unsigned long flags;
        unsigned int iir;
        struct uart_8250_port *up = up_to_u8250p(port);
 
-       spin_lock(&up->port.lock);
+       spin_lock_irqsave(&up->port.lock, flags);
 
        iir = port->serial_in(port, UART_IIR);
        if (iir & UART_IIR_NO_INT) {
@@ -82,7 +83,7 @@ int fsl8250_handle_irq(struct uart_port *port)
 
        up->lsr_saved_flags = orig_lsr;
 
-       uart_unlock_and_check_sysrq(&up->port);
+       uart_unlock_and_check_sysrq_irqrestore(&up->port, flags);
 
        return 1;
 }
index f7d3023..fb65dc6 100644 (file)
@@ -93,10 +93,13 @@ static void mtk8250_dma_rx_complete(void *param)
        struct dma_tx_state state;
        int copied, total, cnt;
        unsigned char *ptr;
+       unsigned long flags;
 
        if (data->rx_status == DMA_RX_SHUTDOWN)
                return;
 
+       spin_lock_irqsave(&up->port.lock, flags);
+
        dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state);
        total = dma->rx_size - state.residue;
        cnt = total;
@@ -120,6 +123,8 @@ static void mtk8250_dma_rx_complete(void *param)
        tty_flip_buffer_push(tty_port);
 
        mtk8250_rx_dma(up);
+
+       spin_unlock_irqrestore(&up->port.lock, flags);
 }
 
 static void mtk8250_rx_dma(struct uart_8250_port *up)
index 75827b6..a808c28 100644 (file)
@@ -3836,6 +3836,12 @@ static const struct pci_device_id blacklist[] = {
        { PCI_VDEVICE(INTEL, 0x0f0c), },
        { PCI_VDEVICE(INTEL, 0x228a), },
        { PCI_VDEVICE(INTEL, 0x228c), },
+       { PCI_VDEVICE(INTEL, 0x4b96), },
+       { PCI_VDEVICE(INTEL, 0x4b97), },
+       { PCI_VDEVICE(INTEL, 0x4b98), },
+       { PCI_VDEVICE(INTEL, 0x4b99), },
+       { PCI_VDEVICE(INTEL, 0x4b9a), },
+       { PCI_VDEVICE(INTEL, 0x4b9b), },
        { PCI_VDEVICE(INTEL, 0x9ce3), },
        { PCI_VDEVICE(INTEL, 0x9ce4), },
 
@@ -3996,6 +4002,7 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
                if (pci_match_id(pci_use_msi, dev)) {
                        dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n");
                        pci_set_master(dev);
+                       uart.port.flags &= ~UPF_SHARE_IRQ;
                        rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES);
                } else {
                        dev_dbg(&dev->dev, "Using legacy interrupts\n");
index 2164290..1da29a2 100644 (file)
@@ -311,7 +311,11 @@ static const struct serial8250_config uart_config[] = {
 /* Uart divisor latch read */
 static int default_serial_dl_read(struct uart_8250_port *up)
 {
-       return serial_in(up, UART_DLL) | serial_in(up, UART_DLM) << 8;
+       /* Assign these in pieces to truncate any bits above 7.  */
+       unsigned char dll = serial_in(up, UART_DLL);
+       unsigned char dlm = serial_in(up, UART_DLM);
+
+       return dll | dlm << 8;
 }
 
 /* Uart divisor latch write */
@@ -1297,9 +1301,11 @@ static void autoconfig(struct uart_8250_port *up)
        serial_out(up, UART_LCR, 0);
 
        serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
-       scratch = serial_in(up, UART_IIR) >> 6;
 
-       switch (scratch) {
+       /* Assign this as it is to truncate any bits above 7.  */
+       scratch = serial_in(up, UART_IIR);
+
+       switch (scratch >> 6) {
        case 0:
                autoconfig_8250(up);
                break;
@@ -1893,11 +1899,12 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
        unsigned char status;
        struct uart_8250_port *up = up_to_u8250p(port);
        bool skip_rx = false;
+       unsigned long flags;
 
        if (iir & UART_IIR_NO_INT)
                return 0;
 
-       spin_lock(&port->lock);
+       spin_lock_irqsave(&port->lock, flags);
 
        status = serial_port_in(port, UART_LSR);
 
@@ -1923,7 +1930,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir)
                (up->ier & UART_IER_THRI))
                serial8250_tx_chars(up);
 
-       uart_unlock_and_check_sysrq(port);
+       uart_unlock_and_check_sysrq_irqrestore(port, flags);
 
        return 1;
 }
index 508128d..f0e5da7 100644 (file)
@@ -1415,7 +1415,7 @@ static unsigned int lpuart_get_mctrl(struct uart_port *port)
 
 static unsigned int lpuart32_get_mctrl(struct uart_port *port)
 {
-       unsigned int mctrl = 0;
+       unsigned int mctrl = TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
        u32 reg;
 
        reg = lpuart32_read(port, UARTCTRL);
index 0c1e4df..ef11860 100644 (file)
@@ -1293,7 +1293,8 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
                freq = uartclk;
        if (freq == 0) {
                dev_err(dev, "Cannot get clock rate\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out_clk;
        }
 
        if (xtal) {
index 2220327..eba5b9e 100644 (file)
@@ -1045,9 +1045,11 @@ static int tegra_uart_hw_init(struct tegra_uart_port *tup)
 
        if (tup->cdata->fifo_mode_enable_status) {
                ret = tegra_uart_wait_fifo_mode_enabled(tup);
-               dev_err(tup->uport.dev, "FIFO mode not enabled\n");
-               if (ret < 0)
+               if (ret < 0) {
+                       dev_err(tup->uport.dev,
+                               "Failed to enable FIFO mode: %d\n", ret);
                        return ret;
+               }
        } else {
                /*
                 * For all tegra devices (up to t210), there is a hardware
index ef981d3..cb72393 100644 (file)
@@ -2059,7 +2059,7 @@ static void restore_cur(struct vc_data *vc)
 
 enum { ESnormal, ESesc, ESsquare, ESgetpars, ESfunckey,
        EShash, ESsetG0, ESsetG1, ESpercent, EScsiignore, ESnonstd,
-       ESpalette, ESosc };
+       ESpalette, ESosc, ESapc, ESpm, ESdcs };
 
 /* console_lock is held (except via vc_init()) */
 static void reset_terminal(struct vc_data *vc, int do_clear)
@@ -2133,20 +2133,28 @@ static void vc_setGx(struct vc_data *vc, unsigned int which, int c)
                vc->vc_translate = set_translate(*charset, vc);
 }
 
+/* is this state an ANSI control string? */
+static bool ansi_control_string(unsigned int state)
+{
+       if (state == ESosc || state == ESapc || state == ESpm || state == ESdcs)
+               return true;
+       return false;
+}
+
 /* console_lock is held */
 static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
 {
        /*
         *  Control characters can be used in the _middle_
-        *  of an escape sequence.
+        *  of an escape sequence, aside from ANSI control strings.
         */
-       if (vc->vc_state == ESosc && c>=8 && c<=13) /* ... except for OSC */
+       if (ansi_control_string(vc->vc_state) && c >= 8 && c <= 13)
                return;
        switch (c) {
        case 0:
                return;
        case 7:
-               if (vc->vc_state == ESosc)
+               if (ansi_control_string(vc->vc_state))
                        vc->vc_state = ESnormal;
                else if (vc->vc_bell_duration)
                        kd_mksound(vc->vc_bell_pitch, vc->vc_bell_duration);
@@ -2207,6 +2215,12 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                case ']':
                        vc->vc_state = ESnonstd;
                        return;
+               case '_':
+                       vc->vc_state = ESapc;
+                       return;
+               case '^':
+                       vc->vc_state = ESpm;
+                       return;
                case '%':
                        vc->vc_state = ESpercent;
                        return;
@@ -2224,6 +2238,9 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                        if (vc->state.x < VC_TABSTOPS_COUNT)
                                set_bit(vc->state.x, vc->vc_tab_stop);
                        return;
+               case 'P':
+                       vc->vc_state = ESdcs;
+                       return;
                case 'Z':
                        respond_ID(tty);
                        return;
@@ -2520,8 +2537,14 @@ static void do_con_trol(struct tty_struct *tty, struct vc_data *vc, int c)
                vc_setGx(vc, 1, c);
                vc->vc_state = ESnormal;
                return;
+       case ESapc:
+               return;
        case ESosc:
                return;
+       case ESpm:
+               return;
+       case ESdcs:
+               return;
        default:
                vc->vc_state = ESnormal;
        }
index 0e0cd9e..3639bb6 100644 (file)
@@ -246,6 +246,8 @@ int vt_waitactive(int n)
  *
  * XXX It should at least call into the driver, fbdev's definitely need to
  * restore their engine state. --BenH
+ *
+ * Called with the console lock held.
  */
 static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
 {
@@ -262,7 +264,6 @@ static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
                return -EINVAL;
        }
 
-       /* FIXME: this needs the console lock extending */
        if (vc->vc_mode == mode)
                return 0;
 
@@ -271,12 +272,10 @@ static int vt_kdsetmode(struct vc_data *vc, unsigned long mode)
                return 0;
 
        /* explicitly blank/unblank the screen if switching modes */
-       console_lock();
        if (mode == KD_TEXT)
                do_unblank_screen(1);
        else
                do_blank_screen(1);
-       console_unlock();
 
        return 0;
 }
@@ -378,7 +377,10 @@ static int vt_k_ioctl(struct tty_struct *tty, unsigned int cmd,
                if (!perm)
                        return -EPERM;
 
-               return vt_kdsetmode(vc, arg);
+               console_lock();
+               ret = vt_kdsetmode(vc, arg);
+               console_unlock();
+               return ret;
 
        case KDGETMODE:
                return put_user(vc->vc_mode, (int __user *)arg);
index 02ec7ab..e29989d 100644 (file)
@@ -731,6 +731,7 @@ static int cdns3_gadget_ep0_queue(struct usb_ep *ep,
                request->actual = 0;
                priv_dev->status_completion_no_call = true;
                priv_dev->pending_status_request = request;
+               usb_gadget_set_state(&priv_dev->gadget, USB_STATE_CONFIGURED);
                spin_unlock_irqrestore(&priv_dev->lock, flags);
 
                /*
index c23f53e..27df0c6 100644 (file)
@@ -1882,7 +1882,7 @@ static int __cdnsp_gadget_init(struct cdns *cdns)
        pdev->gadget.name = "cdnsp-gadget";
        pdev->gadget.speed = USB_SPEED_UNKNOWN;
        pdev->gadget.sg_supported = 1;
-       pdev->gadget.max_speed = USB_SPEED_SUPER_PLUS;
+       pdev->gadget.max_speed = max_speed;
        pdev->gadget.lpm_capable = 1;
 
        pdev->setup_buf = kzalloc(CDNSP_EP0_SETUP_SIZE, GFP_KERNEL);
index 783ca8f..f740fa6 100644 (file)
@@ -383,8 +383,8 @@ struct cdnsp_intr_reg {
 #define IMAN_IE                        BIT(1)
 #define IMAN_IP                        BIT(0)
 /* bits 2:31 need to be preserved */
-#define IMAN_IE_SET(p)         (((p) & IMAN_IE) | 0x2)
-#define IMAN_IE_CLEAR(p)       (((p) & IMAN_IE) & ~(0x2))
+#define IMAN_IE_SET(p)         ((p) | IMAN_IE)
+#define IMAN_IE_CLEAR(p)       ((p) & ~IMAN_IE)
 
 /* IMOD - Interrupter Moderation Register - irq_control bitmasks. */
 /*
index 6897274..1b14384 100644 (file)
@@ -1932,15 +1932,13 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
                }
 
                if (enqd_len + trb_buff_len >= full_len) {
-                       if (need_zero_pkt && zero_len_trb) {
-                               zero_len_trb = true;
-                       } else {
-                               field &= ~TRB_CHAIN;
-                               field |= TRB_IOC;
-                               more_trbs_coming = false;
-                               need_zero_pkt = false;
-                               preq->td.last_trb = ring->enqueue;
-                       }
+                       if (need_zero_pkt)
+                               zero_len_trb = !zero_len_trb;
+
+                       field &= ~TRB_CHAIN;
+                       field |= TRB_IOC;
+                       more_trbs_coming = false;
+                       preq->td.last_trb = ring->enqueue;
                }
 
                /* Only set interrupt on short packet for OUT endpoints. */
@@ -1955,7 +1953,7 @@ int cdnsp_queue_bulk_tx(struct cdnsp_device *pdev, struct cdnsp_request *preq)
                length_field = TRB_LEN(trb_buff_len) | TRB_TD_SIZE(remainder) |
                        TRB_INTR_TARGET(0);
 
-               cdnsp_queue_trb(pdev, ring, more_trbs_coming | need_zero_pkt,
+               cdnsp_queue_trb(pdev, ring, more_trbs_coming | zero_len_trb,
                                lower_32_bits(send_addr),
                                upper_32_bits(send_addr),
                                length_field,
index 74d5a9c..73f419a 100644 (file)
@@ -2324,17 +2324,10 @@ static void usbtmc_interrupt(struct urb *urb)
                dev_err(dev, "overflow with length %d, actual length is %d\n",
                        data->iin_wMaxPacketSize, urb->actual_length);
                fallthrough;
-       case -ECONNRESET:
-       case -ENOENT:
-       case -ESHUTDOWN:
-       case -EILSEQ:
-       case -ETIME:
-       case -EPIPE:
+       default:
                /* urb terminated, clean up */
                dev_dbg(dev, "urb terminated, status: %d\n", status);
                return;
-       default:
-               dev_err(dev, "unknown status received: %d\n", status);
        }
 exit:
        rv = usb_submit_urb(urb, GFP_ATOMIC);
index 3740cf9..0697fde 100644 (file)
@@ -193,7 +193,11 @@ static void otg_start_hnp_polling(struct otg_fsm *fsm)
        if (!fsm->host_req_flag)
                return;
 
-       INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work);
+       if (!fsm->hnp_work_inited) {
+               INIT_DELAYED_WORK(&fsm->hnp_polling_work, otg_hnp_polling_work);
+               fsm->hnp_work_inited = true;
+       }
+
        schedule_delayed_work(&fsm->hnp_polling_work,
                                        msecs_to_jiffies(T_HOST_REQ_POLL));
 }
index 45f2bc0..ccb68fe 100644 (file)
@@ -940,19 +940,19 @@ static struct dwc3_trb *dwc3_ep_prev_trb(struct dwc3_ep *dep, u8 index)
 
 static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
 {
-       struct dwc3_trb         *tmp;
        u8                      trbs_left;
 
        /*
-        * If enqueue & dequeue are equal than it is either full or empty.
-        *
-        * One way to know for sure is if the TRB right before us has HWO bit
-        * set or not. If it has, then we're definitely full and can't fit any
-        * more transfers in our ring.
+        * If the enqueue & dequeue are equal then the TRB ring is either full
+        * or empty. It's considered full when there are DWC3_TRB_NUM-1 of TRBs
+        * pending to be processed by the driver.
         */
        if (dep->trb_enqueue == dep->trb_dequeue) {
-               tmp = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
-               if (tmp->ctrl & DWC3_TRB_CTRL_HWO)
+               /*
+                * If there is any request remained in the started_list at
+                * this point, that means there is no TRB available.
+                */
+               if (!list_empty(&dep->started_list))
                        return 0;
 
                return DWC3_TRB_NUM - 1;
@@ -2243,10 +2243,19 @@ static int dwc3_gadget_pullup(struct usb_gadget *g, int is_on)
 
                ret = wait_for_completion_timeout(&dwc->ep0_in_setup,
                                msecs_to_jiffies(DWC3_PULL_UP_TIMEOUT));
-               if (ret == 0) {
-                       dev_err(dwc->dev, "timed out waiting for SETUP phase\n");
-                       return -ETIMEDOUT;
-               }
+               if (ret == 0)
+                       dev_warn(dwc->dev, "timed out waiting for SETUP phase\n");
+       }
+
+       /*
+        * Avoid issuing a runtime resume if the device is already in the
+        * suspended state during gadget disconnect.  DWC3 gadget was already
+        * halted/stopped during runtime suspend.
+        */
+       if (!is_on) {
+               pm_runtime_barrier(dwc->dev);
+               if (pm_runtime_suspended(dwc->dev))
+                       return 0;
        }
 
        /*
@@ -2447,6 +2456,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
        /* begin to receive SETUP packets */
        dwc->ep0state = EP0_SETUP_PHASE;
        dwc->link_state = DWC3_LINK_STATE_SS_DIS;
+       dwc->delayed_status = false;
        dwc3_ep0_out_start(dwc);
 
        dwc3_gadget_enable_irq(dwc);
index 02683ac..bb476e1 100644 (file)
@@ -41,6 +41,7 @@ struct f_hidg {
        unsigned char                   bInterfaceSubClass;
        unsigned char                   bInterfaceProtocol;
        unsigned char                   protocol;
+       unsigned char                   idle;
        unsigned short                  report_desc_length;
        char                            *report_desc;
        unsigned short                  report_length;
@@ -338,6 +339,11 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer,
 
        spin_lock_irqsave(&hidg->write_spinlock, flags);
 
+       if (!hidg->req) {
+               spin_unlock_irqrestore(&hidg->write_spinlock, flags);
+               return -ESHUTDOWN;
+       }
+
 #define WRITE_COND (!hidg->write_pending)
 try_again:
        /* write queue */
@@ -358,8 +364,14 @@ try_again:
        count  = min_t(unsigned, count, hidg->report_length);
 
        spin_unlock_irqrestore(&hidg->write_spinlock, flags);
-       status = copy_from_user(req->buf, buffer, count);
 
+       if (!req) {
+               ERROR(hidg->func.config->cdev, "hidg->req is NULL\n");
+               status = -ESHUTDOWN;
+               goto release_write_pending;
+       }
+
+       status = copy_from_user(req->buf, buffer, count);
        if (status != 0) {
                ERROR(hidg->func.config->cdev,
                        "copy_from_user error\n");
@@ -387,14 +399,17 @@ try_again:
 
        spin_unlock_irqrestore(&hidg->write_spinlock, flags);
 
+       if (!hidg->in_ep->enabled) {
+               ERROR(hidg->func.config->cdev, "in_ep is disabled\n");
+               status = -ESHUTDOWN;
+               goto release_write_pending;
+       }
+
        status = usb_ep_queue(hidg->in_ep, req, GFP_ATOMIC);
-       if (status < 0) {
-               ERROR(hidg->func.config->cdev,
-                       "usb_ep_queue error on int endpoint %zd\n", status);
+       if (status < 0)
                goto release_write_pending;
-       } else {
+       else
                status = count;
-       }
 
        return status;
 release_write_pending:
@@ -523,6 +538,14 @@ static int hidg_setup(struct usb_function *f,
                goto respond;
                break;
 
+       case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
+                 | HID_REQ_GET_IDLE):
+               VDBG(cdev, "get_idle\n");
+               length = min_t(unsigned int, length, 1);
+               ((u8 *) req->buf)[0] = hidg->idle;
+               goto respond;
+               break;
+
        case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
                  | HID_REQ_SET_REPORT):
                VDBG(cdev, "set_report | wLength=%d\n", ctrl->wLength);
@@ -546,6 +569,14 @@ static int hidg_setup(struct usb_function *f,
                goto stall;
                break;
 
+       case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8
+                 | HID_REQ_SET_IDLE):
+               VDBG(cdev, "set_idle\n");
+               length = 0;
+               hidg->idle = value >> 8;
+               goto respond;
+               break;
+
        case ((USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_INTERFACE) << 8
                  | USB_REQ_GET_DESCRIPTOR):
                switch (value >> 8) {
@@ -773,6 +804,7 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f)
        hidg_interface_desc.bInterfaceSubClass = hidg->bInterfaceSubClass;
        hidg_interface_desc.bInterfaceProtocol = hidg->bInterfaceProtocol;
        hidg->protocol = HID_REPORT_PROTOCOL;
+       hidg->idle = 1;
        hidg_ss_in_ep_desc.wMaxPacketSize = cpu_to_le16(hidg->report_length);
        hidg_ss_in_comp_desc.wBytesPerInterval =
                                cpu_to_le16(hidg->report_length);
index 018dd09..9e5c950 100644 (file)
@@ -230,7 +230,13 @@ static void u_audio_iso_fback_complete(struct usb_ep *ep,
        int status = req->status;
 
        /* i/f shutting down */
-       if (!prm->fb_ep_enabled || req->status == -ESHUTDOWN)
+       if (!prm->fb_ep_enabled) {
+               kfree(req->buf);
+               usb_ep_free_request(ep, req);
+               return;
+       }
+
+       if (req->status == -ESHUTDOWN)
                return;
 
        /*
@@ -388,8 +394,6 @@ static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep)
        if (!prm->ep_enabled)
                return;
 
-       prm->ep_enabled = false;
-
        audio_dev = uac->audio_dev;
        params = &audio_dev->params;
 
@@ -407,6 +411,8 @@ static inline void free_ep(struct uac_rtd_params *prm, struct usb_ep *ep)
                }
        }
 
+       prm->ep_enabled = false;
+
        if (usb_ep_disable(ep))
                dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
 }
@@ -418,15 +424,16 @@ static inline void free_ep_fback(struct uac_rtd_params *prm, struct usb_ep *ep)
        if (!prm->fb_ep_enabled)
                return;
 
-       prm->fb_ep_enabled = false;
-
        if (prm->req_fback) {
-               usb_ep_dequeue(ep, prm->req_fback);
-               kfree(prm->req_fback->buf);
-               usb_ep_free_request(ep, prm->req_fback);
+               if (usb_ep_dequeue(ep, prm->req_fback)) {
+                       kfree(prm->req_fback->buf);
+                       usb_ep_free_request(ep, prm->req_fback);
+               }
                prm->req_fback = NULL;
        }
 
+       prm->fb_ep_enabled = false;
+
        if (usb_ep_disable(ep))
                dev_err(uac->card->dev, "%s:%d Error!\n", __func__, __LINE__);
 }
index 34f4db5..d2a2b20 100644 (file)
@@ -1255,12 +1255,14 @@ static int max3420_probe(struct spi_device *spi)
        err = devm_request_irq(&spi->dev, irq, max3420_irq_handler, 0,
                               "max3420", udc);
        if (err < 0)
-               return err;
+               goto del_gadget;
 
        udc->thread_task = kthread_create(max3420_thread, udc,
                                          "max3420-thread");
-       if (IS_ERR(udc->thread_task))
-               return PTR_ERR(udc->thread_task);
+       if (IS_ERR(udc->thread_task)) {
+               err = PTR_ERR(udc->thread_task);
+               goto del_gadget;
+       }
 
        irq = of_irq_get_byname(spi->dev.of_node, "vbus");
        if (irq <= 0) { /* no vbus irq implies self-powered design */
@@ -1280,10 +1282,14 @@ static int max3420_probe(struct spi_device *spi)
                err = devm_request_irq(&spi->dev, irq,
                                       max3420_vbus_handler, 0, "vbus", udc);
                if (err < 0)
-                       return err;
+                       goto del_gadget;
        }
 
        return 0;
+
+del_gadget:
+       usb_del_gadget_udc(&udc->gadget);
+       return err;
 }
 
 static int max3420_remove(struct spi_device *spi)
index 9bbd7dd..a24aea3 100644 (file)
@@ -611,8 +611,6 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
        if (ohci_at91->wakeup)
                enable_irq_wake(hcd->irq);
 
-       ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
-
        ret = ohci_suspend(hcd, ohci_at91->wakeup);
        if (ret) {
                if (ohci_at91->wakeup)
@@ -632,7 +630,10 @@ ohci_hcd_at91_drv_suspend(struct device *dev)
                /* flush the writes */
                (void) ohci_readl (ohci, &ohci->regs->control);
                msleep(1);
+               ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
                at91_stop_clock(ohci_at91);
+       } else {
+               ohci_at91_port_suspend(ohci_at91->sfr_regmap, 1);
        }
 
        return ret;
@@ -644,6 +645,8 @@ ohci_hcd_at91_drv_resume(struct device *dev)
        struct usb_hcd  *hcd = dev_get_drvdata(dev);
        struct ohci_at91_priv *ohci_at91 = hcd_to_ohci_at91_priv(hcd);
 
+       ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0);
+
        if (ohci_at91->wakeup)
                disable_irq_wake(hcd->irq);
        else
@@ -651,8 +654,6 @@ ohci_hcd_at91_drv_resume(struct device *dev)
 
        ohci_resume(hcd, false);
 
-       ohci_at91_port_suspend(ohci_at91->sfr_regmap, 0);
-
        return 0;
 }
 
index 5923844..ef5e91a 100644 (file)
@@ -207,7 +207,8 @@ static int renesas_check_rom_state(struct pci_dev *pdev)
                        return 0;
 
                case RENESAS_ROM_STATUS_NO_RESULT: /* No result yet */
-                       return 0;
+                       dev_dbg(&pdev->dev, "Unknown ROM status ...\n");
+                       return -ENOENT;
 
                case RENESAS_ROM_STATUS_ERROR: /* Error State */
                default: /* All other states are marked as "Reserved states" */
@@ -224,14 +225,6 @@ static int renesas_fw_check_running(struct pci_dev *pdev)
        u8 fw_state;
        int err;
 
-       /* Check if device has ROM and loaded, if so skip everything */
-       err = renesas_check_rom(pdev);
-       if (err) { /* we have rom */
-               err = renesas_check_rom_state(pdev);
-               if (!err)
-                       return err;
-       }
-
        /*
         * Test if the device is actually needing the firmware. As most
         * BIOSes will initialize the device for us. If the device is
@@ -591,21 +584,39 @@ int renesas_xhci_check_request_fw(struct pci_dev *pdev,
                        (struct xhci_driver_data *)id->driver_data;
        const char *fw_name = driver_data->firmware;
        const struct firmware *fw;
+       bool has_rom;
        int err;
 
+       /* Check if device has ROM and loaded, if so skip everything */
+       has_rom = renesas_check_rom(pdev);
+       if (has_rom) {
+               err = renesas_check_rom_state(pdev);
+               if (!err)
+                       return 0;
+               else if (err != -ENOENT)
+                       has_rom = false;
+       }
+
        err = renesas_fw_check_running(pdev);
        /* Continue ahead, if the firmware is already running. */
        if (err == 0)
                return 0;
 
+       /* no firmware interface available */
        if (err != 1)
-               return err;
+               return has_rom ? 0 : err;
 
        pci_dev_get(pdev);
-       err = request_firmware(&fw, fw_name, &pdev->dev);
+       err = firmware_request_nowarn(&fw, fw_name, &pdev->dev);
        pci_dev_put(pdev);
        if (err) {
-               dev_err(&pdev->dev, "request_firmware failed: %d\n", err);
+               if (has_rom) {
+                       dev_info(&pdev->dev, "failed to load firmware %s, fallback to ROM\n",
+                                fw_name);
+                       return 0;
+               }
+               dev_err(&pdev->dev, "failed to load firmware %s: %d\n",
+                       fw_name, err);
                return err;
        }
 
index 640a46f..f086960 100644 (file)
@@ -35,6 +35,7 @@ struct omap2430_glue {
        struct device           *control_otghs;
        unsigned int            is_runtime_suspended:1;
        unsigned int            needs_resume:1;
+       unsigned int            phy_suspended:1;
 };
 #define glue_to_musb(g)                platform_get_drvdata(g->musb)
 
@@ -458,8 +459,10 @@ static int omap2430_runtime_suspend(struct device *dev)
 
        omap2430_low_level_exit(musb);
 
-       phy_power_off(musb->phy);
-       phy_exit(musb->phy);
+       if (!glue->phy_suspended) {
+               phy_power_off(musb->phy);
+               phy_exit(musb->phy);
+       }
 
        glue->is_runtime_suspended = 1;
 
@@ -474,8 +477,10 @@ static int omap2430_runtime_resume(struct device *dev)
        if (!musb)
                return 0;
 
-       phy_init(musb->phy);
-       phy_power_on(musb->phy);
+       if (!glue->phy_suspended) {
+               phy_init(musb->phy);
+               phy_power_on(musb->phy);
+       }
 
        omap2430_low_level_init(musb);
        musb_writel(musb->mregs, OTG_INTERFSEL,
@@ -489,7 +494,21 @@ static int omap2430_runtime_resume(struct device *dev)
        return 0;
 }
 
+/* I2C and SPI PHYs need to be suspended before the glue layer */
 static int omap2430_suspend(struct device *dev)
+{
+       struct omap2430_glue *glue = dev_get_drvdata(dev);
+       struct musb *musb = glue_to_musb(glue);
+
+       phy_power_off(musb->phy);
+       phy_exit(musb->phy);
+       glue->phy_suspended = 1;
+
+       return 0;
+}
+
+/* Glue layer needs to be suspended after musb_suspend() */
+static int omap2430_suspend_late(struct device *dev)
 {
        struct omap2430_glue *glue = dev_get_drvdata(dev);
 
@@ -501,7 +520,7 @@ static int omap2430_suspend(struct device *dev)
        return omap2430_runtime_suspend(dev);
 }
 
-static int omap2430_resume(struct device *dev)
+static int omap2430_resume_early(struct device *dev)
 {
        struct omap2430_glue *glue = dev_get_drvdata(dev);
 
@@ -513,10 +532,24 @@ static int omap2430_resume(struct device *dev)
        return omap2430_runtime_resume(dev);
 }
 
+static int omap2430_resume(struct device *dev)
+{
+       struct omap2430_glue *glue = dev_get_drvdata(dev);
+       struct musb *musb = glue_to_musb(glue);
+
+       phy_init(musb->phy);
+       phy_power_on(musb->phy);
+       glue->phy_suspended = 0;
+
+       return 0;
+}
+
 static const struct dev_pm_ops omap2430_pm_ops = {
        .runtime_suspend = omap2430_runtime_suspend,
        .runtime_resume = omap2430_runtime_resume,
        .suspend = omap2430_suspend,
+       .suspend_late = omap2430_suspend_late,
+       .resume_early = omap2430_resume_early,
        .resume = omap2430_resume,
 };
 
index 4a1f3a9..33bbb34 100644 (file)
@@ -219,6 +219,7 @@ static const struct usb_device_id id_table_combined[] = {
        { USB_DEVICE(FTDI_VID, FTDI_MTXORB_6_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_R2000KU_TRUE_RNG) },
        { USB_DEVICE(FTDI_VID, FTDI_VARDAAN_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_AUTO_M3_OP_COM_V2_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0100_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0101_PID) },
        { USB_DEVICE(MTXORB_VID, MTXORB_FTDI_RANGE_0102_PID) },
index add602b..755858c 100644 (file)
 /* Vardaan Enterprises Serial Interface VEUSB422R3 */
 #define FTDI_VARDAAN_PID       0xF070
 
+/* Auto-M3 Ltd. - OP-COM USB V2 - OBD interface Adapter */
+#define FTDI_AUTO_M3_OP_COM_V2_PID     0x4f50
+
 /*
  * Xsens Technologies BV products (http://www.xsens.com).
  */
index 0fbe253..29c765c 100644 (file)
@@ -1203,6 +1203,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(2) | RSVD(3) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1055, 0xff),    /* Telit FN980 (PCIe) */
          .driver_info = NCTRL(0) | RSVD(1) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1056, 0xff),    /* Telit FD980 */
+         .driver_info = NCTRL(2) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
          .driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
        { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
@@ -2072,6 +2074,8 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = RSVD(4) | RSVD(5) },
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x0105, 0xff),                     /* Fibocom NL678 series */
          .driver_info = RSVD(6) },
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0xff, 0x30) },    /* Fibocom FG150 Diag */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x2cb7, 0x010b, 0xff, 0, 0) },          /* Fibocom FG150 AT */
        { USB_DEVICE_INTERFACE_CLASS(0x2cb7, 0x01a0, 0xff) },                   /* Fibocom NL668-AM/NL652-EU (laptop MBIM) */
        { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) },                   /* LongSung M5710 */
        { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) },                   /* GosunCn GM500 RNDIS */
index 2f2f504..930b3d5 100644 (file)
@@ -418,24 +418,34 @@ static int pl2303_detect_type(struct usb_serial *serial)
        bcdDevice = le16_to_cpu(desc->bcdDevice);
        bcdUSB = le16_to_cpu(desc->bcdUSB);
 
-       switch (bcdDevice) {
-       case 0x100:
-               /*
-                * Assume it's an HXN-type if the device doesn't support the old read
-                * request value.
-                */
-               if (bcdUSB == 0x200 && !pl2303_supports_hx_status(serial))
-                       return TYPE_HXN;
+       switch (bcdUSB) {
+       case 0x110:
+               switch (bcdDevice) {
+               case 0x300:
+                       return TYPE_HX;
+               case 0x400:
+                       return TYPE_HXD;
+               default:
+                       return TYPE_HX;
+               }
                break;
-       case 0x300:
-               if (bcdUSB == 0x200)
+       case 0x200:
+               switch (bcdDevice) {
+               case 0x100:
+               case 0x305:
+                       /*
+                        * Assume it's an HXN-type if the device doesn't
+                        * support the old read request value.
+                        */
+                       if (!pl2303_supports_hx_status(serial))
+                               return TYPE_HXN;
+                       break;
+               case 0x300:
                        return TYPE_TA;
-
-               return TYPE_HX;
-       case 0x400:
-               return TYPE_HXD;
-       case 0x500:
-               return TYPE_TB;
+               case 0x500:
+                       return TYPE_TB;
+               }
+               break;
        }
 
        dev_err(&serial->interface->dev,
index 5b22a1c..5d05de6 100644 (file)
@@ -341,6 +341,7 @@ struct tcpm_port {
        bool vbus_source;
        bool vbus_charge;
 
+       /* Set to true when Discover_Identity Command is expected to be sent in Ready states. */
        bool send_discover;
        bool op_vsafe5v;
 
@@ -370,6 +371,7 @@ struct tcpm_port {
        struct hrtimer send_discover_timer;
        struct kthread_work send_discover_work;
        bool state_machine_running;
+       /* Set to true when VDM State Machine has following actions. */
        bool vdm_sm_running;
 
        struct completion tx_complete;
@@ -1431,6 +1433,7 @@ static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
        /* Set ready, vdm state machine will actually send */
        port->vdm_retries = 0;
        port->vdm_state = VDM_STATE_READY;
+       port->vdm_sm_running = true;
 
        mod_vdm_delayed_work(port, 0);
 }
@@ -1673,7 +1676,6 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
                                rlen = 1;
                        } else {
                                tcpm_register_partner_altmodes(port);
-                               port->vdm_sm_running = false;
                        }
                        break;
                case CMD_ENTER_MODE:
@@ -1721,14 +1723,12 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
                                      (VDO_SVDM_VERS(svdm_version));
                        break;
                }
-               port->vdm_sm_running = false;
                break;
        default:
                response[0] = p[0] | VDO_CMDT(CMDT_RSP_NAK);
                rlen = 1;
                response[0] = (response[0] & ~VDO_SVDM_VERS_MASK) |
                              (VDO_SVDM_VERS(svdm_version));
-               port->vdm_sm_running = false;
                break;
        }
 
@@ -1737,6 +1737,10 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
        return rlen;
 }
 
+static void tcpm_pd_handle_msg(struct tcpm_port *port,
+                              enum pd_msg_request message,
+                              enum tcpm_ams ams);
+
 static void tcpm_handle_vdm_request(struct tcpm_port *port,
                                    const __le32 *payload, int cnt)
 {
@@ -1764,11 +1768,25 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
                port->vdm_state = VDM_STATE_DONE;
        }
 
-       if (PD_VDO_SVDM(p[0])) {
+       if (PD_VDO_SVDM(p[0]) && (adev || tcpm_vdm_ams(port) || port->nr_snk_vdo)) {
+               /*
+                * Here a SVDM is received (INIT or RSP or unknown). Set the vdm_sm_running in
+                * advance because we are dropping the lock but may send VDMs soon.
+                * For the cases of INIT received:
+                *  - If no response to send, it will be cleared later in this function.
+                *  - If there are responses to send, it will be cleared in the state machine.
+                * For the cases of RSP received:
+                *  - If no further INIT to send, it will be cleared later in this function.
+                *  - Otherwise, it will be cleared in the state machine if timeout or it will go
+                *    back here until no further INIT to send.
+                * For the cases of unknown type received:
+                *  - We will send NAK and the flag will be cleared in the state machine.
+                */
+               port->vdm_sm_running = true;
                rlen = tcpm_pd_svdm(port, adev, p, cnt, response, &adev_action);
        } else {
                if (port->negotiated_rev >= PD_REV30)
-                       tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
+                       tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
        }
 
        /*
@@ -1833,6 +1851,8 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
 
        if (rlen > 0)
                tcpm_queue_vdm(port, response[0], &response[1], rlen - 1);
+       else
+               port->vdm_sm_running = false;
 }
 
 static void tcpm_send_vdm(struct tcpm_port *port, u32 vid, int cmd,
@@ -1898,8 +1918,10 @@ static void vdm_run_state_machine(struct tcpm_port *port)
                 * if there's traffic or we're not in PDO ready state don't send
                 * a VDM.
                 */
-               if (port->state != SRC_READY && port->state != SNK_READY)
+               if (port->state != SRC_READY && port->state != SNK_READY) {
+                       port->vdm_sm_running = false;
                        break;
+               }
 
                /* TODO: AMS operation for Unstructured VDM */
                if (PD_VDO_SVDM(vdo_hdr) && PD_VDO_CMDT(vdo_hdr) == CMDT_INIT) {
@@ -2471,10 +2493,7 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
                                           NONE_AMS);
                break;
        case PD_DATA_VENDOR_DEF:
-               if (tcpm_vdm_ams(port) || port->nr_snk_vdo)
-                       tcpm_handle_vdm_request(port, msg->payload, cnt);
-               else if (port->negotiated_rev > PD_REV20)
-                       tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
+               tcpm_handle_vdm_request(port, msg->payload, cnt);
                break;
        case PD_DATA_BIST:
                port->bist_request = le32_to_cpu(msg->payload[0]);
@@ -2555,10 +2574,6 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                                                                       TYPEC_PWR_MODE_PD,
                                                                       port->pps_data.active,
                                                                       port->supply_voltage);
-                               /* Set VDM running flag ASAP */
-                               if (port->data_role == TYPEC_HOST &&
-                                   port->send_discover)
-                                       port->vdm_sm_running = true;
                                tcpm_set_state(port, SNK_READY, 0);
                        } else {
                                /*
@@ -2596,14 +2611,10 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                switch (port->state) {
                case SNK_NEGOTIATE_CAPABILITIES:
                        /* USB PD specification, Figure 8-43 */
-                       if (port->explicit_contract) {
+                       if (port->explicit_contract)
                                next_state = SNK_READY;
-                               if (port->data_role == TYPEC_HOST &&
-                                   port->send_discover)
-                                       port->vdm_sm_running = true;
-                       } else {
+                       else
                                next_state = SNK_WAIT_CAPABILITIES;
-                       }
 
                        /* Threshold was relaxed before sending Request. Restore it back. */
                        tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_PD,
@@ -2618,10 +2629,6 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                        port->pps_status = (type == PD_CTRL_WAIT ?
                                            -EAGAIN : -EOPNOTSUPP);
 
-                       if (port->data_role == TYPEC_HOST &&
-                           port->send_discover)
-                               port->vdm_sm_running = true;
-
                        /* Threshold was relaxed before sending Request. Restore it back. */
                        tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_PD,
                                                               port->pps_data.active,
@@ -2697,10 +2704,6 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                        }
                        break;
                case DR_SWAP_SEND:
-                       if (port->data_role == TYPEC_DEVICE &&
-                           port->send_discover)
-                               port->vdm_sm_running = true;
-
                        tcpm_set_state(port, DR_SWAP_CHANGE_DR, 0);
                        break;
                case PR_SWAP_SEND:
@@ -2738,7 +2741,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                                           PD_MSG_CTRL_NOT_SUPP,
                                           NONE_AMS);
                } else {
-                       if (port->vdm_sm_running) {
+                       if (port->send_discover) {
                                tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
                                break;
                        }
@@ -2754,7 +2757,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                                           PD_MSG_CTRL_NOT_SUPP,
                                           NONE_AMS);
                } else {
-                       if (port->vdm_sm_running) {
+                       if (port->send_discover) {
                                tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
                                break;
                        }
@@ -2763,7 +2766,7 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
                }
                break;
        case PD_CTRL_VCONN_SWAP:
-               if (port->vdm_sm_running) {
+               if (port->send_discover) {
                        tcpm_queue_message(port, PD_MSG_CTRL_WAIT);
                        break;
                }
@@ -4479,18 +4482,20 @@ static void run_state_machine(struct tcpm_port *port)
        /* DR_Swap states */
        case DR_SWAP_SEND:
                tcpm_pd_send_control(port, PD_CTRL_DR_SWAP);
+               if (port->data_role == TYPEC_DEVICE || port->negotiated_rev > PD_REV20)
+                       port->send_discover = true;
                tcpm_set_state_cond(port, DR_SWAP_SEND_TIMEOUT,
                                    PD_T_SENDER_RESPONSE);
                break;
        case DR_SWAP_ACCEPT:
                tcpm_pd_send_control(port, PD_CTRL_ACCEPT);
-               /* Set VDM state machine running flag ASAP */
-               if (port->data_role == TYPEC_DEVICE && port->send_discover)
-                       port->vdm_sm_running = true;
+               if (port->data_role == TYPEC_DEVICE || port->negotiated_rev > PD_REV20)
+                       port->send_discover = true;
                tcpm_set_state_cond(port, DR_SWAP_CHANGE_DR, 0);
                break;
        case DR_SWAP_SEND_TIMEOUT:
                tcpm_swap_complete(port, -ETIMEDOUT);
+               port->send_discover = false;
                tcpm_ams_finish(port);
                tcpm_set_state(port, ready_state(port), 0);
                break;
@@ -4502,7 +4507,6 @@ static void run_state_machine(struct tcpm_port *port)
                } else {
                        tcpm_set_roles(port, true, port->pwr_role,
                                       TYPEC_HOST);
-                       port->send_discover = true;
                }
                tcpm_ams_finish(port);
                tcpm_set_state(port, ready_state(port), 0);
@@ -4645,8 +4649,6 @@ static void run_state_machine(struct tcpm_port *port)
                break;
        case VCONN_SWAP_SEND_TIMEOUT:
                tcpm_swap_complete(port, -ETIMEDOUT);
-               if (port->data_role == TYPEC_HOST && port->send_discover)
-                       port->vdm_sm_running = true;
                tcpm_set_state(port, ready_state(port), 0);
                break;
        case VCONN_SWAP_START:
@@ -4662,14 +4664,10 @@ static void run_state_machine(struct tcpm_port *port)
        case VCONN_SWAP_TURN_ON_VCONN:
                tcpm_set_vconn(port, true);
                tcpm_pd_send_control(port, PD_CTRL_PS_RDY);
-               if (port->data_role == TYPEC_HOST && port->send_discover)
-                       port->vdm_sm_running = true;
                tcpm_set_state(port, ready_state(port), 0);
                break;
        case VCONN_SWAP_TURN_OFF_VCONN:
                tcpm_set_vconn(port, false);
-               if (port->data_role == TYPEC_HOST && port->send_discover)
-                       port->vdm_sm_running = true;
                tcpm_set_state(port, ready_state(port), 0);
                break;
 
@@ -4677,8 +4675,6 @@ static void run_state_machine(struct tcpm_port *port)
        case PR_SWAP_CANCEL:
        case VCONN_SWAP_CANCEL:
                tcpm_swap_complete(port, port->swap_status);
-               if (port->data_role == TYPEC_HOST && port->send_discover)
-                       port->vdm_sm_running = true;
                if (port->pwr_role == TYPEC_SOURCE)
                        tcpm_set_state(port, SRC_READY, 0);
                else
@@ -5028,9 +5024,6 @@ static void _tcpm_pd_vbus_on(struct tcpm_port *port)
        switch (port->state) {
        case SNK_TRANSITION_SINK_VBUS:
                port->explicit_contract = true;
-               /* Set the VDM flag ASAP */
-               if (port->data_role == TYPEC_HOST && port->send_discover)
-                       port->vdm_sm_running = true;
                tcpm_set_state(port, SNK_READY, 0);
                break;
        case SNK_DISCOVERY:
@@ -5369,7 +5362,7 @@ EXPORT_SYMBOL_GPL(tcpm_pd_hard_reset);
 void tcpm_sink_frs(struct tcpm_port *port)
 {
        spin_lock(&port->pd_event_lock);
-       port->pd_events = TCPM_FRS_EVENT;
+       port->pd_events |= TCPM_FRS_EVENT;
        spin_unlock(&port->pd_event_lock);
        kthread_queue_work(port->wq, &port->event_work);
 }
@@ -5378,7 +5371,7 @@ EXPORT_SYMBOL_GPL(tcpm_sink_frs);
 void tcpm_sourcing_vbus(struct tcpm_port *port)
 {
        spin_lock(&port->pd_event_lock);
-       port->pd_events = TCPM_SOURCING_VBUS;
+       port->pd_events |= TCPM_SOURCING_VBUS;
        spin_unlock(&port->pd_event_lock);
        kthread_queue_work(port->wq, &port->event_work);
 }
@@ -5425,15 +5418,18 @@ static void tcpm_send_discover_work(struct kthread_work *work)
        if (!port->send_discover)
                goto unlock;
 
+       if (port->data_role == TYPEC_DEVICE && port->negotiated_rev < PD_REV30) {
+               port->send_discover = false;
+               goto unlock;
+       }
+
        /* Retry if the port is not idle */
        if ((port->state != SRC_READY && port->state != SNK_READY) || port->vdm_sm_running) {
                mod_send_discover_delayed_work(port, SEND_DISCOVER_RETRY_MS);
                goto unlock;
        }
 
-       /* Only send the Message if the port is host for PD rev2.0 */
-       if (port->data_role == TYPEC_HOST || port->negotiated_rev > PD_REV20)
-               tcpm_send_vdm(port, USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0);
+       tcpm_send_vdm(port, USB_SID_PD, CMD_DISCOVER_IDENT, NULL, 0);
 
 unlock:
        mutex_unlock(&port->lock);
index 21b78f1..351c6cf 100644 (file)
@@ -493,9 +493,9 @@ static int ifcvf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        adapter = vdpa_alloc_device(struct ifcvf_adapter, vdpa,
                                    dev, &ifc_vdpa_ops, NULL);
-       if (adapter == NULL) {
+       if (IS_ERR(adapter)) {
                IFCVF_ERR(pdev, "Failed to allocate vDPA structure");
-               return -ENOMEM;
+               return PTR_ERR(adapter);
        }
 
        pci_set_master(pdev);
index dcee603..e59135f 100644 (file)
@@ -512,11 +512,6 @@ out:
        mutex_unlock(&mr->mkey_mtx);
 }
 
-static bool map_empty(struct vhost_iotlb *iotlb)
-{
-       return !vhost_iotlb_itree_first(iotlb, 0, U64_MAX);
-}
-
 int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *iotlb,
                             bool *change_map)
 {
@@ -524,10 +519,6 @@ int mlx5_vdpa_handle_set_map(struct mlx5_vdpa_dev *mvdev, struct vhost_iotlb *io
        int err = 0;
 
        *change_map = false;
-       if (map_empty(iotlb)) {
-               mlx5_vdpa_destroy_mr(mvdev);
-               return 0;
-       }
        mutex_lock(&mr->mkey_mtx);
        if (mr->initialized) {
                mlx5_vdpa_info(mvdev, "memory map update\n");
index 2a31467..3cc12fc 100644 (file)
@@ -526,7 +526,6 @@ static int cq_create(struct mlx5_vdpa_net *ndev, u16 idx, u32 num_ent)
        void __iomem *uar_page = ndev->mvdev.res.uar->map;
        u32 out[MLX5_ST_SZ_DW(create_cq_out)];
        struct mlx5_vdpa_cq *vcq = &mvq->cq;
-       unsigned int irqn;
        __be64 *pas;
        int inlen;
        void *cqc;
@@ -566,7 +565,7 @@ static int cq_create(struct mlx5_vdpa_net *ndev, u16 idx, u32 num_ent)
        /* Use vector 0 by default. Consider adding code to choose least used
         * vector.
         */
-       err = mlx5_vector2eqn(mdev, 0, &eqn, &irqn);
+       err = mlx5_vector2eqn(mdev, 0, &eqn);
        if (err)
                goto err_vec;
 
@@ -753,12 +752,12 @@ static int get_queue_type(struct mlx5_vdpa_net *ndev)
        type_mask = MLX5_CAP_DEV_VDPA_EMULATION(ndev->mvdev.mdev, virtio_queue_type);
 
        /* prefer split queue */
-       if (type_mask & MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_PACKED)
-               return MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED;
+       if (type_mask & MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT)
+               return MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT;
 
-       WARN_ON(!(type_mask & MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT));
+       WARN_ON(!(type_mask & MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_PACKED));
 
-       return MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT;
+       return MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED;
 }
 
 static bool vq_is_tx(u16 idx)
@@ -2030,6 +2029,12 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name)
                return -ENOSPC;
 
        mdev = mgtdev->madev->mdev;
+       if (!(MLX5_CAP_DEV_VDPA_EMULATION(mdev, virtio_queue_type) &
+           MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT)) {
+               dev_warn(mdev->device, "missing support for split virtqueues\n");
+               return -EOPNOTSUPP;
+       }
+
        /* we save one virtqueue for control virtqueue should we require it */
        max_vqs = MLX5_CAP_DEV_VDPA_EMULATION(mdev, max_num_virtio_queues);
        max_vqs = min_t(u32, max_vqs, MLX5_MAX_SUPPORTED_VQS);
index 14e024d..c621cf7 100644 (file)
@@ -251,8 +251,10 @@ struct vdpasim *vdpasim_create(struct vdpasim_dev_attr *dev_attr)
 
        vdpasim = vdpa_alloc_device(struct vdpasim, vdpa, NULL, ops,
                                    dev_attr->name);
-       if (!vdpasim)
+       if (IS_ERR(vdpasim)) {
+               ret = PTR_ERR(vdpasim);
                goto err_alloc;
+       }
 
        vdpasim->dev_attr = *dev_attr;
        INIT_WORK(&vdpasim->work, dev_attr->work_fn);
index 7b4a639..fe05273 100644 (file)
@@ -436,9 +436,9 @@ static int vp_vdpa_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 
        vp_vdpa = vdpa_alloc_device(struct vp_vdpa, vdpa,
                                    dev, &vp_vdpa_ops, NULL);
-       if (vp_vdpa == NULL) {
+       if (IS_ERR(vp_vdpa)) {
                dev_err(dev, "vp_vdpa: Failed to allocate vDPA structure\n");
-               return -ENOMEM;
+               return PTR_ERR(vp_vdpa);
        }
 
        mdev = &vp_vdpa->mdev;
index 210ab35..9479f7f 100644 (file)
@@ -614,7 +614,8 @@ static int vhost_vdpa_process_iotlb_update(struct vhost_vdpa *v,
        long pinned;
        int ret = 0;
 
-       if (msg->iova < v->range.first ||
+       if (msg->iova < v->range.first || !msg->size ||
+           msg->iova > U64_MAX - msg->size + 1 ||
            msg->iova + msg->size - 1 > v->range.last)
                return -EINVAL;
 
index b9e853e..59edb5a 100644 (file)
@@ -735,10 +735,16 @@ static bool log_access_ok(void __user *log_base, u64 addr, unsigned long sz)
                         (sz + VHOST_PAGE_SIZE * 8 - 1) / VHOST_PAGE_SIZE / 8);
 }
 
+/* Make sure 64 bit math will not overflow. */
 static bool vhost_overflow(u64 uaddr, u64 size)
 {
-       /* Make sure 64 bit math will not overflow. */
-       return uaddr > ULONG_MAX || size > ULONG_MAX || uaddr > ULONG_MAX - size;
+       if (uaddr > ULONG_MAX || size > ULONG_MAX)
+               return true;
+
+       if (!size)
+               return false;
+
+       return uaddr > ULONG_MAX - size + 1;
 }
 
 /* Caller should have vq mutex and device mutex. */
index 4af8fa2..14e2043 100644 (file)
@@ -359,7 +359,7 @@ __vringh_iov(struct vringh *vrh, u16 i,
                        iov = wiov;
                else {
                        iov = riov;
-                       if (unlikely(wiov && wiov->i)) {
+                       if (unlikely(wiov && wiov->used)) {
                                vringh_bad("Readable desc %p after writable",
                                           &descs[i]);
                                err = -EINVAL;
index 0d002a3..fbc9f10 100644 (file)
@@ -64,6 +64,14 @@ int acrn_vm_destroy(struct acrn_vm *vm)
            test_and_set_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags))
                return 0;
 
+       ret = hcall_destroy_vm(vm->vmid);
+       if (ret < 0) {
+               dev_err(acrn_dev.this_device,
+                       "Failed to destroy VM %u\n", vm->vmid);
+               clear_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags);
+               return ret;
+       }
+
        /* Remove from global VM list */
        write_lock_bh(&acrn_vm_list_lock);
        list_del_init(&vm->list);
@@ -78,14 +86,6 @@ int acrn_vm_destroy(struct acrn_vm *vm)
                vm->monitor_page = NULL;
        }
 
-       ret = hcall_destroy_vm(vm->vmid);
-       if (ret < 0) {
-               dev_err(acrn_dev.this_device,
-                       "Failed to destroy VM %u\n", vm->vmid);
-               clear_bit(ACRN_VM_FLAG_DESTROYED, &vm->flags);
-               return ret;
-       }
-
        acrn_vm_all_ram_unmap(vm);
 
        dev_dbg(acrn_dev.this_device, "VM %u destroyed.\n", vm->vmid);
index 4b15c00..49984d2 100644 (file)
@@ -355,6 +355,7 @@ int register_virtio_device(struct virtio_device *dev)
        virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
 
        INIT_LIST_HEAD(&dev->vqs);
+       spin_lock_init(&dev->vqs_list_lock);
 
        /*
         * device_add() causes the bus infrastructure to look for a matching
index 09ed55d..b91bc81 100644 (file)
@@ -1242,12 +1242,19 @@ static void virtio_mem_online_page_cb(struct page *page, unsigned int order)
                        do_online = virtio_mem_bbm_get_bb_state(vm, id) !=
                                    VIRTIO_MEM_BBM_BB_FAKE_OFFLINE;
                }
+
+               /*
+                * virtio_mem_set_fake_offline() might sleep, we don't need
+                * the device anymore. See virtio_mem_remove() how races
+                * between memory onlining and device removal are handled.
+                */
+               rcu_read_unlock();
+
                if (do_online)
                        generic_online_page(page, order);
                else
                        virtio_mem_set_fake_offline(PFN_DOWN(addr), 1 << order,
                                                    false);
-               rcu_read_unlock();
                return;
        }
        rcu_read_unlock();
index 222d630..b35bb2d 100644 (file)
@@ -576,6 +576,13 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
        struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
        struct device *dev = get_device(&vp_dev->vdev.dev);
 
+       /*
+        * Device is marked broken on surprise removal so that virtio upper
+        * layers can abort any ongoing operation.
+        */
+       if (!pci_device_is_present(pci_dev))
+               virtio_break_device(&vp_dev->vdev);
+
        pci_disable_sriov(pci_dev);
 
        unregister_virtio_device(&vp_dev->vdev);
index 89bfe46..dd95dfd 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/hrtimer.h>
 #include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
 #include <xen/xen.h>
 
 #ifdef DEBUG
@@ -1755,7 +1756,9 @@ static struct virtqueue *vring_create_virtqueue_packed(
                        cpu_to_le16(vq->packed.event_flags_shadow);
        }
 
+       spin_lock(&vdev->vqs_list_lock);
        list_add_tail(&vq->vq.list, &vdev->vqs);
+       spin_unlock(&vdev->vqs_list_lock);
        return &vq->vq;
 
 err_desc_extra:
@@ -2229,7 +2232,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
        memset(vq->split.desc_state, 0, vring.num *
                        sizeof(struct vring_desc_state_split));
 
+       spin_lock(&vdev->vqs_list_lock);
        list_add_tail(&vq->vq.list, &vdev->vqs);
+       spin_unlock(&vdev->vqs_list_lock);
        return &vq->vq;
 
 err_extra:
@@ -2291,6 +2296,10 @@ void vring_del_virtqueue(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
 
+       spin_lock(&vq->vq.vdev->vqs_list_lock);
+       list_del(&_vq->list);
+       spin_unlock(&vq->vq.vdev->vqs_list_lock);
+
        if (vq->we_own_ring) {
                if (vq->packed_ring) {
                        vring_free_queue(vq->vq.vdev,
@@ -2321,7 +2330,6 @@ void vring_del_virtqueue(struct virtqueue *_vq)
                kfree(vq->split.desc_state);
                kfree(vq->split.desc_extra);
        }
-       list_del(&_vq->list);
        kfree(vq);
 }
 EXPORT_SYMBOL_GPL(vring_del_virtqueue);
@@ -2373,7 +2381,7 @@ bool virtqueue_is_broken(struct virtqueue *_vq)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
 
-       return vq->broken;
+       return READ_ONCE(vq->broken);
 }
 EXPORT_SYMBOL_GPL(virtqueue_is_broken);
 
@@ -2385,10 +2393,14 @@ void virtio_break_device(struct virtio_device *dev)
 {
        struct virtqueue *_vq;
 
+       spin_lock(&dev->vqs_list_lock);
        list_for_each_entry(_vq, &dev->vqs, list) {
                struct vring_virtqueue *vq = to_vvq(_vq);
-               vq->broken = true;
+
+               /* Pairs with READ_ONCE() in virtqueue_is_broken(). */
+               WRITE_ONCE(vq->broken, true);
        }
+       spin_unlock(&dev->vqs_list_lock);
 }
 EXPORT_SYMBOL_GPL(virtio_break_device);
 
index e1a1411..72eaef2 100644 (file)
@@ -151,6 +151,9 @@ virtio_vdpa_setup_vq(struct virtio_device *vdev, unsigned int index,
        if (!name)
                return NULL;
 
+       if (index >= vdpa->nvqs)
+               return ERR_PTR(-ENOENT);
+
        /* Queue shouldn't already be set up. */
        if (ops->get_vq_ready(vdpa, index))
                return ERR_PTR(-ENOENT);
index d7e361f..a78704a 100644 (file)
@@ -198,12 +198,12 @@ static void disable_dynirq(struct irq_data *data);
 
 static DEFINE_PER_CPU(unsigned int, irq_epoch);
 
-static void clear_evtchn_to_irq_row(unsigned row)
+static void clear_evtchn_to_irq_row(int *evtchn_row)
 {
        unsigned col;
 
        for (col = 0; col < EVTCHN_PER_ROW; col++)
-               WRITE_ONCE(evtchn_to_irq[row][col], -1);
+               WRITE_ONCE(evtchn_row[col], -1);
 }
 
 static void clear_evtchn_to_irq_all(void)
@@ -213,7 +213,7 @@ static void clear_evtchn_to_irq_all(void)
        for (row = 0; row < EVTCHN_ROW(xen_evtchn_max_channels()); row++) {
                if (evtchn_to_irq[row] == NULL)
                        continue;
-               clear_evtchn_to_irq_row(row);
+               clear_evtchn_to_irq_row(evtchn_to_irq[row]);
        }
 }
 
@@ -221,6 +221,7 @@ static int set_evtchn_to_irq(evtchn_port_t evtchn, unsigned int irq)
 {
        unsigned row;
        unsigned col;
+       int *evtchn_row;
 
        if (evtchn >= xen_evtchn_max_channels())
                return -EINVAL;
@@ -233,11 +234,18 @@ static int set_evtchn_to_irq(evtchn_port_t evtchn, unsigned int irq)
                if (irq == -1)
                        return 0;
 
-               evtchn_to_irq[row] = (int *)get_zeroed_page(GFP_KERNEL);
-               if (evtchn_to_irq[row] == NULL)
+               evtchn_row = (int *) __get_free_pages(GFP_KERNEL, 0);
+               if (evtchn_row == NULL)
                        return -ENOMEM;
 
-               clear_evtchn_to_irq_row(row);
+               clear_evtchn_to_irq_row(evtchn_row);
+
+               /*
+                * We've prepared an empty row for the mapping. If a different
+                * thread was faster inserting it, we can drop ours.
+                */
+               if (cmpxchg(&evtchn_to_irq[row], NULL, evtchn_row) != NULL)
+                       free_page((unsigned long) evtchn_row);
        }
 
        WRITE_ONCE(evtchn_to_irq[row][col], irq);
@@ -1009,7 +1017,7 @@ static void __unbind_from_irq(unsigned int irq)
 int xen_bind_pirq_gsi_to_irq(unsigned gsi,
                             unsigned pirq, int shareable, char *name)
 {
-       int irq = -1;
+       int irq;
        struct physdev_irq irq_op;
        int ret;
 
index 0117d86..bd5689f 100644 (file)
@@ -629,7 +629,7 @@ again:
         * inode has not been flagged as nocompress.  This flag can
         * change at any time if we discover bad compression ratios.
         */
-       if (nr_pages > 1 && inode_need_compress(BTRFS_I(inode), start, end)) {
+       if (inode_need_compress(BTRFS_I(inode), start, end)) {
                WARN_ON(pages);
                pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS);
                if (!pages) {
@@ -9226,8 +9226,14 @@ static int btrfs_rename_exchange(struct inode *old_dir,
        bool dest_log_pinned = false;
        bool need_abort = false;
 
-       /* we only allow rename subvolume link between subvolumes */
-       if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest)
+       /*
+        * For non-subvolumes allow exchange only within one subvolume, in the
+        * same inode namespace. Two subvolumes (represented as directory) can
+        * be exchanged as they're a logical link and have a fixed inode number.
+        */
+       if (root != dest &&
+           (old_ino != BTRFS_FIRST_FREE_OBJECTID ||
+            new_ino != BTRFS_FIRST_FREE_OBJECTID))
                return -EXDEV;
 
        /* close the race window with snapshot create/destroy ioctl */
index 7bdefd0..39db97f 100644 (file)
@@ -1743,7 +1743,11 @@ int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask,
 
 struct ceph_cap_flush *ceph_alloc_cap_flush(void)
 {
-       return kmem_cache_alloc(ceph_cap_flush_cachep, GFP_KERNEL);
+       struct ceph_cap_flush *cf;
+
+       cf = kmem_cache_alloc(ceph_cap_flush_cachep, GFP_KERNEL);
+       cf->is_capsnap = false;
+       return cf;
 }
 
 void ceph_free_cap_flush(struct ceph_cap_flush *cf)
@@ -1778,7 +1782,7 @@ static bool __detach_cap_flush_from_mdsc(struct ceph_mds_client *mdsc,
                prev->wake = true;
                wake = false;
        }
-       list_del(&cf->g_list);
+       list_del_init(&cf->g_list);
        return wake;
 }
 
@@ -1793,7 +1797,7 @@ static bool __detach_cap_flush_from_ci(struct ceph_inode_info *ci,
                prev->wake = true;
                wake = false;
        }
-       list_del(&cf->i_list);
+       list_del_init(&cf->i_list);
        return wake;
 }
 
@@ -2352,7 +2356,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
        ci->i_ceph_flags &= ~CEPH_I_KICK_FLUSH;
 
        list_for_each_entry_reverse(cf, &ci->i_cap_flush_list, i_list) {
-               if (!cf->caps) {
+               if (cf->is_capsnap) {
                        last_snap_flush = cf->tid;
                        break;
                }
@@ -2371,7 +2375,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
 
                first_tid = cf->tid + 1;
 
-               if (cf->caps) {
+               if (!cf->is_capsnap) {
                        struct cap_msg_args arg;
 
                        dout("kick_flushing_caps %p cap %p tid %llu %s\n",
@@ -3516,7 +3520,7 @@ static void handle_cap_flush_ack(struct inode *inode, u64 flush_tid,
                        cleaned = cf->caps;
 
                /* Is this a capsnap? */
-               if (cf->caps == 0)
+               if (cf->is_capsnap)
                        continue;
 
                if (cf->tid <= flush_tid) {
@@ -3589,8 +3593,9 @@ out:
        while (!list_empty(&to_remove)) {
                cf = list_first_entry(&to_remove,
                                      struct ceph_cap_flush, i_list);
-               list_del(&cf->i_list);
-               ceph_free_cap_flush(cf);
+               list_del_init(&cf->i_list);
+               if (!cf->is_capsnap)
+                       ceph_free_cap_flush(cf);
        }
 
        if (wake_ci)
@@ -4150,11 +4155,19 @@ bad:
 
 /*
  * Delayed work handler to process end of delayed cap release LRU list.
+ *
+ * If new caps are added to the list while processing it, these won't get
+ * processed in this run.  In this case, the ci->i_hold_caps_max will be
+ * returned so that the work can be scheduled accordingly.
  */
-void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
+unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
 {
        struct inode *inode;
        struct ceph_inode_info *ci;
+       struct ceph_mount_options *opt = mdsc->fsc->mount_options;
+       unsigned long delay_max = opt->caps_wanted_delay_max * HZ;
+       unsigned long loop_start = jiffies;
+       unsigned long delay = 0;
 
        dout("check_delayed_caps\n");
        spin_lock(&mdsc->cap_delay_lock);
@@ -4162,6 +4175,11 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
                ci = list_first_entry(&mdsc->cap_delay_list,
                                      struct ceph_inode_info,
                                      i_cap_delay_list);
+               if (time_before(loop_start, ci->i_hold_caps_max - delay_max)) {
+                       dout("%s caps added recently.  Exiting loop", __func__);
+                       delay = ci->i_hold_caps_max;
+                       break;
+               }
                if ((ci->i_ceph_flags & CEPH_I_FLUSH) == 0 &&
                    time_before(jiffies, ci->i_hold_caps_max))
                        break;
@@ -4177,6 +4195,8 @@ void ceph_check_delayed_caps(struct ceph_mds_client *mdsc)
                }
        }
        spin_unlock(&mdsc->cap_delay_lock);
+
+       return delay;
 }
 
 /*
index 9db1b39..0b69aec 100644 (file)
@@ -1616,7 +1616,7 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
                spin_lock(&mdsc->cap_dirty_lock);
 
                list_for_each_entry(cf, &to_remove, i_list)
-                       list_del(&cf->g_list);
+                       list_del_init(&cf->g_list);
 
                if (!list_empty(&ci->i_dirty_item)) {
                        pr_warn_ratelimited(
@@ -1668,8 +1668,9 @@ static int remove_session_caps_cb(struct inode *inode, struct ceph_cap *cap,
                struct ceph_cap_flush *cf;
                cf = list_first_entry(&to_remove,
                                      struct ceph_cap_flush, i_list);
-               list_del(&cf->i_list);
-               ceph_free_cap_flush(cf);
+               list_del_init(&cf->i_list);
+               if (!cf->is_capsnap)
+                       ceph_free_cap_flush(cf);
        }
 
        wake_up_all(&ci->i_cap_wq);
@@ -4490,22 +4491,29 @@ void inc_session_sequence(struct ceph_mds_session *s)
 }
 
 /*
- * delayed work -- periodically trim expired leases, renew caps with mds
+ * delayed work -- periodically trim expired leases, renew caps with mds.  If
+ * the @delay parameter is set to 0 or if it's more than 5 secs, the default
+ * workqueue delay value of 5 secs will be used.
  */
-static void schedule_delayed(struct ceph_mds_client *mdsc)
+static void schedule_delayed(struct ceph_mds_client *mdsc, unsigned long delay)
 {
-       int delay = 5;
-       unsigned hz = round_jiffies_relative(HZ * delay);
-       schedule_delayed_work(&mdsc->delayed_work, hz);
+       unsigned long max_delay = HZ * 5;
+
+       /* 5 secs default delay */
+       if (!delay || (delay > max_delay))
+               delay = max_delay;
+       schedule_delayed_work(&mdsc->delayed_work,
+                             round_jiffies_relative(delay));
 }
 
 static void delayed_work(struct work_struct *work)
 {
-       int i;
        struct ceph_mds_client *mdsc =
                container_of(work, struct ceph_mds_client, delayed_work.work);
+       unsigned long delay;
        int renew_interval;
        int renew_caps;
+       int i;
 
        dout("mdsc delayed_work\n");
 
@@ -4545,7 +4553,7 @@ static void delayed_work(struct work_struct *work)
        }
        mutex_unlock(&mdsc->mutex);
 
-       ceph_check_delayed_caps(mdsc);
+       delay = ceph_check_delayed_caps(mdsc);
 
        ceph_queue_cap_reclaim_work(mdsc);
 
@@ -4553,7 +4561,7 @@ static void delayed_work(struct work_struct *work)
 
        maybe_recover_session(mdsc);
 
-       schedule_delayed(mdsc);
+       schedule_delayed(mdsc, delay);
 }
 
 int ceph_mdsc_init(struct ceph_fs_client *fsc)
@@ -5030,7 +5038,7 @@ void ceph_mdsc_handle_mdsmap(struct ceph_mds_client *mdsc, struct ceph_msg *msg)
                          mdsc->mdsmap->m_epoch);
 
        mutex_unlock(&mdsc->mutex);
-       schedule_delayed(mdsc);
+       schedule_delayed(mdsc, 0);
        return;
 
 bad_unlock:
index abd9af7..3c444b9 100644 (file)
@@ -394,9 +394,11 @@ void ceph_mdsmap_destroy(struct ceph_mdsmap *m)
 {
        int i;
 
-       for (i = 0; i < m->possible_max_rank; i++)
-               kfree(m->m_info[i].export_targets);
-       kfree(m->m_info);
+       if (m->m_info) {
+               for (i = 0; i < m->possible_max_rank; i++)
+                       kfree(m->m_info[i].export_targets);
+               kfree(m->m_info);
+       }
        kfree(m->m_data_pg_pools);
        kfree(m);
 }
index 4ac0606..15105f9 100644 (file)
@@ -67,19 +67,19 @@ void ceph_get_snap_realm(struct ceph_mds_client *mdsc,
 {
        lockdep_assert_held(&mdsc->snap_rwsem);
 
-       dout("get_realm %p %d -> %d\n", realm,
-            atomic_read(&realm->nref), atomic_read(&realm->nref)+1);
        /*
-        * since we _only_ increment realm refs or empty the empty
-        * list with snap_rwsem held, adjusting the empty list here is
-        * safe.  we do need to protect against concurrent empty list
-        * additions, however.
+        * The 0->1 and 1->0 transitions must take the snap_empty_lock
+        * atomically with the refcount change. Go ahead and bump the
+        * nref here, unless it's 0, in which case we take the spinlock
+        * and then do the increment and remove it from the list.
         */
-       if (atomic_inc_return(&realm->nref) == 1) {
-               spin_lock(&mdsc->snap_empty_lock);
+       if (atomic_inc_not_zero(&realm->nref))
+               return;
+
+       spin_lock(&mdsc->snap_empty_lock);
+       if (atomic_inc_return(&realm->nref) == 1)
                list_del_init(&realm->empty_item);
-               spin_unlock(&mdsc->snap_empty_lock);
-       }
+       spin_unlock(&mdsc->snap_empty_lock);
 }
 
 static void __insert_snap_realm(struct rb_root *root,
@@ -208,28 +208,28 @@ static void __put_snap_realm(struct ceph_mds_client *mdsc,
 {
        lockdep_assert_held_write(&mdsc->snap_rwsem);
 
-       dout("__put_snap_realm %llx %p %d -> %d\n", realm->ino, realm,
-            atomic_read(&realm->nref), atomic_read(&realm->nref)-1);
+       /*
+        * We do not require the snap_empty_lock here, as any caller that
+        * increments the value must hold the snap_rwsem.
+        */
        if (atomic_dec_and_test(&realm->nref))
                __destroy_snap_realm(mdsc, realm);
 }
 
 /*
- * caller needn't hold any locks
+ * See comments in ceph_get_snap_realm. Caller needn't hold any locks.
  */
 void ceph_put_snap_realm(struct ceph_mds_client *mdsc,
                         struct ceph_snap_realm *realm)
 {
-       dout("put_snap_realm %llx %p %d -> %d\n", realm->ino, realm,
-            atomic_read(&realm->nref), atomic_read(&realm->nref)-1);
-       if (!atomic_dec_and_test(&realm->nref))
+       if (!atomic_dec_and_lock(&realm->nref, &mdsc->snap_empty_lock))
                return;
 
        if (down_write_trylock(&mdsc->snap_rwsem)) {
+               spin_unlock(&mdsc->snap_empty_lock);
                __destroy_snap_realm(mdsc, realm);
                up_write(&mdsc->snap_rwsem);
        } else {
-               spin_lock(&mdsc->snap_empty_lock);
                list_add(&realm->empty_item, &mdsc->snap_empty);
                spin_unlock(&mdsc->snap_empty_lock);
        }
@@ -487,6 +487,9 @@ static void ceph_queue_cap_snap(struct ceph_inode_info *ci)
                pr_err("ENOMEM allocating ceph_cap_snap on %p\n", inode);
                return;
        }
+       capsnap->cap_flush.is_capsnap = true;
+       INIT_LIST_HEAD(&capsnap->cap_flush.i_list);
+       INIT_LIST_HEAD(&capsnap->cap_flush.g_list);
 
        spin_lock(&ci->i_ceph_lock);
        used = __ceph_caps_used(ci);
index 6b6332a..b1a3636 100644 (file)
@@ -182,8 +182,9 @@ struct ceph_cap {
 
 struct ceph_cap_flush {
        u64 tid;
-       int caps; /* 0 means capsnap */
+       int caps;
        bool wake; /* wake up flush waiters when finish ? */
+       bool is_capsnap; /* true means capsnap */
        struct list_head g_list; // global
        struct list_head i_list; // per inode
 };
@@ -1167,7 +1168,7 @@ extern void ceph_flush_snaps(struct ceph_inode_info *ci,
 extern bool __ceph_should_report_size(struct ceph_inode_info *ci);
 extern void ceph_check_caps(struct ceph_inode_info *ci, int flags,
                            struct ceph_mds_session *session);
-extern void ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
+extern unsigned long ceph_check_delayed_caps(struct ceph_mds_client *mdsc);
 extern void ceph_flush_dirty_caps(struct ceph_mds_client *mdsc);
 extern int  ceph_drop_caps_for_unlink(struct inode *inode);
 extern int ceph_encode_inode_release(void **p, struct inode *inode,
index c0bfc2f..c6a9542 100644 (file)
@@ -1611,6 +1611,11 @@ struct dfs_info3_param {
        int ttl;
 };
 
+struct file_list {
+       struct list_head list;
+       struct cifsFileInfo *cfile;
+};
+
 /*
  * common struct for holding inode info when searching for or updating an
  * inode with new info
index 79402ca..5f8a302 100644 (file)
@@ -100,7 +100,7 @@ build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_USE_PREFIX_PATH)
                pplen = cifs_sb->prepath ? strlen(cifs_sb->prepath) + 1 : 0;
 
-       s = dentry_path_raw(direntry, page, PAGE_SIZE);
+       s = dentry_path_raw(direntry, page, PATH_MAX);
        if (IS_ERR(s))
                return s;
        if (!s[1])      // for root we want "", not "/"
index 0a72840..bb98fbd 100644 (file)
@@ -4847,17 +4847,6 @@ void cifs_oplock_break(struct work_struct *work)
                cifs_dbg(VFS, "Push locks rc = %d\n", rc);
 
 oplock_break_ack:
-       /*
-        * releasing stale oplock after recent reconnect of smb session using
-        * a now incorrect file handle is not a data integrity issue but do
-        * not bother sending an oplock release if session to server still is
-        * disconnected since oplock already released by the server
-        */
-       if (!cfile->oplock_break_cancelled) {
-               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
-                                                            cinode);
-               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
-       }
        /*
         * When oplock break is received and there are no active
         * file handles but cached, then schedule deferred close immediately.
@@ -4865,17 +4854,27 @@ oplock_break_ack:
         */
        spin_lock(&CIFS_I(inode)->deferred_lock);
        is_deferred = cifs_is_deferred_close(cfile, &dclose);
+       spin_unlock(&CIFS_I(inode)->deferred_lock);
        if (is_deferred &&
            cfile->deferred_close_scheduled &&
            delayed_work_pending(&cfile->deferred)) {
-               /*
-                * If there is no pending work, mod_delayed_work queues new work.
-                * So, Increase the ref count to avoid use-after-free.
-                */
-               if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
-                       cifsFileInfo_get(cfile);
+               if (cancel_delayed_work(&cfile->deferred)) {
+                       _cifsFileInfo_put(cfile, false, false);
+                       goto oplock_break_done;
+               }
        }
-       spin_unlock(&CIFS_I(inode)->deferred_lock);
+       /*
+        * releasing stale oplock after recent reconnect of smb session using
+        * a now incorrect file handle is not a data integrity issue but do
+        * not bother sending an oplock release if session to server still is
+        * disconnected since oplock already released by the server
+        */
+       if (!cfile->oplock_break_cancelled) {
+               rc = tcon->ses->server->ops->oplock_response(tcon, &cfile->fid,
+                                                            cinode);
+               cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
+       }
+oplock_break_done:
        _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
        cifs_done_oplock_break(cinode);
 }
index b96b253..65f8a70 100644 (file)
@@ -1625,7 +1625,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
                goto unlink_out;
        }
 
-       cifs_close_all_deferred_files(tcon);
+       cifs_close_deferred_file(CIFS_I(inode));
        if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                                le64_to_cpu(tcon->fsUnixInfo.Capability))) {
                rc = CIFSPOSIXDelFile(xid, tcon, full_path,
@@ -2084,6 +2084,7 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
        FILE_UNIX_BASIC_INFO *info_buf_target;
        unsigned int xid;
        int rc, tmprc;
+       int retry_count = 0;
 
        if (flags & ~RENAME_NOREPLACE)
                return -EINVAL;
@@ -2113,10 +2114,24 @@ cifs_rename2(struct user_namespace *mnt_userns, struct inode *source_dir,
                goto cifs_rename_exit;
        }
 
-       cifs_close_all_deferred_files(tcon);
+       cifs_close_deferred_file(CIFS_I(d_inode(source_dentry)));
+       if (d_inode(target_dentry) != NULL)
+               cifs_close_deferred_file(CIFS_I(d_inode(target_dentry)));
+
        rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
                            to_name);
 
+       if (rc == -EACCES) {
+               while (retry_count < 3) {
+                       cifs_close_all_deferred_files(tcon);
+                       rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
+                                           to_name);
+                       if (rc != -EACCES)
+                               break;
+                       retry_count++;
+               }
+       }
+
        /*
         * No-replace is the natural behavior for CIFS, so skip unlink hacks.
         */
index 844abeb..9469f1c 100644 (file)
@@ -723,13 +723,31 @@ void
 cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)
 {
        struct cifsFileInfo *cfile = NULL;
-       struct cifs_deferred_close *dclose;
+       struct file_list *tmp_list, *tmp_next_list;
+       struct list_head file_head;
+
+       if (cifs_inode == NULL)
+               return;
 
+       INIT_LIST_HEAD(&file_head);
+       spin_lock(&cifs_inode->open_file_lock);
        list_for_each_entry(cfile, &cifs_inode->openFileList, flist) {
-               spin_lock(&cifs_inode->deferred_lock);
-               if (cifs_is_deferred_close(cfile, &dclose))
-                       mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
-               spin_unlock(&cifs_inode->deferred_lock);
+               if (delayed_work_pending(&cfile->deferred)) {
+                       if (cancel_delayed_work(&cfile->deferred)) {
+                               tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
+                               if (tmp_list == NULL)
+                                       continue;
+                               tmp_list->cfile = cfile;
+                               list_add_tail(&tmp_list->list, &file_head);
+                       }
+               }
+       }
+       spin_unlock(&cifs_inode->open_file_lock);
+
+       list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
+               _cifsFileInfo_put(tmp_list->cfile, true, false);
+               list_del(&tmp_list->list);
+               kfree(tmp_list);
        }
 }
 
@@ -738,20 +756,30 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)
 {
        struct cifsFileInfo *cfile;
        struct list_head *tmp;
+       struct file_list *tmp_list, *tmp_next_list;
+       struct list_head file_head;
 
+       INIT_LIST_HEAD(&file_head);
        spin_lock(&tcon->open_file_lock);
        list_for_each(tmp, &tcon->openFileList) {
                cfile = list_entry(tmp, struct cifsFileInfo, tlist);
                if (delayed_work_pending(&cfile->deferred)) {
-                       /*
-                        * If there is no pending work, mod_delayed_work queues new work.
-                        * So, Increase the ref count to avoid use-after-free.
-                        */
-                       if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
-                               cifsFileInfo_get(cfile);
+                       if (cancel_delayed_work(&cfile->deferred)) {
+                               tmp_list = kmalloc(sizeof(struct file_list), GFP_ATOMIC);
+                               if (tmp_list == NULL)
+                                       continue;
+                               tmp_list->cfile = cfile;
+                               list_add_tail(&tmp_list->list, &file_head);
+                       }
                }
        }
        spin_unlock(&tcon->open_file_lock);
+
+       list_for_each_entry_safe(tmp_list, tmp_next_list, &file_head, list) {
+               _cifsFileInfo_put(tmp_list->cfile, true, false);
+               list_del(&tmp_list->list);
+               kfree(tmp_list);
+       }
 }
 
 /* parses DFS refferal V3 structure
index 781d14e..b6d2e35 100644 (file)
@@ -2426,7 +2426,7 @@ create_sd_buf(umode_t mode, bool set_owner, unsigned int *len)
        memcpy(aclptr, &acl, sizeof(struct cifs_acl));
 
        buf->ccontext.DataLength = cpu_to_le32(ptr - (__u8 *)&buf->sd);
-       *len = ptr - (__u8 *)buf;
+       *len = roundup(ptr - (__u8 *)buf, 8);
 
        return buf;
 }
index 5a0be99..0ad3215 100644 (file)
@@ -177,28 +177,22 @@ out:
        return retval;
 }
 
-/* Fill [buffer, buffer + pos) with data coming from @from. */
-static int fill_write_buffer(struct configfs_buffer *buffer, loff_t pos,
+/* Fill @buffer with data coming from @from. */
+static int fill_write_buffer(struct configfs_buffer *buffer,
                             struct iov_iter *from)
 {
-       loff_t to_copy;
        int copied;
-       u8 *to;
 
        if (!buffer->page)
                buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0);
        if (!buffer->page)
                return -ENOMEM;
 
-       to_copy = SIMPLE_ATTR_SIZE - 1 - pos;
-       if (to_copy <= 0)
-               return 0;
-       to = buffer->page + pos;
-       copied = copy_from_iter(to, to_copy, from);
+       copied = copy_from_iter(buffer->page, SIMPLE_ATTR_SIZE - 1, from);
        buffer->needs_read_fill = 1;
        /* if buf is assumed to contain a string, terminate it by \0,
         * so e.g. sscanf() can scan the string easily */
-       to[copied] = 0;
+       buffer->page[copied] = 0;
        return copied ? : -EFAULT;
 }
 
@@ -227,10 +221,10 @@ static ssize_t configfs_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct file *file = iocb->ki_filp;
        struct configfs_buffer *buffer = file->private_data;
-       ssize_t len;
+       int len;
 
        mutex_lock(&buffer->mutex);
-       len = fill_write_buffer(buffer, iocb->ki_pos, from);
+       len = fill_write_buffer(buffer, from);
        if (len > 0)
                len = flush_write_buffer(file, buffer, len);
        if (len > 0)
index da41f93..99b4e78 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -722,7 +722,7 @@ static int copy_cow_page_dax(struct block_device *bdev, struct dax_device *dax_d
                return rc;
 
        id = dax_read_lock();
-       rc = dax_direct_access(dax_dev, pgoff, PHYS_PFN(PAGE_SIZE), &kaddr, NULL);
+       rc = dax_direct_access(dax_dev, pgoff, 1, &kaddr, NULL);
        if (rc < 0) {
                dax_read_unlock(id);
                return rc;
index b96ecba..b60f015 100644 (file)
@@ -244,9 +244,6 @@ int __ext4_journal_get_write_access(const char *where, unsigned int line,
  * "bh" may be NULL: a metadata block may have been freed from memory
  * but there may still be a record of it in the journal, and that record
  * still needs to be revoked.
- *
- * If the handle isn't valid we're not journaling, but we still need to
- * call into ext4_journal_revoke() to put the buffer head.
  */
 int __ext4_forget(const char *where, unsigned int line, handle_t *handle,
                  int is_metadata, struct inode *inode,
index bc364c1..cebea42 100644 (file)
@@ -138,7 +138,7 @@ static int kmmpd(void *data)
        unsigned mmp_check_interval;
        unsigned long last_update_time;
        unsigned long diff;
-       int retval;
+       int retval = 0;
 
        mmp_block = le64_to_cpu(es->s_mmp_block);
        mmp = (struct mmp_struct *)(bh->b_data);
index 5fd56f6..f3bbcd4 100644 (file)
@@ -2517,7 +2517,7 @@ again:
                                goto journal_error;
                        err = ext4_handle_dirty_dx_node(handle, dir,
                                                        frame->bh);
-                       if (err)
+                       if (restart || err)
                                goto journal_error;
                } else {
                        struct dx_root *dxroot;
index e557237..9d58371 100644 (file)
@@ -1235,8 +1235,6 @@ void fuse_dax_conn_free(struct fuse_conn *fc)
 static int fuse_dax_mem_range_init(struct fuse_conn_dax *fcd)
 {
        long nr_pages, nr_ranges;
-       void *kaddr;
-       pfn_t pfn;
        struct fuse_dax_mapping *range;
        int ret, id;
        size_t dax_size = -1;
@@ -1248,8 +1246,8 @@ static int fuse_dax_mem_range_init(struct fuse_conn_dax *fcd)
        INIT_DELAYED_WORK(&fcd->free_work, fuse_dax_free_mem_worker);
 
        id = dax_read_lock();
-       nr_pages = dax_direct_access(fcd->dev, 0, PHYS_PFN(dax_size), &kaddr,
-                                    &pfn);
+       nr_pages = dax_direct_access(fcd->dev, 0, PHYS_PFN(dax_size), NULL,
+                                    NULL);
        dax_read_unlock(id);
        if (nr_pages < 0) {
                pr_debug("dax_direct_access() returned %ld\n", nr_pages);
index cf086b0..7d2ed8c 100644 (file)
@@ -129,7 +129,8 @@ struct io_cb_cancel_data {
        bool cancel_all;
 };
 
-static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index);
+static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index, bool first);
+static void io_wqe_dec_running(struct io_worker *worker);
 
 static bool io_worker_get(struct io_worker *worker)
 {
@@ -168,26 +169,21 @@ static void io_worker_exit(struct io_worker *worker)
 {
        struct io_wqe *wqe = worker->wqe;
        struct io_wqe_acct *acct = io_wqe_get_acct(worker);
-       unsigned flags;
 
        if (refcount_dec_and_test(&worker->ref))
                complete(&worker->ref_done);
        wait_for_completion(&worker->ref_done);
 
-       preempt_disable();
-       current->flags &= ~PF_IO_WORKER;
-       flags = worker->flags;
-       worker->flags = 0;
-       if (flags & IO_WORKER_F_RUNNING)
-               atomic_dec(&acct->nr_running);
-       worker->flags = 0;
-       preempt_enable();
-
        raw_spin_lock_irq(&wqe->lock);
-       if (flags & IO_WORKER_F_FREE)
+       if (worker->flags & IO_WORKER_F_FREE)
                hlist_nulls_del_rcu(&worker->nulls_node);
        list_del_rcu(&worker->all_list);
        acct->nr_workers--;
+       preempt_disable();
+       io_wqe_dec_running(worker);
+       worker->flags = 0;
+       current->flags &= ~PF_IO_WORKER;
+       preempt_enable();
        raw_spin_unlock_irq(&wqe->lock);
 
        kfree_rcu(worker, rcu);
@@ -214,15 +210,19 @@ static bool io_wqe_activate_free_worker(struct io_wqe *wqe)
        struct hlist_nulls_node *n;
        struct io_worker *worker;
 
-       n = rcu_dereference(hlist_nulls_first_rcu(&wqe->free_list));
-       if (is_a_nulls(n))
-               return false;
-
-       worker = hlist_nulls_entry(n, struct io_worker, nulls_node);
-       if (io_worker_get(worker)) {
-               wake_up_process(worker->task);
+       /*
+        * Iterate free_list and see if we can find an idle worker to
+        * activate. If a given worker is on the free_list but in the process
+        * of exiting, keep trying.
+        */
+       hlist_nulls_for_each_entry_rcu(worker, n, &wqe->free_list, nulls_node) {
+               if (!io_worker_get(worker))
+                       continue;
+               if (wake_up_process(worker->task)) {
+                       io_worker_release(worker);
+                       return true;
+               }
                io_worker_release(worker);
-               return true;
        }
 
        return false;
@@ -247,10 +247,21 @@ static void io_wqe_wake_worker(struct io_wqe *wqe, struct io_wqe_acct *acct)
        ret = io_wqe_activate_free_worker(wqe);
        rcu_read_unlock();
 
-       if (!ret && acct->nr_workers < acct->max_workers) {
-               atomic_inc(&acct->nr_running);
-               atomic_inc(&wqe->wq->worker_refs);
-               create_io_worker(wqe->wq, wqe, acct->index);
+       if (!ret) {
+               bool do_create = false, first = false;
+
+               raw_spin_lock_irq(&wqe->lock);
+               if (acct->nr_workers < acct->max_workers) {
+                       atomic_inc(&acct->nr_running);
+                       atomic_inc(&wqe->wq->worker_refs);
+                       if (!acct->nr_workers)
+                               first = true;
+                       acct->nr_workers++;
+                       do_create = true;
+               }
+               raw_spin_unlock_irq(&wqe->lock);
+               if (do_create)
+                       create_io_worker(wqe->wq, wqe, acct->index, first);
        }
 }
 
@@ -271,10 +282,28 @@ static void create_worker_cb(struct callback_head *cb)
 {
        struct create_worker_data *cwd;
        struct io_wq *wq;
+       struct io_wqe *wqe;
+       struct io_wqe_acct *acct;
+       bool do_create = false, first = false;
 
        cwd = container_of(cb, struct create_worker_data, work);
-       wq = cwd->wqe->wq;
-       create_io_worker(wq, cwd->wqe, cwd->index);
+       wqe = cwd->wqe;
+       wq = wqe->wq;
+       acct = &wqe->acct[cwd->index];
+       raw_spin_lock_irq(&wqe->lock);
+       if (acct->nr_workers < acct->max_workers) {
+               if (!acct->nr_workers)
+                       first = true;
+               acct->nr_workers++;
+               do_create = true;
+       }
+       raw_spin_unlock_irq(&wqe->lock);
+       if (do_create) {
+               create_io_worker(wq, wqe, cwd->index, first);
+       } else {
+               atomic_dec(&acct->nr_running);
+               io_worker_ref_put(wq);
+       }
        kfree(cwd);
 }
 
@@ -612,7 +641,7 @@ void io_wq_worker_sleeping(struct task_struct *tsk)
        raw_spin_unlock_irq(&worker->wqe->lock);
 }
 
-static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index)
+static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index, bool first)
 {
        struct io_wqe_acct *acct = &wqe->acct[index];
        struct io_worker *worker;
@@ -635,6 +664,9 @@ static void create_io_worker(struct io_wq *wq, struct io_wqe *wqe, int index)
                kfree(worker);
 fail:
                atomic_dec(&acct->nr_running);
+               raw_spin_lock_irq(&wqe->lock);
+               acct->nr_workers--;
+               raw_spin_unlock_irq(&wqe->lock);
                io_worker_ref_put(wq);
                return;
        }
@@ -650,9 +682,8 @@ fail:
        worker->flags |= IO_WORKER_F_FREE;
        if (index == IO_WQ_ACCT_BOUND)
                worker->flags |= IO_WORKER_F_BOUND;
-       if (!acct->nr_workers && (worker->flags & IO_WORKER_F_BOUND))
+       if (first && (worker->flags & IO_WORKER_F_BOUND))
                worker->flags |= IO_WORKER_F_FIXED;
-       acct->nr_workers++;
        raw_spin_unlock_irq(&wqe->lock);
        wake_up_new_task(tsk);
 }
index bf548af..a2e20a6 100644 (file)
@@ -78,6 +78,7 @@
 #include <linux/task_work.h>
 #include <linux/pagemap.h>
 #include <linux/io_uring.h>
+#include <linux/tracehook.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/io_uring.h>
@@ -1499,7 +1500,8 @@ static bool __io_cqring_overflow_flush(struct io_ring_ctx *ctx, bool force)
        all_flushed = list_empty(&ctx->cq_overflow_list);
        if (all_flushed) {
                clear_bit(0, &ctx->check_cq_overflow);
-               ctx->rings->sq_flags &= ~IORING_SQ_CQ_OVERFLOW;
+               WRITE_ONCE(ctx->rings->sq_flags,
+                          ctx->rings->sq_flags & ~IORING_SQ_CQ_OVERFLOW);
        }
 
        if (posted)
@@ -1578,7 +1580,9 @@ static bool io_cqring_event_overflow(struct io_ring_ctx *ctx, u64 user_data,
        }
        if (list_empty(&ctx->cq_overflow_list)) {
                set_bit(0, &ctx->check_cq_overflow);
-               ctx->rings->sq_flags |= IORING_SQ_CQ_OVERFLOW;
+               WRITE_ONCE(ctx->rings->sq_flags,
+                          ctx->rings->sq_flags | IORING_SQ_CQ_OVERFLOW);
+
        }
        ocqe->cqe.user_data = user_data;
        ocqe->cqe.res = res;
@@ -2222,9 +2226,9 @@ static inline unsigned int io_put_rw_kbuf(struct io_kiocb *req)
 
 static inline bool io_run_task_work(void)
 {
-       if (current->task_works) {
+       if (test_thread_flag(TIF_NOTIFY_SIGNAL) || current->task_works) {
                __set_current_state(TASK_RUNNING);
-               task_work_run();
+               tracehook_notify_signal();
                return true;
        }
 
@@ -2473,8 +2477,10 @@ static void io_fallback_req_func(struct work_struct *work)
        struct llist_node *node = llist_del_all(&ctx->fallback_llist);
        struct io_kiocb *req, *tmp;
 
+       percpu_ref_get(&ctx->refs);
        llist_for_each_entry_safe(req, tmp, node, io_task_work.fallback_node)
                req->io_task_work.func(req);
+       percpu_ref_put(&ctx->refs);
 }
 
 static void __io_complete_rw(struct io_kiocb *req, long res, long res2,
@@ -6803,14 +6809,16 @@ static inline void io_ring_set_wakeup_flag(struct io_ring_ctx *ctx)
 {
        /* Tell userspace we may need a wakeup call */
        spin_lock_irq(&ctx->completion_lock);
-       ctx->rings->sq_flags |= IORING_SQ_NEED_WAKEUP;
+       WRITE_ONCE(ctx->rings->sq_flags,
+                  ctx->rings->sq_flags | IORING_SQ_NEED_WAKEUP);
        spin_unlock_irq(&ctx->completion_lock);
 }
 
 static inline void io_ring_clear_wakeup_flag(struct io_ring_ctx *ctx)
 {
        spin_lock_irq(&ctx->completion_lock);
-       ctx->rings->sq_flags &= ~IORING_SQ_NEED_WAKEUP;
+       WRITE_ONCE(ctx->rings->sq_flags,
+                  ctx->rings->sq_flags & ~IORING_SQ_NEED_WAKEUP);
        spin_unlock_irq(&ctx->completion_lock);
 }
 
@@ -7132,16 +7140,6 @@ static void **io_alloc_page_table(size_t size)
        return table;
 }
 
-static inline void io_rsrc_ref_lock(struct io_ring_ctx *ctx)
-{
-       spin_lock_bh(&ctx->rsrc_ref_lock);
-}
-
-static inline void io_rsrc_ref_unlock(struct io_ring_ctx *ctx)
-{
-       spin_unlock_bh(&ctx->rsrc_ref_lock);
-}
-
 static void io_rsrc_node_destroy(struct io_rsrc_node *ref_node)
 {
        percpu_ref_exit(&ref_node->refs);
@@ -7158,9 +7156,9 @@ static void io_rsrc_node_switch(struct io_ring_ctx *ctx,
                struct io_rsrc_node *rsrc_node = ctx->rsrc_node;
 
                rsrc_node->rsrc_data = data_to_kill;
-               io_rsrc_ref_lock(ctx);
+               spin_lock_irq(&ctx->rsrc_ref_lock);
                list_add_tail(&rsrc_node->node, &ctx->rsrc_ref_list);
-               io_rsrc_ref_unlock(ctx);
+               spin_unlock_irq(&ctx->rsrc_ref_lock);
 
                atomic_inc(&data_to_kill->refs);
                percpu_ref_kill(&rsrc_node->refs);
@@ -7199,17 +7197,19 @@ static int io_rsrc_ref_quiesce(struct io_rsrc_data *data, struct io_ring_ctx *ct
                /* kill initial ref, already quiesced if zero */
                if (atomic_dec_and_test(&data->refs))
                        break;
+               mutex_unlock(&ctx->uring_lock);
                flush_delayed_work(&ctx->rsrc_put_work);
                ret = wait_for_completion_interruptible(&data->done);
-               if (!ret)
+               if (!ret) {
+                       mutex_lock(&ctx->uring_lock);
                        break;
+               }
 
                atomic_inc(&data->refs);
                /* wait for all works potentially completing data->done */
                flush_delayed_work(&ctx->rsrc_put_work);
                reinit_completion(&data->done);
 
-               mutex_unlock(&ctx->uring_lock);
                ret = io_run_task_work_sig();
                mutex_lock(&ctx->uring_lock);
        } while (ret >= 0);
@@ -7668,9 +7668,10 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref)
 {
        struct io_rsrc_node *node = container_of(ref, struct io_rsrc_node, refs);
        struct io_ring_ctx *ctx = node->rsrc_data->ctx;
+       unsigned long flags;
        bool first_add = false;
 
-       io_rsrc_ref_lock(ctx);
+       spin_lock_irqsave(&ctx->rsrc_ref_lock, flags);
        node->done = true;
 
        while (!list_empty(&ctx->rsrc_ref_list)) {
@@ -7682,7 +7683,7 @@ static void io_rsrc_node_ref_zero(struct percpu_ref *ref)
                list_del(&node->node);
                first_add |= llist_add(&node->llist, &ctx->rsrc_put_llist);
        }
-       io_rsrc_ref_unlock(ctx);
+       spin_unlock_irqrestore(&ctx->rsrc_ref_lock, flags);
 
        if (first_add)
                mod_delayed_work(system_wq, &ctx->rsrc_put_work, HZ);
@@ -8653,13 +8654,10 @@ static void io_req_caches_free(struct io_ring_ctx *ctx)
        mutex_unlock(&ctx->uring_lock);
 }
 
-static bool io_wait_rsrc_data(struct io_rsrc_data *data)
+static void io_wait_rsrc_data(struct io_rsrc_data *data)
 {
-       if (!data)
-               return false;
-       if (!atomic_dec_and_test(&data->refs))
+       if (data && !atomic_dec_and_test(&data->refs))
                wait_for_completion(&data->done);
-       return true;
 }
 
 static void io_ring_ctx_free(struct io_ring_ctx *ctx)
@@ -8671,10 +8669,14 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
                ctx->mm_account = NULL;
        }
 
+       /* __io_rsrc_put_work() may need uring_lock to progress, wait w/o it */
+       io_wait_rsrc_data(ctx->buf_data);
+       io_wait_rsrc_data(ctx->file_data);
+
        mutex_lock(&ctx->uring_lock);
-       if (io_wait_rsrc_data(ctx->buf_data))
+       if (ctx->buf_data)
                __io_sqe_buffers_unregister(ctx);
-       if (io_wait_rsrc_data(ctx->file_data))
+       if (ctx->file_data)
                __io_sqe_files_unregister(ctx);
        if (ctx->rings)
                __io_cqring_overflow_flush(ctx, true);
@@ -9370,9 +9372,10 @@ SYSCALL_DEFINE6(io_uring_enter, unsigned int, fd, u32, to_submit,
        if (ctx->flags & IORING_SETUP_SQPOLL) {
                io_cqring_overflow_flush(ctx, false);
 
-               ret = -EOWNERDEAD;
-               if (unlikely(ctx->sq_data->thread == NULL))
+               if (unlikely(ctx->sq_data->thread == NULL)) {
+                       ret = -EOWNERDEAD;
                        goto out;
+               }
                if (flags & IORING_ENTER_SQ_WAKEUP)
                        wake_up(&ctx->sq_data->wait);
                if (flags & IORING_ENTER_SQ_WAIT) {
@@ -9840,10 +9843,11 @@ static int io_register_personality(struct io_ring_ctx *ctx)
 
        ret = xa_alloc_cyclic(&ctx->personalities, &id, (void *)creds,
                        XA_LIMIT(0, USHRT_MAX), &ctx->pers_next, GFP_KERNEL);
-       if (!ret)
-               return id;
-       put_cred(creds);
-       return ret;
+       if (ret < 0) {
+               put_cred(creds);
+               return ret;
+       }
+       return id;
 }
 
 static int io_register_restrictions(struct io_ring_ctx *ctx, void __user *arg,
index ab4174a..97adcb5 100644 (file)
@@ -1716,8 +1716,12 @@ static inline bool may_mount(void)
 }
 
 #ifdef CONFIG_MANDATORY_FILE_LOCKING
-static inline bool may_mandlock(void)
+static bool may_mandlock(void)
 {
+       pr_warn_once("======================================================\n"
+                    "WARNING: the mand mount option is being deprecated and\n"
+                    "         will be removed in v5.15!\n"
+                    "======================================================\n");
        return capable(CAP_SYS_ADMIN);
 }
 #else
@@ -1938,6 +1942,20 @@ void drop_collected_mounts(struct vfsmount *mnt)
        namespace_unlock();
 }
 
+static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
+{
+       struct mount *child;
+
+       list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
+               if (!is_subdir(child->mnt_mountpoint, dentry))
+                       continue;
+
+               if (child->mnt.mnt_flags & MNT_LOCKED)
+                       return true;
+       }
+       return false;
+}
+
 /**
  * clone_private_mount - create a private clone of a path
  * @path: path to clone
@@ -1953,10 +1971,19 @@ struct vfsmount *clone_private_mount(const struct path *path)
        struct mount *old_mnt = real_mount(path->mnt);
        struct mount *new_mnt;
 
+       down_read(&namespace_sem);
        if (IS_MNT_UNBINDABLE(old_mnt))
-               return ERR_PTR(-EINVAL);
+               goto invalid;
+
+       if (!check_mnt(old_mnt))
+               goto invalid;
+
+       if (has_locked_children(old_mnt, path->dentry))
+               goto invalid;
 
        new_mnt = clone_mnt(old_mnt, path->dentry, CL_PRIVATE);
+       up_read(&namespace_sem);
+
        if (IS_ERR(new_mnt))
                return ERR_CAST(new_mnt);
 
@@ -1964,6 +1991,10 @@ struct vfsmount *clone_private_mount(const struct path *path)
        new_mnt->mnt_ns = MNT_NS_INTERNAL;
 
        return &new_mnt->mnt;
+
+invalid:
+       up_read(&namespace_sem);
+       return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL_GPL(clone_private_mount);
 
@@ -2315,19 +2346,6 @@ static int do_change_type(struct path *path, int ms_flags)
        return err;
 }
 
-static bool has_locked_children(struct mount *mnt, struct dentry *dentry)
-{
-       struct mount *child;
-       list_for_each_entry(child, &mnt->mnt_mounts, mnt_child) {
-               if (!is_subdir(child->mnt_mountpoint, dentry))
-                       continue;
-
-               if (child->mnt.mnt_flags & MNT_LOCKED)
-                       return true;
-       }
-       return false;
-}
-
 static struct mount *__do_loopback(struct path *old_path, int recurse)
 {
        struct mount *mnt = ERR_PTR(-EINVAL), *old = real_mount(old_path->mnt);
index 084a83b..6facdf4 100644 (file)
@@ -55,22 +55,27 @@ static int fanotify_max_queued_events __read_mostly;
 
 #include <linux/sysctl.h>
 
+static long ft_zero = 0;
+static long ft_int_max = INT_MAX;
+
 struct ctl_table fanotify_table[] = {
        {
                .procname       = "max_user_groups",
                .data   = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_GROUPS],
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ZERO,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &ft_zero,
+               .extra2         = &ft_int_max,
        },
        {
                .procname       = "max_user_marks",
                .data   = &init_user_ns.ucount_max[UCOUNT_FANOTIFY_MARKS],
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ZERO,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &ft_zero,
+               .extra2         = &ft_int_max,
        },
        {
                .procname       = "max_queued_events",
index 98f61b3..6205124 100644 (file)
@@ -55,22 +55,27 @@ struct kmem_cache *inotify_inode_mark_cachep __read_mostly;
 
 #include <linux/sysctl.h>
 
+static long it_zero = 0;
+static long it_int_max = INT_MAX;
+
 struct ctl_table inotify_table[] = {
        {
                .procname       = "max_user_instances",
                .data           = &init_user_ns.ucount_max[UCOUNT_INOTIFY_INSTANCES],
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ZERO,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &it_zero,
+               .extra2         = &it_int_max,
        },
        {
                .procname       = "max_user_watches",
                .data           = &init_user_ns.ucount_max[UCOUNT_INOTIFY_WATCHES],
-               .maxlen         = sizeof(int),
+               .maxlen         = sizeof(long),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ZERO,
+               .proc_handler   = proc_doulongvec_minmax,
+               .extra1         = &it_zero,
+               .extra2         = &it_int_max,
        },
        {
                .procname       = "max_queued_events",
index 41ebf52..ebde05c 100644 (file)
@@ -392,6 +392,7 @@ static struct dentry *ovl_lookup_real_one(struct dentry *connected,
         */
        take_dentry_name_snapshot(&name, real);
        this = lookup_one_len(name.name.name, connected, name.name.len);
+       release_dentry_name_snapshot(&name);
        err = PTR_ERR(this);
        if (IS_ERR(this)) {
                goto fail;
@@ -406,7 +407,6 @@ static struct dentry *ovl_lookup_real_one(struct dentry *connected,
        }
 
 out:
-       release_dentry_name_snapshot(&name);
        dput(parent);
        inode_unlock(dir);
        return this;
index 4d53d3b..d081faa 100644 (file)
@@ -392,6 +392,51 @@ out_unlock:
        return ret;
 }
 
+/*
+ * Calling iter_file_splice_write() directly from overlay's f_op may deadlock
+ * due to lock order inversion between pipe->mutex in iter_file_splice_write()
+ * and file_start_write(real.file) in ovl_write_iter().
+ *
+ * So do everything ovl_write_iter() does and call iter_file_splice_write() on
+ * the real file.
+ */
+static ssize_t ovl_splice_write(struct pipe_inode_info *pipe, struct file *out,
+                               loff_t *ppos, size_t len, unsigned int flags)
+{
+       struct fd real;
+       const struct cred *old_cred;
+       struct inode *inode = file_inode(out);
+       struct inode *realinode = ovl_inode_real(inode);
+       ssize_t ret;
+
+       inode_lock(inode);
+       /* Update mode */
+       ovl_copyattr(realinode, inode);
+       ret = file_remove_privs(out);
+       if (ret)
+               goto out_unlock;
+
+       ret = ovl_real_fdget(out, &real);
+       if (ret)
+               goto out_unlock;
+
+       old_cred = ovl_override_creds(inode->i_sb);
+       file_start_write(real.file);
+
+       ret = iter_file_splice_write(pipe, real.file, ppos, len, flags);
+
+       file_end_write(real.file);
+       /* Update size */
+       ovl_copyattr(realinode, inode);
+       revert_creds(old_cred);
+       fdput(real);
+
+out_unlock:
+       inode_unlock(inode);
+
+       return ret;
+}
+
 static int ovl_fsync(struct file *file, loff_t start, loff_t end, int datasync)
 {
        struct fd real;
@@ -603,7 +648,7 @@ const struct file_operations ovl_file_operations = {
        .fadvise        = ovl_fadvise,
        .flush          = ovl_flush,
        .splice_read    = generic_file_splice_read,
-       .splice_write   = iter_file_splice_write,
+       .splice_write   = ovl_splice_write,
 
        .copy_file_range        = ovl_copy_file_range,
        .remap_file_range       = ovl_remap_file_range,
index e8ad2c2..150fdf3 100644 (file)
@@ -481,6 +481,8 @@ static int ovl_cache_update_ino(struct path *path, struct ovl_cache_entry *p)
        }
        this = lookup_one_len(p->name, dir, p->len);
        if (IS_ERR_OR_NULL(this) || !this->d_inode) {
+               /* Mark a stale entry */
+               p->is_whiteout = true;
                if (IS_ERR(this)) {
                        err = PTR_ERR(this);
                        this = NULL;
@@ -776,6 +778,9 @@ static int ovl_iterate(struct file *file, struct dir_context *ctx)
                                if (err)
                                        goto out;
                        }
+               }
+               /* ovl_cache_update_ino() sets is_whiteout on stale entry */
+               if (!p->is_whiteout) {
                        if (!dir_emit(ctx, p->name, p->len, p->ino, p->type))
                                break;
                }
index 8e6ef62..6d4342b 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -363,10 +363,9 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                 * _very_ unlikely case that the pipe was full, but we got
                 * no data.
                 */
-               if (unlikely(was_full)) {
+               if (unlikely(was_full))
                        wake_up_interruptible_sync_poll(&pipe->wr_wait, EPOLLOUT | EPOLLWRNORM);
-                       kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
-               }
+               kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
 
                /*
                 * But because we didn't read anything, at this point we can
@@ -385,12 +384,11 @@ pipe_read(struct kiocb *iocb, struct iov_iter *to)
                wake_next_reader = false;
        __pipe_unlock(pipe);
 
-       if (was_full) {
+       if (was_full)
                wake_up_interruptible_sync_poll(&pipe->wr_wait, EPOLLOUT | EPOLLWRNORM);
-               kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
-       }
        if (wake_next_reader)
                wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM);
+       kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT);
        if (ret > 0)
                file_accessed(filp);
        return ret;
@@ -444,9 +442,6 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
 #endif
 
        /*
-        * Epoll nonsensically wants a wakeup whether the pipe
-        * was already empty or not.
-        *
         * If it wasn't empty we try to merge new data into
         * the last buffer.
         *
@@ -455,9 +450,9 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
         * spanning multiple pages.
         */
        head = pipe->head;
-       was_empty = true;
+       was_empty = pipe_empty(head, pipe->tail);
        chars = total_len & (PAGE_SIZE-1);
-       if (chars && !pipe_empty(head, pipe->tail)) {
+       if (chars && !was_empty) {
                unsigned int mask = pipe->ring_size - 1;
                struct pipe_buffer *buf = &pipe->bufs[(head - 1) & mask];
                int offset = buf->offset + buf->len;
@@ -568,10 +563,9 @@ pipe_write(struct kiocb *iocb, struct iov_iter *from)
                 * become empty while we dropped the lock.
                 */
                __pipe_unlock(pipe);
-               if (was_empty) {
+               if (was_empty)
                        wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM);
-                       kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
-               }
+               kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
                wait_event_interruptible_exclusive(pipe->wr_wait, pipe_writable(pipe));
                __pipe_lock(pipe);
                was_empty = pipe_empty(pipe->head, pipe->tail);
@@ -590,11 +584,13 @@ out:
         * This is particularly important for small writes, because of
         * how (for example) the GNU make jobserver uses small writes to
         * wake up pending jobs
+        *
+        * Epoll nonsensically wants a wakeup whether the pipe
+        * was already empty or not.
         */
-       if (was_empty) {
+       if (was_empty || pipe->poll_usage)
                wake_up_interruptible_sync_poll(&pipe->rd_wait, EPOLLIN | EPOLLRDNORM);
-               kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
-       }
+       kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
        if (wake_next_writer)
                wake_up_interruptible_sync_poll(&pipe->wr_wait, EPOLLOUT | EPOLLWRNORM);
        if (ret > 0 && sb_start_write_trylock(file_inode(filp)->i_sb)) {
@@ -654,6 +650,9 @@ pipe_poll(struct file *filp, poll_table *wait)
        struct pipe_inode_info *pipe = filp->private_data;
        unsigned int head, tail;
 
+       /* Epoll has some historical nasty semantics, this enables them */
+       pipe->poll_usage = 1;
+
        /*
         * Reading pipe state only -- no need for acquiring the semaphore.
         *
index 1732541..62669b3 100644 (file)
                NOINSTR_TEXT                                            \
                *(.text..refcount)                                      \
                *(.ref.text)                                            \
+               *(.text.asan.* .text.tsan.*)                            \
                TEXT_CFI_JT                                             \
        MEM_KEEP(init.text*)                                            \
        MEM_KEEP(exit.text*)                                            \
index 8b77d08..6c9b10d 100644 (file)
@@ -201,8 +201,8 @@ static inline void bpf_cgroup_storage_unset(void)
 {
        int i;
 
-       for (i = 0; i < BPF_CGROUP_STORAGE_NEST_MAX; i++) {
-               if (unlikely(this_cpu_read(bpf_cgroup_storage_info[i].task) != current))
+       for (i = BPF_CGROUP_STORAGE_NEST_MAX - 1; i >= 0; i--) {
+               if (likely(this_cpu_read(bpf_cgroup_storage_info[i].task) != current))
                        continue;
 
                this_cpu_write(bpf_cgroup_storage_info[i].task, NULL);
index 59940f1..65d84b6 100644 (file)
@@ -407,6 +407,7 @@ struct dev_links_info {
  * @em_pd:     device's energy model performance domain
  * @pins:      For device pin management.
  *             See Documentation/driver-api/pin-control.rst for details.
+ * @msi_lock:  Lock to protect MSI mask cache and mask register
  * @msi_list:  Hosts MSI descriptors
  * @msi_domain: The generic MSI domain this device is using.
  * @numa_node: NUMA node this device is close to.
@@ -506,6 +507,7 @@ struct device {
        struct dev_pin_info     *pins;
 #endif
 #ifdef CONFIG_GENERIC_MSI_IRQ
+       raw_spinlock_t          msi_lock;
        struct list_head        msi_list;
 #endif
 #ifdef CONFIG_DMA_OPS
index 53aa034..aaf4f1b 100644 (file)
@@ -41,7 +41,7 @@ struct in_device {
        unsigned long           mr_qri;         /* Query Response Interval */
        unsigned char           mr_qrv;         /* Query Robustness Variable */
        unsigned char           mr_gq_running;
-       unsigned char           mr_ifc_count;
+       u32                     mr_ifc_count;
        struct timer_list       mr_gq_timer;    /* general query timer */
        struct timer_list       mr_ifc_timer;   /* interface change timer */
 
index 8e9a9ae..c8293c8 100644 (file)
@@ -569,6 +569,7 @@ struct irq_chip {
  * IRQCHIP_SUPPORTS_NMI:              Chip can deliver NMIs, only for root irqchips
  * IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND:  Invokes __enable_irq()/__disable_irq() for wake irqs
  *                                    in the suspend path if they are in disabled state
+ * IRQCHIP_AFFINITY_PRE_STARTUP:      Default affinity update before startup
  */
 enum {
        IRQCHIP_SET_TYPE_MASKED                 = (1 <<  0),
@@ -581,6 +582,7 @@ enum {
        IRQCHIP_SUPPORTS_LEVEL_MSI              = (1 <<  7),
        IRQCHIP_SUPPORTS_NMI                    = (1 <<  8),
        IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND        = (1 <<  9),
+       IRQCHIP_AFFINITY_PRE_STARTUP            = (1 << 10),
 };
 
 #include <linux/irqdesc.h>
index a70d1ea..3fe6dd8 100644 (file)
@@ -51,10 +51,11 @@ extern atomic_t kfence_allocation_gate;
 static __always_inline bool is_kfence_address(const void *addr)
 {
        /*
-        * The non-NULL check is required in case the __kfence_pool pointer was
-        * never initialized; keep it in the slow-path after the range-check.
+        * The __kfence_pool != NULL check is required to deal with the case
+        * where __kfence_pool == NULL && addr < KFENCE_POOL_SIZE. Keep it in
+        * the slow-path after the range-check!
         */
-       return unlikely((unsigned long)((char *)addr - __kfence_pool) < KFENCE_POOL_SIZE && addr);
+       return unlikely((unsigned long)((char *)addr - __kfence_pool) < KFENCE_POOL_SIZE && __kfence_pool);
 }
 
 /**
index bfe5c48..2479792 100644 (file)
@@ -612,12 +612,15 @@ static inline bool mem_cgroup_disabled(void)
        return !cgroup_subsys_enabled(memory_cgrp_subsys);
 }
 
-static inline unsigned long mem_cgroup_protection(struct mem_cgroup *root,
-                                                 struct mem_cgroup *memcg,
-                                                 bool in_low_reclaim)
+static inline void mem_cgroup_protection(struct mem_cgroup *root,
+                                        struct mem_cgroup *memcg,
+                                        unsigned long *min,
+                                        unsigned long *low)
 {
+       *min = *low = 0;
+
        if (mem_cgroup_disabled())
-               return 0;
+               return;
 
        /*
         * There is no reclaim protection applied to a targeted reclaim.
@@ -653,13 +656,10 @@ static inline unsigned long mem_cgroup_protection(struct mem_cgroup *root,
         *
         */
        if (root == memcg)
-               return 0;
-
-       if (in_low_reclaim)
-               return READ_ONCE(memcg->memory.emin);
+               return;
 
-       return max(READ_ONCE(memcg->memory.emin),
-                  READ_ONCE(memcg->memory.elow));
+       *min = READ_ONCE(memcg->memory.emin);
+       *low = READ_ONCE(memcg->memory.elow);
 }
 
 void mem_cgroup_calculate_protection(struct mem_cgroup *root,
@@ -1147,11 +1147,12 @@ static inline void memcg_memory_event_mm(struct mm_struct *mm,
 {
 }
 
-static inline unsigned long mem_cgroup_protection(struct mem_cgroup *root,
-                                                 struct mem_cgroup *memcg,
-                                                 bool in_low_reclaim)
+static inline void mem_cgroup_protection(struct mem_cgroup *root,
+                                        struct mem_cgroup *memcg,
+                                        unsigned long *min,
+                                        unsigned long *low)
 {
-       return 0;
+       *min = *low = 0;
 }
 
 static inline void mem_cgroup_calculate_protection(struct mem_cgroup *root,
index 5e08468..944aa3a 100644 (file)
@@ -719,13 +719,8 @@ void mhi_device_put(struct mhi_device *mhi_dev);
  *                            host and device execution environments match and
  *                            channels are in a DISABLED state.
  * @mhi_dev: Device associated with the channels
- * @flags: MHI channel flags
  */
-int mhi_prepare_for_transfer(struct mhi_device *mhi_dev,
-                            unsigned int flags);
-
-/* Automatically allocate and queue inbound buffers */
-#define MHI_CH_INBOUND_ALLOC_BUFS BIT(0)
+int mhi_prepare_for_transfer(struct mhi_device *mhi_dev);
 
 /**
  * mhi_unprepare_from_transfer - Reset UL and DL channels for data transfer.
index 1efe374..25a8be5 100644 (file)
@@ -1044,8 +1044,7 @@ void mlx5_unregister_debugfs(void);
 void mlx5_fill_page_array(struct mlx5_frag_buf *buf, __be64 *pas);
 void mlx5_fill_page_frag_array_perm(struct mlx5_frag_buf *buf, __be64 *pas, u8 perm);
 void mlx5_fill_page_frag_array(struct mlx5_frag_buf *frag_buf, __be64 *pas);
-int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn,
-                   unsigned int *irqn);
+int mlx5_vector2eqn(struct mlx5_core_dev *dev, int vector, int *eqn);
 int mlx5_core_attach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn);
 int mlx5_core_detach_mcg(struct mlx5_core_dev *dev, union ib_gid *mgid, u32 qpn);
 
index 98b56b7..1a9c9d9 100644 (file)
@@ -11,13 +11,15 @@ enum {
 };
 
 enum {
-       MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT   = 0x1, // do I check this caps?
-       MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_PACKED  = 0x2,
+       MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT   = 0,
+       MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED  = 1,
 };
 
 enum {
-       MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT   = 0,
-       MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED  = 1,
+       MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_SPLIT =
+               BIT(MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_SPLIT),
+       MLX5_VIRTIO_EMULATION_CAP_VIRTIO_QUEUE_TYPE_PACKED =
+               BIT(MLX5_VIRTIO_EMULATION_VIRTIO_QUEUE_TYPE_PACKED),
 };
 
 struct mlx5_ifc_virtio_q_bits {
index 6aff469..e8bdcb8 100644 (file)
@@ -233,7 +233,7 @@ void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 
 u32 __pci_msix_desc_mask_irq(struct msi_desc *desc, u32 flag);
-u32 __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
+void __pci_msi_desc_mask_irq(struct msi_desc *desc, u32 mask, u32 flag);
 void pci_msi_mask_irq(struct irq_data *data);
 void pci_msi_unmask_irq(struct irq_data *data);
 
index 10279c4..ada1296 100644 (file)
@@ -196,6 +196,9 @@ struct ip_set_region {
        u32 elements;           /* Number of elements vs timeout */
 };
 
+/* Max range where every element is added/deleted in one step */
+#define IPSET_MAX_RANGE                (1<<20)
+
 /* The max revision number supported by any set type + 1 */
 #define IPSET_REVISION_MAX     9
 
index 9225ee6..ae6f4eb 100644 (file)
@@ -7,7 +7,7 @@
 
 bool __do_once_start(bool *done, unsigned long *flags);
 void __do_once_done(bool *done, struct static_key_true *once_key,
-                   unsigned long *flags);
+                   unsigned long *flags, struct module *mod);
 
 /* Call a function exactly once. The idea of DO_ONCE() is to perform
  * a function call such as initialization of random seeds, etc, only
@@ -46,7 +46,7 @@ void __do_once_done(bool *done, struct static_key_true *once_key,
                        if (unlikely(___ret)) {                              \
                                func(__VA_ARGS__);                           \
                                __do_once_done(&___done, &___once_key,       \
-                                              &___flags);                   \
+                                              &___flags, THIS_MODULE);      \
                        }                                                    \
                }                                                            \
                ___ret;                                                      \
index 5d2705f..fc56424 100644 (file)
@@ -48,6 +48,7 @@ struct pipe_buffer {
  *     @files: number of struct file referring this pipe (protected by ->i_lock)
  *     @r_counter: reader counter
  *     @w_counter: writer counter
+ *     @poll_usage: is this pipe used for epoll, which has crazy wakeups?
  *     @fasync_readers: reader side fasync
  *     @fasync_writers: writer side fasync
  *     @bufs: the circular array of pipe buffers
@@ -70,6 +71,7 @@ struct pipe_inode_info {
        unsigned int files;
        unsigned int r_counter;
        unsigned int w_counter;
+       unsigned int poll_usage;
        struct page *tmp_page;
        struct fasync_struct *fasync_readers;
        struct fasync_struct *fasync_writers;
index 24eda04..5b72885 100644 (file)
@@ -120,10 +120,11 @@ enum lockdown_reason {
        LOCKDOWN_MMIOTRACE,
        LOCKDOWN_DEBUGFS,
        LOCKDOWN_XMON_WR,
+       LOCKDOWN_BPF_WRITE_USER,
        LOCKDOWN_INTEGRITY_MAX,
        LOCKDOWN_KCORE,
        LOCKDOWN_KPROBES,
-       LOCKDOWN_BPF_READ,
+       LOCKDOWN_BPF_READ_KERNEL,
        LOCKDOWN_PERF,
        LOCKDOWN_TRACEFS,
        LOCKDOWN_XMON_RW,
index 52d7fb9..c58cc14 100644 (file)
@@ -518,6 +518,25 @@ static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
        if (sysrq_ch)
                handle_sysrq(sysrq_ch);
 }
+
+static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port,
+               unsigned long flags)
+{
+       int sysrq_ch;
+
+       if (!port->has_sysrq) {
+               spin_unlock_irqrestore(&port->lock, flags);
+               return;
+       }
+
+       sysrq_ch = port->sysrq_ch;
+       port->sysrq_ch = 0;
+
+       spin_unlock_irqrestore(&port->lock, flags);
+
+       if (sysrq_ch)
+               handle_sysrq(sysrq_ch);
+}
 #else  /* CONFIG_MAGIC_SYSRQ_SERIAL */
 static inline int uart_handle_sysrq_char(struct uart_port *port, unsigned int ch)
 {
@@ -531,6 +550,11 @@ static inline void uart_unlock_and_check_sysrq(struct uart_port *port)
 {
        spin_unlock(&port->lock);
 }
+static inline void uart_unlock_and_check_sysrq_irqrestore(struct uart_port *port,
+               unsigned long flags)
+{
+       spin_unlock_irqrestore(&port->lock, flags);
+}
 #endif /* CONFIG_MAGIC_SYSRQ_SERIAL */
 
 /*
index 54269e4..3ebfea0 100644 (file)
@@ -27,6 +27,7 @@
 #define TEE_SHM_USER_MAPPED    BIT(4)  /* Memory mapped in user space */
 #define TEE_SHM_POOL           BIT(5)  /* Memory allocated from pool */
 #define TEE_SHM_KERNEL_MAPPED  BIT(6)  /* Memory mapped in kernel space */
+#define TEE_SHM_PRIV           BIT(7)  /* Memory private to TEE driver */
 
 struct device;
 struct tee_device;
@@ -332,6 +333,7 @@ void *tee_get_drvdata(struct tee_device *teedev);
  * @returns a pointer to 'struct tee_shm'
  */
 struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
+struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size);
 
 /**
  * tee_shm_register() - Register shared memory buffer
index 3aee78d..784659d 100644 (file)
@@ -196,6 +196,7 @@ struct otg_fsm {
        struct mutex lock;
        u8 *host_req_flag;
        struct delayed_work hnp_polling_work;
+       bool hnp_work_inited;
        bool state_changed;
 };
 
index 3357ac9..8cfe49d 100644 (file)
@@ -277,6 +277,17 @@ struct vdpa_device *__vdpa_alloc_device(struct device *parent,
                                        const struct vdpa_config_ops *config,
                                        size_t size, const char *name);
 
+/**
+ * vdpa_alloc_device - allocate and initilaize a vDPA device
+ *
+ * @dev_struct: the type of the parent structure
+ * @member: the name of struct vdpa_device within the @dev_struct
+ * @parent: the parent device
+ * @config: the bus operations that is supported by this device
+ * @name: name of the vdpa device
+ *
+ * Return allocated data structure or ERR_PTR upon error
+ */
 #define vdpa_alloc_device(dev_struct, member, parent, config, name)   \
                          container_of(__vdpa_alloc_device( \
                                       parent, config, \
index b1894e0..41edbc0 100644 (file)
@@ -110,6 +110,7 @@ struct virtio_device {
        bool config_enabled;
        bool config_change_pending;
        spinlock_t config_lock;
+       spinlock_t vqs_list_lock; /* Protects VQs list access */
        struct device dev;
        struct virtio_device_id id;
        const struct virtio_config_ops *config;
index 84db7b8..212892c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/virtio_byteorder.h>
 #include <linux/uio.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 #if IS_REACHABLE(CONFIG_VHOST_IOTLB)
 #include <linux/dma-direction.h>
 #include <linux/vhost_iotlb.h>
index f3c2841..1b9d75a 100644 (file)
@@ -319,14 +319,12 @@ flow_action_mixed_hw_stats_check(const struct flow_action *action,
        if (flow_offload_has_one_action(action))
                return true;
 
-       if (action) {
-               flow_action_for_each(i, action_entry, action) {
-                       if (i && action_entry->hw_stats != last_hw_stats) {
-                               NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
-                               return false;
-                       }
-                       last_hw_stats = action_entry->hw_stats;
+       flow_action_for_each(i, action_entry, action) {
+               if (i && action_entry->hw_stats != last_hw_stats) {
+                       NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported");
+                       return false;
                }
+               last_hw_stats = action_entry->hw_stats;
        }
        return true;
 }
index 15b7fbe..c412dde 100644 (file)
@@ -267,7 +267,7 @@ static inline bool fib6_check_expired(const struct fib6_info *f6i)
        return false;
 }
 
-/* Function to safely get fn->sernum for passed in rt
+/* Function to safely get fn->fn_sernum for passed in rt
  * and store result in passed in cookie.
  * Return true if we can get cookie safely
  * Return false if not
@@ -282,7 +282,7 @@ static inline bool fib6_get_cookie_safe(const struct fib6_info *f6i,
 
        if (fn) {
                *cookie = fn->fn_sernum;
-               /* pairs with smp_wmb() in fib6_update_sernum_upto_root() */
+               /* pairs with smp_wmb() in __fib6_update_sernum_upto_root() */
                smp_rmb();
                status = true;
        }
index 37e5300..fefd38d 100644 (file)
@@ -30,7 +30,6 @@ struct nf_tcp_net {
        u8 tcp_ignore_invalid_rst;
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        unsigned int offload_timeout;
-       unsigned int offload_pickup;
 #endif
 };
 
@@ -44,7 +43,6 @@ struct nf_udp_net {
        unsigned int timeouts[UDP_CT_MAX];
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        unsigned int offload_timeout;
-       unsigned int offload_pickup;
 #endif
 };
 
index e328c51..0509d2d 100644 (file)
@@ -31,6 +31,8 @@ struct psample_group *psample_group_get(struct net *net, u32 group_num);
 void psample_group_take(struct psample_group *group);
 void psample_group_put(struct psample_group *group);
 
+struct sk_buff;
+
 #if IS_ENABLED(CONFIG_PSAMPLE)
 
 void psample_sample_packet(struct psample_group *group, struct sk_buff *skb,
index 390270e..f160484 100644 (file)
@@ -48,7 +48,9 @@
        {(unsigned long)__GFP_WRITE,            "__GFP_WRITE"},         \
        {(unsigned long)__GFP_RECLAIM,          "__GFP_RECLAIM"},       \
        {(unsigned long)__GFP_DIRECT_RECLAIM,   "__GFP_DIRECT_RECLAIM"},\
-       {(unsigned long)__GFP_KSWAPD_RECLAIM,   "__GFP_KSWAPD_RECLAIM"}\
+       {(unsigned long)__GFP_KSWAPD_RECLAIM,   "__GFP_KSWAPD_RECLAIM"},\
+       {(unsigned long)__GFP_ZEROTAGS,         "__GFP_ZEROTAGS"},      \
+       {(unsigned long)__GFP_SKIP_KASAN_POISON,"__GFP_SKIP_KASAN_POISON"}\
 
 #define show_gfp_flags(flags)                                          \
        (flags) ? __print_flags(flags, "|",                             \
diff --git a/include/uapi/linux/dvb/audio.h b/include/uapi/linux/dvb/audio.h
new file mode 100644 (file)
index 0000000..2f869da
--- /dev/null
@@ -0,0 +1,101 @@
+/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
+/*
+ * audio.h - DEPRECATED MPEG-TS audio decoder API
+ *
+ * NOTE: should not be used on future drivers
+ *
+ * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
+ *                  & Marcus Metzler <marcus@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Lesser Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef _DVBAUDIO_H_
+#define _DVBAUDIO_H_
+
+#include <linux/types.h>
+
+typedef enum {
+       AUDIO_SOURCE_DEMUX, /* Select the demux as the main source */
+       AUDIO_SOURCE_MEMORY /* Select internal memory as the main source */
+} audio_stream_source_t;
+
+
+typedef enum {
+       AUDIO_STOPPED,      /* Device is stopped */
+       AUDIO_PLAYING,      /* Device is currently playing */
+       AUDIO_PAUSED        /* Device is paused */
+} audio_play_state_t;
+
+
+typedef enum {
+       AUDIO_STEREO,
+       AUDIO_MONO_LEFT,
+       AUDIO_MONO_RIGHT,
+       AUDIO_MONO,
+       AUDIO_STEREO_SWAPPED
+} audio_channel_select_t;
+
+
+typedef struct audio_mixer {
+       unsigned int volume_left;
+       unsigned int volume_right;
+  /* what else do we need? bass, pass-through, ... */
+} audio_mixer_t;
+
+
+typedef struct audio_status {
+       int                    AV_sync_state;  /* sync audio and video? */
+       int                    mute_state;     /* audio is muted */
+       audio_play_state_t     play_state;     /* current playback state */
+       audio_stream_source_t  stream_source;  /* current stream source */
+       audio_channel_select_t channel_select; /* currently selected channel */
+       int                    bypass_mode;    /* pass on audio data to */
+       audio_mixer_t          mixer_state;    /* current mixer state */
+} audio_status_t;                              /* separate decoder hardware */
+
+
+/* for GET_CAPABILITIES and SET_FORMAT, the latter should only set one bit */
+#define AUDIO_CAP_DTS    1
+#define AUDIO_CAP_LPCM   2
+#define AUDIO_CAP_MP1    4
+#define AUDIO_CAP_MP2    8
+#define AUDIO_CAP_MP3   16
+#define AUDIO_CAP_AAC   32
+#define AUDIO_CAP_OGG   64
+#define AUDIO_CAP_SDDS 128
+#define AUDIO_CAP_AC3  256
+
+#define AUDIO_STOP                 _IO('o', 1)
+#define AUDIO_PLAY                 _IO('o', 2)
+#define AUDIO_PAUSE                _IO('o', 3)
+#define AUDIO_CONTINUE             _IO('o', 4)
+#define AUDIO_SELECT_SOURCE        _IO('o', 5)
+#define AUDIO_SET_MUTE             _IO('o', 6)
+#define AUDIO_SET_AV_SYNC          _IO('o', 7)
+#define AUDIO_SET_BYPASS_MODE      _IO('o', 8)
+#define AUDIO_CHANNEL_SELECT       _IO('o', 9)
+#define AUDIO_GET_STATUS           _IOR('o', 10, audio_status_t)
+
+#define AUDIO_GET_CAPABILITIES     _IOR('o', 11, unsigned int)
+#define AUDIO_CLEAR_BUFFER         _IO('o',  12)
+#define AUDIO_SET_ID               _IO('o', 13)
+#define AUDIO_SET_MIXER            _IOW('o', 14, audio_mixer_t)
+#define AUDIO_SET_STREAMTYPE       _IO('o', 15)
+#define AUDIO_BILINGUAL_CHANNEL_SELECT _IO('o', 20)
+
+#endif /* _DVBAUDIO_H_ */
diff --git a/include/uapi/linux/dvb/osd.h b/include/uapi/linux/dvb/osd.h
new file mode 100644 (file)
index 0000000..858997c
--- /dev/null
@@ -0,0 +1,181 @@
+/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
+/*
+ * osd.h - DEPRECATED On Screen Display API
+ *
+ * NOTE: should not be used on future drivers
+ *
+ * Copyright (C) 2001 Ralph  Metzler <ralph@convergence.de>
+ *                  & Marcus Metzler <marcus@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Lesser Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef _DVBOSD_H_
+#define _DVBOSD_H_
+
+#include <linux/compiler.h>
+
+typedef enum {
+       /* All functions return -2 on "not open" */
+       OSD_Close = 1,  /* () */
+       /*
+        * Disables OSD and releases the buffers
+        * returns 0 on success
+        */
+       OSD_Open,       /* (x0,y0,x1,y1,BitPerPixel[2/4/8](color&0x0F),mix[0..15](color&0xF0)) */
+       /*
+        * Opens OSD with this size and bit depth
+        * returns 0 on success, -1 on DRAM allocation error, -2 on "already open"
+        */
+       OSD_Show,       /* () */
+       /*
+        * enables OSD mode
+        * returns 0 on success
+        */
+       OSD_Hide,       /* () */
+       /*
+        * disables OSD mode
+        * returns 0 on success
+        */
+       OSD_Clear,      /* () */
+       /*
+        * Sets all pixel to color 0
+        * returns 0 on success
+        */
+       OSD_Fill,       /* (color) */
+       /*
+        * Sets all pixel to color <col>
+        * returns 0 on success
+        */
+       OSD_SetColor,   /* (color,R{x0},G{y0},B{x1},opacity{y1}) */
+       /*
+        * set palette entry <num> to <r,g,b>, <mix> and <trans> apply
+        * R,G,B: 0..255
+        * R=Red, G=Green, B=Blue
+        * opacity=0:      pixel opacity 0% (only video pixel shows)
+        * opacity=1..254: pixel opacity as specified in header
+        * opacity=255:    pixel opacity 100% (only OSD pixel shows)
+        * returns 0 on success, -1 on error
+        */
+       OSD_SetPalette, /* (firstcolor{color},lastcolor{x0},data) */
+       /*
+        * Set a number of entries in the palette
+        * sets the entries "firstcolor" through "lastcolor" from the array "data"
+        * data has 4 byte for each color:
+        * R,G,B, and a opacity value: 0->transparent, 1..254->mix, 255->pixel
+        */
+       OSD_SetTrans,   /* (transparency{color}) */
+       /*
+        * Sets transparency of mixed pixel (0..15)
+        * returns 0 on success
+        */
+       OSD_SetPixel,   /* (x0,y0,color) */
+       /*
+        * sets pixel <x>,<y> to color number <col>
+        * returns 0 on success, -1 on error
+        */
+       OSD_GetPixel,   /* (x0,y0) */
+       /* returns color number of pixel <x>,<y>,  or -1 */
+       OSD_SetRow,     /* (x0,y0,x1,data) */
+       /*
+        * fills pixels x0,y through  x1,y with the content of data[]
+        * returns 0 on success, -1 on clipping all pixel (no pixel drawn)
+        */
+       OSD_SetBlock,   /* (x0,y0,x1,y1,increment{color},data) */
+       /*
+        * fills pixels x0,y0 through  x1,y1 with the content of data[]
+        * inc contains the width of one line in the data block,
+        * inc<=0 uses blockwidth as linewidth
+        * returns 0 on success, -1 on clipping all pixel
+        */
+       OSD_FillRow,    /* (x0,y0,x1,color) */
+       /*
+        * fills pixels x0,y through  x1,y with the color <col>
+        * returns 0 on success, -1 on clipping all pixel
+        */
+       OSD_FillBlock,  /* (x0,y0,x1,y1,color) */
+       /*
+        * fills pixels x0,y0 through  x1,y1 with the color <col>
+        * returns 0 on success, -1 on clipping all pixel
+        */
+       OSD_Line,       /* (x0,y0,x1,y1,color) */
+       /*
+        * draw a line from x0,y0 to x1,y1 with the color <col>
+        * returns 0 on success
+        */
+       OSD_Query,      /* (x0,y0,x1,y1,xasp{color}}), yasp=11 */
+       /*
+        * fills parameters with the picture dimensions and the pixel aspect ratio
+        * returns 0 on success
+        */
+       OSD_Test,       /* () */
+       /*
+        * draws a test picture. for debugging purposes only
+        * returns 0 on success
+        * TODO: remove "test" in final version
+        */
+       OSD_Text,       /* (x0,y0,size,color,text) */
+       OSD_SetWindow,  /* (x0) set window with number 0<x0<8 as current */
+       OSD_MoveWindow, /* move current window to (x0, y0) */
+       OSD_OpenRaw,    /* Open other types of OSD windows */
+} OSD_Command;
+
+typedef struct osd_cmd_s {
+       OSD_Command cmd;
+       int x0;
+       int y0;
+       int x1;
+       int y1;
+       int color;
+       void __user *data;
+} osd_cmd_t;
+
+/* OSD_OpenRaw: set 'color' to desired window type */
+typedef enum {
+       OSD_BITMAP1,           /* 1 bit bitmap */
+       OSD_BITMAP2,           /* 2 bit bitmap */
+       OSD_BITMAP4,           /* 4 bit bitmap */
+       OSD_BITMAP8,           /* 8 bit bitmap */
+       OSD_BITMAP1HR,         /* 1 Bit bitmap half resolution */
+       OSD_BITMAP2HR,         /* 2 bit bitmap half resolution */
+       OSD_BITMAP4HR,         /* 4 bit bitmap half resolution */
+       OSD_BITMAP8HR,         /* 8 bit bitmap half resolution */
+       OSD_YCRCB422,          /* 4:2:2 YCRCB Graphic Display */
+       OSD_YCRCB444,          /* 4:4:4 YCRCB Graphic Display */
+       OSD_YCRCB444HR,        /* 4:4:4 YCRCB graphic half resolution */
+       OSD_VIDEOTSIZE,        /* True Size Normal MPEG Video Display */
+       OSD_VIDEOHSIZE,        /* MPEG Video Display Half Resolution */
+       OSD_VIDEOQSIZE,        /* MPEG Video Display Quarter Resolution */
+       OSD_VIDEODSIZE,        /* MPEG Video Display Double Resolution */
+       OSD_VIDEOTHSIZE,       /* True Size MPEG Video Display Half Resolution */
+       OSD_VIDEOTQSIZE,       /* True Size MPEG Video Display Quarter Resolution*/
+       OSD_VIDEOTDSIZE,       /* True Size MPEG Video Display Double Resolution */
+       OSD_VIDEONSIZE,        /* Full Size MPEG Video Display */
+       OSD_CURSOR             /* Cursor */
+} osd_raw_window_t;
+
+typedef struct osd_cap_s {
+       int  cmd;
+#define OSD_CAP_MEMSIZE         1  /* memory size */
+       long val;
+} osd_cap_t;
+
+
+#define OSD_SEND_CMD            _IOW('o', 160, osd_cmd_t)
+#define OSD_GET_CAPABILITY      _IOR('o', 161, osd_cap_t)
+
+#endif
diff --git a/include/uapi/linux/dvb/video.h b/include/uapi/linux/dvb/video.h
new file mode 100644 (file)
index 0000000..179f1ec
--- /dev/null
@@ -0,0 +1,220 @@
+/* SPDX-License-Identifier: LGPL-2.1+ WITH Linux-syscall-note */
+/*
+ * video.h - DEPRECATED MPEG-TS video decoder API
+ *
+ * NOTE: should not be used on future drivers
+ *
+ * Copyright (C) 2000 Marcus Metzler <marcus@convergence.de>
+ *                  & Ralph  Metzler <ralph@convergence.de>
+ *                    for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ *
+ */
+
+#ifndef _UAPI_DVBVIDEO_H_
+#define _UAPI_DVBVIDEO_H_
+
+#include <linux/types.h>
+#ifndef __KERNEL__
+#include <time.h>
+#endif
+
+typedef enum {
+       VIDEO_FORMAT_4_3,     /* Select 4:3 format */
+       VIDEO_FORMAT_16_9,    /* Select 16:9 format. */
+       VIDEO_FORMAT_221_1    /* 2.21:1 */
+} video_format_t;
+
+
+typedef enum {
+       VIDEO_PAN_SCAN,       /* use pan and scan format */
+       VIDEO_LETTER_BOX,     /* use letterbox format */
+       VIDEO_CENTER_CUT_OUT  /* use center cut out format */
+} video_displayformat_t;
+
+typedef struct {
+       int w;
+       int h;
+       video_format_t aspect_ratio;
+} video_size_t;
+
+typedef enum {
+       VIDEO_SOURCE_DEMUX, /* Select the demux as the main source */
+       VIDEO_SOURCE_MEMORY /* If this source is selected, the stream
+                              comes from the user through the write
+                              system call */
+} video_stream_source_t;
+
+
+typedef enum {
+       VIDEO_STOPPED, /* Video is stopped */
+       VIDEO_PLAYING, /* Video is currently playing */
+       VIDEO_FREEZED  /* Video is freezed */
+} video_play_state_t;
+
+
+/* Decoder commands */
+#define VIDEO_CMD_PLAY        (0)
+#define VIDEO_CMD_STOP        (1)
+#define VIDEO_CMD_FREEZE      (2)
+#define VIDEO_CMD_CONTINUE    (3)
+
+/* Flags for VIDEO_CMD_FREEZE */
+#define VIDEO_CMD_FREEZE_TO_BLACK      (1 << 0)
+
+/* Flags for VIDEO_CMD_STOP */
+#define VIDEO_CMD_STOP_TO_BLACK                (1 << 0)
+#define VIDEO_CMD_STOP_IMMEDIATELY     (1 << 1)
+
+/* Play input formats: */
+/* The decoder has no special format requirements */
+#define VIDEO_PLAY_FMT_NONE         (0)
+/* The decoder requires full GOPs */
+#define VIDEO_PLAY_FMT_GOP          (1)
+
+/* The structure must be zeroed before use by the application
+   This ensures it can be extended safely in the future. */
+struct video_command {
+       __u32 cmd;
+       __u32 flags;
+       union {
+               struct {
+                       __u64 pts;
+               } stop;
+
+               struct {
+                       /* 0 or 1000 specifies normal speed,
+                          1 specifies forward single stepping,
+                          -1 specifies backward single stepping,
+                          >1: playback at speed/1000 of the normal speed,
+                          <-1: reverse playback at (-speed/1000) of the normal speed. */
+                       __s32 speed;
+                       __u32 format;
+               } play;
+
+               struct {
+                       __u32 data[16];
+               } raw;
+       };
+};
+
+/* FIELD_UNKNOWN can be used if the hardware does not know whether
+   the Vsync is for an odd, even or progressive (i.e. non-interlaced)
+   field. */
+#define VIDEO_VSYNC_FIELD_UNKNOWN      (0)
+#define VIDEO_VSYNC_FIELD_ODD          (1)
+#define VIDEO_VSYNC_FIELD_EVEN         (2)
+#define VIDEO_VSYNC_FIELD_PROGRESSIVE  (3)
+
+struct video_event {
+       __s32 type;
+#define VIDEO_EVENT_SIZE_CHANGED       1
+#define VIDEO_EVENT_FRAME_RATE_CHANGED 2
+#define VIDEO_EVENT_DECODER_STOPPED    3
+#define VIDEO_EVENT_VSYNC              4
+       /* unused, make sure to use atomic time for y2038 if it ever gets used */
+       long timestamp;
+       union {
+               video_size_t size;
+               unsigned int frame_rate;        /* in frames per 1000sec */
+               unsigned char vsync_field;      /* unknown/odd/even/progressive */
+       } u;
+};
+
+
+struct video_status {
+       int                   video_blank;   /* blank video on freeze? */
+       video_play_state_t    play_state;    /* current state of playback */
+       video_stream_source_t stream_source; /* current source (demux/memory) */
+       video_format_t        video_format;  /* current aspect ratio of stream*/
+       video_displayformat_t display_format;/* selected cropping mode */
+};
+
+
+struct video_still_picture {
+       char __user *iFrame;        /* pointer to a single iframe in memory */
+       __s32 size;
+};
+
+
+typedef __u16 video_attributes_t;
+/*   bits: descr. */
+/*   15-14 Video compression mode (0=MPEG-1, 1=MPEG-2) */
+/*   13-12 TV system (0=525/60, 1=625/50) */
+/*   11-10 Aspect ratio (0=4:3, 3=16:9) */
+/*    9- 8 permitted display mode on 4:3 monitor (0=both, 1=only pan-sca */
+/*    7    line 21-1 data present in GOP (1=yes, 0=no) */
+/*    6    line 21-2 data present in GOP (1=yes, 0=no) */
+/*    5- 3 source resolution (0=720x480/576, 1=704x480/576, 2=352x480/57 */
+/*    2    source letterboxed (1=yes, 0=no) */
+/*    0    film/camera mode (0=
+ *camera, 1=film (625/50 only)) */
+
+
+/* bit definitions for capabilities: */
+/* can the hardware decode MPEG1 and/or MPEG2? */
+#define VIDEO_CAP_MPEG1   1
+#define VIDEO_CAP_MPEG2   2
+/* can you send a system and/or program stream to video device?
+   (you still have to open the video and the audio device but only
+    send the stream to the video device) */
+#define VIDEO_CAP_SYS     4
+#define VIDEO_CAP_PROG    8
+/* can the driver also handle SPU, NAVI and CSS encoded data?
+   (CSS API is not present yet) */
+#define VIDEO_CAP_SPU    16
+#define VIDEO_CAP_NAVI   32
+#define VIDEO_CAP_CSS    64
+
+
+#define VIDEO_STOP                 _IO('o', 21)
+#define VIDEO_PLAY                 _IO('o', 22)
+#define VIDEO_FREEZE               _IO('o', 23)
+#define VIDEO_CONTINUE             _IO('o', 24)
+#define VIDEO_SELECT_SOURCE        _IO('o', 25)
+#define VIDEO_SET_BLANK            _IO('o', 26)
+#define VIDEO_GET_STATUS           _IOR('o', 27, struct video_status)
+#define VIDEO_GET_EVENT            _IOR('o', 28, struct video_event)
+#define VIDEO_SET_DISPLAY_FORMAT   _IO('o', 29)
+#define VIDEO_STILLPICTURE         _IOW('o', 30, struct video_still_picture)
+#define VIDEO_FAST_FORWARD         _IO('o', 31)
+#define VIDEO_SLOWMOTION           _IO('o', 32)
+#define VIDEO_GET_CAPABILITIES     _IOR('o', 33, unsigned int)
+#define VIDEO_CLEAR_BUFFER         _IO('o',  34)
+#define VIDEO_SET_STREAMTYPE       _IO('o', 36)
+#define VIDEO_SET_FORMAT           _IO('o', 37)
+#define VIDEO_GET_SIZE             _IOR('o', 55, video_size_t)
+
+/**
+ * VIDEO_GET_PTS
+ *
+ * Read the 33 bit presentation time stamp as defined
+ * in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+ *
+ * The PTS should belong to the currently played
+ * frame if possible, but may also be a value close to it
+ * like the PTS of the last decoded frame or the last PTS
+ * extracted by the PES parser.
+ */
+#define VIDEO_GET_PTS              _IOR('o', 57, __u64)
+
+/* Read the number of displayed frames since the decoder was started */
+#define VIDEO_GET_FRAME_COUNT     _IOR('o', 58, __u64)
+
+#define VIDEO_COMMAND             _IOWR('o', 59, struct video_command)
+#define VIDEO_TRY_COMMAND         _IOWR('o', 60, struct video_command)
+
+#endif /* _UAPI_DVBVIDEO_H_ */
index dc8b722..00a6069 100644 (file)
@@ -66,8 +66,11 @@ enum {
 #define NUD_NONE       0x00
 
 /* NUD_NOARP & NUD_PERMANENT are pseudostates, they never change
-   and make no address resolution or NUD.
-   NUD_PERMANENT also cannot be deleted by garbage collectors.
+ * and make no address resolution or NUD.
+ * NUD_PERMANENT also cannot be deleted by garbage collectors.
+ * When NTF_EXT_LEARNED is set for a bridge fdb entry the different cache entry
+ * states don't make sense and thus are ignored. Such entries don't age and
+ * can roam.
  */
 
 struct nda_cacheinfo {
index 912ec60..bbcd285 100644 (file)
@@ -43,6 +43,15 @@ enum nfnl_hook_chain_info_attributes {
 };
 #define NFNLA_HOOK_INFO_MAX (__NFNLA_HOOK_INFO_MAX - 1)
 
+enum nfnl_hook_chain_desc_attributes {
+       NFNLA_CHAIN_UNSPEC,
+       NFNLA_CHAIN_TABLE,
+       NFNLA_CHAIN_FAMILY,
+       NFNLA_CHAIN_NAME,
+       __NFNLA_CHAIN_MAX,
+};
+#define NFNLA_CHAIN_MAX (__NFNLA_CHAIN_MAX - 1)
+
 /**
  * enum nfnl_hook_chaintype - chain type
  *
index f5b8246..8d97aba 100644 (file)
@@ -397,6 +397,12 @@ static int __init bootconfig_params(char *param, char *val,
        return 0;
 }
 
+static int __init warn_bootconfig(char *str)
+{
+       /* The 'bootconfig' has been handled by bootconfig_params(). */
+       return 0;
+}
+
 static void __init setup_boot_config(void)
 {
        static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
@@ -475,9 +481,8 @@ static int __init warn_bootconfig(char *str)
        pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOT_CONFIG is not set.\n");
        return 0;
 }
-early_param("bootconfig", warn_bootconfig);
-
 #endif
+early_param("bootconfig", warn_bootconfig);
 
 /* Change NUL term back to "=", to make "param" the whole string. */
 static void __init repair_env_string(char *param, char *val)
index b1a5fc0..0a28a80 100644 (file)
@@ -1362,11 +1362,13 @@ u64 __weak bpf_probe_read_kernel(void *dst, u32 size, const void *unsafe_ptr)
 }
 
 /**
- *     __bpf_prog_run - run eBPF program on a given context
+ *     ___bpf_prog_run - run eBPF program on a given context
  *     @regs: is the array of MAX_BPF_EXT_REG eBPF pseudo-registers
  *     @insn: is the array of eBPF instructions
  *
  * Decode and execute eBPF instructions.
+ *
+ * Return: whatever value is in %BPF_R0 at program exit
  */
 static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn)
 {
@@ -1878,6 +1880,9 @@ static void bpf_prog_select_func(struct bpf_prog *fp)
  *
  * Try to JIT eBPF program, if JIT is not available, use interpreter.
  * The BPF program will be executed via BPF_PROG_RUN() macro.
+ *
+ * Return: the &fp argument along with &err set to 0 for success or
+ * a negative errno code on failure
  */
 struct bpf_prog *bpf_prog_select_runtime(struct bpf_prog *fp, int *err)
 {
index 72c58cc..9c011f3 100644 (file)
@@ -1565,8 +1565,8 @@ alloc:
        /* We cannot do copy_from_user or copy_to_user inside
         * the rcu_read_lock. Allocate enough space here.
         */
-       keys = kvmalloc(key_size * bucket_size, GFP_USER | __GFP_NOWARN);
-       values = kvmalloc(value_size * bucket_size, GFP_USER | __GFP_NOWARN);
+       keys = kvmalloc_array(key_size, bucket_size, GFP_USER | __GFP_NOWARN);
+       values = kvmalloc_array(value_size, bucket_size, GFP_USER | __GFP_NOWARN);
        if (!keys || !values) {
                ret = -ENOMEM;
                goto after_loop;
index 62cf003..55f83ea 100644 (file)
@@ -353,9 +353,15 @@ const struct bpf_func_proto bpf_jiffies64_proto = {
 #ifdef CONFIG_CGROUPS
 BPF_CALL_0(bpf_get_current_cgroup_id)
 {
-       struct cgroup *cgrp = task_dfl_cgroup(current);
+       struct cgroup *cgrp;
+       u64 cgrp_id;
 
-       return cgroup_id(cgrp);
+       rcu_read_lock();
+       cgrp = task_dfl_cgroup(current);
+       cgrp_id = cgroup_id(cgrp);
+       rcu_read_unlock();
+
+       return cgrp_id;
 }
 
 const struct bpf_func_proto bpf_get_current_cgroup_id_proto = {
@@ -366,13 +372,17 @@ const struct bpf_func_proto bpf_get_current_cgroup_id_proto = {
 
 BPF_CALL_1(bpf_get_current_ancestor_cgroup_id, int, ancestor_level)
 {
-       struct cgroup *cgrp = task_dfl_cgroup(current);
+       struct cgroup *cgrp;
        struct cgroup *ancestor;
+       u64 cgrp_id;
 
+       rcu_read_lock();
+       cgrp = task_dfl_cgroup(current);
        ancestor = cgroup_ancestor(cgrp, ancestor_level);
-       if (!ancestor)
-               return 0;
-       return cgroup_id(ancestor);
+       cgrp_id = ancestor ? cgroup_id(ancestor) : 0;
+       rcu_read_unlock();
+
+       return cgrp_id;
 }
 
 const struct bpf_func_proto bpf_get_current_ancestor_cgroup_id_proto = {
@@ -397,8 +407,8 @@ BPF_CALL_2(bpf_get_local_storage, struct bpf_map *, map, u64, flags)
        void *ptr;
        int i;
 
-       for (i = 0; i < BPF_CGROUP_STORAGE_NEST_MAX; i++) {
-               if (unlikely(this_cpu_read(bpf_cgroup_storage_info[i].task) != current))
+       for (i = BPF_CGROUP_STORAGE_NEST_MAX - 1; i >= 0; i--) {
+               if (likely(this_cpu_read(bpf_cgroup_storage_info[i].task) != current))
                        continue;
 
                storage = this_cpu_read(bpf_cgroup_storage_info[i].storage[stype]);
@@ -1070,12 +1080,12 @@ bpf_base_func_proto(enum bpf_func_id func_id)
        case BPF_FUNC_probe_read_user:
                return &bpf_probe_read_user_proto;
        case BPF_FUNC_probe_read_kernel:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_kernel_proto;
        case BPF_FUNC_probe_read_user_str:
                return &bpf_probe_read_user_str_proto;
        case BPF_FUNC_probe_read_kernel_str:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_kernel_str_proto;
        case BPF_FUNC_snprintf_btf:
                return &bpf_snprintf_btf_proto;
index f9bda54..49f07e2 100644 (file)
@@ -5150,8 +5150,6 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
        case BPF_MAP_TYPE_RINGBUF:
                if (func_id != BPF_FUNC_ringbuf_output &&
                    func_id != BPF_FUNC_ringbuf_reserve &&
-                   func_id != BPF_FUNC_ringbuf_submit &&
-                   func_id != BPF_FUNC_ringbuf_discard &&
                    func_id != BPF_FUNC_ringbuf_query)
                        goto error;
                break;
@@ -5260,6 +5258,12 @@ static int check_map_func_compatibility(struct bpf_verifier_env *env,
                if (map->map_type != BPF_MAP_TYPE_PERF_EVENT_ARRAY)
                        goto error;
                break;
+       case BPF_FUNC_ringbuf_output:
+       case BPF_FUNC_ringbuf_reserve:
+       case BPF_FUNC_ringbuf_query:
+               if (map->map_type != BPF_MAP_TYPE_RINGBUF)
+                       goto error;
+               break;
        case BPF_FUNC_get_stackid:
                if (map->map_type != BPF_MAP_TYPE_STACK_TRACE)
                        goto error;
@@ -11663,6 +11667,7 @@ static void sanitize_dead_code(struct bpf_verifier_env *env)
                if (aux_data[i].seen)
                        continue;
                memcpy(insn + i, &trap, sizeof(trap));
+               aux_data[i].zext_dst = false;
        }
 }
 
index e17a566..9594cfd 100644 (file)
@@ -248,9 +248,9 @@ static inline cfi_check_fn find_shadow_check_fn(unsigned long ptr)
 {
        cfi_check_fn fn;
 
-       rcu_read_lock_sched();
+       rcu_read_lock_sched_notrace();
        fn = ptr_to_check_fn(rcu_dereference_sched(cfi_shadow), ptr);
-       rcu_read_unlock_sched();
+       rcu_read_unlock_sched_notrace();
 
        return fn;
 }
@@ -269,11 +269,11 @@ static inline cfi_check_fn find_module_check_fn(unsigned long ptr)
        cfi_check_fn fn = NULL;
        struct module *mod;
 
-       rcu_read_lock_sched();
+       rcu_read_lock_sched_notrace();
        mod = __module_address(ptr);
        if (mod)
                fn = mod->cfi_check;
-       rcu_read_unlock_sched();
+       rcu_read_unlock_sched_notrace();
 
        return fn;
 }
index 7f0e589..b264ab5 100644 (file)
@@ -347,19 +347,20 @@ static void cgroup_base_stat_flush(struct cgroup *cgrp, int cpu)
 }
 
 static struct cgroup_rstat_cpu *
-cgroup_base_stat_cputime_account_begin(struct cgroup *cgrp)
+cgroup_base_stat_cputime_account_begin(struct cgroup *cgrp, unsigned long *flags)
 {
        struct cgroup_rstat_cpu *rstatc;
 
        rstatc = get_cpu_ptr(cgrp->rstat_cpu);
-       u64_stats_update_begin(&rstatc->bsync);
+       *flags = u64_stats_update_begin_irqsave(&rstatc->bsync);
        return rstatc;
 }
 
 static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp,
-                                                struct cgroup_rstat_cpu *rstatc)
+                                                struct cgroup_rstat_cpu *rstatc,
+                                                unsigned long flags)
 {
-       u64_stats_update_end(&rstatc->bsync);
+       u64_stats_update_end_irqrestore(&rstatc->bsync, flags);
        cgroup_rstat_updated(cgrp, smp_processor_id());
        put_cpu_ptr(rstatc);
 }
@@ -367,18 +368,20 @@ static void cgroup_base_stat_cputime_account_end(struct cgroup *cgrp,
 void __cgroup_account_cputime(struct cgroup *cgrp, u64 delta_exec)
 {
        struct cgroup_rstat_cpu *rstatc;
+       unsigned long flags;
 
-       rstatc = cgroup_base_stat_cputime_account_begin(cgrp);
+       rstatc = cgroup_base_stat_cputime_account_begin(cgrp, &flags);
        rstatc->bstat.cputime.sum_exec_runtime += delta_exec;
-       cgroup_base_stat_cputime_account_end(cgrp, rstatc);
+       cgroup_base_stat_cputime_account_end(cgrp, rstatc, flags);
 }
 
 void __cgroup_account_cputime_field(struct cgroup *cgrp,
                                    enum cpu_usage_stat index, u64 delta_exec)
 {
        struct cgroup_rstat_cpu *rstatc;
+       unsigned long flags;
 
-       rstatc = cgroup_base_stat_cputime_account_begin(cgrp);
+       rstatc = cgroup_base_stat_cputime_account_begin(cgrp, &flags);
 
        switch (index) {
        case CPUTIME_USER:
@@ -394,7 +397,7 @@ void __cgroup_account_cputime_field(struct cgroup *cgrp,
                break;
        }
 
-       cgroup_base_stat_cputime_account_end(cgrp, rstatc);
+       cgroup_base_stat_cputime_account_end(cgrp, rstatc, flags);
 }
 
 /*
index e6fd2b3..f784e08 100644 (file)
@@ -286,13 +286,13 @@ struct cred *prepare_creds(void)
        new->security = NULL;
 #endif
 
-       if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
-               goto error;
-
        new->ucounts = get_ucounts(new->ucounts);
        if (!new->ucounts)
                goto error;
 
+       if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
+               goto error;
+
        validate_creds(new);
        return new;
 
@@ -753,13 +753,13 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
 #ifdef CONFIG_SECURITY
        new->security = NULL;
 #endif
-       if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
-               goto error;
-
        new->ucounts = get_ucounts(new->ucounts);
        if (!new->ucounts)
                goto error;
 
+       if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0)
+               goto error;
+
        put_cred(old);
        validate_creds(new);
        return new;
index 4649170..1cb1f9b 100644 (file)
@@ -11917,6 +11917,37 @@ again:
        return gctx;
 }
 
+static bool
+perf_check_permission(struct perf_event_attr *attr, struct task_struct *task)
+{
+       unsigned int ptrace_mode = PTRACE_MODE_READ_REALCREDS;
+       bool is_capable = perfmon_capable();
+
+       if (attr->sigtrap) {
+               /*
+                * perf_event_attr::sigtrap sends signals to the other task.
+                * Require the current task to also have CAP_KILL.
+                */
+               rcu_read_lock();
+               is_capable &= ns_capable(__task_cred(task)->user_ns, CAP_KILL);
+               rcu_read_unlock();
+
+               /*
+                * If the required capabilities aren't available, checks for
+                * ptrace permissions: upgrade to ATTACH, since sending signals
+                * can effectively change the target task.
+                */
+               ptrace_mode = PTRACE_MODE_ATTACH_REALCREDS;
+       }
+
+       /*
+        * Preserve ptrace permission check for backwards compatibility. The
+        * ptrace check also includes checks that the current task and other
+        * task have matching uids, and is therefore not done here explicitly.
+        */
+       return is_capable || ptrace_may_access(task, ptrace_mode);
+}
+
 /**
  * sys_perf_event_open - open a performance event, associate it to a task/cpu
  *
@@ -12163,15 +12194,13 @@ SYSCALL_DEFINE5(perf_event_open,
                        goto err_file;
 
                /*
-                * Preserve ptrace permission check for backwards compatibility.
-                *
                 * We must hold exec_update_lock across this and any potential
                 * perf_install_in_context() call for this new event to
                 * serialize against exec() altering our credentials (and the
                 * perf_event_exit_task() that could imply).
                 */
                err = -EACCES;
-               if (!perfmon_capable() && !ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS))
+               if (!perf_check_permission(&attr, task))
                        goto err_cred;
        }
 
index bc94b2c..44f4c2d 100644 (file)
@@ -828,10 +828,10 @@ void __init fork_init(void)
        for (i = 0; i < MAX_PER_NAMESPACE_UCOUNTS; i++)
                init_user_ns.ucount_max[i] = max_threads/2;
 
-       set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_NPROC, task_rlimit(&init_task, RLIMIT_NPROC));
-       set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MSGQUEUE, task_rlimit(&init_task, RLIMIT_MSGQUEUE));
-       set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_SIGPENDING, task_rlimit(&init_task, RLIMIT_SIGPENDING));
-       set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK, task_rlimit(&init_task, RLIMIT_MEMLOCK));
+       set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_NPROC,      RLIM_INFINITY);
+       set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MSGQUEUE,   RLIM_INFINITY);
+       set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_SIGPENDING, RLIM_INFINITY);
+       set_rlimit_ucount_max(&init_user_ns, UCOUNT_RLIMIT_MEMLOCK,    RLIM_INFINITY);
 
 #ifdef CONFIG_VMAP_STACK
        cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache",
index 7f04c7d..a98bcfc 100644 (file)
@@ -265,8 +265,11 @@ int irq_startup(struct irq_desc *desc, bool resend, bool force)
        } else {
                switch (__irq_startup_managed(desc, aff, force)) {
                case IRQ_STARTUP_NORMAL:
+                       if (d->chip->flags & IRQCHIP_AFFINITY_PRE_STARTUP)
+                               irq_setup_affinity(desc);
                        ret = __irq_startup(desc);
-                       irq_setup_affinity(desc);
+                       if (!(d->chip->flags & IRQCHIP_AFFINITY_PRE_STARTUP))
+                               irq_setup_affinity(desc);
                        break;
                case IRQ_STARTUP_MANAGED:
                        irq_do_set_affinity(d, aff, false);
index c41965e..85df3ca 100644 (file)
@@ -476,11 +476,6 @@ skip_activate:
        return 0;
 
 cleanup:
-       for_each_msi_vector(desc, i, dev) {
-               irq_data = irq_domain_get_irq_data(domain, i);
-               if (irqd_is_activated(irq_data))
-                       irq_domain_deactivate_irq(irq_data);
-       }
        msi_domain_free_irqs(domain, dev);
        return ret;
 }
@@ -505,7 +500,15 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev,
 
 void __msi_domain_free_irqs(struct irq_domain *domain, struct device *dev)
 {
+       struct irq_data *irq_data;
        struct msi_desc *desc;
+       int i;
+
+       for_each_msi_vector(desc, i, dev) {
+               irq_data = irq_domain_get_irq_data(domain, i);
+               if (irqd_is_activated(irq_data))
+                       irq_domain_deactivate_irq(irq_data);
+       }
 
        for_each_msi_entry(desc, dev) {
                /*
index d309d6f..4d2a702 100644 (file)
@@ -453,6 +453,11 @@ static __always_inline void __irq_timings_store(int irq, struct irqt_stat *irqs,
         */
        index = irq_timings_interval_index(interval);
 
+       if (index > PREDICTION_BUFFER_SIZE - 1) {
+               irqs->count = 0;
+               return;
+       }
+
        /*
         * Store the index as an element of the pattern in another
         * circular array.
index b5d9bb5..ad0db32 100644 (file)
@@ -343,7 +343,7 @@ static __always_inline bool
 rt_mutex_cond_detect_deadlock(struct rt_mutex_waiter *waiter,
                              enum rtmutex_chainwalk chwalk)
 {
-       if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEX))
+       if (IS_ENABLED(CONFIG_DEBUG_RT_MUTEXES))
                return waiter != NULL;
        return chwalk == RT_MUTEX_FULL_CHAINWALK;
 }
index 2d9ff40..f3b27c6 100644 (file)
@@ -237,9 +237,30 @@ static DEFINE_MUTEX(sched_core_mutex);
 static atomic_t sched_core_count;
 static struct cpumask sched_core_mask;
 
+static void sched_core_lock(int cpu, unsigned long *flags)
+{
+       const struct cpumask *smt_mask = cpu_smt_mask(cpu);
+       int t, i = 0;
+
+       local_irq_save(*flags);
+       for_each_cpu(t, smt_mask)
+               raw_spin_lock_nested(&cpu_rq(t)->__lock, i++);
+}
+
+static void sched_core_unlock(int cpu, unsigned long *flags)
+{
+       const struct cpumask *smt_mask = cpu_smt_mask(cpu);
+       int t;
+
+       for_each_cpu(t, smt_mask)
+               raw_spin_unlock(&cpu_rq(t)->__lock);
+       local_irq_restore(*flags);
+}
+
 static void __sched_core_flip(bool enabled)
 {
-       int cpu, t, i;
+       unsigned long flags;
+       int cpu, t;
 
        cpus_read_lock();
 
@@ -250,19 +271,12 @@ static void __sched_core_flip(bool enabled)
        for_each_cpu(cpu, &sched_core_mask) {
                const struct cpumask *smt_mask = cpu_smt_mask(cpu);
 
-               i = 0;
-               local_irq_disable();
-               for_each_cpu(t, smt_mask) {
-                       /* supports up to SMT8 */
-                       raw_spin_lock_nested(&cpu_rq(t)->__lock, i++);
-               }
+               sched_core_lock(cpu, &flags);
 
                for_each_cpu(t, smt_mask)
                        cpu_rq(t)->core_enabled = enabled;
 
-               for_each_cpu(t, smt_mask)
-                       raw_spin_unlock(&cpu_rq(t)->__lock);
-               local_irq_enable();
+               sched_core_unlock(cpu, &flags);
 
                cpumask_andnot(&sched_core_mask, &sched_core_mask, smt_mask);
        }
@@ -1981,12 +1995,18 @@ void deactivate_task(struct rq *rq, struct task_struct *p, int flags)
        dequeue_task(rq, p, flags);
 }
 
-/*
- * __normal_prio - return the priority that is based on the static prio
- */
-static inline int __normal_prio(struct task_struct *p)
+static inline int __normal_prio(int policy, int rt_prio, int nice)
 {
-       return p->static_prio;
+       int prio;
+
+       if (dl_policy(policy))
+               prio = MAX_DL_PRIO - 1;
+       else if (rt_policy(policy))
+               prio = MAX_RT_PRIO - 1 - rt_prio;
+       else
+               prio = NICE_TO_PRIO(nice);
+
+       return prio;
 }
 
 /*
@@ -1998,15 +2018,7 @@ static inline int __normal_prio(struct task_struct *p)
  */
 static inline int normal_prio(struct task_struct *p)
 {
-       int prio;
-
-       if (task_has_dl_policy(p))
-               prio = MAX_DL_PRIO-1;
-       else if (task_has_rt_policy(p))
-               prio = MAX_RT_PRIO-1 - p->rt_priority;
-       else
-               prio = __normal_prio(p);
-       return prio;
+       return __normal_prio(p->policy, p->rt_priority, PRIO_TO_NICE(p->static_prio));
 }
 
 /*
@@ -4099,7 +4111,7 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p)
                } else if (PRIO_TO_NICE(p->static_prio) < 0)
                        p->static_prio = NICE_TO_PRIO(0);
 
-               p->prio = p->normal_prio = __normal_prio(p);
+               p->prio = p->normal_prio = p->static_prio;
                set_load_weight(p, false);
 
                /*
@@ -5738,35 +5750,109 @@ void queue_core_balance(struct rq *rq)
        queue_balance_callback(rq, &per_cpu(core_balance_head, rq->cpu), sched_core_balance);
 }
 
-static inline void sched_core_cpu_starting(unsigned int cpu)
+static void sched_core_cpu_starting(unsigned int cpu)
 {
        const struct cpumask *smt_mask = cpu_smt_mask(cpu);
-       struct rq *rq, *core_rq = NULL;
-       int i;
+       struct rq *rq = cpu_rq(cpu), *core_rq = NULL;
+       unsigned long flags;
+       int t;
+
+       sched_core_lock(cpu, &flags);
 
-       core_rq = cpu_rq(cpu)->core;
+       WARN_ON_ONCE(rq->core != rq);
 
-       if (!core_rq) {
-               for_each_cpu(i, smt_mask) {
-                       rq = cpu_rq(i);
-                       if (rq->core && rq->core == rq)
-                               core_rq = rq;
+       /* if we're the first, we'll be our own leader */
+       if (cpumask_weight(smt_mask) == 1)
+               goto unlock;
+
+       /* find the leader */
+       for_each_cpu(t, smt_mask) {
+               if (t == cpu)
+                       continue;
+               rq = cpu_rq(t);
+               if (rq->core == rq) {
+                       core_rq = rq;
+                       break;
                }
+       }
 
-               if (!core_rq)
-                       core_rq = cpu_rq(cpu);
+       if (WARN_ON_ONCE(!core_rq)) /* whoopsie */
+               goto unlock;
 
-               for_each_cpu(i, smt_mask) {
-                       rq = cpu_rq(i);
+       /* install and validate core_rq */
+       for_each_cpu(t, smt_mask) {
+               rq = cpu_rq(t);
 
-                       WARN_ON_ONCE(rq->core && rq->core != core_rq);
+               if (t == cpu)
                        rq->core = core_rq;
-               }
+
+               WARN_ON_ONCE(rq->core != core_rq);
+       }
+
+unlock:
+       sched_core_unlock(cpu, &flags);
+}
+
+static void sched_core_cpu_deactivate(unsigned int cpu)
+{
+       const struct cpumask *smt_mask = cpu_smt_mask(cpu);
+       struct rq *rq = cpu_rq(cpu), *core_rq = NULL;
+       unsigned long flags;
+       int t;
+
+       sched_core_lock(cpu, &flags);
+
+       /* if we're the last man standing, nothing to do */
+       if (cpumask_weight(smt_mask) == 1) {
+               WARN_ON_ONCE(rq->core != rq);
+               goto unlock;
        }
+
+       /* if we're not the leader, nothing to do */
+       if (rq->core != rq)
+               goto unlock;
+
+       /* find a new leader */
+       for_each_cpu(t, smt_mask) {
+               if (t == cpu)
+                       continue;
+               core_rq = cpu_rq(t);
+               break;
+       }
+
+       if (WARN_ON_ONCE(!core_rq)) /* impossible */
+               goto unlock;
+
+       /* copy the shared state to the new leader */
+       core_rq->core_task_seq      = rq->core_task_seq;
+       core_rq->core_pick_seq      = rq->core_pick_seq;
+       core_rq->core_cookie        = rq->core_cookie;
+       core_rq->core_forceidle     = rq->core_forceidle;
+       core_rq->core_forceidle_seq = rq->core_forceidle_seq;
+
+       /* install new leader */
+       for_each_cpu(t, smt_mask) {
+               rq = cpu_rq(t);
+               rq->core = core_rq;
+       }
+
+unlock:
+       sched_core_unlock(cpu, &flags);
 }
+
+static inline void sched_core_cpu_dying(unsigned int cpu)
+{
+       struct rq *rq = cpu_rq(cpu);
+
+       if (rq->core != rq)
+               rq->core = rq;
+}
+
 #else /* !CONFIG_SCHED_CORE */
 
 static inline void sched_core_cpu_starting(unsigned int cpu) {}
+static inline void sched_core_cpu_deactivate(unsigned int cpu) {}
+static inline void sched_core_cpu_dying(unsigned int cpu) {}
 
 static struct task_struct *
 pick_next_task(struct rq *rq, struct task_struct *prev, struct rq_flags *rf)
@@ -6341,6 +6427,18 @@ int default_wake_function(wait_queue_entry_t *curr, unsigned mode, int wake_flag
 }
 EXPORT_SYMBOL(default_wake_function);
 
+static void __setscheduler_prio(struct task_struct *p, int prio)
+{
+       if (dl_prio(prio))
+               p->sched_class = &dl_sched_class;
+       else if (rt_prio(prio))
+               p->sched_class = &rt_sched_class;
+       else
+               p->sched_class = &fair_sched_class;
+
+       p->prio = prio;
+}
+
 #ifdef CONFIG_RT_MUTEXES
 
 static inline int __rt_effective_prio(struct task_struct *pi_task, int prio)
@@ -6456,22 +6554,19 @@ void rt_mutex_setprio(struct task_struct *p, struct task_struct *pi_task)
                } else {
                        p->dl.pi_se = &p->dl;
                }
-               p->sched_class = &dl_sched_class;
        } else if (rt_prio(prio)) {
                if (dl_prio(oldprio))
                        p->dl.pi_se = &p->dl;
                if (oldprio < prio)
                        queue_flag |= ENQUEUE_HEAD;
-               p->sched_class = &rt_sched_class;
        } else {
                if (dl_prio(oldprio))
                        p->dl.pi_se = &p->dl;
                if (rt_prio(oldprio))
                        p->rt.timeout = 0;
-               p->sched_class = &fair_sched_class;
        }
 
-       p->prio = prio;
+       __setscheduler_prio(p, prio);
 
        if (queued)
                enqueue_task(rq, p, queue_flag);
@@ -6824,35 +6919,6 @@ static void __setscheduler_params(struct task_struct *p,
        set_load_weight(p, true);
 }
 
-/* Actually do priority change: must hold pi & rq lock. */
-static void __setscheduler(struct rq *rq, struct task_struct *p,
-                          const struct sched_attr *attr, bool keep_boost)
-{
-       /*
-        * If params can't change scheduling class changes aren't allowed
-        * either.
-        */
-       if (attr->sched_flags & SCHED_FLAG_KEEP_PARAMS)
-               return;
-
-       __setscheduler_params(p, attr);
-
-       /*
-        * Keep a potential priority boosting if called from
-        * sched_setscheduler().
-        */
-       p->prio = normal_prio(p);
-       if (keep_boost)
-               p->prio = rt_effective_prio(p, p->prio);
-
-       if (dl_prio(p->prio))
-               p->sched_class = &dl_sched_class;
-       else if (rt_prio(p->prio))
-               p->sched_class = &rt_sched_class;
-       else
-               p->sched_class = &fair_sched_class;
-}
-
 /*
  * Check the target process has a UID that matches the current process's:
  */
@@ -6873,10 +6939,8 @@ static int __sched_setscheduler(struct task_struct *p,
                                const struct sched_attr *attr,
                                bool user, bool pi)
 {
-       int newprio = dl_policy(attr->sched_policy) ? MAX_DL_PRIO - 1 :
-                     MAX_RT_PRIO - 1 - attr->sched_priority;
-       int retval, oldprio, oldpolicy = -1, queued, running;
-       int new_effective_prio, policy = attr->sched_policy;
+       int oldpolicy = -1, policy = attr->sched_policy;
+       int retval, oldprio, newprio, queued, running;
        const struct sched_class *prev_class;
        struct callback_head *head;
        struct rq_flags rf;
@@ -7074,6 +7138,7 @@ change:
        p->sched_reset_on_fork = reset_on_fork;
        oldprio = p->prio;
 
+       newprio = __normal_prio(policy, attr->sched_priority, attr->sched_nice);
        if (pi) {
                /*
                 * Take priority boosted tasks into account. If the new
@@ -7082,8 +7147,8 @@ change:
                 * the runqueue. This will be done when the task deboost
                 * itself.
                 */
-               new_effective_prio = rt_effective_prio(p, newprio);
-               if (new_effective_prio == oldprio)
+               newprio = rt_effective_prio(p, newprio);
+               if (newprio == oldprio)
                        queue_flags &= ~DEQUEUE_MOVE;
        }
 
@@ -7096,7 +7161,10 @@ change:
 
        prev_class = p->sched_class;
 
-       __setscheduler(rq, p, attr, pi);
+       if (!(attr->sched_flags & SCHED_FLAG_KEEP_PARAMS)) {
+               __setscheduler_params(p, attr);
+               __setscheduler_prio(p, newprio);
+       }
        __setscheduler_uclamp(p, attr);
 
        if (queued) {
@@ -8727,6 +8795,8 @@ int sched_cpu_deactivate(unsigned int cpu)
         */
        if (cpumask_weight(cpu_smt_mask(cpu)) == 2)
                static_branch_dec_cpuslocked(&sched_smt_present);
+
+       sched_core_cpu_deactivate(cpu);
 #endif
 
        if (!sched_smp_initialized)
@@ -8831,6 +8901,7 @@ int sched_cpu_dying(unsigned int cpu)
        calc_load_migrate(rq);
        update_max_interval();
        hrtick_clear(rq);
+       sched_core_cpu_dying(cpu);
        return 0;
 }
 #endif
@@ -9042,7 +9113,7 @@ void __init sched_init(void)
                atomic_set(&rq->nr_iowait, 0);
 
 #ifdef CONFIG_SCHED_CORE
-               rq->core = NULL;
+               rq->core = rq;
                rq->core_pick = NULL;
                rq->core_enabled = 0;
                rq->core_tree = RB_ROOT;
index 14a41a2..ddefb04 100644 (file)
@@ -1093,7 +1093,7 @@ struct rq {
        unsigned int            core_sched_seq;
        struct rb_root          core_tree;
 
-       /* shared state */
+       /* shared state -- careful with sched_core_cpu_deactivate() */
        unsigned int            core_task_seq;
        unsigned int            core_pick_seq;
        unsigned long           core_cookie;
@@ -2255,6 +2255,9 @@ static inline struct task_struct *get_push_task(struct rq *rq)
        if (p->nr_cpus_allowed == 1)
                return NULL;
 
+       if (p->migration_disabled)
+               return NULL;
+
        rq->push_busy = true;
        return get_task_struct(p);
 }
index 057e17f..6469eca 100644 (file)
@@ -602,7 +602,7 @@ static inline void seccomp_sync_threads(unsigned long flags)
                smp_store_release(&thread->seccomp.filter,
                                  caller->seccomp.filter);
                atomic_set(&thread->seccomp.filter_count,
-                          atomic_read(&thread->seccomp.filter_count));
+                          atomic_read(&caller->seccomp.filter_count));
 
                /*
                 * Don't let an unprivileged task work around
index 9eb11c2..e3d2c23 100644 (file)
@@ -1265,8 +1265,10 @@ static inline void timer_base_unlock_expiry(struct timer_base *base)
 static void timer_sync_wait_running(struct timer_base *base)
 {
        if (atomic_read(&base->timer_waiters)) {
+               raw_spin_unlock_irq(&base->lock);
                spin_unlock(&base->expiry_lock);
                spin_lock(&base->expiry_lock);
+               raw_spin_lock_irq(&base->lock);
        }
 }
 
@@ -1457,14 +1459,14 @@ static void expire_timers(struct timer_base *base, struct hlist_head *head)
                if (timer->flags & TIMER_IRQSAFE) {
                        raw_spin_unlock(&base->lock);
                        call_timer_fn(timer, fn, baseclk);
-                       base->running_timer = NULL;
                        raw_spin_lock(&base->lock);
+                       base->running_timer = NULL;
                } else {
                        raw_spin_unlock_irq(&base->lock);
                        call_timer_fn(timer, fn, baseclk);
+                       raw_spin_lock_irq(&base->lock);
                        base->running_timer = NULL;
                        timer_sync_wait_running(base);
-                       raw_spin_lock_irq(&base->lock);
                }
        }
 }
index d567b17..3ee23f4 100644 (file)
@@ -219,6 +219,11 @@ config DYNAMIC_FTRACE_WITH_DIRECT_CALLS
        depends on DYNAMIC_FTRACE_WITH_REGS
        depends on HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS
 
+config DYNAMIC_FTRACE_WITH_ARGS
+       def_bool y
+       depends on DYNAMIC_FTRACE
+       depends on HAVE_DYNAMIC_FTRACE_WITH_ARGS
+
 config FUNCTION_PROFILER
        bool "Kernel function profiler"
        depends on FUNCTION_TRACER
index b4916ef..fdd1407 100644 (file)
@@ -990,28 +990,29 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_get_numa_node_id_proto;
        case BPF_FUNC_perf_event_read:
                return &bpf_perf_event_read_proto;
-       case BPF_FUNC_probe_write_user:
-               return bpf_get_probe_write_proto();
        case BPF_FUNC_current_task_under_cgroup:
                return &bpf_current_task_under_cgroup_proto;
        case BPF_FUNC_get_prandom_u32:
                return &bpf_get_prandom_u32_proto;
+       case BPF_FUNC_probe_write_user:
+               return security_locked_down(LOCKDOWN_BPF_WRITE_USER) < 0 ?
+                      NULL : bpf_get_probe_write_proto();
        case BPF_FUNC_probe_read_user:
                return &bpf_probe_read_user_proto;
        case BPF_FUNC_probe_read_kernel:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_kernel_proto;
        case BPF_FUNC_probe_read_user_str:
                return &bpf_probe_read_user_str_proto;
        case BPF_FUNC_probe_read_kernel_str:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_kernel_str_proto;
 #ifdef CONFIG_ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
        case BPF_FUNC_probe_read:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_compat_proto;
        case BPF_FUNC_probe_read_str:
-               return security_locked_down(LOCKDOWN_BPF_READ) < 0 ?
+               return security_locked_down(LOCKDOWN_BPF_READ_KERNEL) < 0 ?
                       NULL : &bpf_probe_read_compat_str_proto;
 #endif
 #ifdef CONFIG_CGROUPS
index 33899a7..a1adb29 100644 (file)
@@ -2897,14 +2897,26 @@ int tracepoint_printk_sysctl(struct ctl_table *table, int write,
 
 void trace_event_buffer_commit(struct trace_event_buffer *fbuffer)
 {
+       enum event_trigger_type tt = ETT_NONE;
+       struct trace_event_file *file = fbuffer->trace_file;
+
+       if (__event_trigger_test_discard(file, fbuffer->buffer, fbuffer->event,
+                       fbuffer->entry, &tt))
+               goto discard;
+
        if (static_key_false(&tracepoint_printk_key.key))
                output_printk(fbuffer);
 
        if (static_branch_unlikely(&trace_event_exports_enabled))
                ftrace_exports(fbuffer->event, TRACE_EXPORT_EVENT);
-       event_trigger_unlock_commit_regs(fbuffer->trace_file, fbuffer->buffer,
-                                   fbuffer->event, fbuffer->entry,
-                                   fbuffer->trace_ctx, fbuffer->regs);
+
+       trace_buffer_unlock_commit_regs(file->tr, fbuffer->buffer,
+                       fbuffer->event, fbuffer->trace_ctx, fbuffer->regs);
+
+discard:
+       if (tt)
+               event_triggers_post_call(file, tt);
+
 }
 EXPORT_SYMBOL_GPL(trace_event_buffer_commit);
 
index a180abf..4a0e693 100644 (file)
@@ -1389,38 +1389,6 @@ event_trigger_unlock_commit(struct trace_event_file *file,
                event_triggers_post_call(file, tt);
 }
 
-/**
- * event_trigger_unlock_commit_regs - handle triggers and finish event commit
- * @file: The file pointer associated with the event
- * @buffer: The ring buffer that the event is being written to
- * @event: The event meta data in the ring buffer
- * @entry: The event itself
- * @trace_ctx: The tracing context flags.
- *
- * This is a helper function to handle triggers that require data
- * from the event itself. It also tests the event against filters and
- * if the event is soft disabled and should be discarded.
- *
- * Same as event_trigger_unlock_commit() but calls
- * trace_buffer_unlock_commit_regs() instead of trace_buffer_unlock_commit().
- */
-static inline void
-event_trigger_unlock_commit_regs(struct trace_event_file *file,
-                                struct trace_buffer *buffer,
-                                struct ring_buffer_event *event,
-                                void *entry, unsigned int trace_ctx,
-                                struct pt_regs *regs)
-{
-       enum event_trigger_type tt = ETT_NONE;
-
-       if (!__event_trigger_test_discard(file, buffer, event, entry, &tt))
-               trace_buffer_unlock_commit_regs(file->tr, buffer, event,
-                                               trace_ctx, regs);
-
-       if (tt)
-               event_triggers_post_call(file, tt);
-}
-
 #define FILTER_PRED_INVALID    ((unsigned short)-1)
 #define FILTER_PRED_IS_RIGHT   (1 << 15)
 #define FILTER_PRED_FOLD       (1 << 15)
index 949ef09..a48aa2a 100644 (file)
@@ -3430,6 +3430,8 @@ trace_action_create_field_var(struct hist_trigger_data *hist_data,
                        event = data->match_data.event;
                }
 
+               if (!event)
+                       goto free;
                /*
                 * At this point, we're looking at a field on another
                 * event.  Because we can't modify a hist trigger on
index a7e3c24..b61eefe 100644 (file)
@@ -253,10 +253,40 @@ static struct osnoise_data {
  */
 static bool osnoise_busy;
 
+#ifdef CONFIG_PREEMPT_RT
 /*
  * Print the osnoise header info.
  */
 static void print_osnoise_headers(struct seq_file *s)
+{
+       if (osnoise_data.tainted)
+               seq_puts(s, "# osnoise is tainted!\n");
+
+       seq_puts(s, "#                                _-------=> irqs-off\n");
+       seq_puts(s, "#                               / _------=> need-resched\n");
+       seq_puts(s, "#                              | / _-----=> need-resched-lazy\n");
+       seq_puts(s, "#                              || / _----=> hardirq/softirq\n");
+       seq_puts(s, "#                              ||| / _---=> preempt-depth\n");
+       seq_puts(s, "#                              |||| / _--=> preempt-lazy-depth\n");
+       seq_puts(s, "#                              ||||| / _-=> migrate-disable\n");
+
+       seq_puts(s, "#                              |||||| /          ");
+       seq_puts(s, "                                     MAX\n");
+
+       seq_puts(s, "#                              ||||| /                         ");
+       seq_puts(s, "                    SINGLE      Interference counters:\n");
+
+       seq_puts(s, "#                              |||||||               RUNTIME   ");
+       seq_puts(s, "   NOISE  %% OF CPU  NOISE    +-----------------------------+\n");
+
+       seq_puts(s, "#           TASK-PID      CPU# |||||||   TIMESTAMP    IN US    ");
+       seq_puts(s, "   IN US  AVAILABLE  IN US     HW    NMI    IRQ   SIRQ THREAD\n");
+
+       seq_puts(s, "#              | |         |   |||||||      |           |      ");
+       seq_puts(s, "       |    |            |      |      |      |      |      |\n");
+}
+#else /* CONFIG_PREEMPT_RT */
+static void print_osnoise_headers(struct seq_file *s)
 {
        if (osnoise_data.tainted)
                seq_puts(s, "# osnoise is tainted!\n");
@@ -279,6 +309,7 @@ static void print_osnoise_headers(struct seq_file *s)
        seq_puts(s, "#              | |         |   ||||      |           |      ");
        seq_puts(s, "       |    |            |      |      |      |      |      |\n");
 }
+#endif /* CONFIG_PREEMPT_RT */
 
 /*
  * osnoise_taint - report an osnoise error.
@@ -323,6 +354,24 @@ static void trace_osnoise_sample(struct osnoise_sample *sample)
 /*
  * Print the timerlat header info.
  */
+#ifdef CONFIG_PREEMPT_RT
+static void print_timerlat_headers(struct seq_file *s)
+{
+       seq_puts(s, "#                                _-------=> irqs-off\n");
+       seq_puts(s, "#                               / _------=> need-resched\n");
+       seq_puts(s, "#                              | / _-----=> need-resched-lazy\n");
+       seq_puts(s, "#                              || / _----=> hardirq/softirq\n");
+       seq_puts(s, "#                              ||| / _---=> preempt-depth\n");
+       seq_puts(s, "#                              |||| / _--=> preempt-lazy-depth\n");
+       seq_puts(s, "#                              ||||| / _-=> migrate-disable\n");
+       seq_puts(s, "#                              |||||| /\n");
+       seq_puts(s, "#                              |||||||             ACTIVATION\n");
+       seq_puts(s, "#           TASK-PID      CPU# |||||||   TIMESTAMP    ID     ");
+       seq_puts(s, "       CONTEXT                LATENCY\n");
+       seq_puts(s, "#              | |         |   |||||||      |         |      ");
+       seq_puts(s, "            |                       |\n");
+}
+#else /* CONFIG_PREEMPT_RT */
 static void print_timerlat_headers(struct seq_file *s)
 {
        seq_puts(s, "#                                _-----=> irqs-off\n");
@@ -336,6 +385,7 @@ static void print_timerlat_headers(struct seq_file *s)
        seq_puts(s, "#              | |         |   ||||      |         |      ");
        seq_puts(s, "            |                       |\n");
 }
+#endif /* CONFIG_PREEMPT_RT */
 
 /*
  * Record an timerlat_sample into the tracer buffer.
@@ -1025,9 +1075,13 @@ diff_osn_sample_stats(struct osnoise_variables *osn_var, struct osnoise_sample *
 /*
  * osnoise_stop_tracing - Stop tracing and the tracer.
  */
-static void osnoise_stop_tracing(void)
+static __always_inline void osnoise_stop_tracing(void)
 {
        struct trace_array *tr = osnoise_trace;
+
+       trace_array_printk_buf(tr->array_buffer.buffer, _THIS_IP_,
+                       "stop tracing hit on cpu %d\n", smp_processor_id());
+
        tracer_tracing_off(tr);
 }
 
index fc32821..efd14c7 100644 (file)
 #include <linux/sched/task.h>
 #include <linux/static_key.h>
 
+enum tp_func_state {
+       TP_FUNC_0,
+       TP_FUNC_1,
+       TP_FUNC_2,
+       TP_FUNC_N,
+};
+
 extern tracepoint_ptr_t __start___tracepoints_ptrs[];
 extern tracepoint_ptr_t __stop___tracepoints_ptrs[];
 
 DEFINE_SRCU(tracepoint_srcu);
 EXPORT_SYMBOL_GPL(tracepoint_srcu);
 
+enum tp_transition_sync {
+       TP_TRANSITION_SYNC_1_0_1,
+       TP_TRANSITION_SYNC_N_2_1,
+
+       _NR_TP_TRANSITION_SYNC,
+};
+
+struct tp_transition_snapshot {
+       unsigned long rcu;
+       unsigned long srcu;
+       bool ongoing;
+};
+
+/* Protected by tracepoints_mutex */
+static struct tp_transition_snapshot tp_transition_snapshot[_NR_TP_TRANSITION_SYNC];
+
+static void tp_rcu_get_state(enum tp_transition_sync sync)
+{
+       struct tp_transition_snapshot *snapshot = &tp_transition_snapshot[sync];
+
+       /* Keep the latest get_state snapshot. */
+       snapshot->rcu = get_state_synchronize_rcu();
+       snapshot->srcu = start_poll_synchronize_srcu(&tracepoint_srcu);
+       snapshot->ongoing = true;
+}
+
+static void tp_rcu_cond_sync(enum tp_transition_sync sync)
+{
+       struct tp_transition_snapshot *snapshot = &tp_transition_snapshot[sync];
+
+       if (!snapshot->ongoing)
+               return;
+       cond_synchronize_rcu(snapshot->rcu);
+       if (!poll_state_synchronize_srcu(&tracepoint_srcu, snapshot->srcu))
+               synchronize_srcu(&tracepoint_srcu);
+       snapshot->ongoing = false;
+}
+
 /* Set to 1 to enable tracepoint debug output */
 static const int tracepoint_debug;
 
@@ -246,26 +291,29 @@ static void *func_remove(struct tracepoint_func **funcs,
        return old;
 }
 
-static void tracepoint_update_call(struct tracepoint *tp, struct tracepoint_func *tp_funcs, bool sync)
+/*
+ * Count the number of functions (enum tp_func_state) in a tp_funcs array.
+ */
+static enum tp_func_state nr_func_state(const struct tracepoint_func *tp_funcs)
+{
+       if (!tp_funcs)
+               return TP_FUNC_0;
+       if (!tp_funcs[1].func)
+               return TP_FUNC_1;
+       if (!tp_funcs[2].func)
+               return TP_FUNC_2;
+       return TP_FUNC_N;       /* 3 or more */
+}
+
+static void tracepoint_update_call(struct tracepoint *tp, struct tracepoint_func *tp_funcs)
 {
        void *func = tp->iterator;
 
        /* Synthetic events do not have static call sites */
        if (!tp->static_call_key)
                return;
-
-       if (!tp_funcs[1].func) {
+       if (nr_func_state(tp_funcs) == TP_FUNC_1)
                func = tp_funcs[0].func;
-               /*
-                * If going from the iterator back to a single caller,
-                * we need to synchronize with __DO_TRACE to make sure
-                * that the data passed to the callback is the one that
-                * belongs to that callback.
-                */
-               if (sync)
-                       tracepoint_synchronize_unregister();
-       }
-
        __static_call_update(tp->static_call_key, tp->static_call_tramp, func);
 }
 
@@ -299,9 +347,41 @@ static int tracepoint_add_func(struct tracepoint *tp,
         * a pointer to it.  This array is referenced by __DO_TRACE from
         * include/linux/tracepoint.h using rcu_dereference_sched().
         */
-       tracepoint_update_call(tp, tp_funcs, false);
-       rcu_assign_pointer(tp->funcs, tp_funcs);
-       static_key_enable(&tp->key);
+       switch (nr_func_state(tp_funcs)) {
+       case TP_FUNC_1:         /* 0->1 */
+               /*
+                * Make sure new static func never uses old data after a
+                * 1->0->1 transition sequence.
+                */
+               tp_rcu_cond_sync(TP_TRANSITION_SYNC_1_0_1);
+               /* Set static call to first function */
+               tracepoint_update_call(tp, tp_funcs);
+               /* Both iterator and static call handle NULL tp->funcs */
+               rcu_assign_pointer(tp->funcs, tp_funcs);
+               static_key_enable(&tp->key);
+               break;
+       case TP_FUNC_2:         /* 1->2 */
+               /* Set iterator static call */
+               tracepoint_update_call(tp, tp_funcs);
+               /*
+                * Iterator callback installed before updating tp->funcs.
+                * Requires ordering between RCU assign/dereference and
+                * static call update/call.
+                */
+               fallthrough;
+       case TP_FUNC_N:         /* N->N+1 (N>1) */
+               rcu_assign_pointer(tp->funcs, tp_funcs);
+               /*
+                * Make sure static func never uses incorrect data after a
+                * N->...->2->1 (N>1) transition sequence.
+                */
+               if (tp_funcs[0].data != old[0].data)
+                       tp_rcu_get_state(TP_TRANSITION_SYNC_N_2_1);
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               break;
+       }
 
        release_probes(old);
        return 0;
@@ -328,17 +408,52 @@ static int tracepoint_remove_func(struct tracepoint *tp,
                /* Failed allocating new tp_funcs, replaced func with stub */
                return 0;
 
-       if (!tp_funcs) {
+       switch (nr_func_state(tp_funcs)) {
+       case TP_FUNC_0:         /* 1->0 */
                /* Removed last function */
                if (tp->unregfunc && static_key_enabled(&tp->key))
                        tp->unregfunc();
 
                static_key_disable(&tp->key);
+               /* Set iterator static call */
+               tracepoint_update_call(tp, tp_funcs);
+               /* Both iterator and static call handle NULL tp->funcs */
+               rcu_assign_pointer(tp->funcs, NULL);
+               /*
+                * Make sure new static func never uses old data after a
+                * 1->0->1 transition sequence.
+                */
+               tp_rcu_get_state(TP_TRANSITION_SYNC_1_0_1);
+               break;
+       case TP_FUNC_1:         /* 2->1 */
                rcu_assign_pointer(tp->funcs, tp_funcs);
-       } else {
+               /*
+                * Make sure static func never uses incorrect data after a
+                * N->...->2->1 (N>2) transition sequence. If the first
+                * element's data has changed, then force the synchronization
+                * to prevent current readers that have loaded the old data
+                * from calling the new function.
+                */
+               if (tp_funcs[0].data != old[0].data)
+                       tp_rcu_get_state(TP_TRANSITION_SYNC_N_2_1);
+               tp_rcu_cond_sync(TP_TRANSITION_SYNC_N_2_1);
+               /* Set static call to first function */
+               tracepoint_update_call(tp, tp_funcs);
+               break;
+       case TP_FUNC_2:         /* N->N-1 (N>2) */
+               fallthrough;
+       case TP_FUNC_N:
                rcu_assign_pointer(tp->funcs, tp_funcs);
-               tracepoint_update_call(tp, tp_funcs,
-                                      tp_funcs[0].func != old[0].func);
+               /*
+                * Make sure static func never uses incorrect data after a
+                * N->...->2->1 (N>2) transition sequence.
+                */
+               if (tp_funcs[0].data != old[0].data)
+                       tp_rcu_get_state(TP_TRANSITION_SYNC_N_2_1);
+               break;
+       default:
+               WARN_ON_ONCE(1);
+               break;
        }
        release_probes(old);
        return 0;
index 77be3bb..bb51849 100644 (file)
@@ -58,14 +58,17 @@ static struct ctl_table_root set_root = {
        .permissions = set_permissions,
 };
 
-#define UCOUNT_ENTRY(name)                             \
-       {                                               \
-               .procname       = name,                 \
-               .maxlen         = sizeof(int),          \
-               .mode           = 0644,                 \
-               .proc_handler   = proc_dointvec_minmax, \
-               .extra1         = SYSCTL_ZERO,          \
-               .extra2         = SYSCTL_INT_MAX,       \
+static long ue_zero = 0;
+static long ue_int_max = INT_MAX;
+
+#define UCOUNT_ENTRY(name)                                     \
+       {                                                       \
+               .procname       = name,                         \
+               .maxlen         = sizeof(long),                 \
+               .mode           = 0644,                         \
+               .proc_handler   = proc_doulongvec_minmax,       \
+               .extra1         = &ue_zero,                     \
+               .extra2         = &ue_int_max,                  \
        }
 static struct ctl_table user_table[] = {
        UCOUNT_ENTRY("max_user_namespaces"),
index c0d67c5..60be9e2 100644 (file)
@@ -19,7 +19,7 @@
  */
 int devmem_is_allowed(unsigned long pfn)
 {
-       if (iomem_is_exclusive(pfn << PAGE_SHIFT))
+       if (iomem_is_exclusive(PFN_PHYS(pfn)))
                return 0;
        if (!page_is_ram(pfn))
                return 1;
index 8b7d623..59149bf 100644 (file)
@@ -3,10 +3,12 @@
 #include <linux/spinlock.h>
 #include <linux/once.h>
 #include <linux/random.h>
+#include <linux/module.h>
 
 struct once_work {
        struct work_struct work;
        struct static_key_true *key;
+       struct module *module;
 };
 
 static void once_deferred(struct work_struct *w)
@@ -16,10 +18,11 @@ static void once_deferred(struct work_struct *w)
        work = container_of(w, struct once_work, work);
        BUG_ON(!static_key_enabled(work->key));
        static_branch_disable(work->key);
+       module_put(work->module);
        kfree(work);
 }
 
-static void once_disable_jump(struct static_key_true *key)
+static void once_disable_jump(struct static_key_true *key, struct module *mod)
 {
        struct once_work *w;
 
@@ -29,6 +32,8 @@ static void once_disable_jump(struct static_key_true *key)
 
        INIT_WORK(&w->work, once_deferred);
        w->key = key;
+       w->module = mod;
+       __module_get(mod);
        schedule_work(&w->work);
 }
 
@@ -53,11 +58,11 @@ bool __do_once_start(bool *done, unsigned long *flags)
 EXPORT_SYMBOL(__do_once_start);
 
 void __do_once_done(bool *done, struct static_key_true *once_key,
-                   unsigned long *flags)
+                   unsigned long *flags, struct module *mod)
        __releases(once_lock)
 {
        *done = true;
        spin_unlock_irqrestore(&once_lock, *flags);
-       once_disable_jump(once_key);
+       once_disable_jump(once_key, mod);
 }
 EXPORT_SYMBOL(__do_once_done);
index 77bd0b1..b2de45a 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 
+#include <asm/unaligned.h>
 #include <asm/byteorder.h>
 #include <asm/word-at-a-time.h>
 #include <asm/page.h>
@@ -935,6 +936,21 @@ __visible int memcmp(const void *cs, const void *ct, size_t count)
        const unsigned char *su1, *su2;
        int res = 0;
 
+#ifdef CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS
+       if (count >= sizeof(unsigned long)) {
+               const unsigned long *u1 = cs;
+               const unsigned long *u2 = ct;
+               do {
+                       if (get_unaligned(u1) != get_unaligned(u2))
+                               break;
+                       u1++;
+                       u2++;
+                       count -= sizeof(unsigned long);
+               } while (count >= sizeof(unsigned long));
+               cs = u1;
+               ct = u2;
+       }
+#endif
        for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--)
                if ((res = *su1 - *su2) != 0)
                        break;
index 42b8b1f..b947179 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1558,9 +1558,12 @@ long faultin_vma_page_range(struct vm_area_struct *vma, unsigned long start,
                gup_flags |= FOLL_WRITE;
 
        /*
-        * See check_vma_flags(): Will return -EFAULT on incompatible mappings
-        * or with insufficient permissions.
+        * We want to report -EINVAL instead of -EFAULT for any permission
+        * problems or incompatible mappings.
         */
+       if (check_vma_flags(vma, gup_flags))
+               return -EINVAL;
+
        return __get_user_pages(mm, start, nr_pages, gup_flags,
                                NULL, NULL, locked);
 }
index dfc940d..8ea35ba 100644 (file)
@@ -2476,7 +2476,7 @@ void restore_reserve_on_error(struct hstate *h, struct vm_area_struct *vma,
                if (!rc) {
                        /*
                         * This indicates there is an entry in the reserve map
-                        * added by alloc_huge_page.  We know it was added
+                        * not added by alloc_huge_page.  We know it was added
                         * before the alloc_huge_page call, otherwise
                         * HPageRestoreReserve would be set on the page.
                         * Remove the entry so that a subsequent allocation
@@ -4660,7 +4660,9 @@ retry_avoidcopy:
        spin_unlock(ptl);
        mmu_notifier_invalidate_range_end(&range);
 out_release_all:
-       restore_reserve_on_error(h, vma, haddr, new_page);
+       /* No restore in case of successful pagetable update (Break COW) */
+       if (new_page != old_page)
+               restore_reserve_on_error(h, vma, haddr, new_page);
        put_page(new_page);
 out_release_old:
        put_page(old_page);
@@ -4776,7 +4778,7 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
        pte_t new_pte;
        spinlock_t *ptl;
        unsigned long haddr = address & huge_page_mask(h);
-       bool new_page = false;
+       bool new_page, new_pagecache_page = false;
 
        /*
         * Currently, we are forced to kill the process in the event the
@@ -4799,6 +4801,7 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
                goto out;
 
 retry:
+       new_page = false;
        page = find_lock_page(mapping, idx);
        if (!page) {
                /* Check for page in userfault range */
@@ -4842,6 +4845,7 @@ retry:
                                        goto retry;
                                goto out;
                        }
+                       new_pagecache_page = true;
                } else {
                        lock_page(page);
                        if (unlikely(anon_vma_prepare(vma))) {
@@ -4926,7 +4930,9 @@ backout:
        spin_unlock(ptl);
 backout_unlocked:
        unlock_page(page);
-       restore_reserve_on_error(h, vma, haddr, page);
+       /* restore reserve for newly allocated pages not in page cache */
+       if (new_page && !new_pagecache_page)
+               restore_reserve_on_error(h, vma, haddr, page);
        put_page(page);
        goto out;
 }
@@ -5135,6 +5141,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
        int ret = -ENOMEM;
        struct page *page;
        int writable;
+       bool new_pagecache_page = false;
 
        if (is_continue) {
                ret = -EFAULT;
@@ -5228,6 +5235,7 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm,
                ret = huge_add_to_page_cache(page, mapping, idx);
                if (ret)
                        goto out_release_nounlock;
+               new_pagecache_page = true;
        }
 
        ptl = huge_pte_lockptr(h, dst_mm, dst_pte);
@@ -5291,7 +5299,8 @@ out_release_unlock:
        if (vm_shared || is_continue)
                unlock_page(page);
 out_release_nounlock:
-       restore_reserve_on_error(h, dst_vma, dst_addr, page);
+       if (!new_pagecache_page)
+               restore_reserve_on_error(h, dst_vma, dst_addr, page);
        put_page(page);
        goto out;
 }
index 228a2fb..73d46d1 100644 (file)
@@ -290,7 +290,7 @@ static void hex_dump_object(struct seq_file *seq,
        warn_or_seq_printf(seq, "  hex dump (first %zu bytes):\n", len);
        kasan_disable_current();
        warn_or_seq_hex_dump(seq, DUMP_PREFIX_NONE, HEX_ROW_SIZE,
-                            HEX_GROUP_SIZE, ptr, len, HEX_ASCII);
+                            HEX_GROUP_SIZE, kasan_reset_tag((void *)ptr), len, HEX_ASCII);
        kasan_enable_current();
 }
 
@@ -1171,7 +1171,7 @@ static bool update_checksum(struct kmemleak_object *object)
 
        kasan_disable_current();
        kcsan_disable_current();
-       object->checksum = crc32(0, (void *)object->pointer, object->size);
+       object->checksum = crc32(0, kasan_reset_tag((void *)object->pointer), object->size);
        kasan_enable_current();
        kcsan_enable_current();
 
@@ -1246,7 +1246,7 @@ static void scan_block(void *_start, void *_end,
                        break;
 
                kasan_disable_current();
-               pointer = *ptr;
+               pointer = *(unsigned long *)kasan_reset_tag((void *)ptr);
                kasan_enable_current();
 
                untagged_ptr = (unsigned long)kasan_reset_tag((void *)pointer);
index 6d3d348..5c065bc 100644 (file)
@@ -862,10 +862,12 @@ static long madvise_populate(struct vm_area_struct *vma,
                        switch (pages) {
                        case -EINTR:
                                return -EINTR;
-                       case -EFAULT: /* Incompatible mappings / permissions. */
+                       case -EINVAL: /* Incompatible mappings / permissions. */
                                return -EINVAL;
                        case -EHWPOISON:
                                return -EHWPOISON;
+                       case -EFAULT: /* VM_FAULT_SIGBUS or VM_FAULT_SIGSEGV */
+                               return -EFAULT;
                        default:
                                pr_warn_once("%s: unhandled return value: %ld\n",
                                             __func__, pages);
index eb8e87c..702a81d 100644 (file)
@@ -3106,13 +3106,15 @@ void mod_objcg_state(struct obj_cgroup *objcg, struct pglist_data *pgdat,
                stock->cached_pgdat = pgdat;
        } else if (stock->cached_pgdat != pgdat) {
                /* Flush the existing cached vmstat data */
+               struct pglist_data *oldpg = stock->cached_pgdat;
+
                if (stock->nr_slab_reclaimable_b) {
-                       mod_objcg_mlstate(objcg, pgdat, NR_SLAB_RECLAIMABLE_B,
+                       mod_objcg_mlstate(objcg, oldpg, NR_SLAB_RECLAIMABLE_B,
                                          stock->nr_slab_reclaimable_b);
                        stock->nr_slab_reclaimable_b = 0;
                }
                if (stock->nr_slab_unreclaimable_b) {
-                       mod_objcg_mlstate(objcg, pgdat, NR_SLAB_UNRECLAIMABLE_B,
+                       mod_objcg_mlstate(objcg, oldpg, NR_SLAB_UNRECLAIMABLE_B,
                                          stock->nr_slab_unreclaimable_b);
                        stock->nr_slab_unreclaimable_b = 0;
                }
index eefd823..470400c 100644 (file)
@@ -1146,7 +1146,7 @@ static int __get_hwpoison_page(struct page *page)
         * unexpected races caused by taking a page refcount.
         */
        if (!HWPoisonHandlable(head))
-               return 0;
+               return -EBUSY;
 
        if (PageTransHuge(head)) {
                /*
@@ -1199,9 +1199,15 @@ try_again:
                        }
                        goto out;
                } else if (ret == -EBUSY) {
-                       /* We raced with freeing huge page to buddy, retry. */
-                       if (pass++ < 3)
+                       /*
+                        * We raced with (possibly temporary) unhandlable
+                        * page, retry.
+                        */
+                       if (pass++ < 3) {
+                               shake_page(p, 1);
                                goto try_again;
+                       }
+                       ret = -EIO;
                        goto out;
                }
        }
index 8cb75b2..86c3af7 100644 (file)
@@ -1731,6 +1731,7 @@ failed_removal_isolated:
        undo_isolate_page_range(start_pfn, end_pfn, MIGRATE_MOVABLE);
        memory_notify(MEM_CANCEL_OFFLINE, &arg);
 failed_removal_pcplists_disabled:
+       lru_cache_enable();
        zone_pcp_enable(zone);
 failed_removal:
        pr_debug("memory offlining [mem %#010llx-%#010llx] failed due to %s\n",
index 856b175..eeb3a9c 100644 (file)
@@ -3453,19 +3453,10 @@ void free_unref_page_list(struct list_head *list)
                 * comment in free_unref_page.
                 */
                migratetype = get_pcppage_migratetype(page);
-               if (unlikely(migratetype >= MIGRATE_PCPTYPES)) {
-                       if (unlikely(is_migrate_isolate(migratetype))) {
-                               list_del(&page->lru);
-                               free_one_page(page_zone(page), page, pfn, 0,
-                                                       migratetype, FPI_NONE);
-                               continue;
-                       }
-
-                       /*
-                        * Non-isolated types over MIGRATE_PCPTYPES get added
-                        * to the MIGRATE_MOVABLE pcp list.
-                        */
-                       set_pcppage_migratetype(page, MIGRATE_MOVABLE);
+               if (unlikely(is_migrate_isolate(migratetype))) {
+                       list_del(&page->lru);
+                       free_one_page(page_zone(page), page, pfn, 0, migratetype, FPI_NONE);
+                       continue;
                }
 
                set_page_private(page, pfn);
@@ -3475,7 +3466,15 @@ void free_unref_page_list(struct list_head *list)
        list_for_each_entry_safe(page, next, list, lru) {
                pfn = page_private(page);
                set_page_private(page, 0);
+
+               /*
+                * Non-isolated types over MIGRATE_PCPTYPES get added
+                * to the MIGRATE_MOVABLE pcp list.
+                */
                migratetype = get_pcppage_migratetype(page);
+               if (unlikely(migratetype >= MIGRATE_PCPTYPES))
+                       migratetype = MIGRATE_MOVABLE;
+
                trace_mm_page_free_batched(page);
                free_unref_page_commit(page, pfn, migratetype, 0);
 
index 70d9ce2..dacda74 100644 (file)
@@ -1696,8 +1696,7 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        struct address_space *mapping = inode->i_mapping;
        struct shmem_inode_info *info = SHMEM_I(inode);
        struct mm_struct *charge_mm = vma ? vma->vm_mm : NULL;
-       struct swap_info_struct *si;
-       struct page *page = NULL;
+       struct page *page;
        swp_entry_t swap;
        int error;
 
@@ -1705,12 +1704,6 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        swap = radix_to_swp_entry(*pagep);
        *pagep = NULL;
 
-       /* Prevent swapoff from happening to us. */
-       si = get_swap_device(swap);
-       if (!si) {
-               error = EINVAL;
-               goto failed;
-       }
        /* Look it up and read it in.. */
        page = lookup_swap_cache(swap, NULL, 0);
        if (!page) {
@@ -1772,8 +1765,6 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index,
        swap_free(swap);
 
        *pagep = page;
-       if (si)
-               put_swap_device(si);
        return 0;
 failed:
        if (!shmem_confirm_swap(mapping, index, swap))
@@ -1784,9 +1775,6 @@ unlock:
                put_page(page);
        }
 
-       if (si)
-               put_swap_device(si);
-
        return error;
 }
 
index af984e4..f77d8cd 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -576,8 +576,8 @@ static void print_section(char *level, char *text, u8 *addr,
                          unsigned int length)
 {
        metadata_access_enable();
-       print_hex_dump(level, kasan_reset_tag(text), DUMP_PREFIX_ADDRESS,
-                       16, 1, addr, length, 1);
+       print_hex_dump(level, text, DUMP_PREFIX_ADDRESS,
+                       16, 1, kasan_reset_tag((void *)addr), length, 1);
        metadata_access_disable();
 }
 
@@ -1400,12 +1400,13 @@ check_slabs:
 static int __init setup_slub_debug(char *str)
 {
        slab_flags_t flags;
+       slab_flags_t global_flags;
        char *saved_str;
        char *slab_list;
        bool global_slub_debug_changed = false;
        bool slab_list_specified = false;
 
-       slub_debug = DEBUG_DEFAULT_FLAGS;
+       global_flags = DEBUG_DEFAULT_FLAGS;
        if (*str++ != '=' || !*str)
                /*
                 * No options specified. Switch on full debugging.
@@ -1417,7 +1418,7 @@ static int __init setup_slub_debug(char *str)
                str = parse_slub_debug_flags(str, &flags, &slab_list, true);
 
                if (!slab_list) {
-                       slub_debug = flags;
+                       global_flags = flags;
                        global_slub_debug_changed = true;
                } else {
                        slab_list_specified = true;
@@ -1426,16 +1427,18 @@ static int __init setup_slub_debug(char *str)
 
        /*
         * For backwards compatibility, a single list of flags with list of
-        * slabs means debugging is only enabled for those slabs, so the global
-        * slub_debug should be 0. We can extended that to multiple lists as
+        * slabs means debugging is only changed for those slabs, so the global
+        * slub_debug should be unchanged (0 or DEBUG_DEFAULT_FLAGS, depending
+        * on CONFIG_SLUB_DEBUG_ON). We can extended that to multiple lists as
         * long as there is no option specifying flags without a slab list.
         */
        if (slab_list_specified) {
                if (!global_slub_debug_changed)
-                       slub_debug = 0;
+                       global_flags = slub_debug;
                slub_debug_string = saved_str;
        }
 out:
+       slub_debug = global_flags;
        if (slub_debug != 0 || slub_debug_string)
                static_branch_enable(&slub_debug_enabled);
        else
@@ -3236,12 +3239,12 @@ struct detached_freelist {
        struct kmem_cache *s;
 };
 
-static inline void free_nonslab_page(struct page *page)
+static inline void free_nonslab_page(struct page *page, void *object)
 {
        unsigned int order = compound_order(page);
 
        VM_BUG_ON_PAGE(!PageCompound(page), page);
-       kfree_hook(page_address(page));
+       kfree_hook(object);
        mod_lruvec_page_state(page, NR_SLAB_UNRECLAIMABLE_B, -(PAGE_SIZE << order));
        __free_pages(page, order);
 }
@@ -3282,7 +3285,7 @@ int build_detached_freelist(struct kmem_cache *s, size_t size,
        if (!s) {
                /* Handle kalloc'ed objects */
                if (unlikely(!PageSlab(page))) {
-                       free_nonslab_page(page);
+                       free_nonslab_page(page, object);
                        p[size] = NULL; /* mark object processed */
                        return size;
                }
@@ -4258,7 +4261,7 @@ void kfree(const void *x)
 
        page = virt_to_head_page(x);
        if (unlikely(!PageSlab(page))) {
-               free_nonslab_page(page);
+               free_nonslab_page(page, object);
                return;
        }
        slab_free(page->slab_cache, page, object, NULL, 1, _RET_IP_);
index c56aa9a..bc7cee6 100644 (file)
@@ -628,13 +628,6 @@ struct page *swap_cluster_readahead(swp_entry_t entry, gfp_t gfp_mask,
        if (!mask)
                goto skip;
 
-       /* Test swap type to make sure the dereference is safe */
-       if (likely(si->flags & (SWP_BLKDEV | SWP_FS_OPS))) {
-               struct inode *inode = si->swap_file->f_mapping->host;
-               if (inode_read_congested(inode))
-                       goto skip;
-       }
-
        do_poll = false;
        /* Read a page_cluster sized and aligned cluster around offset. */
        start_offset = offset & ~mask;
index 4620df6..eeae2f6 100644 (file)
@@ -100,9 +100,12 @@ struct scan_control {
        unsigned int may_swap:1;
 
        /*
-        * Cgroups are not reclaimed below their configured memory.low,
-        * unless we threaten to OOM. If any cgroups are skipped due to
-        * memory.low and nothing was reclaimed, go back for memory.low.
+        * Cgroup memory below memory.low is protected as long as we
+        * don't threaten to OOM. If any cgroup is reclaimed at
+        * reduced force or passed over entirely due to its memory.low
+        * setting (memcg_low_skipped), and nothing is reclaimed as a
+        * result, then go back for one more cycle that reclaims the protected
+        * memory (memcg_low_reclaim) to avert OOM.
         */
        unsigned int memcg_low_reclaim:1;
        unsigned int memcg_low_skipped:1;
@@ -2537,15 +2540,14 @@ out:
        for_each_evictable_lru(lru) {
                int file = is_file_lru(lru);
                unsigned long lruvec_size;
+               unsigned long low, min;
                unsigned long scan;
-               unsigned long protection;
 
                lruvec_size = lruvec_lru_size(lruvec, lru, sc->reclaim_idx);
-               protection = mem_cgroup_protection(sc->target_mem_cgroup,
-                                                  memcg,
-                                                  sc->memcg_low_reclaim);
+               mem_cgroup_protection(sc->target_mem_cgroup, memcg,
+                                     &min, &low);
 
-               if (protection) {
+               if (min || low) {
                        /*
                         * Scale a cgroup's reclaim pressure by proportioning
                         * its current usage to its memory.low or memory.min
@@ -2576,6 +2578,15 @@ out:
                         * hard protection.
                         */
                        unsigned long cgroup_size = mem_cgroup_size(memcg);
+                       unsigned long protection;
+
+                       /* memory.low scaling, make sure we retry before OOM */
+                       if (!sc->memcg_low_reclaim && low > min) {
+                               protection = low;
+                               sc->memcg_low_skipped = 1;
+                       } else {
+                               protection = min;
+                       }
 
                        /* Avoid TOCTOU with earlier protection check */
                        cgroup_size = max(cgroup_size, protection);
@@ -4413,11 +4424,13 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
                .may_swap = 1,
                .reclaim_idx = gfp_zone(gfp_mask),
        };
+       unsigned long pflags;
 
        trace_mm_vmscan_node_reclaim_begin(pgdat->node_id, order,
                                           sc.gfp_mask);
 
        cond_resched();
+       psi_memstall_enter(&pflags);
        fs_reclaim_acquire(sc.gfp_mask);
        /*
         * We need to be able to allocate from the reserves for RECLAIM_UNMAP
@@ -4442,6 +4455,7 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
        current->flags &= ~PF_SWAPWRITE;
        memalloc_noreclaim_restore(noreclaim_flag);
        fs_reclaim_release(sc.gfp_mask);
+       psi_memstall_leave(&pflags);
 
        trace_mm_vmscan_node_reclaim_end(sc.nr_reclaimed);
 
index 1cc75c8..caa16bf 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/vmalloc.h>
 #include <linux/etherdevice.h>
 #include <linux/filter.h>
+#include <linux/rcupdate_trace.h>
 #include <linux/sched/signal.h>
 #include <net/bpf_sk_storage.h>
 #include <net/sock.h>
@@ -951,7 +952,10 @@ int bpf_prog_test_run_syscall(struct bpf_prog *prog,
                        goto out;
                }
        }
+
+       rcu_read_lock_trace();
        retval = bpf_prog_run_pin_on_cpu(prog, ctx);
+       rcu_read_unlock_trace();
 
        if (copy_to_user(&uattr->test.retval, &retval, sizeof(u32))) {
                err = -EFAULT;
index bbab998..ef743f9 100644 (file)
@@ -166,8 +166,7 @@ static int br_switchdev_event(struct notifier_block *unused,
        case SWITCHDEV_FDB_ADD_TO_BRIDGE:
                fdb_info = ptr;
                err = br_fdb_external_learn_add(br, p, fdb_info->addr,
-                                               fdb_info->vid,
-                                               fdb_info->is_local, false);
+                                               fdb_info->vid, false);
                if (err) {
                        err = notifier_from_errno(err);
                        break;
index 835cec1..5dee309 100644 (file)
@@ -1044,10 +1044,7 @@ static int __br_fdb_add(struct ndmsg *ndm, struct net_bridge *br,
                                           "FDB entry towards bridge must be permanent");
                        return -EINVAL;
                }
-
-               err = br_fdb_external_learn_add(br, p, addr, vid,
-                                               ndm->ndm_state & NUD_PERMANENT,
-                                               true);
+               err = br_fdb_external_learn_add(br, p, addr, vid, true);
        } else {
                spin_lock_bh(&br->hash_lock);
                err = fdb_add_entry(br, p, addr, ndm, nlh_flags, vid, nfea_tb);
@@ -1275,7 +1272,7 @@ void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p)
 }
 
 int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
-                             const unsigned char *addr, u16 vid, bool is_local,
+                             const unsigned char *addr, u16 vid,
                              bool swdev_notify)
 {
        struct net_bridge_fdb_entry *fdb;
@@ -1293,7 +1290,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                if (swdev_notify)
                        flags |= BIT(BR_FDB_ADDED_BY_USER);
 
-               if (is_local)
+               if (!p)
                        flags |= BIT(BR_FDB_LOCAL);
 
                fdb = fdb_create(br, p, addr, vid, flags);
@@ -1322,7 +1319,7 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                if (swdev_notify)
                        set_bit(BR_FDB_ADDED_BY_USER, &fdb->flags);
 
-               if (is_local)
+               if (!p)
                        set_bit(BR_FDB_LOCAL, &fdb->flags);
 
                if (modified)
index 6e4a323..14cd6ef 100644 (file)
@@ -616,6 +616,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev,
 
        err = dev_set_allmulti(dev, 1);
        if (err) {
+               br_multicast_del_port(p);
                kfree(p);       /* kobject not yet init'd, manually free */
                goto err1;
        }
@@ -729,6 +730,7 @@ err4:
 err3:
        sysfs_remove_link(br->ifobj, p->dev->name);
 err2:
+       br_multicast_del_port(p);
        kobject_put(&p->kobj);
        dev_set_allmulti(dev, -1);
 err1:
index aa64d8d..2b48b20 100644 (file)
@@ -711,7 +711,7 @@ int br_fdb_get(struct sk_buff *skb, struct nlattr *tb[], struct net_device *dev,
 int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p);
 void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p);
 int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
-                             const unsigned char *addr, u16 vid, bool is_local,
+                             const unsigned char *addr, u16 vid,
                              bool swdev_notify);
 int br_fdb_external_learn_del(struct net_bridge *br, struct net_bridge_port *p,
                              const unsigned char *addr, u16 vid,
index 8d033a7..fdbed31 100644 (file)
@@ -88,6 +88,12 @@ static int nf_br_ip_fragment(struct net *net, struct sock *sk,
 
                        skb = ip_fraglist_next(&iter);
                }
+
+               if (!err)
+                       return 0;
+
+               kfree_skb_list(iter.frag);
+
                return err;
        }
 slow_path:
index 75431ca..1a45584 100644 (file)
@@ -158,7 +158,7 @@ static void linkwatch_do_dev(struct net_device *dev)
        clear_bit(__LINK_STATE_LINKWATCH_PENDING, &dev->state);
 
        rfc2863_policy(dev);
-       if (dev->flags & IFF_UP && netif_device_present(dev)) {
+       if (dev->flags & IFF_UP) {
                if (netif_carrier_ok(dev))
                        dev_activate(dev);
                else
@@ -204,7 +204,8 @@ static void __linkwatch_run_queue(int urgent_only)
                dev = list_first_entry(&wrk, struct net_device, link_watch_list);
                list_del_init(&dev->link_watch_list);
 
-               if (urgent_only && !linkwatch_urgent_event(dev)) {
+               if (!netif_device_present(dev) ||
+                   (urgent_only && !linkwatch_urgent_event(dev))) {
                        list_add_tail(&dev->link_watch_list, &lweventlist);
                        continue;
                }
index 5e4eb45..8ab7b40 100644 (file)
@@ -634,7 +634,15 @@ bool page_pool_return_skb_page(struct page *page)
        struct page_pool *pp;
 
        page = compound_head(page);
-       if (unlikely(page->pp_magic != PP_SIGNATURE))
+
+       /* page->pp_magic is OR'ed with PP_SIGNATURE after the allocation
+        * in order to preserve any existing bits, such as bit 0 for the
+        * head page of compound page and bit 1 for pfmemalloc page, so
+        * mask those bits for freeing side when doing below checking,
+        * and page_is_pfmemalloc() is checked in __page_pool_put_page()
+        * to avoid recycling the pfmemalloc page.
+        */
+       if (unlikely((page->pp_magic & ~0x3UL) != PP_SIGNATURE))
                return false;
 
        pp = page->pp;
index f6af3e7..662eb1c 100644 (file)
@@ -2608,6 +2608,7 @@ static int do_setlink(const struct sk_buff *skb,
                return err;
 
        if (tb[IFLA_NET_NS_PID] || tb[IFLA_NET_NS_FD] || tb[IFLA_TARGET_NETNSID]) {
+               const char *pat = ifname && ifname[0] ? ifname : NULL;
                struct net *net;
                int new_ifindex;
 
@@ -2623,7 +2624,7 @@ static int do_setlink(const struct sk_buff *skb,
                else
                        new_ifindex = 0;
 
-               err = __dev_change_net_namespace(dev, net, ifname, new_ifindex);
+               err = __dev_change_net_namespace(dev, net, pat, new_ifindex);
                put_net(net);
                if (err)
                        goto errout;
index 9cc9d1e..c5c1d2b 100644 (file)
@@ -41,9 +41,9 @@ extern bool dccp_debug;
 #define dccp_pr_debug_cat(format, a...)   DCCP_PRINTK(dccp_debug, format, ##a)
 #define dccp_debug(fmt, a...)            dccp_pr_debug_cat(KERN_DEBUG fmt, ##a)
 #else
-#define dccp_pr_debug(format, a...)
-#define dccp_pr_debug_cat(format, a...)
-#define dccp_debug(format, a...)
+#define dccp_pr_debug(format, a...)      do {} while (0)
+#define dccp_pr_debug_cat(format, a...)          do {} while (0)
+#define dccp_debug(format, a...)         do {} while (0)
 #endif
 
 extern struct inet_hashinfo dccp_hashinfo;
index 532085d..23be8e0 100644 (file)
@@ -2291,8 +2291,8 @@ static int dsa_slave_netdevice_event(struct notifier_block *nb,
 static void
 dsa_fdb_offload_notify(struct dsa_switchdev_event_work *switchdev_work)
 {
+       struct switchdev_notifier_fdb_info info = {};
        struct dsa_switch *ds = switchdev_work->ds;
-       struct switchdev_notifier_fdb_info info;
        struct dsa_port *dp;
 
        if (!dsa_is_user_port(ds, switchdev_work->port))
index a45a040..c25f761 100644 (file)
@@ -984,6 +984,11 @@ static const struct proto_ops ieee802154_dgram_ops = {
        .sendpage          = sock_no_sendpage,
 };
 
+static void ieee802154_sock_destruct(struct sock *sk)
+{
+       skb_queue_purge(&sk->sk_receive_queue);
+}
+
 /* Create a socket. Initialise the socket, blank the addresses
  * set the state.
  */
@@ -1024,7 +1029,7 @@ static int ieee802154_create(struct net *net, struct socket *sock,
        sock->ops = ops;
 
        sock_init_data(sock, sk);
-       /* FIXME: sk->sk_destruct */
+       sk->sk_destruct = ieee802154_sock_destruct;
        sk->sk_family = PF_IEEE802154;
 
        /* Checksums on by default */
index 099259f..7fbd0b5 100644 (file)
@@ -465,14 +465,16 @@ void cipso_v4_doi_free(struct cipso_v4_doi *doi_def)
        if (!doi_def)
                return;
 
-       switch (doi_def->type) {
-       case CIPSO_V4_MAP_TRANS:
-               kfree(doi_def->map.std->lvl.cipso);
-               kfree(doi_def->map.std->lvl.local);
-               kfree(doi_def->map.std->cat.cipso);
-               kfree(doi_def->map.std->cat.local);
-               kfree(doi_def->map.std);
-               break;
+       if (doi_def->map.std) {
+               switch (doi_def->type) {
+               case CIPSO_V4_MAP_TRANS:
+                       kfree(doi_def->map.std->lvl.cipso);
+                       kfree(doi_def->map.std->lvl.local);
+                       kfree(doi_def->map.std->cat.cipso);
+                       kfree(doi_def->map.std->cat.local);
+                       kfree(doi_def->map.std);
+                       break;
+               }
        }
        kfree(doi_def);
 }
index 6b3c558..00576ba 100644 (file)
@@ -803,10 +803,17 @@ static void igmp_gq_timer_expire(struct timer_list *t)
 static void igmp_ifc_timer_expire(struct timer_list *t)
 {
        struct in_device *in_dev = from_timer(in_dev, t, mr_ifc_timer);
+       u32 mr_ifc_count;
 
        igmpv3_send_cr(in_dev);
-       if (in_dev->mr_ifc_count) {
-               in_dev->mr_ifc_count--;
+restart:
+       mr_ifc_count = READ_ONCE(in_dev->mr_ifc_count);
+
+       if (mr_ifc_count) {
+               if (cmpxchg(&in_dev->mr_ifc_count,
+                           mr_ifc_count,
+                           mr_ifc_count - 1) != mr_ifc_count)
+                       goto restart;
                igmp_ifc_start_timer(in_dev,
                                     unsolicited_report_interval(in_dev));
        }
@@ -818,7 +825,7 @@ static void igmp_ifc_event(struct in_device *in_dev)
        struct net *net = dev_net(in_dev->dev);
        if (IGMP_V1_SEEN(in_dev) || IGMP_V2_SEEN(in_dev))
                return;
-       in_dev->mr_ifc_count = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv;
+       WRITE_ONCE(in_dev->mr_ifc_count, in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv);
        igmp_ifc_start_timer(in_dev, 1);
 }
 
@@ -957,7 +964,7 @@ static bool igmp_heard_query(struct in_device *in_dev, struct sk_buff *skb,
                                in_dev->mr_qri;
                }
                /* cancel the interface change timer */
-               in_dev->mr_ifc_count = 0;
+               WRITE_ONCE(in_dev->mr_ifc_count, 0);
                if (del_timer(&in_dev->mr_ifc_timer))
                        __in_dev_put(in_dev);
                /* clear deleted report items */
@@ -1724,7 +1731,7 @@ void ip_mc_down(struct in_device *in_dev)
                igmp_group_dropped(pmc);
 
 #ifdef CONFIG_IP_MULTICAST
-       in_dev->mr_ifc_count = 0;
+       WRITE_ONCE(in_dev->mr_ifc_count, 0);
        if (del_timer(&in_dev->mr_ifc_timer))
                __in_dev_put(in_dev);
        in_dev->mr_gq_running = 0;
@@ -1941,7 +1948,7 @@ static int ip_mc_del_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                pmc->sfmode = MCAST_INCLUDE;
 #ifdef CONFIG_IP_MULTICAST
                pmc->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv;
-               in_dev->mr_ifc_count = pmc->crcount;
+               WRITE_ONCE(in_dev->mr_ifc_count, pmc->crcount);
                for (psf = pmc->sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = 0;
                igmp_ifc_event(pmc->interface);
@@ -2120,7 +2127,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode,
                /* else no filters; keep old mode for reports */
 
                pmc->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv;
-               in_dev->mr_ifc_count = pmc->crcount;
+               WRITE_ONCE(in_dev->mr_ifc_count, pmc->crcount);
                for (psf = pmc->sources; psf; psf = psf->sf_next)
                        psf->sf_crcount = 0;
                igmp_ifc_event(in_dev);
index 12dca0c..95419b7 100644 (file)
@@ -473,6 +473,8 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
 
 static int gre_handle_offloads(struct sk_buff *skb, bool csum)
 {
+       if (csum && skb_checksum_start(skb) < skb->data)
+               return -EINVAL;
        return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
 }
 
index 99c0694..a6f20ee 100644 (file)
@@ -600,14 +600,14 @@ static struct fib_nh_exception *fnhe_oldest(struct fnhe_hash_bucket *hash)
        return oldest;
 }
 
-static inline u32 fnhe_hashfun(__be32 daddr)
+static u32 fnhe_hashfun(__be32 daddr)
 {
-       static u32 fnhe_hashrnd __read_mostly;
-       u32 hval;
+       static siphash_key_t fnhe_hash_key __read_mostly;
+       u64 hval;
 
-       net_get_random_once(&fnhe_hashrnd, sizeof(fnhe_hashrnd));
-       hval = jhash_1word((__force u32)daddr, fnhe_hashrnd);
-       return hash_32(hval, FNHE_HASH_SHIFT);
+       net_get_random_once(&fnhe_hash_key, sizeof(fnhe_hash_key));
+       hval = siphash_1u32((__force u32)daddr, &fnhe_hash_key);
+       return hash_64(hval, FNHE_HASH_SHIFT);
 }
 
 static void fill_route_from_fnhe(struct rtable *rt, struct fib_nh_exception *fnhe)
index 6ea3dc2..6274462 100644 (file)
@@ -1041,7 +1041,7 @@ static void bbr_init(struct sock *sk)
        bbr->prior_cwnd = 0;
        tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
        bbr->rtt_cnt = 0;
-       bbr->next_rtt_delivered = 0;
+       bbr->next_rtt_delivered = tp->delivered;
        bbr->prev_ca_state = TCP_CA_Open;
        bbr->packet_conservation = 0;
 
index 2d650dc..ef75c9b 100644 (file)
@@ -1341,7 +1341,7 @@ static void __fib6_update_sernum_upto_root(struct fib6_info *rt,
        struct fib6_node *fn = rcu_dereference_protected(rt->fib6_node,
                                lockdep_is_held(&rt->fib6_table->tb6_lock));
 
-       /* paired with smp_rmb() in rt6_get_cookie_safe() */
+       /* paired with smp_rmb() in fib6_get_cookie_safe() */
        smp_wmb();
        while (fn) {
                fn->fn_sernum = sernum;
index bc224f9..7a5e90e 100644 (file)
@@ -629,6 +629,8 @@ drop:
 
 static int gre_handle_offloads(struct sk_buff *skb, bool csum)
 {
+       if (csum && skb_checksum_start(skb) < skb->data)
+               return -EINVAL;
        return iptunnel_handle_offloads(skb,
                                        csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
 }
index b6ddf23..c5e8ecb 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
 #include <linux/jhash.h>
+#include <linux/siphash.h>
 #include <net/net_namespace.h>
 #include <net/snmp.h>
 #include <net/ipv6.h>
@@ -1484,17 +1485,24 @@ static void rt6_exception_remove_oldest(struct rt6_exception_bucket *bucket)
 static u32 rt6_exception_hash(const struct in6_addr *dst,
                              const struct in6_addr *src)
 {
-       static u32 seed __read_mostly;
-       u32 val;
+       static siphash_key_t rt6_exception_key __read_mostly;
+       struct {
+               struct in6_addr dst;
+               struct in6_addr src;
+       } __aligned(SIPHASH_ALIGNMENT) combined = {
+               .dst = *dst,
+       };
+       u64 val;
 
-       net_get_random_once(&seed, sizeof(seed));
-       val = jhash2((const u32 *)dst, sizeof(*dst)/sizeof(u32), seed);
+       net_get_random_once(&rt6_exception_key, sizeof(rt6_exception_key));
 
 #ifdef CONFIG_IPV6_SUBTREES
        if (src)
-               val = jhash2((const u32 *)src, sizeof(*src)/sizeof(u32), val);
+               combined.src = *src;
 #endif
-       return hash_32(val, FIB6_EXCEPTION_BUCKET_SIZE_SHIFT);
+       val = siphash(&combined, sizeof(combined), &rt6_exception_key);
+
+       return hash_64(val, FIB6_EXCEPTION_BUCKET_SIZE_SHIFT);
 }
 
 /* Helper function to find the cached rt in the hash table
index 05f4c3c..fcae76d 100644 (file)
@@ -260,6 +260,8 @@ static void ieee80211_restart_work(struct work_struct *work)
        flush_work(&local->radar_detected_work);
 
        rtnl_lock();
+       /* we might do interface manipulations, so need both */
+       wiphy_lock(local->hw.wiphy);
 
        WARN(test_bit(SCAN_HW_SCANNING, &local->scanning),
             "%s called with hardware scan in progress\n", __func__);
index 4452455..7adcbc1 100644 (file)
@@ -885,20 +885,16 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
                return subflow->mp_capable;
        }
 
-       if (mp_opt->dss && mp_opt->use_ack) {
+       if ((mp_opt->dss && mp_opt->use_ack) ||
+           (mp_opt->add_addr && !mp_opt->echo)) {
                /* subflows are fully established as soon as we get any
-                * additional ack.
+                * additional ack, including ADD_ADDR.
                 */
                subflow->fully_established = 1;
                WRITE_ONCE(msk->fully_established, true);
                goto fully_established;
        }
 
-       if (mp_opt->add_addr) {
-               WRITE_ONCE(msk->fully_established, true);
-               return true;
-       }
-
        /* If the first established packet does not contain MP_CAPABLE + data
         * then fallback to TCP. Fallback scenarios requires a reset for
         * MP_JOIN subflows.
index 56263c2..7b37944 100644 (file)
@@ -1135,36 +1135,12 @@ next:
        return 0;
 }
 
-struct addr_entry_release_work {
-       struct rcu_work rwork;
-       struct mptcp_pm_addr_entry *entry;
-};
-
-static void mptcp_pm_release_addr_entry(struct work_struct *work)
+/* caller must ensure the RCU grace period is already elapsed */
+static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
 {
-       struct addr_entry_release_work *w;
-       struct mptcp_pm_addr_entry *entry;
-
-       w = container_of(to_rcu_work(work), struct addr_entry_release_work, rwork);
-       entry = w->entry;
-       if (entry) {
-               if (entry->lsk)
-                       sock_release(entry->lsk);
-               kfree(entry);
-       }
-       kfree(w);
-}
-
-static void mptcp_pm_free_addr_entry(struct mptcp_pm_addr_entry *entry)
-{
-       struct addr_entry_release_work *w;
-
-       w = kmalloc(sizeof(*w), GFP_ATOMIC);
-       if (w) {
-               INIT_RCU_WORK(&w->rwork, mptcp_pm_release_addr_entry);
-               w->entry = entry;
-               queue_rcu_work(system_wq, &w->rwork);
-       }
+       if (entry->lsk)
+               sock_release(entry->lsk);
+       kfree(entry);
 }
 
 static int mptcp_nl_remove_id_zero_address(struct net *net,
@@ -1244,7 +1220,8 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
        spin_unlock_bh(&pernet->lock);
 
        mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
-       mptcp_pm_free_addr_entry(entry);
+       synchronize_rcu();
+       __mptcp_pm_release_addr_entry(entry);
 
        return ret;
 }
@@ -1297,6 +1274,7 @@ static void mptcp_nl_remove_addrs_list(struct net *net,
        }
 }
 
+/* caller must ensure the RCU grace period is already elapsed */
 static void __flush_addrs(struct list_head *list)
 {
        while (!list_empty(list)) {
@@ -1305,7 +1283,7 @@ static void __flush_addrs(struct list_head *list)
                cur = list_entry(list->next,
                                 struct mptcp_pm_addr_entry, list);
                list_del_rcu(&cur->list);
-               mptcp_pm_free_addr_entry(cur);
+               __mptcp_pm_release_addr_entry(cur);
        }
 }
 
@@ -1329,6 +1307,7 @@ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
        bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
        spin_unlock_bh(&pernet->lock);
        mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
+       synchronize_rcu();
        __flush_addrs(&free_list);
        return 0;
 }
@@ -1939,7 +1918,8 @@ static void __net_exit pm_nl_exit_net(struct list_head *net_list)
                struct pm_nl_pernet *pernet = net_generic(net, pm_nl_pernet_id);
 
                /* net is removed from namespace list, can't race with
-                * other modifiers
+                * other modifiers, also netns core already waited for a
+                * RCU grace period.
                 */
                __flush_addrs(&pernet->local_addr_list);
        }
index d1bef23..dd30c03 100644 (file)
@@ -132,8 +132,11 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
                        return ret;
-               if (ip > ip_to)
+               if (ip > ip_to) {
+                       if (ip_to == 0)
+                               return -IPSET_ERR_HASH_ELEM;
                        swap(ip, ip_to);
+               }
        } else if (tb[IPSET_ATTR_CIDR]) {
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
@@ -144,6 +147,10 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
 
        hosts = h->netmask == 32 ? 1 : 2 << (32 - h->netmask - 1);
 
+       /* 64bit division is not allowed on 32bit */
+       if (((u64)ip_to - ip + 1) >> (32 - h->netmask) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried) {
                ip = ntohl(h->next.ip);
                e.ip = htonl(ip);
index 18346d1..153de34 100644 (file)
@@ -121,6 +121,8 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
 
        e.mark = ntohl(nla_get_be32(tb[IPSET_ATTR_MARK]));
        e.mark &= h->markmask;
+       if (e.mark == 0 && e.ip == 0)
+               return -IPSET_ERR_HASH_ELEM;
 
        if (adt == IPSET_TEST ||
            !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR])) {
@@ -133,8 +135,11 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to);
                if (ret)
                        return ret;
-               if (ip > ip_to)
+               if (ip > ip_to) {
+                       if (e.mark == 0 && ip_to == 0)
+                               return -IPSET_ERR_HASH_ELEM;
                        swap(ip, ip_to);
+               }
        } else if (tb[IPSET_ATTR_CIDR]) {
                u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]);
 
@@ -143,6 +148,9 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
                ip_set_mask_from_to(ip, ip_to, cidr);
        }
 
+       if (((u64)ip_to - ip + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index e1ca111..7303138 100644 (file)
@@ -173,6 +173,9 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index ab179e0..334fb1a 100644 (file)
@@ -180,6 +180,9 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        for (; ip <= ip_to; ip++) {
index 8f075b4..7df94f4 100644 (file)
@@ -253,6 +253,9 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
                        swap(port, port_to);
        }
 
+       if (((u64)ip_to - ip + 1)*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        ip2_to = ip2_from;
        if (tb[IPSET_ATTR_IP2_TO]) {
                ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP2_TO], &ip2_to);
index c1a11f0..1422739 100644 (file)
@@ -140,7 +140,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_net4_elem e = { .cidr = HOST_MASK };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0;
+       u32 ip = 0, ip_to = 0, ipn, n = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -188,6 +188,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
                if (ip + UINT_MAX == ip_to)
                        return -IPSET_ERR_HASH_RANGE;
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n > IPSET_MAX_RANGE)
+               return -ERANGE;
+
        if (retried)
                ip = ntohl(h->next.ip);
        do {
index ddd51c2..9810f5b 100644 (file)
@@ -202,7 +202,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 ip = 0, ip_to = 0;
+       u32 ip = 0, ip_to = 0, ipn, n = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -256,6 +256,14 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip, ip_to, e.cidr);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried)
                ip = ntohl(h->next.ip);
index 6532f05..3d09eef 100644 (file)
@@ -168,7 +168,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        struct hash_netnet4_elem e = { };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        u32 ip = 0, ip_to = 0;
-       u32 ip2 = 0, ip2_from = 0, ip2_to = 0;
+       u32 ip2 = 0, ip2_from = 0, ip2_to = 0, ipn;
+       u64 n = 0, m = 0;
        int ret;
 
        if (tb[IPSET_ATTR_LINENO])
@@ -244,6 +245,19 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
+               n++;
+       } while (ipn++ < ip_to);
+       ipn = ip2_from;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
+               m++;
+       } while (ipn++ < ip2_to);
+
+       if (n*m > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip[0]);
index ec1564a..09cf72e 100644 (file)
@@ -158,7 +158,8 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        ipset_adtfn adtfn = set->variant->adt[adt];
        struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
-       u32 port, port_to, p = 0, ip = 0, ip_to = 0;
+       u32 port, port_to, p = 0, ip = 0, ip_to = 0, ipn;
+       u64 n = 0;
        bool with_ports = false;
        u8 cidr;
        int ret;
@@ -235,6 +236,14 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &cidr);
+               n++;
+       } while (ipn++ < ip_to);
+
+       if (n*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip);
index 0e91d1e..19bcdb3 100644 (file)
@@ -182,7 +182,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        struct hash_netportnet4_elem e = { };
        struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
        u32 ip = 0, ip_to = 0, p = 0, port, port_to;
-       u32 ip2_from = 0, ip2_to = 0, ip2;
+       u32 ip2_from = 0, ip2_to = 0, ip2, ipn;
+       u64 n = 0, m = 0;
        bool with_ports = false;
        int ret;
 
@@ -284,6 +285,19 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
        } else {
                ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
        }
+       ipn = ip;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip_to, &e.cidr[0]);
+               n++;
+       } while (ipn++ < ip_to);
+       ipn = ip2_from;
+       do {
+               ipn = ip_set_range_to_cidr(ipn, ip2_to, &e.cidr[1]);
+               m++;
+       } while (ipn++ < ip2_to);
+
+       if (n*m*(port_to - port + 1) > IPSET_MAX_RANGE)
+               return -ERANGE;
 
        if (retried) {
                ip = ntohl(h->next.ip[0]);
index 5c03e51..d31dbcc 100644 (file)
@@ -66,22 +66,17 @@ EXPORT_SYMBOL_GPL(nf_conntrack_hash);
 
 struct conntrack_gc_work {
        struct delayed_work     dwork;
-       u32                     last_bucket;
+       u32                     next_bucket;
        bool                    exiting;
        bool                    early_drop;
-       long                    next_gc_run;
 };
 
 static __read_mostly struct kmem_cache *nf_conntrack_cachep;
 static DEFINE_SPINLOCK(nf_conntrack_locks_all_lock);
 static __read_mostly bool nf_conntrack_locks_all;
 
-/* every gc cycle scans at most 1/GC_MAX_BUCKETS_DIV part of table */
-#define GC_MAX_BUCKETS_DIV     128u
-/* upper bound of full table scan */
-#define GC_MAX_SCAN_JIFFIES    (16u * HZ)
-/* desired ratio of entries found to be expired */
-#define GC_EVICT_RATIO 50u
+#define GC_SCAN_INTERVAL       (120u * HZ)
+#define GC_SCAN_MAX_DURATION   msecs_to_jiffies(10)
 
 static struct conntrack_gc_work conntrack_gc_work;
 
@@ -1363,17 +1358,13 @@ static bool gc_worker_can_early_drop(const struct nf_conn *ct)
 
 static void gc_worker(struct work_struct *work)
 {
-       unsigned int min_interval = max(HZ / GC_MAX_BUCKETS_DIV, 1u);
-       unsigned int i, goal, buckets = 0, expired_count = 0;
-       unsigned int nf_conntrack_max95 = 0;
+       unsigned long end_time = jiffies + GC_SCAN_MAX_DURATION;
+       unsigned int i, hashsz, nf_conntrack_max95 = 0;
+       unsigned long next_run = GC_SCAN_INTERVAL;
        struct conntrack_gc_work *gc_work;
-       unsigned int ratio, scanned = 0;
-       unsigned long next_run;
-
        gc_work = container_of(work, struct conntrack_gc_work, dwork.work);
 
-       goal = nf_conntrack_htable_size / GC_MAX_BUCKETS_DIV;
-       i = gc_work->last_bucket;
+       i = gc_work->next_bucket;
        if (gc_work->early_drop)
                nf_conntrack_max95 = nf_conntrack_max / 100u * 95u;
 
@@ -1381,15 +1372,15 @@ static void gc_worker(struct work_struct *work)
                struct nf_conntrack_tuple_hash *h;
                struct hlist_nulls_head *ct_hash;
                struct hlist_nulls_node *n;
-               unsigned int hashsz;
                struct nf_conn *tmp;
 
-               i++;
                rcu_read_lock();
 
                nf_conntrack_get_ht(&ct_hash, &hashsz);
-               if (i >= hashsz)
-                       i = 0;
+               if (i >= hashsz) {
+                       rcu_read_unlock();
+                       break;
+               }
 
                hlist_nulls_for_each_entry_rcu(h, n, &ct_hash[i], hnnode) {
                        struct nf_conntrack_net *cnet;
@@ -1397,7 +1388,6 @@ static void gc_worker(struct work_struct *work)
 
                        tmp = nf_ct_tuplehash_to_ctrack(h);
 
-                       scanned++;
                        if (test_bit(IPS_OFFLOAD_BIT, &tmp->status)) {
                                nf_ct_offload_timeout(tmp);
                                continue;
@@ -1405,7 +1395,6 @@ static void gc_worker(struct work_struct *work)
 
                        if (nf_ct_is_expired(tmp)) {
                                nf_ct_gc_expired(tmp);
-                               expired_count++;
                                continue;
                        }
 
@@ -1438,7 +1427,14 @@ static void gc_worker(struct work_struct *work)
                 */
                rcu_read_unlock();
                cond_resched();
-       } while (++buckets < goal);
+               i++;
+
+               if (time_after(jiffies, end_time) && i < hashsz) {
+                       gc_work->next_bucket = i;
+                       next_run = 0;
+                       break;
+               }
+       } while (i < hashsz);
 
        if (gc_work->exiting)
                return;
@@ -1449,40 +1445,17 @@ static void gc_worker(struct work_struct *work)
         *
         * This worker is only here to reap expired entries when system went
         * idle after a busy period.
-        *
-        * The heuristics below are supposed to balance conflicting goals:
-        *
-        * 1. Minimize time until we notice a stale entry
-        * 2. Maximize scan intervals to not waste cycles
-        *
-        * Normally, expire ratio will be close to 0.
-        *
-        * As soon as a sizeable fraction of the entries have expired
-        * increase scan frequency.
         */
-       ratio = scanned ? expired_count * 100 / scanned : 0;
-       if (ratio > GC_EVICT_RATIO) {
-               gc_work->next_gc_run = min_interval;
-       } else {
-               unsigned int max = GC_MAX_SCAN_JIFFIES / GC_MAX_BUCKETS_DIV;
-
-               BUILD_BUG_ON((GC_MAX_SCAN_JIFFIES / GC_MAX_BUCKETS_DIV) == 0);
-
-               gc_work->next_gc_run += min_interval;
-               if (gc_work->next_gc_run > max)
-                       gc_work->next_gc_run = max;
+       if (next_run) {
+               gc_work->early_drop = false;
+               gc_work->next_bucket = 0;
        }
-
-       next_run = gc_work->next_gc_run;
-       gc_work->last_bucket = i;
-       gc_work->early_drop = false;
        queue_delayed_work(system_power_efficient_wq, &gc_work->dwork, next_run);
 }
 
 static void conntrack_gc_work_init(struct conntrack_gc_work *gc_work)
 {
        INIT_DEFERRABLE_WORK(&gc_work->dwork, gc_worker);
-       gc_work->next_gc_run = HZ;
        gc_work->exiting = false;
 }
 
index 3259416..af5115e 100644 (file)
@@ -1478,7 +1478,6 @@ void nf_conntrack_tcp_init_net(struct net *net)
 
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        tn->offload_timeout = 30 * HZ;
-       tn->offload_pickup = 120 * HZ;
 #endif
 }
 
index 698fee4..f8e3c0d 100644 (file)
@@ -271,7 +271,6 @@ void nf_conntrack_udp_init_net(struct net *net)
 
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        un->offload_timeout = 30 * HZ;
-       un->offload_pickup = 30 * HZ;
 #endif
 }
 
index 214d9f9..e84b499 100644 (file)
@@ -575,7 +575,6 @@ enum nf_ct_sysctl_index {
        NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_UNACK,
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD,
-       NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP,
 #endif
        NF_SYSCTL_CT_PROTO_TCP_LOOSE,
        NF_SYSCTL_CT_PROTO_TCP_LIBERAL,
@@ -585,7 +584,6 @@ enum nf_ct_sysctl_index {
        NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM,
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD,
-       NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP,
 #endif
        NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP,
        NF_SYSCTL_CT_PROTO_TIMEOUT_ICMPV6,
@@ -776,12 +774,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       [NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP] = {
-               .procname       = "nf_flowtable_tcp_pickup",
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec_jiffies,
-       },
 #endif
        [NF_SYSCTL_CT_PROTO_TCP_LOOSE] = {
                .procname       = "nf_conntrack_tcp_loose",
@@ -832,12 +824,6 @@ static struct ctl_table nf_ct_sysctl_table[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec_jiffies,
        },
-       [NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP] = {
-               .procname       = "nf_flowtable_udp_pickup",
-               .maxlen         = sizeof(unsigned int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec_jiffies,
-       },
 #endif
        [NF_SYSCTL_CT_PROTO_TIMEOUT_ICMP] = {
                .procname       = "nf_conntrack_icmp_timeout",
@@ -1018,7 +1004,6 @@ static void nf_conntrack_standalone_init_tcp_sysctl(struct net *net,
 
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD].data = &tn->offload_timeout;
-       table[NF_SYSCTL_CT_PROTO_TIMEOUT_TCP_OFFLOAD_PICKUP].data = &tn->offload_pickup;
 #endif
 
 }
@@ -1111,7 +1096,6 @@ static int nf_conntrack_standalone_init_sysctl(struct net *net)
        table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_STREAM].data = &un->timeouts[UDP_CT_REPLIED];
 #if IS_ENABLED(CONFIG_NF_FLOW_TABLE)
        table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD].data = &un->offload_timeout;
-       table[NF_SYSCTL_CT_PROTO_TIMEOUT_UDP_OFFLOAD_PICKUP].data = &un->offload_pickup;
 #endif
 
        nf_conntrack_standalone_init_tcp_sysctl(net, table);
index 551976e..8788b51 100644 (file)
@@ -183,7 +183,7 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
        const struct nf_conntrack_l4proto *l4proto;
        struct net *net = nf_ct_net(ct);
        int l4num = nf_ct_protonum(ct);
-       unsigned int timeout;
+       s32 timeout;
 
        l4proto = nf_ct_l4proto_find(l4num);
        if (!l4proto)
@@ -192,15 +192,20 @@ static void flow_offload_fixup_ct_timeout(struct nf_conn *ct)
        if (l4num == IPPROTO_TCP) {
                struct nf_tcp_net *tn = nf_tcp_pernet(net);
 
-               timeout = tn->offload_pickup;
+               timeout = tn->timeouts[TCP_CONNTRACK_ESTABLISHED];
+               timeout -= tn->offload_timeout;
        } else if (l4num == IPPROTO_UDP) {
                struct nf_udp_net *tn = nf_udp_pernet(net);
 
-               timeout = tn->offload_pickup;
+               timeout = tn->timeouts[UDP_CT_REPLIED];
+               timeout -= tn->offload_timeout;
        } else {
                return;
        }
 
+       if (timeout < 0)
+               timeout = 0;
+
        if (nf_flow_timeout_delta(ct->timeout) > (__s32)timeout)
                ct->timeout = nfct_time_stamp + timeout;
 }
index 202f57d..f554e2e 100644 (file)
@@ -89,11 +89,15 @@ static int nfnl_hook_put_nft_chain_info(struct sk_buff *nlskb,
        if (!nest2)
                goto cancel_nest;
 
-       ret = nla_put_string(nlskb, NFTA_CHAIN_TABLE, chain->table->name);
+       ret = nla_put_string(nlskb, NFNLA_CHAIN_TABLE, chain->table->name);
        if (ret)
                goto cancel_nest;
 
-       ret = nla_put_string(nlskb, NFTA_CHAIN_NAME, chain->name);
+       ret = nla_put_string(nlskb, NFNLA_CHAIN_NAME, chain->name);
+       if (ret)
+               goto cancel_nest;
+
+       ret = nla_put_u8(nlskb, NFNLA_CHAIN_FAMILY, chain->table->family);
        if (ret)
                goto cancel_nest;
 
@@ -109,18 +113,19 @@ cancel_nest:
 static int nfnl_hook_dump_one(struct sk_buff *nlskb,
                              const struct nfnl_dump_hook_data *ctx,
                              const struct nf_hook_ops *ops,
-                             unsigned int seq)
+                             int family, unsigned int seq)
 {
        u16 event = nfnl_msg_type(NFNL_SUBSYS_HOOK, NFNL_MSG_HOOK_GET);
        unsigned int portid = NETLINK_CB(nlskb).portid;
        struct nlmsghdr *nlh;
        int ret = -EMSGSIZE;
+       u32 hooknum;
 #ifdef CONFIG_KALLSYMS
        char sym[KSYM_SYMBOL_LEN];
        char *module_name;
 #endif
        nlh = nfnl_msg_put(nlskb, portid, seq, event,
-                          NLM_F_MULTI, ops->pf, NFNETLINK_V0, 0);
+                          NLM_F_MULTI, family, NFNETLINK_V0, 0);
        if (!nlh)
                goto nla_put_failure;
 
@@ -135,6 +140,7 @@ static int nfnl_hook_dump_one(struct sk_buff *nlskb,
        if (module_name) {
                char *end;
 
+               *module_name = '\0';
                module_name += 2;
                end = strchr(module_name, ']');
                if (end) {
@@ -151,7 +157,12 @@ static int nfnl_hook_dump_one(struct sk_buff *nlskb,
                goto nla_put_failure;
 #endif
 
-       ret = nla_put_be32(nlskb, NFNLA_HOOK_HOOKNUM, htonl(ops->hooknum));
+       if (ops->pf == NFPROTO_INET && ops->hooknum == NF_INET_INGRESS)
+               hooknum = NF_NETDEV_INGRESS;
+       else
+               hooknum = ops->hooknum;
+
+       ret = nla_put_be32(nlskb, NFNLA_HOOK_HOOKNUM, htonl(hooknum));
        if (ret)
                goto nla_put_failure;
 
@@ -259,7 +270,8 @@ static int nfnl_hook_dump(struct sk_buff *nlskb,
        ops = nf_hook_entries_get_hook_ops(e);
 
        for (; i < e->num_hook_entries; i++) {
-               err = nfnl_hook_dump_one(nlskb, ctx, ops[i], cb->seq);
+               err = nfnl_hook_dump_one(nlskb, ctx, ops[i], family,
+                                        cb->nlh->nlmsg_seq);
                if (err)
                        break;
        }
index e586424..9713035 100644 (file)
@@ -293,14 +293,14 @@ static bool icmp6hdr_ok(struct sk_buff *skb)
 }
 
 /**
- * Parse vlan tag from vlan header.
+ * parse_vlan_tag - Parse vlan tag from vlan header.
  * @skb: skb containing frame to parse
  * @key_vh: pointer to parsed vlan tag
  * @untag_vlan: should the vlan header be removed from the frame
  *
- * Returns ERROR on memory error.
- * Returns 0 if it encounters a non-vlan or incomplete packet.
- * Returns 1 after successfully parsing vlan tag.
+ * Return: ERROR on memory error.
+ * %0 if it encounters a non-vlan or incomplete packet.
+ * %1 after successfully parsing vlan tag.
  */
 static int parse_vlan_tag(struct sk_buff *skb, struct vlan_head *key_vh,
                          bool untag_vlan)
@@ -532,6 +532,7 @@ static int parse_nsh(struct sk_buff *skb, struct sw_flow_key *key)
  *       L3 header
  * @key: output flow key
  *
+ * Return: %0 if successful, otherwise a negative errno value.
  */
 static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
 {
@@ -748,8 +749,6 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
  *
  * The caller must ensure that skb->len >= ETH_HLEN.
  *
- * Returns 0 if successful, otherwise a negative errno value.
- *
  * Initializes @skb header fields as follows:
  *
  *    - skb->mac_header: the L2 header.
@@ -764,6 +763,8 @@ static int key_extract_l3l4(struct sk_buff *skb, struct sw_flow_key *key)
  *
  *    - skb->protocol: the type of the data starting at skb->network_header.
  *      Equals to key->eth.type.
+ *
+ * Return: %0 if successful, otherwise a negative errno value.
  */
 static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
 {
index 88deb5b..cf2ce58 100644 (file)
@@ -507,6 +507,7 @@ void ovs_vport_send(struct vport *vport, struct sk_buff *skb, u8 mac_proto)
        }
 
        skb->dev = vport->dev;
+       skb->tstamp = 0;
        vport->ops->send(skb);
        return;
 
index 1dc955c..fa61167 100644 (file)
@@ -15,7 +15,6 @@ struct qrtr_mhi_dev {
        struct qrtr_endpoint ep;
        struct mhi_device *mhi_dev;
        struct device *dev;
-       struct completion ready;
 };
 
 /* From MHI to QRTR */
@@ -51,10 +50,6 @@ static int qcom_mhi_qrtr_send(struct qrtr_endpoint *ep, struct sk_buff *skb)
        struct qrtr_mhi_dev *qdev = container_of(ep, struct qrtr_mhi_dev, ep);
        int rc;
 
-       rc = wait_for_completion_interruptible(&qdev->ready);
-       if (rc)
-               goto free_skb;
-
        if (skb->sk)
                sock_hold(skb->sk);
 
@@ -84,7 +79,7 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
        int rc;
 
        /* start channels */
-       rc = mhi_prepare_for_transfer(mhi_dev, 0);
+       rc = mhi_prepare_for_transfer(mhi_dev);
        if (rc)
                return rc;
 
@@ -101,15 +96,6 @@ static int qcom_mhi_qrtr_probe(struct mhi_device *mhi_dev,
        if (rc)
                return rc;
 
-       /* start channels */
-       rc = mhi_prepare_for_transfer(mhi_dev, MHI_CH_INBOUND_ALLOC_BUFS);
-       if (rc) {
-               qrtr_endpoint_unregister(&qdev->ep);
-               dev_set_drvdata(&mhi_dev->dev, NULL);
-               return rc;
-       }
-
-       complete_all(&qdev->ready);
        dev_dbg(qdev->dev, "Qualcomm MHI QRTR driver probed\n");
 
        return 0;
index 171b7f3..0c30908 100644 (file)
@@ -493,7 +493,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len)
                goto err;
        }
 
-       if (len != ALIGN(size, 4) + hdrlen)
+       if (!size || len != ALIGN(size, 4) + hdrlen)
                goto err;
 
        if (cb->dst_port != QRTR_PORT_CTRL && cb->type != QRTR_TYPE_DATA &&
index 9b6ffff..28c1b00 100644 (file)
@@ -131,9 +131,9 @@ static int rds_ib_post_reg_frmr(struct rds_ib_mr *ibmr)
                cpu_relax();
        }
 
-       ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_len,
+       ret = ib_map_mr_sg_zbva(frmr->mr, ibmr->sg, ibmr->sg_dma_len,
                                &off, PAGE_SIZE);
-       if (unlikely(ret != ibmr->sg_len))
+       if (unlikely(ret != ibmr->sg_dma_len))
                return ret < 0 ? ret : -EINVAL;
 
        if (cmpxchg(&frmr->fr_state,
index 7153c67..2ef4cd2 100644 (file)
@@ -273,6 +273,9 @@ static int tcf_mirred_act(struct sk_buff *skb, const struct tc_action *a,
                        goto out;
        }
 
+       /* All mirred/redirected skbs should clear previous ct info */
+       nf_reset_ct(skb2);
+
        want_ingress = tcf_mirred_act_wants_ingress(m_eaction);
 
        expects_nh = want_ingress || !m_mac_header_xmit;
index 9515428..28af8b1 100644 (file)
@@ -720,7 +720,7 @@ static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb,
 skip_hash:
        if (flow_override)
                flow_hash = flow_override - 1;
-       else if (use_skbhash)
+       else if (use_skbhash && (flow_mode & CAKE_FLOW_FLOWS))
                flow_hash = skb->hash;
        if (host_override) {
                dsthost_hash = host_override - 1;
index c1e84d1..c76701a 100644 (file)
@@ -660,6 +660,13 @@ static int ets_qdisc_change(struct Qdisc *sch, struct nlattr *opt,
        sch_tree_lock(sch);
 
        q->nbands = nbands;
+       for (i = nstrict; i < q->nstrict; i++) {
+               INIT_LIST_HEAD(&q->classes[i].alist);
+               if (q->classes[i].qdisc->q.qlen) {
+                       list_add_tail(&q->classes[i].alist, &q->active);
+                       q->classes[i].deficit = quanta[i];
+               }
+       }
        q->nstrict = nstrict;
        memcpy(q->prio2band, priomap, sizeof(priomap));
 
index 8983896..c038efc 100644 (file)
@@ -795,7 +795,7 @@ static int smc_connect_rdma(struct smc_sock *smc,
                        reason_code = SMC_CLC_DECL_NOSRVLINK;
                        goto connect_abort;
                }
-               smc->conn.lnk = link;
+               smc_switch_link_and_count(&smc->conn, link);
        }
 
        /* create send buffer and rmb */
index cd0d7c9..c160ff5 100644 (file)
@@ -917,8 +917,8 @@ static int smc_switch_cursor(struct smc_sock *smc, struct smc_cdc_tx_pend *pend,
        return rc;
 }
 
-static void smc_switch_link_and_count(struct smc_connection *conn,
-                                     struct smc_link *to_lnk)
+void smc_switch_link_and_count(struct smc_connection *conn,
+                              struct smc_link *to_lnk)
 {
        atomic_dec(&conn->lnk->conn_cnt);
        conn->lnk = to_lnk;
index 6d6fd13..c043ecd 100644 (file)
@@ -97,6 +97,7 @@ struct smc_link {
        unsigned long           *wr_tx_mask;    /* bit mask of used indexes */
        u32                     wr_tx_cnt;      /* number of WR send buffers */
        wait_queue_head_t       wr_tx_wait;     /* wait for free WR send buf */
+       atomic_t                wr_tx_refcnt;   /* tx refs to link */
 
        struct smc_wr_buf       *wr_rx_bufs;    /* WR recv payload buffers */
        struct ib_recv_wr       *wr_rx_ibs;     /* WR recv meta data */
@@ -109,6 +110,7 @@ struct smc_link {
 
        struct ib_reg_wr        wr_reg;         /* WR register memory region */
        wait_queue_head_t       wr_reg_wait;    /* wait for wr_reg result */
+       atomic_t                wr_reg_refcnt;  /* reg refs to link */
        enum smc_wr_reg_state   wr_reg_state;   /* state of wr_reg request */
 
        u8                      gid[SMC_GID_SIZE];/* gid matching used vlan id*/
@@ -444,6 +446,8 @@ void smc_core_exit(void);
 int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
                   u8 link_idx, struct smc_init_info *ini);
 void smcr_link_clear(struct smc_link *lnk, bool log);
+void smc_switch_link_and_count(struct smc_connection *conn,
+                              struct smc_link *to_lnk);
 int smcr_buf_map_lgr(struct smc_link *lnk);
 int smcr_buf_reg_lgr(struct smc_link *lnk);
 void smcr_lgr_set_type(struct smc_link_group *lgr, enum smc_lgr_type new_type);
index 273eaf1..2e7560e 100644 (file)
@@ -888,6 +888,7 @@ int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry)
        if (!rc)
                goto out;
 out_clear_lnk:
+       lnk_new->state = SMC_LNK_INACTIVE;
        smcr_link_clear(lnk_new, false);
 out_reject:
        smc_llc_cli_add_link_reject(qentry);
@@ -1184,6 +1185,7 @@ int smc_llc_srv_add_link(struct smc_link *link)
                goto out_err;
        return 0;
 out_err:
+       link_new->state = SMC_LNK_INACTIVE;
        smcr_link_clear(link_new, false);
        return rc;
 }
@@ -1286,10 +1288,8 @@ static void smc_llc_process_cli_delete_link(struct smc_link_group *lgr)
        del_llc->reason = 0;
        smc_llc_send_message(lnk, &qentry->msg); /* response */
 
-       if (smc_link_downing(&lnk_del->state)) {
-               if (smc_switch_conns(lgr, lnk_del, false))
-                       smc_wr_tx_wait_no_pending_sends(lnk_del);
-       }
+       if (smc_link_downing(&lnk_del->state))
+               smc_switch_conns(lgr, lnk_del, false);
        smcr_link_clear(lnk_del, true);
 
        active_links = smc_llc_active_link_count(lgr);
@@ -1805,8 +1805,6 @@ void smc_llc_link_clear(struct smc_link *link, bool log)
                                    link->smcibdev->ibdev->name, link->ibport);
        complete(&link->llc_testlink_resp);
        cancel_delayed_work_sync(&link->llc_testlink_wrk);
-       smc_wr_wakeup_reg_wait(link);
-       smc_wr_wakeup_tx_wait(link);
 }
 
 /* register a new rtoken at the remote peer (for all links) */
index 289025c..c79361d 100644 (file)
@@ -496,7 +496,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn,
 /* Wakeup sndbuf consumers from any context (IRQ or process)
  * since there is more data to transmit; usable snd_wnd as max transmit
  */
-static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
+static int _smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
 {
        struct smc_cdc_producer_flags *pflags = &conn->local_tx_ctrl.prod_flags;
        struct smc_link *link = conn->lnk;
@@ -550,6 +550,22 @@ out_unlock:
        return rc;
 }
 
+static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
+{
+       struct smc_link *link = conn->lnk;
+       int rc = -ENOLINK;
+
+       if (!link)
+               return rc;
+
+       atomic_inc(&link->wr_tx_refcnt);
+       if (smc_link_usable(link))
+               rc = _smcr_tx_sndbuf_nonempty(conn);
+       if (atomic_dec_and_test(&link->wr_tx_refcnt))
+               wake_up_all(&link->wr_tx_wait);
+       return rc;
+}
+
 static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn)
 {
        struct smc_cdc_producer_flags *pflags = &conn->local_tx_ctrl.prod_flags;
index cbc73a7..a419e9a 100644 (file)
@@ -322,9 +322,12 @@ int smc_wr_reg_send(struct smc_link *link, struct ib_mr *mr)
        if (rc)
                return rc;
 
+       atomic_inc(&link->wr_reg_refcnt);
        rc = wait_event_interruptible_timeout(link->wr_reg_wait,
                                              (link->wr_reg_state != POSTED),
                                              SMC_WR_REG_MR_WAIT_TIME);
+       if (atomic_dec_and_test(&link->wr_reg_refcnt))
+               wake_up_all(&link->wr_reg_wait);
        if (!rc) {
                /* timeout - terminate link */
                smcr_link_down_cond_sched(link);
@@ -566,10 +569,15 @@ void smc_wr_free_link(struct smc_link *lnk)
                return;
        ibdev = lnk->smcibdev->ibdev;
 
+       smc_wr_wakeup_reg_wait(lnk);
+       smc_wr_wakeup_tx_wait(lnk);
+
        if (smc_wr_tx_wait_no_pending_sends(lnk))
                memset(lnk->wr_tx_mask, 0,
                       BITS_TO_LONGS(SMC_WR_BUF_CNT) *
                                                sizeof(*lnk->wr_tx_mask));
+       wait_event(lnk->wr_reg_wait, (!atomic_read(&lnk->wr_reg_refcnt)));
+       wait_event(lnk->wr_tx_wait, (!atomic_read(&lnk->wr_tx_refcnt)));
 
        if (lnk->wr_rx_dma_addr) {
                ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
@@ -728,7 +736,9 @@ int smc_wr_create_link(struct smc_link *lnk)
        memset(lnk->wr_tx_mask, 0,
               BITS_TO_LONGS(SMC_WR_BUF_CNT) * sizeof(*lnk->wr_tx_mask));
        init_waitqueue_head(&lnk->wr_tx_wait);
+       atomic_set(&lnk->wr_tx_refcnt, 0);
        init_waitqueue_head(&lnk->wr_reg_wait);
+       atomic_set(&lnk->wr_reg_refcnt, 0);
        return rc;
 
 dma_unmap:
index d66a8e4..dbb4182 100644 (file)
@@ -835,7 +835,8 @@ static int svc_handle_xprt(struct svc_rqst *rqstp, struct svc_xprt *xprt)
                rqstp->rq_stime = ktime_get();
                rqstp->rq_reserved = serv->sv_max_mesg;
                atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
-       }
+       } else
+               svc_xprt_received(xprt);
 out:
        trace_svc_handle_xprt(xprt, len);
        return len;
index cf58684..1b7a487 100644 (file)
@@ -913,7 +913,7 @@ static int link_schedule_user(struct tipc_link *l, struct tipc_msg *hdr)
        skb = tipc_msg_create(SOCK_WAKEUP, 0, INT_H_SIZE, 0,
                              dnode, l->addr, dport, 0, 0);
        if (!skb)
-               return -ENOMEM;
+               return -ENOBUFS;
        msg_set_dest_droppable(buf_msg(skb), true);
        TIPC_SKB_CB(skb)->chain_imp = msg_importance(hdr);
        skb_queue_tail(&l->wakeupq, skb);
@@ -1031,7 +1031,7 @@ void tipc_link_reset(struct tipc_link *l)
  *
  * Consumes the buffer chain.
  * Messages at TIPC_SYSTEM_IMPORTANCE are always accepted
- * Return: 0 if success, or errno: -ELINKCONG, -EMSGSIZE or -ENOBUFS or -ENOMEM
+ * Return: 0 if success, or errno: -ELINKCONG, -EMSGSIZE or -ENOBUFS
  */
 int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                   struct sk_buff_head *xmitq)
@@ -1089,7 +1089,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                        if (!_skb) {
                                kfree_skb(skb);
                                __skb_queue_purge(list);
-                               return -ENOMEM;
+                               return -ENOBUFS;
                        }
                        __skb_queue_tail(transmq, skb);
                        tipc_link_set_skb_retransmit_time(skb, l);
index 75b99b7..8754bd8 100644 (file)
@@ -1518,7 +1518,7 @@ static int __tipc_sendmsg(struct socket *sock, struct msghdr *m, size_t dlen)
 
        if (unlikely(syn && !rc)) {
                tipc_set_sk_state(sk, TIPC_CONNECTING);
-               if (timeout) {
+               if (dlen && timeout) {
                        timeout = msecs_to_jiffies(timeout);
                        tipc_wait_for_connect(sock, &timeout);
                }
index e0c2c99..4f7c99d 100644 (file)
@@ -357,11 +357,14 @@ static void virtio_vsock_event_fill(struct virtio_vsock *vsock)
 
 static void virtio_vsock_reset_sock(struct sock *sk)
 {
-       lock_sock(sk);
+       /* vmci_transport.c doesn't take sk_lock here either.  At least we're
+        * under vsock_table_lock so the sock cannot disappear while we're
+        * executing.
+        */
+
        sk->sk_state = TCP_CLOSE;
        sk->sk_err = ECONNRESET;
        sk_error_report(sk);
-       release_sock(sk);
 }
 
 static void virtio_vsock_update_guest_cid(struct virtio_vsock *vsock)
index f67b125..94cd49e 100755 (executable)
@@ -1,10 +1,10 @@
 #! /usr/bin/env perl
 # SPDX-License-Identifier: GPL-2.0
 #
-# checkversion find uses of LINUX_VERSION_CODE or KERNEL_VERSION
-# without including <linux/version.h>, or cases of
-# including <linux/version.h> that don't need it.
-# Copyright (C) 2003, Randy Dunlap <rdunlap@xenotime.net>
+# checkversion finds uses of all macros in <linux/version.h>
+# where the source files do not #include <linux/version.h>; or cases
+# of including <linux/version.h> where it is not needed.
+# Copyright (C) 2003, Randy Dunlap <rdunlap@infradead.org>
 
 use strict;
 
@@ -13,7 +13,8 @@ $| = 1;
 my $debugging;
 
 foreach my $file (@ARGV) {
-    next if $file =~ "include/linux/version\.h";
+    next if $file =~ "include/generated/uapi/linux/version\.h";
+    next if $file =~ "usr/include/linux/version\.h";
     # Open this file.
     open( my $f, '<', $file )
       or die "Can't open $file: $!\n";
@@ -41,8 +42,11 @@ foreach my $file (@ARGV) {
            $iLinuxVersion      = $. if m/^\s*#\s*include\s*<linux\/version\.h>/o;
        }
 
-       # Look for uses: LINUX_VERSION_CODE, KERNEL_VERSION, UTS_RELEASE
-       if (($_ =~ /LINUX_VERSION_CODE/) || ($_ =~ /\WKERNEL_VERSION/)) {
+       # Look for uses: LINUX_VERSION_CODE, KERNEL_VERSION,
+       # LINUX_VERSION_MAJOR, LINUX_VERSION_PATCHLEVEL, LINUX_VERSION_SUBLEVEL
+       if (($_ =~ /LINUX_VERSION_CODE/) || ($_ =~ /\WKERNEL_VERSION/) ||
+           ($_ =~ /LINUX_VERSION_MAJOR/) || ($_ =~ /LINUX_VERSION_PATCHLEVEL/) ||
+           ($_ =~ /LINUX_VERSION_SUBLEVEL/)) {
            $fUseVersion = 1;
             last if $iLinuxVersion;
         }
index 09533cb..9ffa9e9 100644 (file)
@@ -58,10 +58,11 @@ const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
        [LOCKDOWN_MMIOTRACE] = "unsafe mmio",
        [LOCKDOWN_DEBUGFS] = "debugfs access",
        [LOCKDOWN_XMON_WR] = "xmon write access",
+       [LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",
        [LOCKDOWN_INTEGRITY_MAX] = "integrity",
        [LOCKDOWN_KCORE] = "/proc/kcore access",
        [LOCKDOWN_KPROBES] = "use of kprobes",
-       [LOCKDOWN_BPF_READ] = "use of bpf to read kernel RAM",
+       [LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",
        [LOCKDOWN_PERF] = "unsafe use of perf",
        [LOCKDOWN_TRACEFS] = "use of tracefs",
        [LOCKDOWN_XMON_RW] = "xmon read and write access",
index 83b79ed..439a358 100644 (file)
@@ -215,7 +215,7 @@ static int snd_dma_continuous_mmap(struct snd_dma_buffer *dmab,
                                   struct vm_area_struct *area)
 {
        return remap_pfn_range(area, area->vm_start,
-                              dmab->addr >> PAGE_SHIFT,
+                              page_to_pfn(virt_to_page(dmab->area)),
                               area->vm_end - area->vm_start,
                               area->vm_page_prot);
 }
index 6a2971a..71323d8 100644 (file)
@@ -246,12 +246,15 @@ static bool hw_support_mmap(struct snd_pcm_substream *substream)
        if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_MMAP))
                return false;
 
-       if (substream->ops->mmap)
+       if (substream->ops->mmap || substream->ops->page)
                return true;
 
        switch (substream->dma_buffer.dev.type) {
        case SNDRV_DMA_TYPE_UNKNOWN:
-               return false;
+               /* we can't know the device, so just assume that the driver does
+                * everything right
+                */
+               return true;
        case SNDRV_DMA_TYPE_CONTINUOUS:
        case SNDRV_DMA_TYPE_VMALLOC:
                return true;
index b9c2ce2..84d7863 100644 (file)
@@ -514,10 +514,11 @@ static int check_and_subscribe_port(struct snd_seq_client *client,
        return err;
 }
 
-static void delete_and_unsubscribe_port(struct snd_seq_client *client,
-                                       struct snd_seq_client_port *port,
-                                       struct snd_seq_subscribers *subs,
-                                       bool is_src, bool ack)
+/* called with grp->list_mutex held */
+static void __delete_and_unsubscribe_port(struct snd_seq_client *client,
+                                         struct snd_seq_client_port *port,
+                                         struct snd_seq_subscribers *subs,
+                                         bool is_src, bool ack)
 {
        struct snd_seq_port_subs_info *grp;
        struct list_head *list;
@@ -525,7 +526,6 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
 
        grp = is_src ? &port->c_src : &port->c_dest;
        list = is_src ? &subs->src_list : &subs->dest_list;
-       down_write(&grp->list_mutex);
        write_lock_irq(&grp->list_lock);
        empty = list_empty(list);
        if (!empty)
@@ -535,6 +535,18 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client,
 
        if (!empty)
                unsubscribe_port(client, port, grp, &subs->info, ack);
+}
+
+static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+                                       struct snd_seq_client_port *port,
+                                       struct snd_seq_subscribers *subs,
+                                       bool is_src, bool ack)
+{
+       struct snd_seq_port_subs_info *grp;
+
+       grp = is_src ? &port->c_src : &port->c_dest;
+       down_write(&grp->list_mutex);
+       __delete_and_unsubscribe_port(client, port, subs, is_src, ack);
        up_write(&grp->list_mutex);
 }
 
@@ -590,27 +602,30 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
                            struct snd_seq_client_port *dest_port,
                            struct snd_seq_port_subscribe *info)
 {
-       struct snd_seq_port_subs_info *src = &src_port->c_src;
+       struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
        struct snd_seq_subscribers *subs;
        int err = -ENOENT;
 
-       down_write(&src->list_mutex);
+       /* always start from deleting the dest port for avoiding concurrent
+        * deletions
+        */
+       down_write(&dest->list_mutex);
        /* look for the connection */
-       list_for_each_entry(subs, &src->list_head, src_list) {
+       list_for_each_entry(subs, &dest->list_head, dest_list) {
                if (match_subs_info(info, &subs->info)) {
-                       atomic_dec(&subs->ref_count); /* mark as not ready */
+                       __delete_and_unsubscribe_port(dest_client, dest_port,
+                                                     subs, false,
+                                                     connector->number != dest_client->number);
                        err = 0;
                        break;
                }
        }
-       up_write(&src->list_mutex);
+       up_write(&dest->list_mutex);
        if (err < 0)
                return err;
 
        delete_and_unsubscribe_port(src_client, src_port, subs, true,
                                    connector->number != src_client->number);
-       delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
-                                   connector->number != dest_client->number);
        kfree(subs);
        return 0;
 }
index 0ef242f..fff18b5 100644 (file)
@@ -153,7 +153,7 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
        struct cmp_connection *conn;
        enum cmp_direction c_dir;
        enum amdtp_stream_direction s_dir;
-       unsigned int flags = CIP_UNAWARE_SYT;
+       unsigned int flags = 0;
        int err;
 
        if (!(oxfw->quirks & SND_OXFW_QUIRK_BLOCKING_TRANSMISSION))
@@ -161,6 +161,13 @@ static int init_stream(struct snd_oxfw *oxfw, struct amdtp_stream *stream)
        else
                flags |= CIP_BLOCKING;
 
+       // OXFW 970/971 has no function to generate playback timing according to the sequence
+       // of value in syt field, thus the packet should include NO_INFO value in the field.
+       // However, some models just ignore data blocks in packet with NO_INFO for audio data
+       // processing.
+       if (!(oxfw->quirks & SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET))
+               flags |= CIP_UNAWARE_SYT;
+
        if (stream == &oxfw->tx_stream) {
                conn = &oxfw->out_conn;
                c_dir = CMP_OUTPUT;
index 84971d7..cb5b5e3 100644 (file)
@@ -159,8 +159,10 @@ static int detect_quirks(struct snd_oxfw *oxfw, const struct ieee1394_device_id
                return snd_oxfw_scs1x_add(oxfw);
        }
 
-       if (entry->vendor_id == OUI_APOGEE && entry->model_id == MODEL_DUET_FW)
-               oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION;
+       if (entry->vendor_id == OUI_APOGEE && entry->model_id == MODEL_DUET_FW) {
+               oxfw->quirks |= SND_OXFW_QUIRK_BLOCKING_TRANSMISSION |
+                               SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET;
+       }
 
        /*
         * TASCAM FireOne has physical control and requires a pair of additional
index ee47abc..c13034f 100644 (file)
@@ -42,6 +42,11 @@ enum snd_oxfw_quirk {
        SND_OXFW_QUIRK_BLOCKING_TRANSMISSION = 0x04,
        // Stanton SCS1.d and SCS1.m support unique transaction.
        SND_OXFW_QUIRK_SCS_TRANSACTION = 0x08,
+       // Apogee Duet FireWire ignores data blocks in packet with NO_INFO for audio data
+       // processing, while output level meter moves. Any value in syt field of packet takes
+       // the device to process audio data even if the value is invalid in a point of
+       // IEC 61883-1/6.
+       SND_OXFW_QUIRK_IGNORE_NO_INFO_PACKET = 0x10,
 };
 
 /* This is an arbitrary number for convinience. */
index e97d005..481d8f8 100644 (file)
@@ -3460,7 +3460,7 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
        struct hda_gen_spec *spec = codec->spec;
        const struct hda_input_mux *imux;
        struct nid_path *path;
-       int i, adc_idx, err = 0;
+       int i, adc_idx, ret, err = 0;
 
        imux = &spec->input_mux;
        adc_idx = kcontrol->id.index;
@@ -3470,9 +3470,13 @@ static int cap_put_caller(struct snd_kcontrol *kcontrol,
                if (!path || !path->ctls[type])
                        continue;
                kcontrol->private_value = path->ctls[type];
-               err = func(kcontrol, ucontrol);
-               if (err < 0)
+               ret = func(kcontrol, ucontrol);
+               if (ret < 0) {
+                       err = ret;
                        break;
+               }
+               if (ret > 0)
+                       err = 1;
        }
        mutex_unlock(&codec->control_mutex);
        if (err >= 0 && spec->cap_sync_hook)
index 0322b28..0062c18 100644 (file)
@@ -883,10 +883,11 @@ static unsigned int azx_get_pos_skl(struct azx *chip, struct azx_dev *azx_dev)
        return azx_get_pos_posbuf(chip, azx_dev);
 }
 
-static void azx_shutdown_chip(struct azx *chip)
+static void __azx_shutdown_chip(struct azx *chip, bool skip_link_reset)
 {
        azx_stop_chip(chip);
-       azx_enter_link_reset(chip);
+       if (!skip_link_reset)
+               azx_enter_link_reset(chip);
        azx_clear_irq_pending(chip);
        display_power(chip, false);
 }
@@ -895,6 +896,11 @@ static void azx_shutdown_chip(struct azx *chip)
 static DEFINE_MUTEX(card_list_lock);
 static LIST_HEAD(card_list);
 
+static void azx_shutdown_chip(struct azx *chip)
+{
+       __azx_shutdown_chip(chip, false);
+}
+
 static void azx_add_card_list(struct azx *chip)
 {
        struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
@@ -2385,7 +2391,7 @@ static void azx_shutdown(struct pci_dev *pci)
                return;
        chip = card->private_data;
        if (chip && chip->running)
-               azx_shutdown_chip(chip);
+               __azx_shutdown_chip(chip, true);
 }
 
 /* PCI IDs */
index caaf0e8..7ad689f 100644 (file)
@@ -6658,6 +6658,7 @@ enum {
        ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP,
        ALC623_FIXUP_LENOVO_THINKSTATION_P340,
        ALC255_FIXUP_ACER_HEADPHONE_AND_MIC,
+       ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -8242,6 +8243,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC255_FIXUP_XIAOMI_HEADSET_MIC
        },
+       [ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc269_fixup_limit_int_mic_boost,
+               .chained = true,
+               .chain_id = ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -8274,9 +8281,11 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1025, 0x1290, "Acer Veriton Z4860G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1291, "Acer Veriton Z4660G", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x129c, "Acer SWIFT SF314-55", ALC256_FIXUP_ACER_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1025, 0x1300, "Acer SWIFT SF314-56", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x1308, "Acer Aspire Z24-890", ALC286_FIXUP_ACER_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x132a, "Acer TravelMate B114-21", ALC233_FIXUP_ACER_HEADSET_MIC),
        SND_PCI_QUIRK(0x1025, 0x1330, "Acer TravelMate X514-51T", ALC255_FIXUP_ACER_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1025, 0x142b, "Acer Swift SF314-42", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
        SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
@@ -8330,6 +8339,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0a2e, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0a30, "Dell", ALC236_FIXUP_DELL_AIO_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0a58, "Dell", ALC255_FIXUP_DELL_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1028, 0x0a61, "Dell XPS 15 9510", 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),
@@ -8429,13 +8439,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
+       SND_PCI_QUIRK(0x103c, 0x8805, "HP ProBook 650 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
-       SND_PCI_QUIRK(0x103c, 0x8862, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
-       SND_PCI_QUIRK(0x103c, 0x8863, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+       SND_PCI_QUIRK(0x103c, 0x8862, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST),
+       SND_PCI_QUIRK(0x103c, 0x8863, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
        SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
@@ -8463,6 +8474,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
        SND_PCI_QUIRK(0x1043, 0x1740, "ASUS UX430UA", ALC295_FIXUP_ASUS_DACS),
        SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
+       SND_PCI_QUIRK(0x1043, 0x1662, "ASUS GV301QH", ALC294_FIXUP_ASUS_DUAL_SPK),
        SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
        SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
index a5c1a2c..773a136 100644 (file)
@@ -1041,6 +1041,7 @@ static const struct hda_fixup via_fixups[] = {
 };
 
 static const struct snd_pci_quirk vt2002p_fixups[] = {
+       SND_PCI_QUIRK(0x1043, 0x13f7, "Asus B23E", VIA_FIXUP_POWER_SAVE),
        SND_PCI_QUIRK(0x1043, 0x1487, "Asus G75", VIA_FIXUP_ASUS_G75),
        SND_PCI_QUIRK(0x1043, 0x8532, "Asus X202E", VIA_FIXUP_INTMIC_BOOST),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", VIA_FIXUP_POWER_SAVE),
index 8a13462..5dcf77a 100644 (file)
@@ -36,6 +36,7 @@ config SND_SOC_COMPRESS
 
 config SND_SOC_TOPOLOGY
        bool
+       select SND_DYNAMIC_MINORS
 
 config SND_SOC_TOPOLOGY_KUNIT_TEST
        tristate "KUnit tests for SoC topology"
index 9449fb4..3c60c5f 100644 (file)
@@ -525,6 +525,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                                | SND_SOC_DAIFMT_CBM_CFM,
                .init = cz_da7219_init,
                .dpcm_playback = 1,
+               .stop_dma_first = 1,
                .ops = &cz_da7219_play_ops,
                SND_SOC_DAILINK_REG(designware1, dlgs, platform),
        },
@@ -534,6 +535,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
                .dpcm_capture = 1,
+               .stop_dma_first = 1,
                .ops = &cz_da7219_cap_ops,
                SND_SOC_DAILINK_REG(designware2, dlgs, platform),
        },
@@ -543,6 +545,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
                .dpcm_playback = 1,
+               .stop_dma_first = 1,
                .ops = &cz_max_play_ops,
                SND_SOC_DAILINK_REG(designware3, mx, platform),
        },
@@ -553,6 +556,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
                .dpcm_capture = 1,
+               .stop_dma_first = 1,
                .ops = &cz_dmic0_cap_ops,
                SND_SOC_DAILINK_REG(designware3, adau, platform),
        },
@@ -563,6 +567,7 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = {
                .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
                                | SND_SOC_DAIFMT_CBM_CFM,
                .dpcm_capture = 1,
+               .stop_dma_first = 1,
                .ops = &cz_dmic1_cap_ops,
                SND_SOC_DAILINK_REG(designware2, adau, platform),
        },
index 143155a..cc1ce6f 100644 (file)
@@ -969,7 +969,7 @@ static int acp_dma_hw_params(struct snd_soc_component *component,
 
        acp_set_sram_bank_state(rtd->acp_mmio, 0, true);
        /* Save for runtime private data */
-       rtd->dma_addr = substream->dma_buffer.addr;
+       rtd->dma_addr = runtime->dma_addr;
        rtd->order = get_order(size);
 
        /* Fill the page table entries in ACP SRAM */
index 8148b0d..597d7c4 100644 (file)
@@ -286,7 +286,7 @@ static int acp3x_dma_hw_params(struct snd_soc_component *component,
                pr_err("pinfo failed\n");
        }
        size = params_buffer_bytes(params);
-       rtd->dma_addr = substream->dma_buffer.addr;
+       rtd->dma_addr = substream->runtime->dma_addr;
        rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
        config_acp3x_dma(rtd, substream->stream);
        return 0;
index bd20622..0391c28 100644 (file)
@@ -242,7 +242,7 @@ static int acp_pdm_dma_hw_params(struct snd_soc_component *component,
                return -EINVAL;
        size = params_buffer_bytes(params);
        period_bytes = params_period_bytes(params);
-       rtd->dma_addr = substream->dma_buffer.addr;
+       rtd->dma_addr = substream->runtime->dma_addr;
        rtd->num_pages = (PAGE_ALIGN(size) >> PAGE_SHIFT);
        config_acp_dma(rtd, substream->stream);
        init_pdm_ring_buffer(MEM_WINDOW_START, size, period_bytes,
index 19438da..7b8040e 100644 (file)
@@ -382,6 +382,8 @@ static const struct dev_pm_ops rn_acp_pm = {
        .runtime_resume =  snd_rn_acp_resume,
        .suspend = snd_rn_acp_suspend,
        .resume =       snd_rn_acp_resume,
+       .restore =      snd_rn_acp_resume,
+       .poweroff =     snd_rn_acp_suspend,
 };
 
 static void snd_rn_acp_remove(struct pci_dev *pci)
index a3b784e..db16071 100644 (file)
@@ -1559,6 +1559,7 @@ config SND_SOC_WCD934X
 config SND_SOC_WCD938X
        depends on SND_SOC_WCD938X_SDW
        tristate
+       depends on SOUNDWIRE || !SOUNDWIRE
 
 config SND_SOC_WCD938X_SDW
        tristate "WCD9380/WCD9385 Codec - SDW"
index de8b83d..7bb38c3 100644 (file)
@@ -583,7 +583,10 @@ obj-$(CONFIG_SND_SOC_WCD_MBHC)     += snd-soc-wcd-mbhc.o
 obj-$(CONFIG_SND_SOC_WCD9335)  += snd-soc-wcd9335.o
 obj-$(CONFIG_SND_SOC_WCD934X)  += snd-soc-wcd934x.o
 obj-$(CONFIG_SND_SOC_WCD938X)  += snd-soc-wcd938x.o
-obj-$(CONFIG_SND_SOC_WCD938X_SDW) += snd-soc-wcd938x-sdw.o
+ifdef CONFIG_SND_SOC_WCD938X_SDW
+# avoid link failure by forcing sdw code built-in when needed
+obj-$(CONFIG_SND_SOC_WCD938X) += snd-soc-wcd938x-sdw.o
+endif
 obj-$(CONFIG_SND_SOC_WL1273)   += snd-soc-wl1273.o
 obj-$(CONFIG_SND_SOC_WM0010)   += snd-soc-wm0010.o
 obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
index eff013f..99c022b 100644 (file)
@@ -405,7 +405,7 @@ static const struct regmap_config cs42l42_regmap = {
        .use_single_write = true,
 };
 
-static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, false);
+static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true);
 static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
 
 static const char * const cs42l42_hpf_freq_text[] = {
@@ -425,34 +425,23 @@ static SOC_ENUM_SINGLE_DECL(cs42l42_wnf3_freq_enum, CS42L42_ADC_WNF_HPF_CTL,
                            CS42L42_ADC_WNF_CF_SHIFT,
                            cs42l42_wnf3_freq_text);
 
-static const char * const cs42l42_wnf05_freq_text[] = {
-       "280Hz", "315Hz", "350Hz", "385Hz",
-       "420Hz", "455Hz", "490Hz", "525Hz"
-};
-
-static SOC_ENUM_SINGLE_DECL(cs42l42_wnf05_freq_enum, CS42L42_ADC_WNF_HPF_CTL,
-                           CS42L42_ADC_WNF_CF_SHIFT,
-                           cs42l42_wnf05_freq_text);
-
 static const struct snd_kcontrol_new cs42l42_snd_controls[] = {
        /* ADC Volume and Filter Controls */
        SOC_SINGLE("ADC Notch Switch", CS42L42_ADC_CTL,
-                               CS42L42_ADC_NOTCH_DIS_SHIFT, true, false),
+                               CS42L42_ADC_NOTCH_DIS_SHIFT, true, true),
        SOC_SINGLE("ADC Weak Force Switch", CS42L42_ADC_CTL,
                                CS42L42_ADC_FORCE_WEAK_VCM_SHIFT, true, false),
        SOC_SINGLE("ADC Invert Switch", CS42L42_ADC_CTL,
                                CS42L42_ADC_INV_SHIFT, true, false),
        SOC_SINGLE("ADC Boost Switch", CS42L42_ADC_CTL,
                                CS42L42_ADC_DIG_BOOST_SHIFT, true, false),
-       SOC_SINGLE_SX_TLV("ADC Volume", CS42L42_ADC_VOLUME,
-                               CS42L42_ADC_VOL_SHIFT, 0xA0, 0x6C, adc_tlv),
+       SOC_SINGLE_S8_TLV("ADC Volume", CS42L42_ADC_VOLUME, -97, 12, adc_tlv),
        SOC_SINGLE("ADC WNF Switch", CS42L42_ADC_WNF_HPF_CTL,
                                CS42L42_ADC_WNF_EN_SHIFT, true, false),
        SOC_SINGLE("ADC HPF Switch", CS42L42_ADC_WNF_HPF_CTL,
                                CS42L42_ADC_HPF_EN_SHIFT, true, false),
        SOC_ENUM("HPF Corner Freq", cs42l42_hpf_freq_enum),
        SOC_ENUM("WNF 3dB Freq", cs42l42_wnf3_freq_enum),
-       SOC_ENUM("WNF 05dB Freq", cs42l42_wnf05_freq_enum),
 
        /* DAC Volume and Filter Controls */
        SOC_SINGLE("DACA Invert Switch", CS42L42_DAC_CTL1,
@@ -471,8 +460,8 @@ static const struct snd_soc_dapm_widget cs42l42_dapm_widgets[] = {
        SND_SOC_DAPM_OUTPUT("HP"),
        SND_SOC_DAPM_DAC("DAC", NULL, CS42L42_PWR_CTL1, CS42L42_HP_PDN_SHIFT, 1),
        SND_SOC_DAPM_MIXER("MIXER", CS42L42_PWR_CTL1, CS42L42_MIXER_PDN_SHIFT, 1, NULL, 0),
-       SND_SOC_DAPM_AIF_IN("SDIN1", NULL, 0, CS42L42_ASP_RX_DAI0_EN, CS42L42_ASP_RX0_CH1_SHIFT, 0),
-       SND_SOC_DAPM_AIF_IN("SDIN2", NULL, 1, CS42L42_ASP_RX_DAI0_EN, CS42L42_ASP_RX0_CH2_SHIFT, 0),
+       SND_SOC_DAPM_AIF_IN("SDIN1", NULL, 0, SND_SOC_NOPM, 0, 0),
+       SND_SOC_DAPM_AIF_IN("SDIN2", NULL, 1, SND_SOC_NOPM, 0, 0),
 
        /* Playback Requirements */
        SND_SOC_DAPM_SUPPLY("ASP DAI0", CS42L42_PWR_CTL1, CS42L42_ASP_DAI_PDN_SHIFT, 1, NULL, 0),
@@ -630,6 +619,8 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
 
        for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) {
                if (pll_ratio_table[i].sclk == clk) {
+                       cs42l42->pll_config = i;
+
                        /* Configure the internal sample rate */
                        snd_soc_component_update_bits(component, CS42L42_MCLK_CTL,
                                        CS42L42_INTERNAL_FS_MASK,
@@ -638,14 +629,9 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
                                        (pll_ratio_table[i].mclk_int !=
                                        24000000)) <<
                                        CS42L42_INTERNAL_FS_SHIFT);
-                       /* Set the MCLK src (PLL or SCLK) and the divide
-                        * ratio
-                        */
+
                        snd_soc_component_update_bits(component, CS42L42_MCLK_SRC_SEL,
-                                       CS42L42_MCLK_SRC_SEL_MASK |
                                        CS42L42_MCLKDIV_MASK,
-                                       (pll_ratio_table[i].mclk_src_sel
-                                       << CS42L42_MCLK_SRC_SEL_SHIFT) |
                                        (pll_ratio_table[i].mclk_div <<
                                        CS42L42_MCLKDIV_SHIFT));
                        /* Set up the LRCLK */
@@ -681,15 +667,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component)
                                        CS42L42_FSYNC_PULSE_WIDTH_MASK,
                                        CS42L42_FRAC1_VAL(fsync - 1) <<
                                        CS42L42_FSYNC_PULSE_WIDTH_SHIFT);
-                       snd_soc_component_update_bits(component,
-                                       CS42L42_ASP_FRM_CFG,
-                                       CS42L42_ASP_5050_MASK,
-                                       CS42L42_ASP_5050_MASK);
-                       /* Set the frame delay to 1.0 SCLK clocks */
-                       snd_soc_component_update_bits(component, CS42L42_ASP_FRM_CFG,
-                                       CS42L42_ASP_FSD_MASK,
-                                       CS42L42_ASP_FSD_1_0 <<
-                                       CS42L42_ASP_FSD_SHIFT);
                        /* Set the sample rates (96k or lower) */
                        snd_soc_component_update_bits(component, CS42L42_FS_RATE_EN,
                                        CS42L42_FS_EN_MASK,
@@ -789,7 +766,18 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        /* interface format */
        switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
        case SND_SOC_DAIFMT_I2S:
-       case SND_SOC_DAIFMT_LEFT_J:
+               /*
+                * 5050 mode, frame starts on falling edge of LRCLK,
+                * frame delayed by 1.0 SCLKs
+                */
+               snd_soc_component_update_bits(component,
+                                             CS42L42_ASP_FRM_CFG,
+                                             CS42L42_ASP_STP_MASK |
+                                             CS42L42_ASP_5050_MASK |
+                                             CS42L42_ASP_FSD_MASK,
+                                             CS42L42_ASP_5050_MASK |
+                                             (CS42L42_ASP_FSD_1_0 <<
+                                               CS42L42_ASP_FSD_SHIFT));
                break;
        default:
                return -EINVAL;
@@ -819,6 +807,25 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
        return 0;
 }
 
+static int cs42l42_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai)
+{
+       struct snd_soc_component *component = dai->component;
+       struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component);
+
+       /*
+        * Sample rates < 44.1 kHz would produce an out-of-range SCLK with
+        * a standard I2S frame. If the machine driver sets SCLK it must be
+        * legal.
+        */
+       if (cs42l42->sclk)
+               return 0;
+
+       /* Machine driver has not set a SCLK, limit bottom end to 44.1 kHz */
+       return snd_pcm_hw_constraint_minmax(substream->runtime,
+                                           SNDRV_PCM_HW_PARAM_RATE,
+                                           44100, 192000);
+}
+
 static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *dai)
@@ -832,6 +839,10 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
        cs42l42->srate = params_rate(params);
        cs42l42->bclk = snd_soc_params_to_bclk(params);
 
+       /* I2S frame always has 2 channels even for mono audio */
+       if (channels == 1)
+               cs42l42->bclk *= 2;
+
        switch(substream->stream) {
        case SNDRV_PCM_STREAM_CAPTURE:
                if (channels == 2) {
@@ -855,6 +866,17 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream,
                snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH2_AP_RES,
                                                         CS42L42_ASP_RX_CH_AP_MASK |
                                                         CS42L42_ASP_RX_CH_RES_MASK, val);
+
+               /* Channel B comes from the last active channel */
+               snd_soc_component_update_bits(component, CS42L42_SP_RX_CH_SEL,
+                                             CS42L42_SP_RX_CHB_SEL_MASK,
+                                             (channels - 1) << CS42L42_SP_RX_CHB_SEL_SHIFT);
+
+               /* Both LRCLK slots must be enabled */
+               snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_EN,
+                                             CS42L42_ASP_RX0_CH_EN_MASK,
+                                             BIT(CS42L42_ASP_RX0_CH1_SHIFT) |
+                                             BIT(CS42L42_ASP_RX0_CH2_SHIFT));
                break;
        default:
                break;
@@ -900,13 +922,21 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
                         */
                        regmap_multi_reg_write(cs42l42->regmap, cs42l42_to_osc_seq,
                                               ARRAY_SIZE(cs42l42_to_osc_seq));
+
+                       /* Must disconnect PLL before stopping it */
+                       snd_soc_component_update_bits(component,
+                                                     CS42L42_MCLK_SRC_SEL,
+                                                     CS42L42_MCLK_SRC_SEL_MASK,
+                                                     0);
+                       usleep_range(100, 200);
+
                        snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
                                                      CS42L42_PLL_START_MASK, 0);
                }
        } else {
                if (!cs42l42->stream_use) {
                        /* SCLK must be running before codec unmute */
-                       if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) {
+                       if (pll_ratio_table[cs42l42->pll_config].mclk_src_sel) {
                                snd_soc_component_update_bits(component, CS42L42_PLL_CTL1,
                                                              CS42L42_PLL_START_MASK, 1);
 
@@ -927,6 +957,12 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
                                                               CS42L42_PLL_LOCK_TIMEOUT_US);
                                if (ret < 0)
                                        dev_warn(component->dev, "PLL failed to lock: %d\n", ret);
+
+                               /* PLL must be running to drive glitchless switch logic */
+                               snd_soc_component_update_bits(component,
+                                                             CS42L42_MCLK_SRC_SEL,
+                                                             CS42L42_MCLK_SRC_SEL_MASK,
+                                                             CS42L42_MCLK_SRC_SEL_MASK);
                        }
 
                        /* Mark SCLK as present, turn off internal oscillator */
@@ -960,8 +996,8 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
                         SNDRV_PCM_FMTBIT_S24_LE |\
                         SNDRV_PCM_FMTBIT_S32_LE )
 
-
 static const struct snd_soc_dai_ops cs42l42_ops = {
+       .startup        = cs42l42_dai_startup,
        .hw_params      = cs42l42_pcm_hw_params,
        .set_fmt        = cs42l42_set_dai_fmt,
        .set_sysclk     = cs42l42_set_sysclk,
index 206b3c8..8734f68 100644 (file)
 
 /* Page 0x25 Audio Port Registers */
 #define CS42L42_SP_RX_CH_SEL           (CS42L42_PAGE_25 + 0x01)
+#define CS42L42_SP_RX_CHB_SEL_SHIFT    2
+#define CS42L42_SP_RX_CHB_SEL_MASK     (3 << CS42L42_SP_RX_CHB_SEL_SHIFT)
 
 #define CS42L42_SP_RX_ISOC_CTL         (CS42L42_PAGE_25 + 0x02)
 #define CS42L42_SP_RX_RSYNC_SHIFT      6
@@ -775,6 +777,7 @@ struct  cs42l42_private {
        struct gpio_desc *reset_gpio;
        struct completion pdn_done;
        struct snd_soc_jack *jack;
+       int pll_config;
        int bclk;
        u32 sclk;
        u32 srate;
index 15bd833..db88be4 100644 (file)
@@ -828,36 +828,6 @@ static void nau8824_int_status_clear_all(struct regmap *regmap)
        }
 }
 
-static void nau8824_dapm_disable_pin(struct nau8824 *nau8824, const char *pin)
-{
-       struct snd_soc_dapm_context *dapm = nau8824->dapm;
-       const char *prefix = dapm->component->name_prefix;
-       char prefixed_pin[80];
-
-       if (prefix) {
-               snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
-                        prefix, pin);
-               snd_soc_dapm_disable_pin(dapm, prefixed_pin);
-       } else {
-               snd_soc_dapm_disable_pin(dapm, pin);
-       }
-}
-
-static void nau8824_dapm_enable_pin(struct nau8824 *nau8824, const char *pin)
-{
-       struct snd_soc_dapm_context *dapm = nau8824->dapm;
-       const char *prefix = dapm->component->name_prefix;
-       char prefixed_pin[80];
-
-       if (prefix) {
-               snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
-                        prefix, pin);
-               snd_soc_dapm_force_enable_pin(dapm, prefixed_pin);
-       } else {
-               snd_soc_dapm_force_enable_pin(dapm, pin);
-       }
-}
-
 static void nau8824_eject_jack(struct nau8824 *nau8824)
 {
        struct snd_soc_dapm_context *dapm = nau8824->dapm;
@@ -866,8 +836,8 @@ static void nau8824_eject_jack(struct nau8824 *nau8824)
        /* Clear all interruption status */
        nau8824_int_status_clear_all(regmap);
 
-       nau8824_dapm_disable_pin(nau8824, "SAR");
-       nau8824_dapm_disable_pin(nau8824, "MICBIAS");
+       snd_soc_dapm_disable_pin(dapm, "SAR");
+       snd_soc_dapm_disable_pin(dapm, "MICBIAS");
        snd_soc_dapm_sync(dapm);
 
        /* Enable the insertion interruption, disable the ejection
@@ -897,8 +867,8 @@ static void nau8824_jdet_work(struct work_struct *work)
        struct regmap *regmap = nau8824->regmap;
        int adc_value, event = 0, event_mask = 0;
 
-       nau8824_dapm_enable_pin(nau8824, "MICBIAS");
-       nau8824_dapm_enable_pin(nau8824, "SAR");
+       snd_soc_dapm_enable_pin(dapm, "MICBIAS");
+       snd_soc_dapm_enable_pin(dapm, "SAR");
        snd_soc_dapm_sync(dapm);
 
        msleep(100);
@@ -909,8 +879,8 @@ static void nau8824_jdet_work(struct work_struct *work)
        if (adc_value < HEADSET_SARADC_THD) {
                event |= SND_JACK_HEADPHONE;
 
-               nau8824_dapm_disable_pin(nau8824, "SAR");
-               nau8824_dapm_disable_pin(nau8824, "MICBIAS");
+               snd_soc_dapm_disable_pin(dapm, "SAR");
+               snd_soc_dapm_disable_pin(dapm, "MICBIAS");
                snd_soc_dapm_sync(dapm);
        } else {
                event |= SND_JACK_HEADSET;
index abcd6f4..51ecaa2 100644 (file)
@@ -44,6 +44,7 @@ static const struct reg_sequence patch_list[] = {
        {RT5682_I2C_CTRL, 0x000f},
        {RT5682_PLL2_INTERNAL, 0x8266},
        {RT5682_SAR_IL_CMD_3, 0x8365},
+       {RT5682_SAR_IL_CMD_6, 0x0180},
 };
 
 void rt5682_apply_patch_list(struct rt5682_priv *rt5682, struct device *dev)
index b504d63..52d2c96 100644 (file)
@@ -35,6 +35,9 @@
 
 #include "tlv320aic31xx.h"
 
+static int aic31xx_set_jack(struct snd_soc_component *component,
+                            struct snd_soc_jack *jack, void *data);
+
 static const struct reg_default aic31xx_reg_defaults[] = {
        { AIC31XX_CLKMUX, 0x00 },
        { AIC31XX_PLLPR, 0x11 },
@@ -1256,6 +1259,13 @@ static int aic31xx_power_on(struct snd_soc_component *component)
                return ret;
        }
 
+       /*
+        * The jack detection configuration is in the same register
+        * that is used to report jack detect status so is volatile
+        * and not covered by the cache sync, restore it separately.
+        */
+       aic31xx_set_jack(component, aic31xx->jack, NULL);
+
        return 0;
 }
 
index dcd8aeb..2e9175b 100644 (file)
@@ -682,11 +682,20 @@ static int aic32x4_set_dosr(struct snd_soc_component *component, u16 dosr)
 static int aic32x4_set_processing_blocks(struct snd_soc_component *component,
                                                u8 r_block, u8 p_block)
 {
-       if (r_block > 18 || p_block > 25)
-               return -EINVAL;
+       struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
+
+       if (aic32x4->type == AIC32X4_TYPE_TAS2505) {
+               if (r_block || p_block > 3)
+                       return -EINVAL;
 
-       snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
-       snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
+               snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
+       } else { /* AIC32x4 */
+               if (r_block > 18 || p_block > 25)
+                       return -EINVAL;
+
+               snd_soc_component_write(component, AIC32X4_ADCSPB, r_block);
+               snd_soc_component_write(component, AIC32X4_DACSPB, p_block);
+       }
 
        return 0;
 }
@@ -695,6 +704,7 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
                                unsigned int sample_rate, unsigned int channels,
                                unsigned int bit_depth)
 {
+       struct aic32x4_priv *aic32x4 = snd_soc_component_get_drvdata(component);
        u8 aosr;
        u16 dosr;
        u8 adc_resource_class, dac_resource_class;
@@ -721,19 +731,28 @@ static int aic32x4_setup_clocks(struct snd_soc_component *component,
                adc_resource_class = 6;
                dac_resource_class = 8;
                dosr_increment = 8;
-               aic32x4_set_processing_blocks(component, 1, 1);
+               if (aic32x4->type == AIC32X4_TYPE_TAS2505)
+                       aic32x4_set_processing_blocks(component, 0, 1);
+               else
+                       aic32x4_set_processing_blocks(component, 1, 1);
        } else if (sample_rate <= 96000) {
                aosr = 64;
                adc_resource_class = 6;
                dac_resource_class = 8;
                dosr_increment = 4;
-               aic32x4_set_processing_blocks(component, 1, 9);
+               if (aic32x4->type == AIC32X4_TYPE_TAS2505)
+                       aic32x4_set_processing_blocks(component, 0, 1);
+               else
+                       aic32x4_set_processing_blocks(component, 1, 9);
        } else if (sample_rate == 192000) {
                aosr = 32;
                adc_resource_class = 3;
                dac_resource_class = 4;
                dosr_increment = 2;
-               aic32x4_set_processing_blocks(component, 13, 19);
+               if (aic32x4->type == AIC32X4_TYPE_TAS2505)
+                       aic32x4_set_processing_blocks(component, 0, 1);
+               else
+                       aic32x4_set_processing_blocks(component, 13, 19);
        } else {
                dev_err(component->dev, "Sampling rate not supported\n");
                return -EINVAL;
index 549d982..fe15cbc 100644 (file)
@@ -747,7 +747,6 @@ static void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
 static void wm_adsp2_cleanup_debugfs(struct wm_adsp *dsp)
 {
        wm_adsp_debugfs_clear(dsp);
-       debugfs_remove_recursive(dsp->debugfs_root);
 }
 #else
 static inline void wm_adsp2_init_debugfs(struct wm_adsp *dsp,
index 4124aa2..905c796 100644 (file)
@@ -127,7 +127,7 @@ static void sst_fill_alloc_params(struct snd_pcm_substream *substream,
        snd_pcm_uframes_t period_size;
        ssize_t periodbytes;
        ssize_t buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
-       u32 buffer_addr = virt_to_phys(substream->dma_buffer.area);
+       u32 buffer_addr = virt_to_phys(substream->runtime->dma_area);
 
        channels = substream->runtime->channels;
        period_size = substream->runtime->period_size;
@@ -233,7 +233,6 @@ static int sst_platform_alloc_stream(struct snd_pcm_substream *substream,
        /* set codec params and inform SST driver the same */
        sst_fill_pcm_params(substream, &param);
        sst_fill_alloc_params(substream, &alloc_params);
-       substream->runtime->dma_area = substream->dma_buffer.area;
        str_params.sparams = param;
        str_params.aparams = alloc_params;
        str_params.codec = SST_CODEC_TYPE_PCM;
index 896251d..b7b3b0b 100644 (file)
@@ -404,7 +404,7 @@ static int audio_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        /* By default dais[0] is configured for max98373 */
-       if (!strcmp(pdev->name, "sof_da7219_max98360a")) {
+       if (!strcmp(pdev->name, "sof_da7219_mx98360a")) {
                dais[0] = (struct snd_soc_dai_link) {
                        .name = "SSP1-Codec",
                        .id = 0,
index c2a5933..700a185 100644 (file)
@@ -104,8 +104,6 @@ static int kirkwood_dma_open(struct snd_soc_component *component,
        int err;
        struct snd_pcm_runtime *runtime = substream->runtime;
        struct kirkwood_dma_data *priv = kirkwood_priv(substream);
-       const struct mbus_dram_target_info *dram;
-       unsigned long addr;
 
        snd_soc_set_runtime_hwparams(substream, &kirkwood_dma_snd_hw);
 
@@ -142,20 +140,14 @@ static int kirkwood_dma_open(struct snd_soc_component *component,
                writel((unsigned int)-1, priv->io + KIRKWOOD_ERR_MASK);
        }
 
-       dram = mv_mbus_dram_info();
-       addr = substream->dma_buffer.addr;
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                if (priv->substream_play)
                        return -EBUSY;
                priv->substream_play = substream;
-               kirkwood_dma_conf_mbus_windows(priv->io,
-                       KIRKWOOD_PLAYBACK_WIN, addr, dram);
        } else {
                if (priv->substream_rec)
                        return -EBUSY;
                priv->substream_rec = substream;
-               kirkwood_dma_conf_mbus_windows(priv->io,
-                       KIRKWOOD_RECORD_WIN, addr, dram);
        }
 
        return 0;
@@ -182,6 +174,23 @@ static int kirkwood_dma_close(struct snd_soc_component *component,
        return 0;
 }
 
+static int kirkwood_dma_hw_params(struct snd_soc_component *component,
+                                 struct snd_pcm_substream *substream,
+                                 struct snd_pcm_hw_params *params)
+{
+       struct kirkwood_dma_data *priv = kirkwood_priv(substream);
+       const struct mbus_dram_target_info *dram = mv_mbus_dram_info();
+       unsigned long addr = substream->runtime->dma_addr;
+
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+               kirkwood_dma_conf_mbus_windows(priv->io,
+                       KIRKWOOD_PLAYBACK_WIN, addr, dram);
+       else
+               kirkwood_dma_conf_mbus_windows(priv->io,
+                       KIRKWOOD_RECORD_WIN, addr, dram);
+       return 0;
+}
+
 static int kirkwood_dma_prepare(struct snd_soc_component *component,
                                struct snd_pcm_substream *substream)
 {
@@ -246,6 +255,7 @@ const struct snd_soc_component_driver kirkwood_soc_component = {
        .name           = DRV_NAME,
        .open           = kirkwood_dma_open,
        .close          = kirkwood_dma_close,
+       .hw_params      = kirkwood_dma_hw_params,
        .prepare        = kirkwood_dma_prepare,
        .pointer        = kirkwood_dma_pointer,
        .pcm_construct  = kirkwood_dma_new,
index 3a5e84e..c8dfd0d 100644 (file)
@@ -148,86 +148,75 @@ int snd_soc_component_set_bias_level(struct snd_soc_component *component,
        return soc_component_ret(component, ret);
 }
 
-static int soc_component_pin(struct snd_soc_component *component,
-                            const char *pin,
-                            int (*pin_func)(struct snd_soc_dapm_context *dapm,
-                                            const char *pin))
-{
-       struct snd_soc_dapm_context *dapm =
-               snd_soc_component_get_dapm(component);
-       char *full_name;
-       int ret;
-
-       if (!component->name_prefix) {
-               ret = pin_func(dapm, pin);
-               goto end;
-       }
-
-       full_name = kasprintf(GFP_KERNEL, "%s %s", component->name_prefix, pin);
-       if (!full_name) {
-               ret = -ENOMEM;
-               goto end;
-       }
-
-       ret = pin_func(dapm, full_name);
-       kfree(full_name);
-end:
-       return soc_component_ret(component, ret);
-}
-
 int snd_soc_component_enable_pin(struct snd_soc_component *component,
                                 const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_enable_pin);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_enable_pin(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin);
 
 int snd_soc_component_enable_pin_unlocked(struct snd_soc_component *component,
                                          const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_enable_pin_unlocked);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_enable_pin_unlocked(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_enable_pin_unlocked);
 
 int snd_soc_component_disable_pin(struct snd_soc_component *component,
                                  const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_disable_pin);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_disable_pin(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin);
 
 int snd_soc_component_disable_pin_unlocked(struct snd_soc_component *component,
                                           const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_disable_pin_unlocked);
+       struct snd_soc_dapm_context *dapm = 
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_disable_pin_unlocked(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_disable_pin_unlocked);
 
 int snd_soc_component_nc_pin(struct snd_soc_component *component,
                             const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_nc_pin);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_nc_pin(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin);
 
 int snd_soc_component_nc_pin_unlocked(struct snd_soc_component *component,
                                      const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_nc_pin_unlocked);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_nc_pin_unlocked(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_nc_pin_unlocked);
 
 int snd_soc_component_get_pin_status(struct snd_soc_component *component,
                                     const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_get_pin_status);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_get_pin_status(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_get_pin_status);
 
 int snd_soc_component_force_enable_pin(struct snd_soc_component *component,
                                       const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_force_enable_pin(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin);
 
@@ -235,7 +224,9 @@ int snd_soc_component_force_enable_pin_unlocked(
        struct snd_soc_component *component,
        const char *pin)
 {
-       return soc_component_pin(component, pin, snd_soc_dapm_force_enable_pin_unlocked);
+       struct snd_soc_dapm_context *dapm =
+               snd_soc_component_get_dapm(component);
+       return snd_soc_dapm_force_enable_pin_unlocked(dapm, pin);
 }
 EXPORT_SYMBOL_GPL(snd_soc_component_force_enable_pin_unlocked);
 
index 4bce89b..4447f51 100644 (file)
@@ -278,6 +278,8 @@ config SND_SOC_SOF_HDA
 
 config SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
        tristate
+       select SOUNDWIRE_INTEL if SND_SOC_SOF_INTEL_SOUNDWIRE
+       select SND_INTEL_SOUNDWIRE_ACPI if SND_SOC_SOF_INTEL_SOUNDWIRE
 
 config SND_SOC_SOF_INTEL_SOUNDWIRE
        tristate "SOF support for SoundWire"
@@ -285,8 +287,6 @@ config SND_SOC_SOF_INTEL_SOUNDWIRE
        depends on SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
        depends on ACPI && SOUNDWIRE
        depends on !(SOUNDWIRE=m && SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE=y)
-       select SOUNDWIRE_INTEL
-       select SND_INTEL_SOUNDWIRE_ACPI
        help
          This adds support for SoundWire with Sound Open Firmware
          for Intel(R) platforms.
index c91aa95..acfeca4 100644 (file)
@@ -107,8 +107,8 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
        } else {
                /* reply correct size ? */
                if (reply.hdr.size != msg->reply_size &&
-                       /* getter payload is never known upfront */
-                       !(reply.hdr.cmd & SOF_IPC_GLB_PROBE)) {
+                   /* getter payload is never known upfront */
+                   ((reply.hdr.cmd & SOF_GLB_TYPE_MASK) != SOF_IPC_GLB_PROBE)) {
                        dev_err(sdev->dev, "error: reply expected %zu got %u bytes\n",
                                msg->reply_size, reply.hdr.size);
                        ret = -EINVAL;
index e1e368f..891e6e1 100644 (file)
@@ -187,12 +187,16 @@ static int hda_sdw_probe(struct snd_sof_dev *sdev)
 int hda_sdw_startup(struct snd_sof_dev *sdev)
 {
        struct sof_intel_hda_dev *hdev;
+       struct snd_sof_pdata *pdata = sdev->pdata;
 
        hdev = sdev->pdata->hw_pdata;
 
        if (!hdev->sdw)
                return 0;
 
+       if (pdata->machine && !pdata->machine->mach_params.link_mask)
+               return 0;
+
        return sdw_intel_startup(hdev->sdw);
 }
 
@@ -1002,6 +1006,14 @@ static int hda_generic_machine_select(struct snd_sof_dev *sdev)
                        hda_mach->mach_params.dmic_num = dmic_num;
                        pdata->machine = hda_mach;
                        pdata->tplg_filename = tplg_filename;
+
+                       if (codec_num == 2) {
+                               /*
+                                * Prevent SoundWire links from starting when an external
+                                * HDaudio codec is used
+                                */
+                               hda_mach->mach_params.link_mask = 0;
+                       }
                }
        }
 
index 3c1628a..3d9736e 100644 (file)
@@ -198,7 +198,7 @@ static int uniphier_aiodma_mmap(struct snd_soc_component *component,
        vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
 
        return remap_pfn_range(vma, vma->vm_start,
-                              substream->dma_buffer.addr >> PAGE_SHIFT,
+                              substream->runtime->dma_addr >> PAGE_SHIFT,
                               vma->vm_end - vma->vm_start, vma->vm_page_prot);
 }
 
index 1d59fb6..91afea9 100644 (file)
@@ -452,8 +452,8 @@ static int xlnx_formatter_pcm_hw_params(struct snd_soc_component *component,
 
        stream_data->buffer_size = size;
 
-       low = lower_32_bits(substream->dma_buffer.addr);
-       high = upper_32_bits(substream->dma_buffer.addr);
+       low = lower_32_bits(runtime->dma_addr);
+       high = upper_32_bits(runtime->dma_addr);
        writel(low, stream_data->mmio + XLNX_AUD_BUFF_ADDR_LSB);
        writel(high, stream_data->mmio + XLNX_AUD_BUFF_ADDR_MSB);
 
index 2f6a624..a1f8c3a 100644 (file)
@@ -907,7 +907,7 @@ static void usb_audio_disconnect(struct usb_interface *intf)
                }
        }
 
-       if (chip->quirk_type & QUIRK_SETUP_DISABLE_AUTOSUSPEND)
+       if (chip->quirk_type == QUIRK_SETUP_DISABLE_AUTOSUSPEND)
                usb_enable_autosuspend(interface_to_usbdev(intf));
 
        chip->num_interfaces--;
index 52de522..14456f6 100644 (file)
@@ -324,6 +324,12 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
                                              sources[ret - 1],
                                              visited, validate);
                if (ret > 0) {
+                       /*
+                        * For Samsung USBC Headset (AKG), setting clock selector again
+                        * will result in incorrect default clock setting problems
+                        */
+                       if (chip->usb_id == USB_ID(0x04e8, 0xa051))
+                               return ret;
                        err = uac_clock_selector_set_val(chip, entity_id, cur);
                        if (err < 0)
                                return err;
index f4cdaf1..9b713b4 100644 (file)
@@ -1816,6 +1816,15 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer,
                strlcat(name, " - Output Jack", name_size);
 }
 
+/* get connector value to "wake up" the USB audio */
+static int connector_mixer_resume(struct usb_mixer_elem_list *list)
+{
+       struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
+
+       get_connector_value(cval, NULL, NULL);
+       return 0;
+}
+
 /* Build a mixer control for a UAC connector control (jack-detect) */
 static void build_connector_control(struct usb_mixer_interface *mixer,
                                    const struct usbmix_name_map *imap,
@@ -1833,6 +1842,10 @@ static void build_connector_control(struct usb_mixer_interface *mixer,
        if (!cval)
                return;
        snd_usb_mixer_elem_init_std(&cval->head, mixer, term->id);
+
+       /* set up a specific resume callback */
+       cval->head.resume = connector_mixer_resume;
+
        /*
         * UAC2: The first byte from reading the UAC2_TE_CONNECTOR control returns the
         * number of channels connected.
@@ -3642,23 +3655,15 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list)
        return 0;
 }
 
-static int default_mixer_resume(struct usb_mixer_elem_list *list)
-{
-       struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list);
-
-       /* get connector value to "wake up" the USB audio */
-       if (cval->val_type == USB_MIXER_BOOLEAN && cval->channels == 1)
-               get_connector_value(cval, NULL, NULL);
-
-       return 0;
-}
-
 static int default_mixer_reset_resume(struct usb_mixer_elem_list *list)
 {
-       int err = default_mixer_resume(list);
+       int err;
 
-       if (err < 0)
-               return err;
+       if (list->resume) {
+               err = list->resume(list);
+               if (err < 0)
+                       return err;
+       }
        return restore_mixer_value(list);
 }
 
@@ -3697,7 +3702,7 @@ void snd_usb_mixer_elem_init_std(struct usb_mixer_elem_list *list,
        list->id = unitid;
        list->dump = snd_usb_mixer_dump_cval;
 #ifdef CONFIG_PM
-       list->resume = default_mixer_resume;
+       list->resume = NULL;
        list->reset_resume = default_mixer_reset_resume;
 #endif
 }
index f9d698a..3d5848d 100644 (file)
@@ -228,7 +228,7 @@ enum {
 };
 
 static const char *const scarlett2_dim_mute_names[SCARLETT2_DIM_MUTE_COUNT] = {
-       "Mute", "Dim"
+       "Mute Playback Switch", "Dim Playback Switch"
 };
 
 /* Description of each hardware port type:
@@ -1856,9 +1856,15 @@ static int scarlett2_mute_ctl_get(struct snd_kcontrol *kctl,
                                        struct snd_ctl_elem_value *ucontrol)
 {
        struct usb_mixer_elem_info *elem = kctl->private_data;
-       struct scarlett2_data *private = elem->head.mixer->private_data;
+       struct usb_mixer_interface *mixer = elem->head.mixer;
+       struct scarlett2_data *private = mixer->private_data;
        int index = line_out_remap(private, elem->control);
 
+       mutex_lock(&private->data_mutex);
+       if (private->vol_updated)
+               scarlett2_update_volumes(mixer);
+       mutex_unlock(&private->data_mutex);
+
        ucontrol->value.integer.value[0] = private->mute_switch[index];
        return 0;
 }
@@ -1955,10 +1961,12 @@ static void scarlett2_vol_ctl_set_writable(struct usb_mixer_interface *mixer,
                        ~SNDRV_CTL_ELEM_ACCESS_WRITE;
        }
 
-       /* Notify of write bit change */
-       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
+       /* Notify of write bit and possible value change */
+       snd_ctl_notify(card,
+                      SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
                       &private->vol_ctls[index]->id);
-       snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
+       snd_ctl_notify(card,
+                      SNDRV_CTL_EVENT_MASK_VALUE | SNDRV_CTL_EVENT_MASK_INFO,
                       &private->mute_ctls[index]->id);
 }
 
@@ -2530,14 +2538,18 @@ static int scarlett2_add_direct_monitor_ctl(struct usb_mixer_interface *mixer)
 {
        struct scarlett2_data *private = mixer->private_data;
        const struct scarlett2_device_info *info = private->info;
+       const char *s;
 
        if (!info->direct_monitor)
                return 0;
 
+       s = info->direct_monitor == 1
+             ? "Direct Monitor Playback Switch"
+             : "Direct Monitor Playback Enum";
+
        return scarlett2_add_new_ctl(
                mixer, &scarlett2_direct_monitor_ctl[info->direct_monitor - 1],
-               0, 1, "Direct Monitor Playback Switch",
-               &private->direct_monitor_ctl);
+               0, 1, s, &private->direct_monitor_ctl);
 }
 
 /*** Speaker Switching Control ***/
@@ -2589,7 +2601,9 @@ static int scarlett2_speaker_switch_enable(struct usb_mixer_interface *mixer)
 
                /* disable the line out SW/HW switch */
                scarlett2_sw_hw_ctl_ro(private, i);
-               snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_INFO,
+               snd_ctl_notify(card,
+                              SNDRV_CTL_EVENT_MASK_VALUE |
+                                SNDRV_CTL_EVENT_MASK_INFO,
                               &private->sw_hw_ctls[i]->id);
        }
 
@@ -2913,7 +2927,7 @@ static int scarlett2_dim_mute_ctl_put(struct snd_kcontrol *kctl,
                        if (private->vol_sw_hw_switch[line_index]) {
                                private->mute_switch[line_index] = val;
                                snd_ctl_notify(mixer->chip->card,
-                                              SNDRV_CTL_EVENT_MASK_INFO,
+                                              SNDRV_CTL_EVENT_MASK_VALUE,
                                               &private->mute_ctls[i]->id);
                        }
                }
@@ -3455,7 +3469,7 @@ static int scarlett2_add_msd_ctl(struct usb_mixer_interface *mixer)
 
        /* Add MSD control */
        return scarlett2_add_new_ctl(mixer, &scarlett2_msd_ctl,
-                                    0, 1, "MSD Mode", NULL);
+                                    0, 1, "MSD Mode Switch", NULL);
 }
 
 /*** Cleanup/Suspend Callbacks ***/
index e7accd8..326d1b0 100644 (file)
@@ -1899,6 +1899,7 @@ static const struct registration_quirk registration_quirks[] = {
        REG_QUIRK_ENTRY(0x0951, 0x16ea, 2),     /* Kingston HyperX Cloud Flight S */
        REG_QUIRK_ENTRY(0x0ecb, 0x1f46, 2),     /* JBL Quantum 600 */
        REG_QUIRK_ENTRY(0x0ecb, 0x2039, 2),     /* JBL Quantum 400 */
+       REG_QUIRK_ENTRY(0x0ecb, 0x203c, 2),     /* JBL Quantum 600 */
        REG_QUIRK_ENTRY(0x0ecb, 0x203e, 2),     /* JBL Quantum 800 */
        { 0 }                                   /* terminator */
 };
index 8146181..d9bd6f5 100644 (file)
@@ -131,8 +131,7 @@ static int copy_file(struct io_uring *ring, off_t insize)
        writes = reads = offset = 0;
 
        while (insize || write_left) {
-               unsigned long had_reads;
-               int got_comp;
+               int had_reads, got_comp;
 
                /*
                 * Queue up as many reads as we can
@@ -174,8 +173,13 @@ static int copy_file(struct io_uring *ring, off_t insize)
                        if (!got_comp) {
                                ret = io_uring_wait_cqe(ring, &cqe);
                                got_comp = 1;
-                       } else
+                       } else {
                                ret = io_uring_peek_cqe(ring, &cqe);
+                               if (ret == -EAGAIN) {
+                                       cqe = NULL;
+                                       ret = 0;
+                               }
+                       }
                        if (ret < 0) {
                                fprintf(stderr, "io_uring_peek_cqe: %s\n",
                                                        strerror(-ret));
@@ -194,7 +198,7 @@ static int copy_file(struct io_uring *ring, off_t insize)
                                fprintf(stderr, "cqe failed: %s\n",
                                                strerror(-cqe->res));
                                return 1;
-                       } else if ((size_t) cqe->res != data->iov.iov_len) {
+                       } else if (cqe->res != data->iov.iov_len) {
                                /* Short read/write, adjust and requeue */
                                data->iov.iov_base += cqe->res;
                                data->iov.iov_len -= cqe->res;
@@ -221,6 +225,25 @@ static int copy_file(struct io_uring *ring, off_t insize)
                }
        }
 
+       /* wait out pending writes */
+       while (writes) {
+               struct io_data *data;
+
+               ret = io_uring_wait_cqe(ring, &cqe);
+               if (ret) {
+                       fprintf(stderr, "wait_cqe=%d\n", ret);
+                       return 1;
+               }
+               if (cqe->res < 0) {
+                       fprintf(stderr, "write res=%d\n", cqe->res);
+                       return 1;
+               }
+               data = io_uring_cqe_get_data(cqe);
+               free(data);
+               writes--;
+               io_uring_cqe_seen(ring, cqe);
+       }
+
        return 0;
 }
 
index b46760b..7ff3d5c 100644 (file)
@@ -804,6 +804,7 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
        btf->nr_types = 0;
        btf->start_id = 1;
        btf->start_str_off = 0;
+       btf->fd = -1;
 
        if (base_btf) {
                btf->base_btf = base_btf;
@@ -832,8 +833,6 @@ static struct btf *btf_new(const void *data, __u32 size, struct btf *base_btf)
        if (err)
                goto done;
 
-       btf->fd = -1;
-
 done:
        if (err) {
                btf__free(btf);
index ecaae29..cd8c703 100644 (file)
@@ -75,6 +75,9 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
        case BPF_PROG_TYPE_CGROUP_SOCK_ADDR:
                xattr.expected_attach_type = BPF_CGROUP_INET4_CONNECT;
                break;
+       case BPF_PROG_TYPE_CGROUP_SOCKOPT:
+               xattr.expected_attach_type = BPF_CGROUP_GETSOCKOPT;
+               break;
        case BPF_PROG_TYPE_SK_LOOKUP:
                xattr.expected_attach_type = BPF_SK_LOOKUP;
                break;
@@ -104,7 +107,6 @@ probe_load(enum bpf_prog_type prog_type, const struct bpf_insn *insns,
        case BPF_PROG_TYPE_SK_REUSEPORT:
        case BPF_PROG_TYPE_FLOW_DISSECTOR:
        case BPF_PROG_TYPE_CGROUP_SYSCTL:
-       case BPF_PROG_TYPE_CGROUP_SOCKOPT:
        case BPF_PROG_TYPE_TRACING:
        case BPF_PROG_TYPE_STRUCT_OPS:
        case BPF_PROG_TYPE_EXT:
index 54f367c..b1bff5f 100644 (file)
@@ -434,7 +434,7 @@ static int nd_intel_test_finish_query(struct nfit_test *t,
                dev_dbg(dev, "%s: transition out verify\n", __func__);
                fw->state = FW_STATE_UPDATED;
                fw->missed_activate = false;
-               /* fall through */
+               fallthrough;
        case FW_STATE_UPDATED:
                nd_cmd->status = 0;
                /* bogus test version */
index 2c8935b..ee45432 100644 (file)
        .result = ACCEPT,
        .retval = 2,
 },
+{
+       "dead code: zero extension",
+       .insns = {
+       BPF_MOV64_IMM(BPF_REG_0, 0),
+       BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4),
+       BPF_JMP_IMM(BPF_JGE, BPF_REG_0, 0, 1),
+       BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_10, -4),
+       BPF_EXIT_INSN(),
+       },
+       .result = ACCEPT,
+       .retval = 0,
+},
index dee7a3d..92bbc5a 100644 (file)
@@ -55,10 +55,27 @@ static bool alloc_q1q2_ctx(const uint8_t *s, const uint8_t *m,
        return true;
 }
 
+static void reverse_bytes(void *data, int length)
+{
+       int i = 0;
+       int j = length - 1;
+       uint8_t temp;
+       uint8_t *ptr = data;
+
+       while (i < j) {
+               temp = ptr[i];
+               ptr[i] = ptr[j];
+               ptr[j] = temp;
+               i++;
+               j--;
+       }
+}
+
 static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
                      uint8_t *q2)
 {
        struct q1q2_ctx ctx;
+       int len;
 
        if (!alloc_q1q2_ctx(s, m, &ctx)) {
                fprintf(stderr, "Not enough memory for Q1Q2 calculation\n");
@@ -89,8 +106,10 @@ static bool calc_q1q2(const uint8_t *s, const uint8_t *m, uint8_t *q1,
                goto out;
        }
 
-       BN_bn2bin(ctx.q1, q1);
-       BN_bn2bin(ctx.q2, q2);
+       len = BN_bn2bin(ctx.q1, q1);
+       reverse_bytes(q1, len);
+       len = BN_bn2bin(ctx.q2, q2);
+       reverse_bytes(q2, len);
 
        free_q1q2_ctx(&ctx);
        return true;
@@ -152,22 +171,6 @@ static RSA *gen_sign_key(void)
        return key;
 }
 
-static void reverse_bytes(void *data, int length)
-{
-       int i = 0;
-       int j = length - 1;
-       uint8_t temp;
-       uint8_t *ptr = data;
-
-       while (i < j) {
-               temp = ptr[i];
-               ptr[i] = ptr[j];
-               ptr[j] = temp;
-               i++;
-               j--;
-       }
-}
-
 enum mrtags {
        MRECREATE = 0x0045544145524345,
        MREADD = 0x0000000044444145,
@@ -367,8 +370,6 @@ bool encl_measure(struct encl *encl)
        /* BE -> LE */
        reverse_bytes(sigstruct->signature, SGX_MODULUS_SIZE);
        reverse_bytes(sigstruct->modulus, SGX_MODULUS_SIZE);
-       reverse_bytes(sigstruct->q1, SGX_MODULUS_SIZE);
-       reverse_bytes(sigstruct->q2, SGX_MODULUS_SIZE);
 
        EVP_MD_CTX_destroy(ctx);
        RSA_free(key);
index b587b9a..0d7bbe4 100644 (file)
@@ -4,7 +4,8 @@ test: virtio_test vringh_test
 virtio_test: virtio_ring.o virtio_test.o
 vringh_test: vringh_test.o vringh.o virtio_ring.o
 
-CFLAGS += -g -O2 -Werror -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h
+CFLAGS += -g -O2 -Werror -Wno-maybe-uninitialized -Wall -I. -I../include/ -I ../../usr/include/ -Wno-pointer-sign -fno-strict-overflow -fno-strict-aliasing -fno-common -MMD -U_FORTIFY_SOURCE -include ../../include/linux/kconfig.h
+LDFLAGS += -lpthread
 vpath %.c ../../drivers/virtio ../../drivers/vhost
 mod:
        ${MAKE} -C `pwd`/../.. M=`pwd`/vhost_test V=${V}
diff --git a/tools/virtio/linux/spinlock.h b/tools/virtio/linux/spinlock.h
new file mode 100644 (file)
index 0000000..028e3cd
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef SPINLOCK_H_STUB
+#define SPINLOCK_H_STUB
+
+#include <pthread.h>
+
+typedef pthread_spinlock_t  spinlock_t;
+
+static inline void spin_lock_init(spinlock_t *lock)
+{
+       int r = pthread_spin_init(lock, 0);
+       assert(!r);
+}
+
+static inline void spin_lock(spinlock_t *lock)
+{
+       int ret = pthread_spin_lock(lock);
+       assert(!ret);
+}
+
+static inline void spin_unlock(spinlock_t *lock)
+{
+       int ret = pthread_spin_unlock(lock);
+       assert(!ret);
+}
+
+static inline void spin_lock_bh(spinlock_t *lock)
+{
+       spin_lock(lock);
+}
+
+static inline void spin_unlock_bh(spinlock_t *lock)
+{
+       spin_unlock(lock);
+}
+
+static inline void spin_lock_irq(spinlock_t *lock)
+{
+       spin_lock(lock);
+}
+
+static inline void spin_unlock_irq(spinlock_t *lock)
+{
+       spin_unlock(lock);
+}
+
+static inline void spin_lock_irqsave(spinlock_t *lock, unsigned long f)
+{
+       spin_lock(lock);
+}
+
+static inline void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f)
+{
+       spin_unlock(lock);
+}
+
+#endif
index 5d90254..363b982 100644 (file)
@@ -3,6 +3,7 @@
 #define LINUX_VIRTIO_H
 #include <linux/scatterlist.h>
 #include <linux/kernel.h>
+#include <linux/spinlock.h>
 
 struct device {
        void *parent;
@@ -12,6 +13,7 @@ struct virtio_device {
        struct device dev;
        u64 features;
        struct list_head vqs;
+       spinlock_t vqs_list_lock;
 };
 
 struct virtqueue {