Merge remote-tracking branch 'torvalds/master' into perf-tools-next
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 4 Aug 2023 13:06:38 +0000 (10:06 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 4 Aug 2023 13:06:38 +0000 (10:06 -0300)
To pick up the fixes that were just merged from perf-tools/perf-tools
for v6.5.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
842 files changed:
.mailmap
Documentation/ABI/testing/sysfs-bus-cxl
Documentation/ABI/testing/sysfs-module
Documentation/admin-guide/devices.txt
Documentation/admin-guide/hw-vuln/spectre.rst
Documentation/arch/arm64/silicon-errata.rst
Documentation/devicetree/bindings/hwmon/moortec,mr75203.yaml
Documentation/devicetree/bindings/net/mediatek,net.yaml
Documentation/devicetree/bindings/net/rockchip-dwmac.yaml
Documentation/devicetree/bindings/serial/atmel,at91-usart.yaml
Documentation/devicetree/bindings/serial/cavium-uart.txt [deleted file]
Documentation/devicetree/bindings/serial/nxp,lpc1850-uart.txt [deleted file]
Documentation/devicetree/bindings/sound/audio-graph-card2.yaml
Documentation/devicetree/bindings/sound/google,sc7180-trogdor.yaml
Documentation/devicetree/bindings/sound/qcom,lpass-cpu.yaml
Documentation/filesystems/tmpfs.rst
Documentation/networking/napi.rst
Documentation/process/embargoed-hardware-issues.rst
Documentation/process/security-bugs.rst
MAINTAINERS
Makefile
arch/arm/boot/dts/microchip/sam9x60.dtsi
arch/arm/boot/dts/nspire/nspire.dtsi
arch/arm/boot/dts/nxp/imx/imx53-sk-imx53.dts
arch/arm/boot/dts/nxp/imx/imx6sll.dtsi
arch/arm/configs/axm55xx_defconfig
arch/arm/configs/davinci_all_defconfig
arch/arm/configs/exynos_defconfig
arch/arm/configs/footbridge_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/keystone_defconfig
arch/arm/configs/lpc32xx_defconfig
arch/arm/configs/milbeaut_m10v_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/omap1_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/pxa_defconfig
arch/arm/configs/rpc_defconfig
arch/arm/configs/s5pv210_defconfig
arch/arm/configs/socfpga_defconfig
arch/arm/configs/spear13xx_defconfig
arch/arm/configs/spear3xx_defconfig
arch/arm/configs/spear6xx_defconfig
arch/arm/mach-pxa/sharpsl_pm.h
arch/arm/mach-pxa/spitz_pm.c
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk.dts
arch/arm64/boot/dts/altera/socfpga_stratix10_socdk_nand.dts
arch/arm64/boot/dts/arm/vexpress-v2m-rs1.dtsi [deleted symlink]
arch/arm64/boot/dts/freescale/imx8mm-phyboard-polis-rdk.dts
arch/arm64/boot/dts/freescale/imx8mm-phycore-som.dtsi
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7903.dts
arch/arm64/boot/dts/freescale/imx8mm-venice-gw7904.dts
arch/arm64/boot/dts/freescale/imx8mn-var-som.dtsi
arch/arm64/boot/dts/freescale/imx8mq.dtsi
arch/arm64/boot/dts/renesas/r9a07g044.dtsi
arch/arm64/boot/dts/renesas/r9a07g054.dtsi
arch/arm64/configs/defconfig
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_pgtable.h
arch/arm64/include/asm/virt.h
arch/arm64/kernel/fpsimd.c
arch/arm64/kernel/vdso/vgettimeofday.c
arch/arm64/kvm/arch_timer.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/hyp/hyp-entry.S
arch/arm64/kvm/hyp/nvhe/host.S
arch/arm64/kvm/hyp/nvhe/psci-relay.c
arch/arm64/kvm/hyp/pgtable.c
arch/arm64/kvm/mmu.c
arch/arm64/kvm/pkvm.c
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/vgic/vgic-v3.c
arch/arm64/kvm/vgic/vgic-v4.c
arch/arm64/mm/trans_pgd.c
arch/arm64/net/bpf_jit_comp.c
arch/arm64/tools/sysreg
arch/ia64/configs/bigsur_defconfig
arch/ia64/configs/generic_defconfig
arch/ia64/configs/gensparse_defconfig
arch/ia64/configs/tiger_defconfig
arch/ia64/kernel/sys_ia64.c
arch/loongarch/Kconfig
arch/loongarch/Makefile
arch/loongarch/configs/loongson3_defconfig
arch/loongarch/include/asm/fpu.h
arch/loongarch/kernel/setup.c
arch/loongarch/lib/clear_user.S
arch/loongarch/lib/copy_user.S
arch/loongarch/net/bpf_jit.h
arch/m68k/fpsp040/skeleton.S
arch/m68k/ifpsp060/os.S
arch/m68k/kernel/relocate_kernel.S
arch/mips/configs/bigsur_defconfig
arch/mips/configs/fuloong2e_defconfig
arch/mips/configs/ip22_defconfig
arch/mips/configs/ip32_defconfig
arch/mips/configs/jazz_defconfig
arch/mips/configs/lemote2f_defconfig
arch/mips/configs/loongson2k_defconfig
arch/mips/configs/loongson3_defconfig
arch/mips/configs/mtx1_defconfig
arch/mips/configs/pic32mzda_defconfig
arch/mips/configs/rm200_defconfig
arch/parisc/configs/generic-32bit_defconfig
arch/parisc/configs/generic-64bit_defconfig
arch/parisc/kernel/sys_parisc.c
arch/powerpc/configs/44x/sam440ep_defconfig
arch/powerpc/configs/85xx/stx_gp3_defconfig
arch/powerpc/configs/cell_defconfig
arch/powerpc/configs/ep8248e_defconfig
arch/powerpc/configs/mgcoge_defconfig
arch/powerpc/configs/pasemi_defconfig
arch/powerpc/configs/pmac32_defconfig
arch/powerpc/configs/powernv_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/ppc64e_defconfig
arch/powerpc/configs/ppc6xx_defconfig
arch/powerpc/configs/ps3_defconfig
arch/powerpc/crypto/.gitignore [new file with mode: 0644]
arch/powerpc/include/asm/bug.h
arch/powerpc/include/asm/elf.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/include/asm/word-at-a-time.h
arch/powerpc/kernel/traps.c
arch/powerpc/mm/kasan/Makefile
arch/powerpc/platforms/512x/mpc512x_lpbfifo.c
arch/powerpc/platforms/pseries/vas.c
arch/riscv/configs/defconfig
arch/riscv/configs/rv32_defconfig
arch/s390/configs/debug_defconfig
arch/s390/configs/defconfig
arch/s390/configs/zfcpdump_defconfig
arch/s390/crypto/paes_s390.c
arch/s390/include/uapi/asm/ptrace.h
arch/s390/kernel/sthyi.c
arch/s390/kvm/intercept.c
arch/s390/kvm/pv.c
arch/s390/mm/fault.c
arch/s390/mm/gmap.c
arch/s390/mm/vmem.c
arch/sh/configs/espt_defconfig
arch/sh/configs/sdk7780_defconfig
arch/sh/configs/sdk7786_defconfig
arch/sh/configs/sh03_defconfig
arch/sh/configs/sh7763rdp_defconfig
arch/sparc/configs/sparc32_defconfig
arch/um/configs/i386_defconfig
arch/um/configs/x86_64_defconfig
arch/um/os-Linux/sigio.c
arch/x86/configs/i386_defconfig
arch/x86/configs/x86_64_defconfig
arch/x86/entry/entry_64.S
arch/x86/include/asm/kvm-x86-ops.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/microcode.h
arch/x86/include/asm/microcode_amd.h
arch/x86/include/asm/msr-index.h
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/mce/amd.c
arch/x86/kernel/traps.c
arch/x86/kvm/lapic.c
arch/x86/kvm/svm/svm.c
arch/x86/kvm/vmx/vmenter.S
arch/x86/kvm/vmx/vmx.c
arch/x86/kvm/vmx/vmx_ops.h
arch/x86/kvm/x86.c
block/blk-core.c
block/blk-iocost.c
block/blk-mq.c
drivers/accel/habanalabs/common/habanalabs.h
drivers/accel/qaic/qaic_control.c
drivers/acpi/arm64/iort.c
drivers/ata/libata-core.c
drivers/ata/pata_arasan_cf.c
drivers/ata/pata_ns87415.c
drivers/ata/pata_octeon_cf.c
drivers/ata/pata_parport/aten.c
drivers/ata/pata_parport/bpck.c
drivers/ata/pata_parport/bpck6.c
drivers/ata/pata_parport/comm.c
drivers/ata/pata_parport/dstr.c
drivers/ata/pata_parport/epat.c
drivers/ata/pata_parport/epia.c
drivers/ata/pata_parport/fit2.c
drivers/ata/pata_parport/fit3.c
drivers/ata/pata_parport/friq.c
drivers/ata/pata_parport/frpw.c
drivers/ata/pata_parport/kbic.c
drivers/ata/pata_parport/ktti.c
drivers/ata/pata_parport/on20.c
drivers/ata/pata_parport/on26.c
drivers/base/power/power.h
drivers/base/power/wakeirq.c
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-i2c.c
drivers/base/regmap/regmap-kunit.c
drivers/base/regmap/regmap-spi-avmm.c
drivers/base/regmap/regmap.c
drivers/block/loop.c
drivers/block/rbd.c
drivers/block/ublk_drv.c
drivers/bluetooth/btusb.c
drivers/char/tpm/st33zp24/i2c.c
drivers/char/tpm/tpm_i2c_atmel.c
drivers/char/tpm/tpm_i2c_infineon.c
drivers/char/tpm/tpm_i2c_nuvoton.c
drivers/char/tpm/tpm_tis_core.c
drivers/char/tpm/tpm_tis_i2c.c
drivers/char/tpm/tpm_tis_i2c_cr50.c
drivers/cxl/Kconfig
drivers/cxl/acpi.c
drivers/cxl/core/mbox.c
drivers/cxl/core/memdev.c
drivers/cxl/cxlmem.h
drivers/dma-buf/dma-resv.c
drivers/firmware/arm_scmi/mailbox.c
drivers/firmware/arm_scmi/raw_mode.c
drivers/firmware/arm_scmi/smc.c
drivers/firmware/smccc/soc_id.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-tps68470.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mes.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vkms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.h
drivers/gpu/drm/amd/amdgpu/aqua_vanjaram_reg_init.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
drivers/gpu/drm/amd/amdgpu/gfxhub_v1_2.c
drivers/gpu/drm/amd/amdgpu/psp_v13_0.c
drivers/gpu/drm/amd/amdkfd/kfd_debug.c
drivers/gpu/drm/amd/amdkfd/kfd_debug.h
drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h
drivers/gpu/drm/amd/display/dc/clk_mgr/dcn31/dcn31_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_optc.h
drivers/gpu/drm/amd/display/dc/dcn301/Makefile
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c [new file with mode: 0644]
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h [new file with mode: 0644]
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_dccg.c
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c
drivers/gpu/drm/amd/display/dc/dml/dcn314/dcn314_fpu.c
drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/drm_atomic.c
drivers/gpu/drm/drm_client_modeset.c
drivers/gpu/drm/i915/Makefile
drivers/gpu/drm/i915/display/intel_display_device.c
drivers/gpu/drm/i915/display/intel_dpt.c
drivers/gpu/drm/i915/display/intel_fbdev.c
drivers/gpu/drm/i915/gem/selftests/huge_pages.c
drivers/gpu/drm/i915/i915_pci.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
drivers/gpu/drm/msm/adreno/a6xx_gpu_state.h
drivers/gpu/drm/msm/adreno/adreno_device.c
drivers/gpu/drm/msm/adreno/adreno_gpu.h
drivers/gpu/drm/msm/disp/dpu1/dpu_core_perf.h
drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c
drivers/gpu/drm/msm/dsi/phy/dsi_phy_14nm.c
drivers/gpu/drm/msm/msm_fence.c
drivers/gpu/drm/msm/msm_gem_submit.c
drivers/gpu/drm/msm/msm_mdss.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c
drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c
drivers/hwmon/aquacomputer_d5next.c
drivers/hwmon/k10temp.c
drivers/hwmon/nct6775-core.c
drivers/hwmon/nct6775-platform.c
drivers/hwmon/nct6775.h
drivers/hwmon/nct7802.c
drivers/hwmon/oxp-sensors.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/idle/intel_idle.c
drivers/infiniband/core/cma.c
drivers/infiniband/hw/bnxt_re/ib_verbs.c
drivers/infiniband/hw/bnxt_re/qplib_fp.c
drivers/infiniband/hw/bnxt_re/qplib_fp.h
drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
drivers/infiniband/hw/irdma/ctrl.c
drivers/infiniband/hw/irdma/defs.h
drivers/infiniband/hw/irdma/hw.c
drivers/infiniband/hw/irdma/main.h
drivers/infiniband/hw/irdma/puda.c
drivers/infiniband/hw/irdma/type.h
drivers/infiniband/hw/irdma/uk.c
drivers/infiniband/hw/irdma/utils.c
drivers/infiniband/hw/mlx4/qp.c
drivers/infiniband/hw/mthca/mthca_qp.c
drivers/infiniband/sw/rxe/rxe_mw.c
drivers/iommu/iommufd/device.c
drivers/iommu/iommufd/iommufd_private.h
drivers/iommu/iommufd/main.c
drivers/iommu/iommufd/pages.c
drivers/irqchip/irq-bcm6345-l1.c
drivers/irqchip/irq-gic-v3-its.c
drivers/irqchip/irq-gic-v3.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/md/dm-cache-policy-smq.c
drivers/md/dm-integrity.c
drivers/md/dm-raid.c
drivers/md/md.c
drivers/media/cec/usb/pulse8/pulse8-cec.c
drivers/media/i2c/tc358746.c
drivers/media/pci/cx23885/cx23885-dvb.c
drivers/media/platform/amphion/vpu_core.c
drivers/media/platform/amphion/vpu_mbox.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_dec_hw.c
drivers/media/platform/mediatek/jpeg/mtk_jpeg_enc_hw.c
drivers/media/platform/mediatek/vcodec/vdec_msg_queue.c
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg-hw.h
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.h
drivers/media/platform/verisilicon/hantro.h
drivers/media/platform/verisilicon/hantro_postproc.c
drivers/memory/tegra/mc.c
drivers/memory/tegra/tegra194.c
drivers/memory/tegra/tegra234.c
drivers/misc/sram.c
drivers/net/bonding/bond_main.c
drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c
drivers/net/can/spi/mcp251xfd/mcp251xfd.h
drivers/net/can/usb/gs_usb.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/microchip/ksz8795.c
drivers/net/dsa/microchip/ksz_common.c
drivers/net/dsa/microchip/ksz_common.h
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/qca/ar9331.c
drivers/net/dsa/qca/qca8k-8xxx.c
drivers/net/dsa/qca/qca8k-common.c
drivers/net/ethernet/atheros/atl1c/atl1c_main.c
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/atheros/atlx/atl1.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_xdp.h
drivers/net/ethernet/brocade/bna/bnad_debugfs.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.c
drivers/net/ethernet/hisilicon/hns3/hns3_common/hclge_comm_cmd.h
drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_debugfs.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h
drivers/net/ethernet/intel/i40e/i40e_debugfs.c
drivers/net/ethernet/intel/iavf/iavf.h
drivers/net/ethernet/intel/iavf/iavf_ethtool.c
drivers/net/ethernet/intel/iavf/iavf_main.c
drivers/net/ethernet/intel/iavf/iavf_virtchnl.c
drivers/net/ethernet/intel/ice/ice_base.c
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_ethtool_fdir.c
drivers/net/ethernet/intel/ice/ice_lib.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/korina.c
drivers/net/ethernet/marvell/octeon_ep/octep_ctrl_mbox.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.h
drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/prestera/prestera_pci.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_ppe_debugfs.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
drivers/net/ethernet/mellanox/mlx5/core/en/xsk/rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_rxtx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_arfs.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/esw/bridge_debugfs.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/lib/fs_chains.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_action.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_domain.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v0.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_ste_v1.c
drivers/net/ethernet/mellanox/mlx5/core/steering/dr_types.h
drivers/net/ethernet/mellanox/mlx5/core/steering/fs_dr.c
drivers/net/ethernet/mellanox/mlx5/core/steering/mlx5dr.h
drivers/net/ethernet/mscc/ocelot_fdma.c
drivers/net/ethernet/qlogic/qed/qed_dev_api.h
drivers/net/ethernet/qlogic/qed/qed_fcoe.c
drivers/net/ethernet/qlogic/qed/qed_fcoe.h
drivers/net/ethernet/qlogic/qed/qed_hw.c
drivers/net/ethernet/qlogic/qed/qed_iscsi.c
drivers/net/ethernet/qlogic/qed/qed_iscsi.h
drivers/net/ethernet/qlogic/qed/qed_l2.c
drivers/net/ethernet/qlogic/qed/qed_l2.h
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qualcomm/emac/emac-mac.c
drivers/net/ethernet/realtek/r8169_main.c
drivers/net/ethernet/sfc/falcon/selftest.c
drivers/net/ethernet/sfc/selftest.c
drivers/net/ethernet/sfc/siena/selftest.c
drivers/net/ethernet/socionext/netsec.c
drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
drivers/net/ethernet/ti/cpsw_ale.c
drivers/net/ethernet/wangxun/libwx/wx_hw.c
drivers/net/ethernet/xilinx/ll_temac_main.c
drivers/net/ipa/ipa_table.c
drivers/net/macvlan.c
drivers/net/phy/marvell10g.c
drivers/net/phy/phy_device.c
drivers/net/tap.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/lan78xx.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/usbnet.c
drivers/net/usb/zaurus.c
drivers/net/virtio_net.c
drivers/net/vrf.c
drivers/net/vxlan/vxlan_core.c
drivers/net/wireless/ath/ath11k/ahb.c
drivers/net/wireless/ath/ath11k/pcic.c
drivers/net/wireless/ath/ath6kl/Makefile
drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
drivers/net/wireless/legacy/rayctl.h
drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c
drivers/of/Kconfig
drivers/of/platform.c
drivers/phy/hisilicon/phy-hisi-inno-usb2.c
drivers/phy/mediatek/phy-mtk-dp.c
drivers/phy/mediatek/phy-mtk-hdmi-mt8195.c
drivers/phy/qualcomm/phy-qcom-snps-femto-v2.c
drivers/platform/x86/amd/pmc-quirks.c
drivers/platform/x86/amd/pmf/acpi.c
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/amd/pmf/pmf.h
drivers/platform/x86/amd/pmf/sps.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/huawei-wmi.c
drivers/platform/x86/intel/hid.c
drivers/platform/x86/msi-laptop.c
drivers/platform/x86/serial-multi-instantiate.c
drivers/platform/x86/think-lmi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/regulator/da9063-regulator.c
drivers/regulator/mt6358-regulator.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_ioctl.c
drivers/s390/crypto/zcrypt_msgtype6.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/scsi/zfcp_fc.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/sg.c
drivers/scsi/storvsc_drv.c
drivers/soc/imx/imx8mp-blk-ctrl.c
drivers/soundwire/amd_manager.c
drivers/soundwire/bus.c
drivers/soundwire/qcom.c
drivers/spi/spi-qcom-qspi.c
drivers/staging/fbtft/fb_ili9341.c
drivers/staging/ks7010/ks_wlan_net.c
drivers/staging/media/atomisp/Kconfig
drivers/staging/rtl8712/rtl871x_xmit.c
drivers/staging/rtl8712/xmit_linux.c
drivers/thermal/thermal_core.c
drivers/thermal/thermal_of.c
drivers/tty/n_gsm.c
drivers/tty/serial/8250/8250_dwlib.c
drivers/tty/serial/qcom_geni_serial.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sifive.c
drivers/tty/serial/ucc_uart.c
drivers/tty/tty_io.c
drivers/usb/cdns3/cdns3-gadget.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/core.h
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/gadget/composite.c
drivers/usb/gadget/legacy/raw_gadget.c
drivers/usb/gadget/udc/core.c
drivers/usb/gadget/udc/tegra-xudc.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/xhci-mtk.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci-tegra.c
drivers/usb/misc/ehset.c
drivers/usb/serial/option.c
drivers/usb/serial/usb-serial-simple.c
drivers/usb/typec/class.c
drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
drivers/usb/typec/ucsi/ucsi.c
drivers/video/console/sticon.c
drivers/video/console/vgacon.c
drivers/video/fbdev/au1200fb.c
drivers/video/fbdev/bw2.c
drivers/video/fbdev/cg14.c
drivers/video/fbdev/cg3.c
drivers/video/fbdev/cg6.c
drivers/video/fbdev/core/fbcon.c
drivers/video/fbdev/ep93xx-fb.c
drivers/video/fbdev/ffb.c
drivers/video/fbdev/grvga.c
drivers/video/fbdev/imxfb.c
drivers/video/fbdev/kyro/STG4000InitDevice.c
drivers/video/fbdev/leo.c
drivers/video/fbdev/mb862xx/mb862xxfb_accel.c
drivers/video/fbdev/mb862xx/mb862xxfbdrv.c
drivers/video/fbdev/omap2/omapfb/displays/panel-dsi-cm.c
drivers/video/fbdev/p9100.c
drivers/video/fbdev/platinumfb.c
drivers/video/fbdev/sbuslib.c
drivers/video/fbdev/sunxvr1000.c
drivers/video/fbdev/sunxvr2500.c
drivers/video/fbdev/sunxvr500.c
drivers/video/fbdev/tcx.c
drivers/video/fbdev/xilinxfb.c
drivers/xen/events/events_base.c
drivers/xen/evtchn.c
drivers/xen/grant-table.c
drivers/xen/xenbus/xenbus_probe.c
fs/9p/fid.h
fs/9p/v9fs.c
fs/9p/v9fs.h
fs/9p/vfs_dir.c
fs/9p/vfs_file.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/autofs/Kconfig
fs/btrfs/block-group.c
fs/btrfs/block-group.h
fs/btrfs/block-rsv.c
fs/btrfs/disk-io.c
fs/btrfs/free-space-tree.c
fs/btrfs/inode.c
fs/btrfs/qgroup.c
fs/btrfs/raid56.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/btrfs/zoned.c
fs/ceph/metric.c
fs/erofs/super.c
fs/erofs/zdata.c
fs/exfat/balloc.c
fs/exfat/dir.c
fs/ext4/mballoc.c
fs/ext4/xattr.c
fs/file.c
fs/fuse/dir.c
fs/fuse/inode.c
fs/fuse/ioctl.c
fs/iomap/buffered-io.c
fs/jbd2/checkpoint.c
fs/jbd2/commit.c
fs/jbd2/transaction.c
fs/nfsd/nfs4state.c
fs/nfsd/vfs.c
fs/nls/nls_base.c
fs/overlayfs/super.c
fs/proc/vmcore.c
fs/smb/client/cifsfs.h
fs/smb/client/cifsglob.h
fs/smb/client/cifssmb.c
fs/smb/client/connect.c
fs/smb/client/ioctl.c
fs/smb/client/misc.c
fs/smb/client/sess.c
fs/smb/client/smb2pdu.c
fs/smb/server/ksmbd_netlink.h
fs/smb/server/server.c
fs/smb/server/smb2pdu.c
fs/smb/server/smb_common.c
fs/smb/server/smb_common.h
fs/smb/server/vfs.c
fs/smb/server/vfs.h
fs/splice.c
fs/xfs/libxfs/xfs_da_format.h
fs/xfs/libxfs/xfs_fs.h
fs/xfs/xfs_ondisk.h
include/asm-generic/word-at-a-time.h
include/drm/drm_fb_helper.h
include/kvm/arm_vgic.h
include/linux/blk-mq.h
include/linux/cpumask.h
include/linux/ftrace.h
include/linux/jbd2.h
include/linux/mm.h
include/linux/mm_types.h
include/linux/mmap_lock.h
include/linux/nls.h
include/linux/pm_wakeirq.h
include/linux/spi/corgi_lcd.h
include/linux/tcp.h
include/linux/thermal.h
include/net/bluetooth/hci_core.h
include/net/bonding.h
include/net/cfg802154.h
include/net/codel.h
include/net/devlink.h
include/net/gro.h
include/net/inet_frag.h
include/net/inet_sock.h
include/net/ip.h
include/net/ipv6.h
include/net/llc_conn.h
include/net/llc_pdu.h
include/net/nsh.h
include/net/pie.h
include/net/route.h
include/net/rsi_91x.h
include/net/tcp.h
include/net/vxlan.h
include/soc/tegra/mc.h
include/trace/events/jbd2.h
include/uapi/linux/blkzoned.h
include/uapi/linux/fuse.h
include/uapi/linux/if_packet.h
include/uapi/linux/pkt_cls.h
include/uapi/xen/evtchn.h
include/xen/events.h
io_uring/io_uring.c
kernel/bpf/cpumap.c
kernel/bpf/verifier.c
kernel/kprobes.c
kernel/locking/rtmutex.c
kernel/locking/rtmutex_api.c
kernel/locking/rtmutex_common.h
kernel/locking/ww_mutex.h
kernel/signal.c
kernel/trace/bpf_trace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace_events.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_synth.c
kernel/trace/trace_events_trigger.c
kernel/trace/trace_probe.c
kernel/trace/trace_seq.c
kernel/trace/tracing_map.h
lib/Makefile
lib/cpumask.c
lib/genalloc.c
lib/sbitmap.c
lib/test_bitmap.c
mm/damon/core-test.h
mm/memory-failure.c
mm/memory.c
mm/mempolicy.c
mm/mmap.c
mm/pagewalk.c
mm/shmem.c
net/9p/client.c
net/9p/trans_virtio.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/bluetooth/hci_sync.c
net/bluetooth/iso.c
net/bluetooth/mgmt.c
net/bluetooth/sco.c
net/can/bcm.c
net/can/raw.c
net/ceph/messenger.c
net/core/bpf_sk_storage.c
net/core/rtnetlink.c
net/core/sock.c
net/core/sock_map.c
net/dcb/dcbnl.c
net/dccp/ipv6.c
net/dsa/port.c
net/ipv4/esp4.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_diag.c
net/ipv4/inet_hashtables.c
net/ipv4/inet_timewait_sock.c
net/ipv4/ip_gre.c
net/ipv4/ip_output.c
net/ipv4/ip_sockglue.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_fastopen.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_minisocks.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv4/udp_offload.c
net/ipv6/addrconf.c
net/ipv6/ip6_gre.c
net/ipv6/ip6mr.c
net/ipv6/ping.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/udp_offload.c
net/l2tp/l2tp_ip6.c
net/llc/af_llc.c
net/llc/llc_conn.c
net/llc/llc_if.c
net/llc/llc_input.c
net/llc/llc_sap.c
net/mptcp/protocol.c
net/mptcp/sockopt.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_immediate.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_rbtree.c
net/netfilter/nft_socket.c
net/netfilter/xt_socket.c
net/packet/af_packet.c
net/sched/cls_bpf.c
net/sched/cls_flower.c
net/sched/cls_fw.c
net/sched/cls_matchall.c
net/sched/cls_route.c
net/sched/cls_u32.c
net/sched/em_meta.c
net/sched/sch_mqprio.c
net/sched/sch_taprio.c
net/smc/af_smc.c
net/tipc/crypto.c
net/tipc/node.c
net/unix/af_unix.c
net/wireless/scan.c
net/xdp/xsk.c
net/xfrm/xfrm_policy.c
scripts/Makefile.build
scripts/Makefile.host
scripts/clang-tools/gen_compile_commands.py
scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci [deleted file]
scripts/kconfig/gconf.c
scripts/spelling.txt
security/keys/keyctl.c
sound/core/seq/seq_ports.c
sound/core/seq/seq_ump_client.c
sound/drivers/pcmtest.c
sound/pci/hda/patch_realtek.c
sound/soc/amd/acp/amd.h
sound/soc/amd/ps/acp63.h
sound/soc/amd/ps/pci-ps.c
sound/soc/amd/ps/ps-sdw-dma.c
sound/soc/atmel/atmel-i2s.c
sound/soc/codecs/Kconfig
sound/soc/codecs/cs42l51-i2c.c
sound/soc/codecs/cs42l51.c
sound/soc/codecs/cs42l51.h
sound/soc/codecs/da7219-aad.c
sound/soc/codecs/es8316.c
sound/soc/codecs/nau8821.c
sound/soc/codecs/rt5640.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt5682-sdw.c
sound/soc/codecs/rt711-sdca-sdw.c
sound/soc/codecs/rt711-sdw.c
sound/soc/codecs/rt712-sdca-sdw.c
sound/soc/codecs/rt722-sdca-sdw.c
sound/soc/codecs/wcd-mbhc-v2.c
sound/soc/codecs/wcd934x.c
sound/soc/codecs/wcd938x.c
sound/soc/codecs/wm8904.c
sound/soc/fsl/fsl_sai.c
sound/soc/fsl/fsl_sai.h
sound/soc/fsl/fsl_spdif.c
sound/soc/qcom/qdsp6/q6afe-dai.c
sound/soc/qcom/qdsp6/q6apm-dai.c
sound/soc/qcom/qdsp6/q6apm.c
sound/soc/qcom/qdsp6/topology.c
sound/soc/soc-core.c
sound/soc/soc-topology.c
sound/soc/sof/amd/acp.c
sound/soc/sof/ipc3-dtrace.c
sound/soc/tegra/tegra210_adx.c
sound/soc/tegra/tegra210_amx.c
sound/usb/mixer_maps.c
sound/usb/quirks.c
tools/net/ynl/lib/ynl.py
tools/perf/arch/arm64/util/pmu.c
tools/perf/arch/powerpc/util/skip-callchain-idx.c
tools/perf/tests/parse-events.c
tools/perf/tests/shell/test_uprobe_from_different_cu.sh
tools/perf/util/parse-events.c
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/pmus.c
tools/testing/cxl/test/cxl.c
tools/testing/selftests/alsa/.gitignore
tools/testing/selftests/alsa/test-pcmtest-driver.c
tools/testing/selftests/bpf/progs/async_stack_depth.c
tools/testing/selftests/ftrace/test.d/dynevent/add_remove_btfarg.tc
tools/testing/selftests/kvm/include/kvm_util_base.h
tools/testing/selftests/kvm/kvm_binary_stats_test.c
tools/testing/selftests/kvm/x86_64/set_sregs_test.c
tools/testing/selftests/net/mptcp/mptcp_join.sh
tools/testing/selftests/net/so_incoming_cpu.c
tools/testing/selftests/rseq/rseq.c
tools/testing/selftests/tc-testing/config
tools/testing/selftests/tc-testing/settings [new file with mode: 0644]
tools/testing/selftests/tc-testing/tc-tests/qdiscs/taprio.json
tools/testing/vsock/Makefile
virt/kvm/kvm_main.c

index 89b7f33..5dd3181 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -13,7 +13,9 @@
 Aaron Durbin <adurbin@google.com>
 Abel Vesa <abelvesa@kernel.org> <abel.vesa@nxp.com>
 Abel Vesa <abelvesa@kernel.org> <abelvesa@gmail.com>
+Abhijeet Dharmapurikar <quic_adharmap@quicinc.com> <adharmap@codeaurora.org>
 Abhinav Kumar <quic_abhinavk@quicinc.com> <abhinavk@codeaurora.org>
+Ahmad Masri <quic_amasri@quicinc.com> <amasri@codeaurora.org>
 Adam Oldham <oldhamca@gmail.com>
 Adam Radford <aradford@gmail.com>
 Adriana Reus <adi.reus@gmail.com> <adriana.reus@intel.com>
@@ -30,6 +32,7 @@ Alexander Mikhalitsyn <alexander@mihalicyn.com> <alexander.mikhalitsyn@virtuozzo
 Alexander Mikhalitsyn <alexander@mihalicyn.com> <aleksandr.mikhalitsyn@canonical.com>
 Alexandre Belloni <alexandre.belloni@bootlin.com> <alexandre.belloni@free-electrons.com>
 Alexandre Ghiti <alex@ghiti.fr> <alexandre.ghiti@canonical.com>
+Alexei Avshalom Lazar <quic_ailizaro@quicinc.com> <ailizaro@codeaurora.org>
 Alexei Starovoitov <ast@kernel.org> <alexei.starovoitov@gmail.com>
 Alexei Starovoitov <ast@kernel.org> <ast@fb.com>
 Alexei Starovoitov <ast@kernel.org> <ast@plumgrid.com>
@@ -37,8 +40,11 @@ Alex Hung <alexhung@gmail.com> <alex.hung@canonical.com>
 Alex Shi <alexs@kernel.org> <alex.shi@intel.com>
 Alex Shi <alexs@kernel.org> <alex.shi@linaro.org>
 Alex Shi <alexs@kernel.org> <alex.shi@linux.alibaba.com>
+Aloka Dixit <quic_alokad@quicinc.com> <alokad@codeaurora.org>
 Al Viro <viro@ftp.linux.org.uk>
 Al Viro <viro@zenIV.linux.org.uk>
+Amit Blay <quic_ablay@quicinc.com> <ablay@codeaurora.org>
+Amit Nischal <quic_anischal@quicinc.com> <anischal@codeaurora.org>
 Andi Kleen <ak@linux.intel.com> <ak@suse.de>
 Andi Shyti <andi@etezian.org> <andi.shyti@samsung.com>
 Andreas Herrmann <aherrman@de.ibm.com>
@@ -54,6 +60,8 @@ Andrey Ryabinin <ryabinin.a.a@gmail.com> <aryabinin@virtuozzo.com>
 Andrzej Hajda <andrzej.hajda@intel.com> <a.hajda@samsung.com>
 André Almeida <andrealmeid@igalia.com> <andrealmeid@collabora.com>
 Andy Adamson <andros@citi.umich.edu>
+Anilkumar Kolli <quic_akolli@quicinc.com> <akolli@codeaurora.org>
+Anirudh Ghayal <quic_aghayal@quicinc.com> <aghayal@codeaurora.org>
 Antoine Tenart <atenart@kernel.org> <antoine.tenart@bootlin.com>
 Antoine Tenart <atenart@kernel.org> <antoine.tenart@free-electrons.com>
 Antonio Ospite <ao2@ao2.it> <ao2@amarulasolutions.com>
@@ -62,9 +70,17 @@ Archit Taneja <archit@ti.com>
 Ard Biesheuvel <ardb@kernel.org> <ard.biesheuvel@linaro.org>
 Arnaud Patard <arnaud.patard@rtp-net.org>
 Arnd Bergmann <arnd@arndb.de>
+Arun Kumar Neelakantam <quic_aneela@quicinc.com> <aneela@codeaurora.org>
+Ashok Raj Nagarajan <quic_arnagara@quicinc.com> <arnagara@codeaurora.org>
+Ashwin Chaugule <quic_ashwinc@quicinc.com> <ashwinc@codeaurora.org>
+Asutosh Das <quic_asutoshd@quicinc.com> <asutoshd@codeaurora.org>
 Atish Patra <atishp@atishpatra.org> <atish.patra@wdc.com>
+Avaneesh Kumar Dwivedi <quic_akdwived@quicinc.com> <akdwived@codeaurora.org>
 Axel Dyks <xl@xlsigned.net>
 Axel Lin <axel.lin@gmail.com>
+Balakrishna Godavarthi <quic_bgodavar@quicinc.com> <bgodavar@codeaurora.org>
+Banajit Goswami <quic_bgoswami@quicinc.com> <bgoswami@codeaurora.org>
+Baochen Qiang <quic_bqiang@quicinc.com> <bqiang@codeaurora.org>
 Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@linaro.org>
 Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@spreadtrum.com>
 Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@unisoc.com>
@@ -93,12 +109,15 @@ Brian Avery <b.avery@hp.com>
 Brian King <brking@us.ibm.com>
 Brian Silverman <bsilver16384@gmail.com> <brian.silverman@bluerivertech.com>
 Cai Huoqing <cai.huoqing@linux.dev> <caihuoqing@baidu.com>
+Can Guo <quic_cang@quicinc.com> <cang@codeaurora.org>
+Carl Huang <quic_cjhuang@quicinc.com> <cjhuang@codeaurora.org>
 Changbin Du <changbin.du@intel.com> <changbin.du@gmail.com>
 Changbin Du <changbin.du@intel.com> <changbin.du@intel.com>
 Chao Yu <chao@kernel.org> <chao2.yu@samsung.com>
 Chao Yu <chao@kernel.org> <yuchao0@huawei.com>
 Chris Chiu <chris.chiu@canonical.com> <chiu@endlessm.com>
 Chris Chiu <chris.chiu@canonical.com> <chiu@endlessos.org>
+Chris Lew <quic_clew@quicinc.com> <clew@codeaurora.org>
 Christian Borntraeger <borntraeger@linux.ibm.com> <borntraeger@de.ibm.com>
 Christian Borntraeger <borntraeger@linux.ibm.com> <cborntra@de.ibm.com>
 Christian Borntraeger <borntraeger@linux.ibm.com> <borntrae@de.ibm.com>
@@ -119,7 +138,10 @@ Daniel Borkmann <daniel@iogearbox.net> <dborkmann@redhat.com>
 Daniel Borkmann <daniel@iogearbox.net> <dborkman@redhat.com>
 Daniel Borkmann <daniel@iogearbox.net> <dxchgb@gmail.com>
 David Brownell <david-b@pacbell.net>
+David Collins <quic_collinsd@quicinc.com> <collinsd@codeaurora.org>
 David Woodhouse <dwmw2@shinybook.infradead.org>
+Dedy Lansky <quic_dlansky@quicinc.com> <dlansky@codeaurora.org>
+Deepak Kumar Singh <quic_deesin@quicinc.com> <deesin@codeaurora.org>
 Dengcheng Zhu <dzhu@wavecomp.com> <dczhu@mips.com>
 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@gmail.com>
 Dengcheng Zhu <dzhu@wavecomp.com> <dengcheng.zhu@imgtec.com>
@@ -136,6 +158,7 @@ Dmitry Safonov <0x7f454c46@gmail.com> <dsafonov@virtuozzo.com>
 Domen Puncer <domen@coderock.org>
 Douglas Gilbert <dougg@torque.net>
 Ed L. Cashin <ecashin@coraid.com>
+Elliot Berman <quic_eberman@quicinc.com> <eberman@codeaurora.org>
 Enric Balletbo i Serra <eballetbo@kernel.org> <enric.balletbo@collabora.com>
 Enric Balletbo i Serra <eballetbo@kernel.org> <eballetbo@iseebcn.com>
 Erik Kaneda <erik.kaneda@intel.com> <erik.schmauss@intel.com>
@@ -148,6 +171,7 @@ Faith Ekstrand <faith.ekstrand@collabora.com> <jason.ekstrand@collabora.com>
 Felipe W Damasio <felipewd@terra.com.br>
 Felix Kuhling <fxkuehl@gmx.de>
 Felix Moeller <felix@derklecks.de>
+Fenglin Wu <quic_fenglinw@quicinc.com> <fenglinw@codeaurora.org>
 Filipe Lautert <filipe@icewall.org>
 Finn Thain <fthain@linux-m68k.org> <fthain@telegraphics.com.au>
 Franck Bui-Huu <vagabon.xyz@gmail.com>
@@ -171,8 +195,11 @@ Greg Kurz <groug@kaod.org> <gkurz@linux.vnet.ibm.com>
 Gregory CLEMENT <gregory.clement@bootlin.com> <gregory.clement@free-electrons.com>
 Guilherme G. Piccoli <kernel@gpiccoli.net> <gpiccoli@linux.vnet.ibm.com>
 Guilherme G. Piccoli <kernel@gpiccoli.net> <gpiccoli@canonical.com>
+Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com> <gokulsri@codeaurora.org>
+Govindaraj Saminathan <quic_gsamin@quicinc.com> <gsamin@codeaurora.org>
 Guo Ren <guoren@kernel.org> <guoren@linux.alibaba.com>
 Guo Ren <guoren@kernel.org> <ren_guo@c-sky.com>
+Guru Das Srinagesh <quic_gurus@quicinc.com> <gurus@codeaurora.org>
 Gustavo Padovan <gustavo@las.ic.unicamp.br>
 Gustavo Padovan <padovan@profusion.mobi>
 Hanjun Guo <guohanjun@huawei.com> <hanjun.guo@linaro.org>
@@ -190,6 +217,7 @@ Huacai Chen <chenhuacai@kernel.org> <chenhuacai@loongson.cn>
 J. Bruce Fields <bfields@fieldses.org> <bfields@redhat.com>
 J. Bruce Fields <bfields@fieldses.org> <bfields@citi.umich.edu>
 Jacob Shin <Jacob.Shin@amd.com>
+Jack Pham <quic_jackp@quicinc.com> <jackp@codeaurora.org>
 Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@google.com>
 Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk.kim@samsung.com>
 Jaegeuk Kim <jaegeuk@kernel.org> <jaegeuk@motorola.com>
@@ -217,10 +245,12 @@ Jayachandran C <c.jayachandran@gmail.com> <jchandra@digeo.com>
 Jayachandran C <c.jayachandran@gmail.com> <jnair@caviumnetworks.com>
 <jean-philippe@linaro.org> <jean-philippe.brucker@arm.com>
 Jean Tourrilhes <jt@hpl.hp.com>
+Jeevan Shriram <quic_jshriram@quicinc.com> <jshriram@codeaurora.org>
 Jeff Garzik <jgarzik@pretzel.yyz.us>
 Jeff Layton <jlayton@kernel.org> <jlayton@poochiereds.net>
 Jeff Layton <jlayton@kernel.org> <jlayton@primarydata.com>
 Jeff Layton <jlayton@kernel.org> <jlayton@redhat.com>
+Jeffrey Hugo <quic_jhugo@quicinc.com> <jhugo@codeaurora.org>
 Jens Axboe <axboe@kernel.dk> <axboe@suse.de>
 Jens Axboe <axboe@kernel.dk> <jens.axboe@oracle.com>
 Jens Axboe <axboe@kernel.dk> <axboe@fb.com>
@@ -228,6 +258,7 @@ Jens Axboe <axboe@kernel.dk> <axboe@meta.com>
 Jens Osterkamp <Jens.Osterkamp@de.ibm.com>
 Jernej Skrabec <jernej.skrabec@gmail.com> <jernej.skrabec@siol.net>
 Jessica Zhang <quic_jesszhan@quicinc.com> <jesszhan@codeaurora.org>
+Jilai Wang <quic_jilaiw@quicinc.com> <jilaiw@codeaurora.org>
 Jiri Pirko <jiri@resnulli.us> <jiri@nvidia.com>
 Jiri Pirko <jiri@resnulli.us> <jiri@mellanox.com>
 Jiri Pirko <jiri@resnulli.us> <jpirko@redhat.com>
@@ -238,9 +269,11 @@ Jiri Slaby <jirislaby@kernel.org> <jslaby@suse.cz>
 Jiri Slaby <jirislaby@kernel.org> <xslaby@fi.muni.cz>
 Jisheng Zhang <jszhang@kernel.org> <jszhang@marvell.com>
 Jisheng Zhang <jszhang@kernel.org> <Jisheng.Zhang@synaptics.com>
+Jishnu Prakash <quic_jprakash@quicinc.com> <jprakash@codeaurora.org>
 Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
 Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
 John Crispin <john@phrozen.org> <blogic@openwrt.org>
+John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com>
 John Keeping <john@keeping.me.uk> <john@metanate.com>
 John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
 John Stultz <johnstul@us.ibm.com>
@@ -255,6 +288,7 @@ Jordan Crouse <jordan@cosmicpenguin.net> <jcrouse@codeaurora.org>
 <josh@joshtriplett.org> <josht@vnet.ibm.com>
 Josh Poimboeuf <jpoimboe@kernel.org> <jpoimboe@redhat.com>
 Josh Poimboeuf <jpoimboe@kernel.org> <jpoimboe@us.ibm.com>
+Jouni Malinen <quic_jouni@quicinc.com> <jouni@codeaurora.org>
 Juha Yrjola <at solidboot.com>
 Juha Yrjola <juha.yrjola@nokia.com>
 Juha Yrjola <juha.yrjola@solidboot.com>
@@ -262,6 +296,8 @@ Julien Thierry <julien.thierry.kdev@gmail.com> <julien.thierry@arm.com>
 Iskren Chernev <me@iskren.info> <iskren.chernev@gmail.com>
 Kalle Valo <kvalo@kernel.org> <kvalo@codeaurora.org>
 Kalyan Thota <quic_kalyant@quicinc.com> <kalyan_t@codeaurora.org>
+Karthikeyan Periyasamy <quic_periyasa@quicinc.com> <periyasa@codeaurora.org>
+Kathiravan T <quic_kathirav@quicinc.com> <kathirav@codeaurora.org>
 Kay Sievers <kay.sievers@vrfy.org>
 Kees Cook <keescook@chromium.org> <kees.cook@canonical.com>
 Kees Cook <keescook@chromium.org> <keescook@google.com>
@@ -270,6 +306,8 @@ Kees Cook <keescook@chromium.org> <kees@ubuntu.com>
 Keith Busch <kbusch@kernel.org> <keith.busch@intel.com>
 Keith Busch <kbusch@kernel.org> <keith.busch@linux.intel.com>
 Kenneth W Chen <kenneth.w.chen@intel.com>
+Kenneth Westfield <quic_kwestfie@quicinc.com> <kwestfie@codeaurora.org>
+Kiran Gunda <quic_kgunda@quicinc.com> <kgunda@codeaurora.org>
 Kirill Tkhai <tkhai@ya.ru> <ktkhai@virtuozzo.com>
 Konstantin Khlebnikov <koct9i@gmail.com> <khlebnikov@yandex-team.ru>
 Konstantin Khlebnikov <koct9i@gmail.com> <k.khlebnikov@samsung.com>
@@ -278,6 +316,7 @@ Krishna Manikandan <quic_mkrishn@quicinc.com> <mkrishn@codeaurora.org>
 Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski.k@gmail.com>
 Krzysztof Kozlowski <krzk@kernel.org> <k.kozlowski@samsung.com>
 Krzysztof Kozlowski <krzk@kernel.org> <krzysztof.kozlowski@canonical.com>
+Kshitiz Godara <quic_kgodara@quicinc.com> <kgodara@codeaurora.org>
 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 Kuogee Hsieh <quic_khsieh@quicinc.com> <khsieh@codeaurora.org>
 Lee Jones <lee@kernel.org> <joneslee@google.com>
@@ -291,19 +330,27 @@ Leonid I Ananiev <leonid.i.ananiev@intel.com>
 Leon Romanovsky <leon@kernel.org> <leon@leon.nu>
 Leon Romanovsky <leon@kernel.org> <leonro@mellanox.com>
 Leon Romanovsky <leon@kernel.org> <leonro@nvidia.com>
+Liam Mark <quic_lmark@quicinc.com> <lmark@codeaurora.org>
 Linas Vepstas <linas@austin.ibm.com>
 Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@ascom.ch>
 Linus Lüssing <linus.luessing@c0d3.blue> <linus.luessing@web.de>
 <linux-hardening@vger.kernel.org> <kernel-hardening@lists.openwall.com>
 Li Yang <leoyang.li@nxp.com> <leoli@freescale.com>
 Li Yang <leoyang.li@nxp.com> <leo@zh-kernel.org>
+Lior David <quic_liord@quicinc.com> <liord@codeaurora.org>
 Lorenzo Pieralisi <lpieralisi@kernel.org> <lorenzo.pieralisi@arm.com>
 Luca Ceresoli <luca.ceresoli@bootlin.com> <luca@lucaceresoli.net>
 Lukasz Luba <lukasz.luba@arm.com> <l.luba@partner.samsung.com>
+Luo Jie <quic_luoj@quicinc.com> <luoj@codeaurora.org>
 Maciej W. Rozycki <macro@mips.com> <macro@imgtec.com>
 Maciej W. Rozycki <macro@orcam.me.uk> <macro@linux-mips.org>
+Maharaja Kennadyrajan <quic_mkenna@quicinc.com> <mkenna@codeaurora.org>
+Maheshwar Ajja <quic_majja@quicinc.com> <majja@codeaurora.org>
+Malathi Gottam <quic_mgottam@quicinc.com> <mgottam@codeaurora.org>
+Manikanta Pubbisetty <quic_mpubbise@quicinc.com> <mpubbise@codeaurora.org>
 Manivannan Sadhasivam <mani@kernel.org> <manivannanece23@gmail.com>
 Manivannan Sadhasivam <mani@kernel.org> <manivannan.sadhasivam@linaro.org>
+Manoj Basapathi <quic_manojbm@quicinc.com> <manojbm@codeaurora.org>
 Marcin Nowakowski <marcin.nowakowski@mips.com> <marcin.nowakowski@imgtec.com>
 Marc Zyngier <maz@kernel.org> <marc.zyngier@arm.com>
 Marek Behún <kabel@kernel.org> <marek.behun@nic.cz>
@@ -333,6 +380,7 @@ Matt Ranostay <matt.ranostay@konsulko.com> <matt@ranostay.consulting>
 Matt Ranostay <mranostay@gmail.com> Matthew Ranostay <mranostay@embeddedalley.com>
 Matt Ranostay <mranostay@gmail.com> <matt.ranostay@intel.com>
 Matt Redfearn <matt.redfearn@mips.com> <matt.redfearn@imgtec.com>
+Maulik Shah <quic_mkshah@quicinc.com> <mkshah@codeaurora.org>
 Mauro Carvalho Chehab <mchehab@kernel.org> <maurochehab@gmail.com>
 Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@brturbo.com.br>
 Mauro Carvalho Chehab <mchehab@kernel.org> <mchehab@infradead.org>
@@ -345,7 +393,10 @@ Maxim Mikityanskiy <maxtram95@gmail.com> <maximmi@nvidia.com>
 Maxime Ripard <mripard@kernel.org> <maxime@cerno.tech>
 Maxime Ripard <mripard@kernel.org> <maxime.ripard@bootlin.com>
 Maxime Ripard <mripard@kernel.org> <maxime.ripard@free-electrons.com>
+Maya Erez <quic_merez@quicinc.com> <merez@codeaurora.org>
 Mayuresh Janorkar <mayur@ti.com>
+Md Sadre Alam <quic_mdalam@quicinc.com> <mdalam@codeaurora.org>
+Miaoqing Pan <quic_miaoqing@quicinc.com> <miaoqing@codeaurora.org>
 Michael Buesch <m@bues.ch>
 Michal Simek <michal.simek@amd.com> <michal.simek@xilinx.com>
 Michel Dänzer <michel@tungstengraphics.com>
@@ -356,6 +407,7 @@ Miguel Ojeda <ojeda@kernel.org> <miguel.ojeda.sandonis@gmail.com>
 Mike Rapoport <rppt@kernel.org> <mike@compulab.co.il>
 Mike Rapoport <rppt@kernel.org> <mike.rapoport@gmail.com>
 Mike Rapoport <rppt@kernel.org> <rppt@linux.ibm.com>
+Mike Tipton <quic_mdtipton@quicinc.com> <mdtipton@codeaurora.org>
 Miodrag Dinic <miodrag.dinic@mips.com> <miodrag.dinic@imgtec.com>
 Miquel Raynal <miquel.raynal@bootlin.com> <miquel.raynal@free-electrons.com>
 Mitesh shah <mshah@teja.com>
@@ -364,9 +416,13 @@ Morten Welinder <terra@gnome.org>
 Morten Welinder <welinder@anemone.rentec.com>
 Morten Welinder <welinder@darter.rentec.com>
 Morten Welinder <welinder@troll.com>
+Mukesh Ojha <quic_mojha@quicinc.com> <mojha@codeaurora.org>
+Muna Sinada <quic_msinada@quicinc.com> <msinada@codeaurora.org>
+Murali Nalajala <quic_mnalajal@quicinc.com> <mnalajal@codeaurora.org>
 Mythri P K <mythripk@ti.com>
 Nadia Yvette Chambers <nyc@holomorphy.com> William Lee Irwin III <wli@holomorphy.com>
 Nathan Chancellor <nathan@kernel.org> <natechancellor@gmail.com>
+Neeraj Upadhyay <quic_neeraju@quicinc.com> <neeraju@codeaurora.org>
 Neil Armstrong <neil.armstrong@linaro.org> <narmstrong@baylibre.com>
 Nguyen Anh Quynh <aquynh@gmail.com>
 Nicholas Piggin <npiggin@gmail.com> <npiggen@suse.de>
@@ -385,6 +441,7 @@ Nikolay Aleksandrov <razor@blackwall.org> <nikolay@redhat.com>
 Nikolay Aleksandrov <razor@blackwall.org> <nikolay@cumulusnetworks.com>
 Nikolay Aleksandrov <razor@blackwall.org> <nikolay@nvidia.com>
 Nikolay Aleksandrov <razor@blackwall.org> <nikolay@isovalent.com>
+Odelu Kukatla <quic_okukatla@quicinc.com> <okukatla@codeaurora.org>
 Oleksandr Natalenko <oleksandr@natalenko.name> <oleksandr@redhat.com>
 Oleksij Rempel <linux@rempel-privat.de> <bug-track@fisher-privat.net>
 Oleksij Rempel <linux@rempel-privat.de> <external.Oleksij.Rempel@de.bosch.com>
@@ -392,6 +449,7 @@ Oleksij Rempel <linux@rempel-privat.de> <fixed-term.Oleksij.Rempel@de.bosch.com>
 Oleksij Rempel <linux@rempel-privat.de> <o.rempel@pengutronix.de>
 Oleksij Rempel <linux@rempel-privat.de> <ore@pengutronix.de>
 Oliver Upton <oliver.upton@linux.dev> <oupton@google.com>
+Oza Pawandeep <quic_poza@quicinc.com> <poza@codeaurora.org>
 Pali Rohár <pali@kernel.org> <pali.rohar@gmail.com>
 Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
 Patrick Mochel <mochel@digitalimplant.org>
@@ -403,11 +461,14 @@ Paul E. McKenney <paulmck@kernel.org> <paulmck@linux.vnet.ibm.com>
 Paul E. McKenney <paulmck@kernel.org> <paulmck@us.ibm.com>
 Paul Mackerras <paulus@ozlabs.org> <paulus@samba.org>
 Paul Mackerras <paulus@ozlabs.org> <paulus@au1.ibm.com>
+Pavankumar Kondeti <quic_pkondeti@quicinc.com> <pkondeti@codeaurora.org>
 Peter A Jonsson <pj@ludd.ltu.se>
 Peter Oruba <peter.oruba@amd.com>
 Peter Oruba <peter@oruba.de>
 Pratyush Anand <pratyush.anand@gmail.com> <pratyush.anand@st.com>
 Praveen BP <praveenbp@ti.com>
+Pradeep Kumar Chitrapu <quic_pradeepc@quicinc.com> <pradeepc@codeaurora.org>
+Prasad Sodagudi <quic_psodagud@quicinc.com> <psodagud@codeaurora.org>
 Punit Agrawal <punitagrawal@gmail.com> <punit.agrawal@arm.com>
 Qais Yousef <qyousef@layalina.io> <qais.yousef@imgtec.com>
 Qais Yousef <qyousef@layalina.io> <qais.yousef@arm.com>
@@ -416,10 +477,16 @@ Quentin Perret <qperret@qperret.net> <quentin.perret@arm.com>
 Rafael J. Wysocki <rjw@rjwysocki.net> <rjw@sisk.pl>
 Rajeev Nandan <quic_rajeevny@quicinc.com> <rajeevny@codeaurora.org>
 Rajendra Nayak <quic_rjendra@quicinc.com> <rnayak@codeaurora.org>
+Rajeshwari Ravindra Kamble <quic_rkambl@quicinc.com> <rkambl@codeaurora.org>
+Raju P.L.S.S.S.N <quic_rplsssn@quicinc.com> <rplsssn@codeaurora.org>
 Rajesh Shah <rajesh.shah@intel.com>
+Rakesh Pillai <quic_pillair@quicinc.com> <pillair@codeaurora.org>
 Ralf Baechle <ralf@linux-mips.org>
 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
+Ram Chandra Jangir <quic_rjangir@quicinc.com> <rjangir@codeaurora.org>
 Randy Dunlap <rdunlap@infradead.org> <rdunlap@xenotime.net>
+Ravi Kumar Bokka <quic_rbokka@quicinc.com> <rbokka@codeaurora.org>
+Ravi Kumar Siddojigari <quic_rsiddoji@quicinc.com> <rsiddoji@codeaurora.org>
 Rémi Denis-Courmont <rdenis@simphalempin.com>
 Ricardo Ribalda <ribalda@kernel.org> <ricardo@ribalda.com>
 Ricardo Ribalda <ribalda@kernel.org> Ricardo Ribalda Delgado <ribalda@kernel.org>
@@ -428,6 +495,7 @@ Richard Leitner <richard.leitner@linux.dev> <dev@g0hl1n.net>
 Richard Leitner <richard.leitner@linux.dev> <me@g0hl1n.net>
 Richard Leitner <richard.leitner@linux.dev> <richard.leitner@skidata.com>
 Robert Foss <rfoss@kernel.org> <robert.foss@linaro.org>
+Rocky Liao <quic_rjliao@quicinc.com> <rjliao@codeaurora.org>
 Roman Gushchin <roman.gushchin@linux.dev> <guro@fb.com>
 Roman Gushchin <roman.gushchin@linux.dev> <guroan@gmail.com>
 Roman Gushchin <roman.gushchin@linux.dev> <klamm@yandex-team.ru>
@@ -445,22 +513,35 @@ Santosh Shilimkar <santosh.shilimkar@oracle.org>
 Santosh Shilimkar <ssantosh@kernel.org>
 Sarangdhar Joshi <spjoshi@codeaurora.org>
 Sascha Hauer <s.hauer@pengutronix.de>
+Sahitya Tummala <quic_stummala@quicinc.com> <stummala@codeaurora.org>
+Sathishkumar Muruganandam <quic_murugana@quicinc.com> <murugana@codeaurora.org>
 Satya Priya <quic_c_skakit@quicinc.com> <skakit@codeaurora.org>
 S.ÇaÄŸlar Onur <caglar@pardus.org.tr>
+Sayali Lokhande <quic_sayalil@quicinc.com> <sayalil@codeaurora.org>
 Sean Christopherson <seanjc@google.com> <sean.j.christopherson@intel.com>
 Sean Nyekjaer <sean@geanix.com> <sean.nyekjaer@prevas.dk>
+Sean Tranchetti <quic_stranche@quicinc.com> <stranche@codeaurora.org>
 Sebastian Reichel <sre@kernel.org> <sebastian.reichel@collabora.co.uk>
 Sebastian Reichel <sre@kernel.org> <sre@debian.org>
 Sedat Dilek <sedat.dilek@gmail.com> <sedat.dilek@credativ.de>
+Senthilkumar N L <quic_snlakshm@quicinc.com> <snlakshm@codeaurora.org>
 Seth Forshee <sforshee@kernel.org> <seth.forshee@canonical.com>
 Shannon Nelson <shannon.nelson@amd.com> <snelson@pensando.io>
+Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@intel.com>
+Shannon Nelson <shannon.nelson@amd.com> <shannon.nelson@oracle.com>
+Sharath Chandra Vurukala <quic_sharathv@quicinc.com> <sharathv@codeaurora.org>
 Shiraz Hashim <shiraz.linux.kernel@gmail.com> <shiraz.hashim@st.com>
 Shuah Khan <shuah@kernel.org> <shuahkhan@gmail.com>
 Shuah Khan <shuah@kernel.org> <shuah.khan@hp.com>
 Shuah Khan <shuah@kernel.org> <shuahkh@osg.samsung.com>
 Shuah Khan <shuah@kernel.org> <shuah.kh@samsung.com>
+Sibi Sankar <quic_sibis@quicinc.com> <sibis@codeaurora.org>
+Sid Manning <quic_sidneym@quicinc.com> <sidneym@codeaurora.org>
 Simon Arlott <simon@octiron.net> <simon@fire.lp0.eu>
 Simon Kelley <simon@thekelleys.org.uk>
+Sricharan Ramabadhran <quic_srichara@quicinc.com> <sricharan@codeaurora.org>
+Srinivas Ramana <quic_sramana@quicinc.com> <sramana@codeaurora.org>
+Sriram R <quic_srirrama@quicinc.com> <srirrama@codeaurora.org>
 Stéphane Witzmann <stephane.witzmann@ubpmes.univ-bpclermont.fr>
 Stephen Hemminger <stephen@networkplumber.org> <shemminger@linux-foundation.org>
 Stephen Hemminger <stephen@networkplumber.org> <shemminger@osdl.org>
@@ -468,22 +549,30 @@ Stephen Hemminger <stephen@networkplumber.org> <sthemmin@microsoft.com>
 Stephen Hemminger <stephen@networkplumber.org> <sthemmin@vyatta.com>
 Steve Wise <larrystevenwise@gmail.com> <swise@chelsio.com>
 Steve Wise <larrystevenwise@gmail.com> <swise@opengridcomputing.com>
-Subash Abhinov Kasiviswanathan <subashab@codeaurora.org>
+Subash Abhinov Kasiviswanathan <quic_subashab@quicinc.com> <subashab@codeaurora.org>
+Subbaraman Narayanamurthy <quic_subbaram@quicinc.com> <subbaram@codeaurora.org>
 Subhash Jadavani <subhashj@codeaurora.org>
+Sudarshan Rajagopalan <quic_sudaraja@quicinc.com> <sudaraja@codeaurora.org>
 Sudeep Holla <sudeep.holla@arm.com> Sudeep KarkadaNagesha <sudeep.karkadanagesha@arm.com>
 Sumit Semwal <sumit.semwal@ti.com>
+Surabhi Vishnoi <quic_svishnoi@quicinc.com> <svishnoi@codeaurora.org>
 Takashi YOSHII <takashi.yoshii.zj@renesas.com>
+Tamizh Chelvam Raja <quic_tamizhr@quicinc.com> <tamizhr@codeaurora.org>
+Taniya Das <quic_tdas@quicinc.com> <tdas@codeaurora.org>
 Tejun Heo <htejun@gmail.com>
 Thomas Graf <tgraf@suug.ch>
 Thomas Körper <socketcan@esd.eu> <thomas.koerper@esd.eu>
 Thomas Pedersen <twp@codeaurora.org>
 Tiezhu Yang <yangtiezhu@loongson.cn> <kernelpatch@126.com>
+Tingwei Zhang <quic_tingwei@quicinc.com> <tingwei@codeaurora.org>
+Tirupathi Reddy <quic_tirupath@quicinc.com> <tirupath@codeaurora.org>
 Tobias Klauser <tklauser@distanz.ch> <tobias.klauser@gmail.com>
 Tobias Klauser <tklauser@distanz.ch> <klto@zhaw.ch>
 Tobias Klauser <tklauser@distanz.ch> <tklauser@nuerscht.ch>
 Tobias Klauser <tklauser@distanz.ch> <tklauser@xenon.tklauser.home>
 Todor Tomov <todor.too@gmail.com> <todor.tomov@linaro.org>
 Tony Luck <tony.luck@intel.com>
+Trilok Soni <quic_tsoni@quicinc.com> <tsoni@codeaurora.org>
 TripleX Chung <xxx.phy@gmail.com> <triplex@zh-kernel.org>
 TripleX Chung <xxx.phy@gmail.com> <zhongyu@18mail.cn>
 Tsuneo Yoshioka <Tsuneo.Yoshioka@f-secure.com>
@@ -496,11 +585,17 @@ Uwe Kleine-König <ukleinek@strlen.de>
 Uwe Kleine-König <ukl@pengutronix.de>
 Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
 Valdis Kletnieks <Valdis.Kletnieks@vt.edu>
+Vara Reddy <quic_varar@quicinc.com> <varar@codeaurora.org>
+Varadarajan Narayanan <quic_varada@quicinc.com> <varada@codeaurora.org>
+Vasanthakumar Thiagarajan <quic_vthiagar@quicinc.com> <vthiagar@codeaurora.org>
 Vasily Averin <vasily.averin@linux.dev> <vvs@virtuozzo.com>
 Vasily Averin <vasily.averin@linux.dev> <vvs@openvz.org>
 Vasily Averin <vasily.averin@linux.dev> <vvs@parallels.com>
 Vasily Averin <vasily.averin@linux.dev> <vvs@sw.ru>
 Valentin Schneider <vschneid@redhat.com> <valentin.schneider@arm.com>
+Veera Sundaram Sankaran <quic_veeras@quicinc.com> <veeras@codeaurora.org>
+Veerabhadrarao Badiganti <quic_vbadigan@quicinc.com> <vbadigan@codeaurora.org>
+Venkateswara Naralasetty <quic_vnaralas@quicinc.com> <vnaralas@codeaurora.org>
 Vikash Garodia <quic_vgarodia@quicinc.com> <vgarodia@codeaurora.org>
 Vinod Koul <vkoul@kernel.org> <vinod.koul@intel.com>
 Vinod Koul <vkoul@kernel.org> <vinod.koul@linux.intel.com>
@@ -510,11 +605,14 @@ Viresh Kumar <vireshk@kernel.org> <viresh.kumar@st.com>
 Viresh Kumar <vireshk@kernel.org> <viresh.linux@gmail.com>
 Viresh Kumar <viresh.kumar@linaro.org> <viresh.kumar@linaro.org>
 Viresh Kumar <viresh.kumar@linaro.org> <viresh.kumar@linaro.com>
+Vivek Aknurwar <quic_viveka@quicinc.com> <viveka@codeaurora.org>
 Vivien Didelot <vivien.didelot@gmail.com> <vivien.didelot@savoirfairelinux.com>
 Vlad Dogaru <ddvlad@gmail.com> <vlad.dogaru@intel.com>
 Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@parallels.com>
 Vladimir Davydov <vdavydov.dev@gmail.com> <vdavydov@virtuozzo.com>
 WeiXiong Liao <gmpy.liaowx@gmail.com> <liaoweixiong@allwinnertech.com>
+Wen Gong <quic_wgong@quicinc.com> <wgong@codeaurora.org>
+Wesley Cheng <quic_wcheng@quicinc.com> <wcheng@codeaurora.org>
 Will Deacon <will@kernel.org> <will.deacon@arm.com>
 Wolfram Sang <wsa@kernel.org> <w.sang@pengutronix.de>
 Wolfram Sang <wsa@kernel.org> <wsa@the-dreams.de>
index 6350dd8..087f762 100644 (file)
@@ -82,7 +82,12 @@ Description:
                whether it resides in persistent capacity, volatile capacity,
                or the LSA, is made permanently unavailable by whatever means
                is appropriate for the media type. This functionality requires
-               the device to be not be actively decoding any HPA ranges.
+               the device to be disabled, that is, not actively decoding any
+               HPA ranges. This permits avoiding explicit global CPU cache
+               management, relying instead for it to be done when a region
+               transitions between software programmed and hardware committed
+               states. If this file is not present, then there is no hardware
+               support for the operation.
 
 
 What            /sys/bus/cxl/devices/memX/security/erase
@@ -92,7 +97,13 @@ Contact:        linux-cxl@vger.kernel.org
 Description:
                (WO) Write a boolean 'true' string value to this attribute to
                secure erase user data by changing the media encryption keys for
-               all user data areas of the device.
+               all user data areas of the device. This functionality requires
+               the device to be disabled, that is, not actively decoding any
+               HPA ranges. This permits avoiding explicit global CPU cache
+               management, relying instead for it to be done when a region
+               transitions between software programmed and hardware committed
+               states. If this file is not present, then there is no hardware
+               support for the operation.
 
 
 What:          /sys/bus/cxl/devices/memX/firmware/
index 0888636..62addab 100644 (file)
@@ -60,3 +60,14 @@ Description: Module taint flags:
                        C   staging driver module
                        E   unsigned module
                        ==  =====================
+
+What:          /sys/module/grant_table/parameters/free_per_iteration
+Date:          July 2023
+KernelVersion: 6.5 but backported to all supported stable branches
+Contact:       Xen developer discussion <xen-devel@lists.xenproject.org>
+Description:   Read and write number of grant entries to attempt to free per iteration.
+
+               Note: Future versions of Xen and Linux may provide a better
+               interface for controlling the rate of deferred grant reclaim
+               or may not need it at all.
+Users:         Qubes OS (https://www.qubes-os.org)
index 06c525e..b1b57f6 100644 (file)
                 45 = /dev/ttyMM1               Marvell MPSC - port 1 (obsolete unused)
                 46 = /dev/ttyCPM0              PPC CPM (SCC or SMC) - port 0
                    ...
-                47 = /dev/ttyCPM5              PPC CPM (SCC or SMC) - port 5
+                49 = /dev/ttyCPM5              PPC CPM (SCC or SMC) - port 3
                 50 = /dev/ttyIOC0              Altix serial card
                    ...
                 81 = /dev/ttyIOC31             Altix serial card
index 4d186f5..32a8893 100644 (file)
@@ -484,11 +484,14 @@ Spectre variant 2
 
    Systems which support enhanced IBRS (eIBRS) enable IBRS protection once at
    boot, by setting the IBRS bit, and they're automatically protected against
-   Spectre v2 variant attacks, including cross-thread branch target injections
-   on SMT systems (STIBP). In other words, eIBRS enables STIBP too.
+   Spectre v2 variant attacks.
 
-   Legacy IBRS systems clear the IBRS bit on exit to userspace and
-   therefore explicitly enable STIBP for that
+   On Intel's enhanced IBRS systems, this includes cross-thread branch target
+   injections on SMT systems (STIBP). In other words, Intel eIBRS enables
+   STIBP, too.
+
+   AMD Automatic IBRS does not protect userspace, and Legacy IBRS systems clear
+   the IBRS bit on exit to userspace, therefore both explicitly enable STIBP.
 
    The retpoline mitigation is turned on by default on vulnerable
    CPUs. It can be forced on or off by the administrator
index 496cdca..bedd3a1 100644 (file)
@@ -148,6 +148,9 @@ stable kernels.
 | ARM            | MMU-700         | #2268618,2812531| N/A                         |
 +----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
+| ARM            | GIC-700         | #2941627        | ARM64_ERRATUM_2941627       |
++----------------+-----------------+-----------------+-----------------------------+
++----------------+-----------------+-----------------+-----------------------------+
 | Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_845719        |
 +----------------+-----------------+-----------------+-----------------------------+
 | Broadcom       | Brahma-B53      | N/A             | ARM64_ERRATUM_843419        |
index ae4f68d..bd67cfe 100644 (file)
@@ -105,7 +105,7 @@ properties:
       G coefficient for temperature equation.
       Default for series 5 = 60000
       Default for series 6 = 57400
-    multipleOf: 1000
+    multipleOf: 100
     minimum: 1000
     $ref: /schemas/types.yaml#/definitions/uint32
 
@@ -114,7 +114,7 @@ properties:
       H coefficient for temperature equation.
       Default for series 5 = 200000
       Default for series 6 = 249400
-    multipleOf: 1000
+    multipleOf: 100
     minimum: 1000
     $ref: /schemas/types.yaml#/definitions/uint32
 
@@ -131,7 +131,7 @@ properties:
       J coefficient for temperature equation.
       Default for series 5 = -100
       Default for series 6 = 0
-    multipleOf: 1000
+    multipleOf: 100
     maximum: 0
     $ref: /schemas/types.yaml#/definitions/int32
 
index acb2b2a..31cc0c4 100644 (file)
@@ -293,7 +293,7 @@ allOf:
 patternProperties:
   "^mac@[0-1]$":
     type: object
-    additionalProperties: false
+    unevaluatedProperties: false
     allOf:
       - $ref: ethernet-controller.yaml#
     description:
@@ -305,14 +305,9 @@ patternProperties:
       reg:
         maxItems: 1
 
-      phy-handle: true
-
-      phy-mode: true
-
     required:
       - reg
       - compatible
-      - phy-handle
 
 required:
   - compatible
index 176ea5f..7f324c6 100644 (file)
@@ -91,12 +91,18 @@ properties:
     $ref: /schemas/types.yaml#/definitions/phandle
 
   tx_delay:
-    description: Delay value for TXD timing. Range value is 0~0x7F, 0x30 as default.
+    description: Delay value for TXD timing.
     $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 0x7F
+    default: 0x30
 
   rx_delay:
-    description: Delay value for RXD timing. Range value is 0~0x7F, 0x10 as default.
+    description: Delay value for RXD timing.
     $ref: /schemas/types.yaml#/definitions/uint32
+    minimum: 0
+    maximum: 0x7F
+    default: 0x10
 
   phy-supply:
     description: PHY regulator
index 30b2131..65cb2e5 100644 (file)
@@ -16,7 +16,6 @@ properties:
       - enum:
           - atmel,at91rm9200-usart
           - atmel,at91sam9260-usart
-          - microchip,sam9x60-usart
       - items:
           - const: atmel,at91rm9200-dbgu
           - const: atmel,at91rm9200-usart
@@ -24,6 +23,9 @@ properties:
           - const: atmel,at91sam9260-dbgu
           - const: atmel,at91sam9260-usart
       - items:
+          - const: microchip,sam9x60-usart
+          - const: atmel,at91sam9260-usart
+      - items:
           - const: microchip,sam9x60-dbgu
           - const: microchip,sam9x60-usart
           - const: atmel,at91sam9260-dbgu
diff --git a/Documentation/devicetree/bindings/serial/cavium-uart.txt b/Documentation/devicetree/bindings/serial/cavium-uart.txt
deleted file mode 100644 (file)
index 87a6c37..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-* Universal Asynchronous Receiver/Transmitter (UART)
-
-- compatible: "cavium,octeon-3860-uart"
-
-  Compatibility with all cn3XXX, cn5XXX and cn6XXX SOCs.
-
-- reg: The base address of the UART register bank.
-
-- interrupts: A single interrupt specifier.
-
-- current-speed: Optional, the current bit rate in bits per second.
-
-Example:
-       uart1: serial@1180000000c00 {
-               compatible = "cavium,octeon-3860-uart","ns16550";
-               reg = <0x11800 0x00000c00 0x0 0x400>;
-               current-speed = <115200>;
-               interrupts = <0 35>;
-       };
diff --git a/Documentation/devicetree/bindings/serial/nxp,lpc1850-uart.txt b/Documentation/devicetree/bindings/serial/nxp,lpc1850-uart.txt
deleted file mode 100644 (file)
index 04e23e6..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-* NXP LPC1850 UART
-
-Required properties:
-- compatible   : "nxp,lpc1850-uart", "ns16550a".
-- reg          : offset and length of the register set for the device.
-- interrupts   : should contain uart interrupt.
-- clocks       : phandle to the input clocks.
-- clock-names  : required elements: "uartclk", "reg".
-
-Optional properties:
-- dmas         : Two or more DMA channel specifiers following the
-                 convention outlined in bindings/dma/dma.txt
-- dma-names    : Names for the dma channels, if present. There must
-                 be at least one channel named "tx" for transmit
-                 and named "rx" for receive.
-
-Since it's also possible to also use the of_serial.c driver all
-parameters from 8250.txt also apply but are optional.
-
-Example:
-uart0: serial@40081000 {
-       compatible = "nxp,lpc1850-uart", "ns16550a";
-       reg = <0x40081000 0x1000>;
-       reg-shift = <2>;
-       interrupts = <24>;
-       clocks = <&ccu2 CLK_APB0_UART0>, <&ccu1 CLK_CPU_UART0>;
-       clock-names = "uartclk", "reg";
-};
index 3de7b36..d3ce4de 100644 (file)
@@ -39,22 +39,4 @@ required:
 
 additionalProperties: false
 
-examples:
-  - |
-    sound {
-        compatible = "audio-graph-card2";
-
-        links = <&cpu_port>;
-    };
-
-    cpu {
-        compatible = "cpu-driver";
-
-        cpu_port: port { cpu_ep: endpoint { remote-endpoint = <&codec_ep>; }; };
-    };
-
-    codec {
-        compatible = "codec-driver";
-
-        port { codec_ep: endpoint { remote-endpoint = <&cpu_ep>; }; };
-    };
+...
index 666a95a..ba5b772 100644 (file)
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
 title: Google SC7180-Trogdor ASoC sound card driver
 
 maintainers:
-  - Rohit kumar <rohitkr@codeaurora.org>
+  - Rohit kumar <quic_rohkumar@quicinc.com>
   - Cheng-Yi Chiang <cychiang@chromium.org>
 
 description:
index 6cc8f86..3a559bd 100644 (file)
@@ -8,7 +8,7 @@ title: Qualcomm Technologies Inc. LPASS CPU dai driver
 
 maintainers:
   - Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
-  - Rohit kumar <rohitkr@codeaurora.org>
+  - Rohit kumar <quic_rohkumar@quicinc.com>
 
 description: |
   Qualcomm Technologies Inc. SOC Low-Power Audio SubSystem (LPASS) that consist
index f18f46b..2cd8fa3 100644 (file)
@@ -84,8 +84,6 @@ nr_inodes  The maximum number of inodes for this instance. The default
            is half of the number of your physical RAM pages, or (on a
            machine with highmem) the number of lowmem RAM pages,
            whichever is the lower.
-noswap     Disables swap. Remounts must respect the original settings.
-           By default swap is enabled.
 =========  ============================================================
 
 These parameters accept a suffix k, m or g for kilo, mega and giga and
@@ -99,36 +97,31 @@ mount with such options, since it allows any user with write access to
 use up all the memory on the machine; but enhances the scalability of
 that instance in a system with many CPUs making intensive use of it.
 
+tmpfs blocks may be swapped out, when there is a shortage of memory.
+tmpfs has a mount option to disable its use of swap:
+
+======  ===========================================================
+noswap  Disables swap. Remounts must respect the original settings.
+        By default swap is enabled.
+======  ===========================================================
+
 tmpfs also supports Transparent Huge Pages which requires a kernel
 configured with CONFIG_TRANSPARENT_HUGEPAGE and with huge supported for
 your system (has_transparent_hugepage(), which is architecture specific).
 The mount options for this are:
 
-======  ============================================================
-huge=0  never: disables huge pages for the mount
-huge=1  always: enables huge pages for the mount
-huge=2  within_size: only allocate huge pages if the page will be
-        fully within i_size, also respect fadvise()/madvise() hints.
-huge=3  advise: only allocate huge pages if requested with
-        fadvise()/madvise()
-======  ============================================================
-
-There is a sysfs file which you can also use to control system wide THP
-configuration for all tmpfs mounts, the file is:
-
-/sys/kernel/mm/transparent_hugepage/shmem_enabled
-
-This sysfs file is placed on top of THP sysfs directory and so is registered
-by THP code. It is however only used to control all tmpfs mounts with one
-single knob. Since it controls all tmpfs mounts it should only be used either
-for emergency or testing purposes. The values you can set for shmem_enabled are:
-
-==  ============================================================
--1  deny: disables huge on shm_mnt and all mounts, for
-    emergency use
--2  force: enables huge on shm_mnt and all mounts, w/o needing
-    option, for testing
-==  ============================================================
+================ ==============================================================
+huge=never       Do not allocate huge pages.  This is the default.
+huge=always      Attempt to allocate huge page every time a new page is needed.
+huge=within_size Only allocate huge page if it will be fully within i_size.
+                 Also respect madvise(2) hints.
+huge=advise      Only allocate huge page if requested with madvise(2).
+================ ==============================================================
+
+See also Documentation/admin-guide/mm/transhuge.rst, which describes the
+sysfs file /sys/kernel/mm/transparent_hugepage/shmem_enabled: which can
+be used to deny huge pages on all tmpfs mounts in an emergency, or to
+force huge pages on all tmpfs mounts for testing.
 
 tmpfs has a mount option to set the NUMA memory allocation policy for
 all files in that instance (if CONFIG_NUMA is enabled) - which can be
index a7a0477..7bf7b95 100644 (file)
@@ -65,15 +65,16 @@ argument - drivers can process completions for any number of Tx
 packets but should only process up to ``budget`` number of
 Rx packets. Rx processing is usually much more expensive.
 
-In other words, it is recommended to ignore the budget argument when
-performing TX buffer reclamation to ensure that the reclamation is not
-arbitrarily bounded; however, it is required to honor the budget argument
-for RX processing.
+In other words for Rx processing the ``budget`` argument limits how many
+packets driver can process in a single poll. Rx specific APIs like page
+pool or XDP cannot be used at all when ``budget`` is 0.
+skb Tx processing should happen regardless of the ``budget``, but if
+the argument is 0 driver cannot call any XDP (or page pool) APIs.
 
 .. warning::
 
-   The ``budget`` argument may be 0 if core tries to only process Tx completions
-   and no Rx packets.
+   The ``budget`` argument may be 0 if core tries to only process
+   skb Tx completions and no Rx or XDP packets.
 
 The poll method returns the amount of work done. If the driver still
 has outstanding work to do (e.g. ``budget`` was exhausted)
index df97812..cb68623 100644 (file)
@@ -254,7 +254,6 @@ an involved disclosed party. The current ambassadors list:
   Samsung      Javier González <javier.gonz@samsung.com>
 
   Microsoft    James Morris <jamorris@linux.microsoft.com>
-  VMware
   Xen          Andrew Cooper <andrew.cooper3@citrix.com>
 
   Canonical    John Johansen <john.johansen@canonical.com>
@@ -263,10 +262,8 @@ an involved disclosed party. The current ambassadors list:
   Red Hat      Josh Poimboeuf <jpoimboe@redhat.com>
   SUSE         Jiri Kosina <jkosina@suse.cz>
 
-  Amazon
   Google       Kees Cook <keescook@chromium.org>
 
-  GCC
   LLVM         Nick Desaulniers <ndesaulniers@google.com>
   ============= ========================================================
 
index 82e2983..5a69937 100644 (file)
@@ -63,31 +63,28 @@ information submitted to the security list and any followup discussions
 of the report are treated confidentially even after the embargo has been
 lifted, in perpetuity.
 
-Coordination
-------------
-
-Fixes for sensitive bugs, such as those that might lead to privilege
-escalations, may need to be coordinated with the private
-<linux-distros@vs.openwall.org> mailing list so that distribution vendors
-are well prepared to issue a fixed kernel upon public disclosure of the
-upstream fix. Distros will need some time to test the proposed patch and
-will generally request at least a few days of embargo, and vendor update
-publication prefers to happen Tuesday through Thursday. When appropriate,
-the security team can assist with this coordination, or the reporter can
-include linux-distros from the start. In this case, remember to prefix
-the email Subject line with "[vs]" as described in the linux-distros wiki:
-<http://oss-security.openwall.org/wiki/mailing-lists/distros#how-to-use-the-lists>
+Coordination with other groups
+------------------------------
+
+The kernel security team strongly recommends that reporters of potential
+security issues NEVER contact the "linux-distros" mailing list until
+AFTER discussing it with the kernel security team.  Do not Cc: both
+lists at once.  You may contact the linux-distros mailing list after a
+fix has been agreed on and you fully understand the requirements that
+doing so will impose on you and the kernel community.
+
+The different lists have different goals and the linux-distros rules do
+not contribute to actually fixing any potential security problems.
 
 CVE assignment
 --------------
 
-The security team does not normally assign CVEs, nor do we require them
-for reports or fixes, as this can needlessly complicate the process and
-may delay the bug handling. If a reporter wishes to have a CVE identifier
-assigned ahead of public disclosure, they will need to contact the private
-linux-distros list, described above. When such a CVE identifier is known
-before a patch is provided, it is desirable to mention it in the commit
-message if the reporter agrees.
+The security team does not assign CVEs, nor do we require them for
+reports or fixes, as this can needlessly complicate the process and may
+delay the bug handling.  If a reporter wishes to have a CVE identifier
+assigned, they should find one by themselves, for example by contacting
+MITRE directly.  However under no circumstances will a patch inclusion
+be delayed to wait for a CVE identifier to arrive.
 
 Non-disclosure agreements
 -------------------------
index e351cfc..a06df3b 100644 (file)
@@ -1865,9 +1865,11 @@ M:       Martin PoviÅ¡er <povik+lin@cutebit.org>
 L:     asahi@lists.linux.dev
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
+F:     Documentation/devicetree/bindings/sound/adi,ssm3515.yaml
 F:     Documentation/devicetree/bindings/sound/apple,*
 F:     sound/soc/apple/*
 F:     sound/soc/codecs/cs42l83-i2c.c
+F:     sound/soc/codecs/ssm3515.c
 
 ARM/APPLE MACHINE SUPPORT
 M:     Hector Martin <marcan@marcan.st>
@@ -3260,9 +3262,8 @@ F:        Documentation/devicetree/bindings/input/atmel,maxtouch.yaml
 F:     drivers/input/touchscreen/atmel_mxt_ts.c
 
 ATMEL WIRELESS DRIVER
-M:     Simon Kelley <simon@thekelleys.org.uk>
 L:     linux-wireless@vger.kernel.org
-S:     Maintained
+S:     Orphan
 W:     http://www.thekelleys.org.uk/atmel
 W:     http://atmelwlandriver.sourceforge.net/
 F:     drivers/net/wireless/atmel/atmel*
@@ -3392,7 +3393,7 @@ F:        drivers/media/radio/radio-aztech*
 B43 WIRELESS DRIVER
 L:     linux-wireless@vger.kernel.org
 L:     b43-dev@lists.infradead.org
-S:     Odd Fixes
+S:     Orphan
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/b43
 F:     drivers/net/wireless/broadcom/b43/
 
@@ -4461,7 +4462,6 @@ CADENCE USB3 DRD IP DRIVER
 M:     Peter Chen <peter.chen@kernel.org>
 M:     Pawel Laszczak <pawell@cadence.com>
 R:     Roger Quadros <rogerq@kernel.org>
-R:     Aswath Govindraju <a-govindraju@ti.com>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/peter.chen/usb.git
@@ -5147,10 +5147,12 @@ S:      Maintained
 F:     include/linux/compiler_attributes.h
 
 COMPUTE EXPRESS LINK (CXL)
+M:     Davidlohr Bueso <dave@stgolabs.net>
+M:     Jonathan Cameron <jonathan.cameron@huawei.com>
+M:     Dave Jiang <dave.jiang@intel.com>
 M:     Alison Schofield <alison.schofield@intel.com>
 M:     Vishal Verma <vishal.l.verma@intel.com>
 M:     Ira Weiny <ira.weiny@intel.com>
-M:     Ben Widawsky <bwidawsk@kernel.org>
 M:     Dan Williams <dan.j.williams@intel.com>
 L:     linux-cxl@vger.kernel.org
 S:     Maintained
@@ -5459,8 +5461,7 @@ F:        Documentation/devicetree/bindings/net/can/ctu,ctucanfd.yaml
 F:     drivers/net/can/ctucanfd/
 
 CW1200 WLAN driver
-M:     Solomon Peachy <pizza@shaftnet.org>
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/st/cw1200/
 
 CX18 VIDEO4LINUX DRIVER
@@ -12589,18 +12590,14 @@ F:    Documentation/devicetree/bindings/net/marvell,pp2.yaml
 F:     drivers/net/ethernet/marvell/mvpp2/
 
 MARVELL MWIFIEX WIRELESS DRIVER
-M:     Amitkumar Karwar <amitkarwar@gmail.com>
-M:     Ganapathi Bhat <ganapathi017@gmail.com>
-M:     Sharvari Harisangam <sharvari.harisangam@nxp.com>
-M:     Xinming Hu <huxinming820@gmail.com>
+M:     Brian Norris <briannorris@chromium.org>
 L:     linux-wireless@vger.kernel.org
-S:     Maintained
+S:     Odd Fixes
 F:     drivers/net/wireless/marvell/mwifiex/
 
 MARVELL MWL8K WIRELESS DRIVER
-M:     Lennert Buytenhek <buytenh@wantstofly.org>
 L:     linux-wireless@vger.kernel.org
-S:     Odd Fixes
+S:     Orphan
 F:     drivers/net/wireless/marvell/mwl8k.c
 
 MARVELL NAND CONTROLLER DRIVER
@@ -17448,6 +17445,7 @@ F:      drivers/media/tuners/qt1010*
 
 QUALCOMM ATH12K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@kernel.org>
+M:     Jeff Johnson <quic_jjohnson@quicinc.com>
 L:     ath12k@lists.infradead.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
@@ -17455,6 +17453,7 @@ F:      drivers/net/wireless/ath/ath12k/
 
 QUALCOMM ATHEROS ATH10K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@kernel.org>
+M:     Jeff Johnson <quic_jjohnson@quicinc.com>
 L:     ath10k@lists.infradead.org
 S:     Supported
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath10k
@@ -17464,6 +17463,7 @@ F:      drivers/net/wireless/ath/ath10k/
 
 QUALCOMM ATHEROS ATH11K WIRELESS DRIVER
 M:     Kalle Valo <kvalo@kernel.org>
+M:     Jeff Johnson <quic_jjohnson@quicinc.com>
 L:     ath11k@lists.infradead.org
 S:     Supported
 W:     https://wireless.wiki.kernel.org/en/users/Drivers/ath11k
@@ -17984,7 +17984,7 @@ T:      git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.g
 F:     drivers/net/wireless/realtek/rtlwifi/
 
 REALTEK WIRELESS DRIVER (rtw88)
-M:     Yan-Hsuan Chuang <tony0620emma@gmail.com>
+M:     Ping-Ke Shih <pkshih@realtek.com>
 L:     linux-wireless@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wireless/realtek/rtw88/
@@ -20403,7 +20403,6 @@ F:      drivers/pwm/pwm-stm32*
 F:     include/linux/*/stm32-*tim*
 
 STMMAC ETHERNET DRIVER
-M:     Giuseppe Cavallaro <peppe.cavallaro@st.com>
 M:     Alexandre Torgue <alexandre.torgue@foss.st.com>
 M:     Jose Abreu <joabreu@synopsys.com>
 L:     netdev@vger.kernel.org
@@ -21641,11 +21640,17 @@ F:    Documentation/translations/zh_TW/
 TTY LAYER
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 M:     Jiri Slaby <jirislaby@kernel.org>
+L:     linux-kernel@vger.kernel.org
+L:     linux-serial@vger.kernel.org
 S:     Supported
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty.git
 F:     Documentation/driver-api/serial/
 F:     drivers/tty/
+F:     drivers/tty/serial/serial_base.h
+F:     drivers/tty/serial/serial_base_bus.c
 F:     drivers/tty/serial/serial_core.c
+F:     drivers/tty/serial/serial_ctrl.c
+F:     drivers/tty/serial/serial_port.c
 F:     include/linux/selection.h
 F:     include/linux/serial.h
 F:     include/linux/serial_core.h
@@ -21674,11 +21679,14 @@ S:    Orphan
 F:     drivers/net/ethernet/dec/tulip/
 
 TUN/TAP driver
-M:     Maxim Krasnyansky <maxk@qti.qualcomm.com>
+M:     Willem de Bruijn <willemdebruijn.kernel@gmail.com>
+M:     Jason Wang <jasowang@redhat.com>
 S:     Maintained
 W:     http://vtun.sourceforge.net/tun
 F:     Documentation/networking/tuntap.rst
 F:     arch/um/os-Linux/drivers/
+F:     drivers/net/tap.c
+F:     drivers/net/tun.c
 
 TURBOCHANNEL SUBSYSTEM
 M:     "Maciej W. Rozycki" <macro@orcam.me.uk>
@@ -21901,9 +21909,8 @@ S:      Maintained
 F:     drivers/usb/misc/apple-mfi-fastcharge.c
 
 USB AR5523 WIRELESS DRIVER
-M:     Pontus Fuchs <pontus.fuchs@gmail.com>
 L:     linux-wireless@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/ath/ar5523/
 
 USB ATTACHED SCSI
@@ -22180,9 +22187,8 @@ F:      drivers/usb/gadget/legacy/webcam.c
 F:     include/uapi/linux/usb/g_uvc.h
 
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
-M:     Jussi Kivilinna <jussi.kivilinna@iki.fi>
 L:     linux-wireless@vger.kernel.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/legacy/rndis_wlan.c
 
 USB XHCI DRIVER
@@ -22957,7 +22963,7 @@ F:      drivers/input/misc/wistron_btns.c
 
 WL3501 WIRELESS PCMCIA CARD DRIVER
 L:     linux-wireless@vger.kernel.org
-S:     Odd fixes
+S:     Orphan
 F:     drivers/net/wireless/legacy/wl3501*
 
 WMI BINARY MOF DRIVER
@@ -23528,11 +23534,8 @@ S:     Maintained
 F:     mm/zbud.c
 
 ZD1211RW WIRELESS DRIVER
-M:     Ulrich Kunitz <kune@deine-taler.de>
 L:     linux-wireless@vger.kernel.org
-L:     zd1211-devs@lists.sourceforge.net (subscribers-only)
-S:     Maintained
-W:     http://zd1211.ath.cx/wiki/DriverRewrite
+S:     Orphan
 F:     drivers/net/wireless/zydas/zd1211rw/
 
 ZD1301 MEDIA DRIVER
index 658ec2b..6532385 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
@@ -555,11 +555,23 @@ LINUXINCLUDE    := \
                $(USERINCLUDE)
 
 KBUILD_AFLAGS   := -D__ASSEMBLY__ -fno-PIE
-KBUILD_CFLAGS   := -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs \
-                  -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE \
-                  -Werror=implicit-function-declaration -Werror=implicit-int \
-                  -Werror=return-type -Wno-format-security -funsigned-char \
-                  -std=gnu11
+
+KBUILD_CFLAGS :=
+KBUILD_CFLAGS += -std=gnu11
+KBUILD_CFLAGS += -fshort-wchar
+KBUILD_CFLAGS += -funsigned-char
+KBUILD_CFLAGS += -fno-common
+KBUILD_CFLAGS += -fno-PIE
+KBUILD_CFLAGS += -fno-strict-aliasing
+KBUILD_CFLAGS += -Wall
+KBUILD_CFLAGS += -Wundef
+KBUILD_CFLAGS += -Werror=implicit-function-declaration
+KBUILD_CFLAGS += -Werror=implicit-int
+KBUILD_CFLAGS += -Werror=return-type
+KBUILD_CFLAGS += -Werror=strict-prototypes
+KBUILD_CFLAGS += -Wno-format-security
+KBUILD_CFLAGS += -Wno-trigraphs
+
 KBUILD_CPPFLAGS := -D__KERNEL__
 KBUILD_RUSTFLAGS := $(rust_common_flags) \
                    --target=$(objtree)/scripts/target.json \
index 8b53997..73d570a 100644 (file)
                                status = "disabled";
 
                                uart4: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <13 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart5: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        atmel,usart-mode = <AT91_USART_MODE_SERIAL>;
                                        interrupts = <14 IRQ_TYPE_LEVEL_HIGH 7>;
                                status = "disabled";
 
                                uart11: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <32 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart12: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <33 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart6: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <9 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart7: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <10 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart8: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <11 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart0: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <5 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart1: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <6 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart2: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <7 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart3: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <8 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart9: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <15 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
                                status = "disabled";
 
                                uart10: serial@200 {
-                                       compatible = "microchip,sam9x60-dbgu", "microchip,sam9x60-usart", "atmel,at91sam9260-dbgu", "atmel,at91sam9260-usart";
+                                       compatible = "microchip,sam9x60-usart", "atmel,at91sam9260-usart";
                                        reg = <0x200 0x200>;
                                        interrupts = <16 IRQ_TYPE_LEVEL_HIGH 7>;
                                        dmas = <&dma0
index bb240e6..088bcc3 100644 (file)
                        };
 
                        watchdog: watchdog@90060000 {
-                               compatible = "arm,amba-primecell";
+                               compatible = "arm,primecell";
                                reg = <0x90060000 0x1000>;
                                interrupts = <3>;
                        };
index 103e731..1a00d29 100644 (file)
        status = "okay";
 };
 
+&cpu0 {
+       /* CPU rated to 800 MHz, not the default 1.2GHz. */
+       operating-points = <
+               /* kHz   uV */
+               166666  850000
+               400000  900000
+               800000  1050000
+       >;
+};
+
 &ecspi1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_ecspi1>;
index 2873369..3659fd5 100644 (file)
                                reg = <0x020ca000 0x1000>;
                                interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SLL_CLK_USBPHY2>;
-                               phy-reg_3p0-supply = <&reg_3p0>;
+                               phy-3p0-supply = <&reg_3p0>;
                                fsl,anatop = <&anatop>;
                        };
 
index bfbaa2d..d1c5508 100644 (file)
@@ -197,7 +197,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=y
 CONFIG_FSCACHE=y
index 821d966..05ea717 100644 (file)
@@ -232,7 +232,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_XFS_FS=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index b0f0baa..53b1d41 100644 (file)
@@ -327,7 +327,7 @@ CONFIG_PWM_SAMSUNG=y
 CONFIG_PHY_EXYNOS5250_SATA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index 87c4893..c9f4594 100644 (file)
@@ -94,7 +94,7 @@ CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_EXT2_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_MSDOS_FS=m
index 0570669..0a90583 100644 (file)
@@ -442,7 +442,7 @@ CONFIG_EXT3_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index d7a0bca..1cb1456 100644 (file)
@@ -207,7 +207,7 @@ CONFIG_RESET_TI_SYSCON=m
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_FANOTIFY=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
index d7df048..e2b0ff0 100644 (file)
@@ -162,7 +162,7 @@ CONFIG_MAX517=y
 CONFIG_PWM=y
 CONFIG_PWM_LPC32XX=y
 CONFIG_EXT2_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index 385ad0f..7d42845 100644 (file)
@@ -81,7 +81,7 @@ CONFIG_SOC_BRCMSTB=y
 CONFIG_MEMORY=y
 # CONFIG_ARM_PMU is not set
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
index f0800f8..c7b2550 100644 (file)
@@ -1226,7 +1226,7 @@ CONFIG_COUNTER=m
 CONFIG_STM32_TIMER_CNT=m
 CONFIG_STM32_LPTIMER_CNT=m
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
index 53dd071..7c2cc7a 100644 (file)
@@ -188,7 +188,7 @@ CONFIG_RTC_DRV_OMAP=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_DNOTIFY is not set
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_MSDOS_FS=y
index 9bd36dd..b685018 100644 (file)
@@ -678,7 +678,7 @@ CONFIG_EXT4_FS_SECURITY=y
 CONFIG_FANOTIFY=y
 CONFIG_QUOTA=y
 CONFIG_QFMT_V2=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index b46e393..b0c3355 100644 (file)
@@ -589,7 +589,7 @@ CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_CUSE=m
 CONFIG_FSCACHE=y
index 65a3fde..b1d12a2 100644 (file)
@@ -79,7 +79,7 @@ CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8583=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_MSDOS_FS=m
index 4c1e480..72df854 100644 (file)
@@ -103,7 +103,7 @@ CONFIG_PHY_SAMSUNG_USB2=m
 CONFIG_PHY_S5PV210_USB2=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index 70739e0..d6dfae1 100644 (file)
@@ -136,7 +136,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT3_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_NTFS_FS=y
 CONFIG_NTFS_RW=y
index bfde0c8..c8128a6 100644 (file)
@@ -85,7 +85,7 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_SECURITY=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=y
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
index a96ed5c..97ea2e9 100644 (file)
@@ -68,7 +68,7 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_SECURITY=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
index 3e2c2ab..a7a3413 100644 (file)
@@ -54,7 +54,7 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_SECURITY=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT3_FS_SECURITY=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=m
 CONFIG_FAT_DEFAULT_IOCHARSET="ascii"
index 20e4cab..623167f 100644 (file)
@@ -105,5 +105,4 @@ void sharpsl_pm_led(int val);
 #define MAX1111_ACIN_VOLT   6u
 int sharpsl_pm_pxa_read_max1111(int channel);
 
-void corgi_lcd_limit_intensity(int limit);
 #endif
index 1c021ce..8bc4ea5 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/apm-emulation.h>
+#include <linux/spi/corgi_lcd.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
index 38ae674..3037f58 100644 (file)
        status = "okay";
        clock-frequency = <100000>;
        i2c-sda-falling-time-ns = <890>;  /* hcnt */
-       i2c-sdl-falling-time-ns = <890>;  /* lcnt */
+       i2c-scl-falling-time-ns = <890>;  /* lcnt */
 
        pinctrl-names = "default", "gpio";
        pinctrl-0 = <&i2c1_pmx_func>;
index ede99dc..f4cf30b 100644 (file)
        status = "okay";
        clock-frequency = <100000>;
        i2c-sda-falling-time-ns = <890>;  /* hcnt */
-       i2c-sdl-falling-time-ns = <890>;  /* lcnt */
+       i2c-scl-falling-time-ns = <890>;  /* lcnt */
 
        adc@14 {
                compatible = "lltc,ltc2497";
diff --git a/arch/arm64/boot/dts/arm/vexpress-v2m-rs1.dtsi b/arch/arm64/boot/dts/arm/vexpress-v2m-rs1.dtsi
deleted file mode 120000 (symlink)
index 68fd0f8..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../arm/boot/dts/vexpress-v2m-rs1.dtsi
\ No newline at end of file
index 03e7679..479948f 100644 (file)
 };
 
 &gpio1 {
-       gpio-line-names = "nINT_ETHPHY", "LED_RED", "WDOG_INT", "X_RTC_INT",
+       gpio-line-names = "", "LED_RED", "WDOG_INT", "X_RTC_INT",
                "", "", "", "RESET_ETHPHY",
                "CAN_nINT", "CAN_EN", "nENABLE_FLATLINK", "",
                "USB_OTG_VBUS_EN", "", "LED_GREEN", "LED_BLUE";
index 92616bc..847f085 100644 (file)
 };
 
 &gpio1 {
-       gpio-line-names = "nINT_ETHPHY", "", "WDOG_INT", "X_RTC_INT",
+       gpio-line-names = "", "", "WDOG_INT", "X_RTC_INT",
                "", "", "", "RESET_ETHPHY",
                "", "", "nENABLE_FLATLINK";
 };
                                };
                        };
 
-                       reg_vdd_gpu: buck3 {
+                       reg_vdd_vpu: buck3 {
                                regulator-always-on;
                                regulator-boot-on;
                                regulator-max-microvolt = <1000000>;
index 6f26914..07b07dc 100644 (file)
        status = "okay";
 };
 
+&disp_blk_ctrl {
+       status = "disabled";
+};
+
 &pgc_mipi {
        status = "disabled";
 };
index 93088fa..d5b7168 100644 (file)
        status = "okay";
 };
 
+&disp_blk_ctrl {
+       status = "disabled";
+};
+
 &pgc_mipi {
        status = "disabled";
 };
index d3a6710..b8946ed 100644 (file)
                        MX8MN_IOMUXC_ENET_RXC_ENET1_RGMII_RXC           0x91
                        MX8MN_IOMUXC_ENET_RX_CTL_ENET1_RGMII_RX_CTL     0x91
                        MX8MN_IOMUXC_ENET_TX_CTL_ENET1_RGMII_TX_CTL     0x1f
-                       MX8MN_IOMUXC_GPIO1_IO09_GPIO1_IO9               0x19
+                       MX8MN_IOMUXC_GPIO1_IO09_GPIO1_IO9               0x159
                >;
        };
 
index 1a2d2c0..01eec42 100644 (file)
                                                                         <&clk IMX8MQ_SYS1_PLL_800M>,
                                                                         <&clk IMX8MQ_VPU_PLL>;
                                                assigned-clock-rates = <600000000>,
-                                                                      <600000000>,
+                                                                      <300000000>,
                                                                       <800000000>,
                                                                       <0>;
                                        };
index 232910e..66f68fc 100644 (file)
                                     <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
                                     <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
                        interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0",
-                                         "tgiv0", "tgie0", "tgif0",
-                                         "tgia1", "tgib1", "tgiv1", "tgiu1",
-                                         "tgia2", "tgib2", "tgiv2", "tgiu2",
+                                         "tciv0", "tgie0", "tgif0",
+                                         "tgia1", "tgib1", "tciv1", "tciu1",
+                                         "tgia2", "tgib2", "tciv2", "tciu2",
                                          "tgia3", "tgib3", "tgic3", "tgid3",
-                                         "tgiv3",
+                                         "tciv3",
                                          "tgia4", "tgib4", "tgic4", "tgid4",
-                                         "tgiv4",
+                                         "tciv4",
                                          "tgiu5", "tgiv5", "tgiw5",
                                          "tgia6", "tgib6", "tgic6", "tgid6",
-                                         "tgiv6",
+                                         "tciv6",
                                          "tgia7", "tgib7", "tgic7", "tgid7",
-                                         "tgiv7",
+                                         "tciv7",
                                          "tgia8", "tgib8", "tgic8", "tgid8",
-                                         "tgiv8", "tgiu8";
+                                         "tciv8", "tciu8";
                        clocks = <&cpg CPG_MOD R9A07G044_MTU_X_MCK_MTU3>;
                        power-domains = <&cpg>;
                        resets = <&cpg R9A07G044_MTU_X_PRESET_MTU3>;
index 2eba3a8..1f1d481 100644 (file)
                                     <GIC_SPI 212 IRQ_TYPE_EDGE_RISING>,
                                     <GIC_SPI 213 IRQ_TYPE_EDGE_RISING>;
                        interrupt-names = "tgia0", "tgib0", "tgic0", "tgid0",
-                                         "tgiv0", "tgie0", "tgif0",
-                                         "tgia1", "tgib1", "tgiv1", "tgiu1",
-                                         "tgia2", "tgib2", "tgiv2", "tgiu2",
+                                         "tciv0", "tgie0", "tgif0",
+                                         "tgia1", "tgib1", "tciv1", "tciu1",
+                                         "tgia2", "tgib2", "tciv2", "tciu2",
                                          "tgia3", "tgib3", "tgic3", "tgid3",
-                                         "tgiv3",
+                                         "tciv3",
                                          "tgia4", "tgib4", "tgic4", "tgid4",
-                                         "tgiv4",
+                                         "tciv4",
                                          "tgiu5", "tgiv5", "tgiw5",
                                          "tgia6", "tgib6", "tgic6", "tgid6",
-                                         "tgiv6",
+                                         "tciv6",
                                          "tgia7", "tgib7", "tgic7", "tgid7",
-                                         "tgiv7",
+                                         "tciv7",
                                          "tgia8", "tgib8", "tgic8", "tgid8",
-                                         "tgiv8", "tgiu8";
+                                         "tciv8", "tciu8";
                        clocks = <&cpg CPG_MOD R9A07G054_MTU_X_MCK_MTU3>;
                        power-domains = <&cpg>;
                        resets = <&cpg R9A07G054_MTU_X_PRESET_MTU3>;
index 0777bca..a25d783 100644 (file)
@@ -1469,7 +1469,7 @@ CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_FANOTIFY=y
 CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
 CONFIG_QUOTA=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=m
 CONFIG_CUSE=m
 CONFIG_OVERLAY_FS=m
index 8b60967..d3dd05b 100644 (file)
@@ -727,6 +727,8 @@ struct kvm_vcpu_arch {
 #define DBG_SS_ACTIVE_PENDING  __vcpu_single_flag(sflags, BIT(5))
 /* PMUSERENR for the guest EL0 is on physical CPU */
 #define PMUSERENR_ON_CPU       __vcpu_single_flag(sflags, BIT(6))
+/* WFI instruction trapped */
+#define IN_WFI                 __vcpu_single_flag(sflags, BIT(7))
 
 
 /* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
index 8294a9a..929d355 100644 (file)
@@ -608,22 +608,26 @@ int kvm_pgtable_stage2_wrprotect(struct kvm_pgtable *pgt, u64 addr, u64 size);
 kvm_pte_t kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr);
 
 /**
- * kvm_pgtable_stage2_mkold() - Clear the access flag in a page-table entry.
+ * kvm_pgtable_stage2_test_clear_young() - Test and optionally clear the access
+ *                                        flag in a page-table entry.
  * @pgt:       Page-table structure initialised by kvm_pgtable_stage2_init*().
  * @addr:      Intermediate physical address to identify the page-table entry.
+ * @size:      Size of the address range to visit.
+ * @mkold:     True if the access flag should be cleared.
  *
  * The offset of @addr within a page is ignored.
  *
- * If there is a valid, leaf page-table entry used to translate @addr, then
- * clear the access flag in that entry.
+ * Tests and conditionally clears the access flag for every valid, leaf
+ * page-table entry used to translate the range [@addr, @addr + @size).
  *
  * Note that it is the caller's responsibility to invalidate the TLB after
  * calling this function to ensure that the updated permissions are visible
  * to the CPUs.
  *
- * Return: The old page-table entry prior to clearing the flag, 0 on failure.
+ * Return: True if any of the visited PTEs had the access flag set.
  */
-kvm_pte_t kvm_pgtable_stage2_mkold(struct kvm_pgtable *pgt, u64 addr);
+bool kvm_pgtable_stage2_test_clear_young(struct kvm_pgtable *pgt, u64 addr,
+                                        u64 size, bool mkold);
 
 /**
  * kvm_pgtable_stage2_relax_perms() - Relax the permissions enforced by a
@@ -646,18 +650,6 @@ int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
                                   enum kvm_pgtable_prot prot);
 
 /**
- * kvm_pgtable_stage2_is_young() - Test whether a page-table entry has the
- *                                access flag set.
- * @pgt:       Page-table structure initialised by kvm_pgtable_stage2_init*().
- * @addr:      Intermediate physical address to identify the page-table entry.
- *
- * The offset of @addr within a page is ignored.
- *
- * Return: True if the page-table entry has the access flag set, false otherwise.
- */
-bool kvm_pgtable_stage2_is_young(struct kvm_pgtable *pgt, u64 addr);
-
-/**
  * kvm_pgtable_stage2_flush_range() - Clean and invalidate data cache to Point
  *                                   of Coherency for guest stage-2 address
  *                                   range.
index 5227db7..261d6e9 100644 (file)
@@ -78,6 +78,7 @@ extern u32 __boot_cpu_mode[2];
 
 void __hyp_set_vectors(phys_addr_t phys_vector_base);
 void __hyp_reset_vectors(void);
+bool is_kvm_arm_initialised(void);
 
 DECLARE_STATIC_KEY_FALSE(kvm_protected_mode_initialized);
 
index 7a1aeb9..520b681 100644 (file)
@@ -847,6 +847,8 @@ void sve_sync_from_fpsimd_zeropad(struct task_struct *task)
 int vec_set_vector_length(struct task_struct *task, enum vec_type type,
                          unsigned long vl, unsigned long flags)
 {
+       bool free_sme = false;
+
        if (flags & ~(unsigned long)(PR_SVE_VL_INHERIT |
                                     PR_SVE_SET_VL_ONEXEC))
                return -EINVAL;
@@ -897,24 +899,39 @@ int vec_set_vector_length(struct task_struct *task, enum vec_type type,
                task->thread.fp_type = FP_STATE_FPSIMD;
        }
 
-       if (system_supports_sme() && type == ARM64_VEC_SME) {
-               task->thread.svcr &= ~(SVCR_SM_MASK |
-                                      SVCR_ZA_MASK);
-               clear_thread_flag(TIF_SME);
+       if (system_supports_sme()) {
+               if (type == ARM64_VEC_SME ||
+                   !(task->thread.svcr & (SVCR_SM_MASK | SVCR_ZA_MASK))) {
+                       /*
+                        * We are changing the SME VL or weren't using
+                        * SME anyway, discard the state and force a
+                        * reallocation.
+                        */
+                       task->thread.svcr &= ~(SVCR_SM_MASK |
+                                              SVCR_ZA_MASK);
+                       clear_thread_flag(TIF_SME);
+                       free_sme = true;
+               }
        }
 
        if (task == current)
                put_cpu_fpsimd_context();
 
+       task_set_vl(task, type, vl);
+
        /*
-        * Force reallocation of task SVE and SME state to the correct
-        * size on next use:
+        * Free the changed states if they are not in use, SME will be
+        * reallocated to the correct size on next use and we just
+        * allocate SVE now in case it is needed for use in streaming
+        * mode.
         */
-       sve_free(task);
-       if (system_supports_sme() && type == ARM64_VEC_SME)
-               sme_free(task);
+       if (system_supports_sve()) {
+               sve_free(task);
+               sve_alloc(task, true);
+       }
 
-       task_set_vl(task, type, vl);
+       if (free_sme)
+               sme_free(task);
 
 out:
        update_tsk_thread_flag(task, vec_vl_inherit_flag(type),
@@ -1649,7 +1666,6 @@ void fpsimd_flush_thread(void)
 
                fpsimd_flush_thread_vl(ARM64_VEC_SME);
                current->thread.svcr = 0;
-               sme_smstop();
        }
 
        current->thread.fp_type = FP_STATE_FPSIMD;
index 4236cf3..9941c5b 100644 (file)
@@ -6,6 +6,10 @@
  *
  */
 
+int __kernel_clock_gettime(clockid_t clock, struct __kernel_timespec *ts);
+int __kernel_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz);
+int __kernel_clock_getres(clockid_t clock_id, struct __kernel_timespec *res);
+
 int __kernel_clock_gettime(clockid_t clock,
                           struct __kernel_timespec *ts)
 {
index 0696732..6dcdae4 100644 (file)
@@ -827,8 +827,8 @@ static void timer_set_traps(struct kvm_vcpu *vcpu, struct timer_map *map)
        assign_clear_set_bit(tpt, CNTHCTL_EL1PCEN << 10, set, clr);
        assign_clear_set_bit(tpc, CNTHCTL_EL1PCTEN << 10, set, clr);
 
-       /* This only happens on VHE, so use the CNTKCTL_EL1 accessor */
-       sysreg_clear_set(cntkctl_el1, clr, set);
+       /* This only happens on VHE, so use the CNTHCTL_EL2 accessor. */
+       sysreg_clear_set(cnthctl_el2, clr, set);
 }
 
 void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu)
@@ -1563,7 +1563,7 @@ no_vgic:
 void kvm_timer_init_vhe(void)
 {
        if (cpus_have_final_cap(ARM64_HAS_ECV_CNTPOFF))
-               sysreg_clear_set(cntkctl_el1, 0, CNTHCTL_ECV);
+               sysreg_clear_set(cnthctl_el2, 0, CNTHCTL_ECV);
 }
 
 int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr)
index c2c1405..72dc53a 100644 (file)
@@ -53,11 +53,16 @@ DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
 
 DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
 
-static bool vgic_present;
+static bool vgic_present, kvm_arm_initialised;
 
 static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
 DEFINE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
+bool is_kvm_arm_initialised(void)
+{
+       return kvm_arm_initialised;
+}
+
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE;
@@ -713,13 +718,15 @@ void kvm_vcpu_wfi(struct kvm_vcpu *vcpu)
         */
        preempt_disable();
        kvm_vgic_vmcr_sync(vcpu);
-       vgic_v4_put(vcpu, true);
+       vcpu_set_flag(vcpu, IN_WFI);
+       vgic_v4_put(vcpu);
        preempt_enable();
 
        kvm_vcpu_halt(vcpu);
        vcpu_clear_flag(vcpu, IN_WFIT);
 
        preempt_disable();
+       vcpu_clear_flag(vcpu, IN_WFI);
        vgic_v4_load(vcpu);
        preempt_enable();
 }
@@ -787,7 +794,7 @@ static int check_vcpu_requests(struct kvm_vcpu *vcpu)
                if (kvm_check_request(KVM_REQ_RELOAD_GICv4, vcpu)) {
                        /* The distributor enable bits were changed */
                        preempt_disable();
-                       vgic_v4_put(vcpu, false);
+                       vgic_v4_put(vcpu);
                        vgic_v4_load(vcpu);
                        preempt_enable();
                }
@@ -1867,8 +1874,17 @@ static void _kvm_arch_hardware_enable(void *discard)
 
 int kvm_arch_hardware_enable(void)
 {
-       int was_enabled = __this_cpu_read(kvm_arm_hardware_enabled);
+       int was_enabled;
+
+       /*
+        * Most calls to this function are made with migration
+        * disabled, but not with preemption disabled. The former is
+        * enough to ensure correctness, but most of the helpers
+        * expect the later and will throw a tantrum otherwise.
+        */
+       preempt_disable();
 
+       was_enabled = __this_cpu_read(kvm_arm_hardware_enabled);
        _kvm_arch_hardware_enable(NULL);
 
        if (!was_enabled) {
@@ -1876,6 +1892,8 @@ int kvm_arch_hardware_enable(void)
                kvm_timer_cpu_up();
        }
 
+       preempt_enable();
+
        return 0;
 }
 
@@ -2482,6 +2500,8 @@ static __init int kvm_arm_init(void)
        if (err)
                goto out_subs;
 
+       kvm_arm_initialised = true;
+
        return 0;
 
 out_subs:
index 8f3f93f..03f97d7 100644 (file)
@@ -154,6 +154,12 @@ SYM_CODE_END(\label)
        esb
        stp     x0, x1, [sp, #-16]!
 662:
+       /*
+        * spectre vectors __bp_harden_hyp_vecs generate br instructions at runtime
+        * that jump at offset 8 at __kvm_hyp_vector.
+        * As hyp .text is guarded section, it needs bti j.
+        */
+       bti j
        b       \target
 
 check_preamble_length 661b, 662b
@@ -165,6 +171,8 @@ check_preamble_length 661b, 662b
        nop
        stp     x0, x1, [sp, #-16]!
 662:
+       /* Check valid_vect */
+       bti j
        b       \target
 
 check_preamble_length 661b, 662b
index c87c631..7693a67 100644 (file)
@@ -297,3 +297,13 @@ SYM_CODE_START(__kvm_hyp_host_forward_smc)
 
        ret
 SYM_CODE_END(__kvm_hyp_host_forward_smc)
+
+/*
+ * kvm_host_psci_cpu_entry is called through br instruction, which requires
+ * bti j instruction as compilers (gcc and llvm) doesn't insert bti j for external
+ * functions, but bti c instead.
+ */
+SYM_CODE_START(kvm_host_psci_cpu_entry)
+       bti j
+       b __kvm_host_psci_cpu_entry
+SYM_CODE_END(kvm_host_psci_cpu_entry)
index 0850878..24543d2 100644 (file)
@@ -200,7 +200,7 @@ static int psci_system_suspend(u64 func_id, struct kvm_cpu_context *host_ctxt)
                         __hyp_pa(init_params), 0);
 }
 
-asmlinkage void __noreturn kvm_host_psci_cpu_entry(bool is_cpu_on)
+asmlinkage void __noreturn __kvm_host_psci_cpu_entry(bool is_cpu_on)
 {
        struct psci_boot_args *boot_args;
        struct kvm_cpu_context *host_ctxt;
index aa740a9..f7a93ef 100644 (file)
@@ -1195,25 +1195,54 @@ kvm_pte_t kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr)
        return pte;
 }
 
-kvm_pte_t kvm_pgtable_stage2_mkold(struct kvm_pgtable *pgt, u64 addr)
+struct stage2_age_data {
+       bool    mkold;
+       bool    young;
+};
+
+static int stage2_age_walker(const struct kvm_pgtable_visit_ctx *ctx,
+                            enum kvm_pgtable_walk_flags visit)
 {
-       kvm_pte_t pte = 0;
-       stage2_update_leaf_attrs(pgt, addr, 1, 0, KVM_PTE_LEAF_ATTR_LO_S2_AF,
-                                &pte, NULL, 0);
+       kvm_pte_t new = ctx->old & ~KVM_PTE_LEAF_ATTR_LO_S2_AF;
+       struct stage2_age_data *data = ctx->arg;
+
+       if (!kvm_pte_valid(ctx->old) || new == ctx->old)
+               return 0;
+
+       data->young = true;
+
+       /*
+        * stage2_age_walker() is always called while holding the MMU lock for
+        * write, so this will always succeed. Nonetheless, this deliberately
+        * follows the race detection pattern of the other stage-2 walkers in
+        * case the locking mechanics of the MMU notifiers is ever changed.
+        */
+       if (data->mkold && !stage2_try_set_pte(ctx, new))
+               return -EAGAIN;
+
        /*
         * "But where's the TLBI?!", you scream.
         * "Over in the core code", I sigh.
         *
         * See the '->clear_flush_young()' callback on the KVM mmu notifier.
         */
-       return pte;
+       return 0;
 }
 
-bool kvm_pgtable_stage2_is_young(struct kvm_pgtable *pgt, u64 addr)
+bool kvm_pgtable_stage2_test_clear_young(struct kvm_pgtable *pgt, u64 addr,
+                                        u64 size, bool mkold)
 {
-       kvm_pte_t pte = 0;
-       stage2_update_leaf_attrs(pgt, addr, 1, 0, 0, &pte, NULL, 0);
-       return pte & KVM_PTE_LEAF_ATTR_LO_S2_AF;
+       struct stage2_age_data data = {
+               .mkold          = mkold,
+       };
+       struct kvm_pgtable_walker walker = {
+               .cb             = stage2_age_walker,
+               .arg            = &data,
+               .flags          = KVM_PGTABLE_WALK_LEAF,
+       };
+
+       WARN_ON(kvm_pgtable_walk(pgt, addr, size, &walker));
+       return data.young;
 }
 
 int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
index 6db9ef2..d3b4fee 100644 (file)
@@ -1756,27 +1756,25 @@ bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 bool kvm_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        u64 size = (range->end - range->start) << PAGE_SHIFT;
-       kvm_pte_t kpte;
-       pte_t pte;
 
        if (!kvm->arch.mmu.pgt)
                return false;
 
-       WARN_ON(size != PAGE_SIZE && size != PMD_SIZE && size != PUD_SIZE);
-
-       kpte = kvm_pgtable_stage2_mkold(kvm->arch.mmu.pgt,
-                                       range->start << PAGE_SHIFT);
-       pte = __pte(kpte);
-       return pte_valid(pte) && pte_young(pte);
+       return kvm_pgtable_stage2_test_clear_young(kvm->arch.mmu.pgt,
+                                                  range->start << PAGE_SHIFT,
+                                                  size, true);
 }
 
 bool kvm_test_age_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
+       u64 size = (range->end - range->start) << PAGE_SHIFT;
+
        if (!kvm->arch.mmu.pgt)
                return false;
 
-       return kvm_pgtable_stage2_is_young(kvm->arch.mmu.pgt,
-                                          range->start << PAGE_SHIFT);
+       return kvm_pgtable_stage2_test_clear_young(kvm->arch.mmu.pgt,
+                                                  range->start << PAGE_SHIFT,
+                                                  size, false);
 }
 
 phys_addr_t kvm_mmu_get_httbr(void)
index 994a494..6ff3ec1 100644 (file)
@@ -244,7 +244,7 @@ static int __init finalize_pkvm(void)
 {
        int ret;
 
-       if (!is_protected_kvm_enabled())
+       if (!is_protected_kvm_enabled() || !is_kvm_arm_initialised())
                return 0;
 
        /*
index bd34318..2ca2973 100644 (file)
@@ -986,7 +986,6 @@ static bool access_pmu_evtyper(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
 
        if (p->is_write) {
                kvm_pmu_set_counter_event_type(vcpu, p->regval, idx);
-               __vcpu_sys_reg(vcpu, reg) = p->regval & ARMV8_PMU_EVTYPE_MASK;
                kvm_vcpu_pmu_restore_guest(vcpu);
        } else {
                p->regval = __vcpu_sys_reg(vcpu, reg) & ARMV8_PMU_EVTYPE_MASK;
@@ -1115,18 +1114,19 @@ static bool access_pmuserenr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
        { SYS_DESC(SYS_DBGWCRn_EL1(n)),                                 \
          trap_wcr, reset_wcr, 0, 0,  get_wcr, set_wcr }
 
-#define PMU_SYS_REG(r)                                         \
-       SYS_DESC(r), .reset = reset_pmu_reg, .visibility = pmu_visibility
+#define PMU_SYS_REG(name)                                              \
+       SYS_DESC(SYS_##name), .reset = reset_pmu_reg,                   \
+       .visibility = pmu_visibility
 
 /* Macro to expand the PMEVCNTRn_EL0 register */
 #define PMU_PMEVCNTR_EL0(n)                                            \
-       { PMU_SYS_REG(SYS_PMEVCNTRn_EL0(n)),                            \
+       { PMU_SYS_REG(PMEVCNTRn_EL0(n)),                                \
          .reset = reset_pmevcntr, .get_user = get_pmu_evcntr,          \
          .access = access_pmu_evcntr, .reg = (PMEVCNTR0_EL0 + n), }
 
 /* Macro to expand the PMEVTYPERn_EL0 register */
 #define PMU_PMEVTYPER_EL0(n)                                           \
-       { PMU_SYS_REG(SYS_PMEVTYPERn_EL0(n)),                           \
+       { PMU_SYS_REG(PMEVTYPERn_EL0(n)),                               \
          .reset = reset_pmevtyper,                                     \
          .access = access_pmu_evtyper, .reg = (PMEVTYPER0_EL0 + n), }
 
@@ -2115,9 +2115,9 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_PMBSR_EL1), undef_access },
        /* PMBIDR_EL1 is not trapped */
 
-       { PMU_SYS_REG(SYS_PMINTENSET_EL1),
+       { PMU_SYS_REG(PMINTENSET_EL1),
          .access = access_pminten, .reg = PMINTENSET_EL1 },
-       { PMU_SYS_REG(SYS_PMINTENCLR_EL1),
+       { PMU_SYS_REG(PMINTENCLR_EL1),
          .access = access_pminten, .reg = PMINTENSET_EL1 },
        { SYS_DESC(SYS_PMMIR_EL1), trap_raz_wi },
 
@@ -2164,41 +2164,41 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_CTR_EL0), access_ctr },
        { SYS_DESC(SYS_SVCR), undef_access },
 
-       { PMU_SYS_REG(SYS_PMCR_EL0), .access = access_pmcr,
+       { PMU_SYS_REG(PMCR_EL0), .access = access_pmcr,
          .reset = reset_pmcr, .reg = PMCR_EL0 },
-       { PMU_SYS_REG(SYS_PMCNTENSET_EL0),
+       { PMU_SYS_REG(PMCNTENSET_EL0),
          .access = access_pmcnten, .reg = PMCNTENSET_EL0 },
-       { PMU_SYS_REG(SYS_PMCNTENCLR_EL0),
+       { PMU_SYS_REG(PMCNTENCLR_EL0),
          .access = access_pmcnten, .reg = PMCNTENSET_EL0 },
-       { PMU_SYS_REG(SYS_PMOVSCLR_EL0),
+       { PMU_SYS_REG(PMOVSCLR_EL0),
          .access = access_pmovs, .reg = PMOVSSET_EL0 },
        /*
         * PM_SWINC_EL0 is exposed to userspace as RAZ/WI, as it was
         * previously (and pointlessly) advertised in the past...
         */
-       { PMU_SYS_REG(SYS_PMSWINC_EL0),
+       { PMU_SYS_REG(PMSWINC_EL0),
          .get_user = get_raz_reg, .set_user = set_wi_reg,
          .access = access_pmswinc, .reset = NULL },
-       { PMU_SYS_REG(SYS_PMSELR_EL0),
+       { PMU_SYS_REG(PMSELR_EL0),
          .access = access_pmselr, .reset = reset_pmselr, .reg = PMSELR_EL0 },
-       { PMU_SYS_REG(SYS_PMCEID0_EL0),
+       { PMU_SYS_REG(PMCEID0_EL0),
          .access = access_pmceid, .reset = NULL },
-       { PMU_SYS_REG(SYS_PMCEID1_EL0),
+       { PMU_SYS_REG(PMCEID1_EL0),
          .access = access_pmceid, .reset = NULL },
-       { PMU_SYS_REG(SYS_PMCCNTR_EL0),
+       { PMU_SYS_REG(PMCCNTR_EL0),
          .access = access_pmu_evcntr, .reset = reset_unknown,
          .reg = PMCCNTR_EL0, .get_user = get_pmu_evcntr},
-       { PMU_SYS_REG(SYS_PMXEVTYPER_EL0),
+       { PMU_SYS_REG(PMXEVTYPER_EL0),
          .access = access_pmu_evtyper, .reset = NULL },
-       { PMU_SYS_REG(SYS_PMXEVCNTR_EL0),
+       { PMU_SYS_REG(PMXEVCNTR_EL0),
          .access = access_pmu_evcntr, .reset = NULL },
        /*
         * PMUSERENR_EL0 resets as unknown in 64bit mode while it resets as zero
         * in 32bit mode. Here we choose to reset it as zero for consistency.
         */
-       { PMU_SYS_REG(SYS_PMUSERENR_EL0), .access = access_pmuserenr,
+       { PMU_SYS_REG(PMUSERENR_EL0), .access = access_pmuserenr,
          .reset = reset_val, .reg = PMUSERENR_EL0, .val = 0 },
-       { PMU_SYS_REG(SYS_PMOVSSET_EL0),
+       { PMU_SYS_REG(PMOVSSET_EL0),
          .access = access_pmovs, .reg = PMOVSSET_EL0 },
 
        { SYS_DESC(SYS_TPIDR_EL0), NULL, reset_unknown, TPIDR_EL0 },
@@ -2354,7 +2354,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
         * PMCCFILTR_EL0 resets as unknown in 64bit mode while it resets as zero
         * in 32bit mode. Here we choose to reset it as zero for consistency.
         */
-       { PMU_SYS_REG(SYS_PMCCFILTR_EL0), .access = access_pmu_evtyper,
+       { PMU_SYS_REG(PMCCFILTR_EL0), .access = access_pmu_evtyper,
          .reset = reset_val, .reg = PMCCFILTR_EL0, .val = 0 },
 
        EL2_REG(VPIDR_EL2, access_rw, reset_unknown, 0),
index c3b8e13..3dfc8b8 100644 (file)
@@ -749,7 +749,7 @@ void vgic_v3_put(struct kvm_vcpu *vcpu)
 {
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
 
-       WARN_ON(vgic_v4_put(vcpu, false));
+       WARN_ON(vgic_v4_put(vcpu));
 
        vgic_v3_vmcr_sync(vcpu);
 
index c1c28fe..339a551 100644 (file)
@@ -336,14 +336,14 @@ void vgic_v4_teardown(struct kvm *kvm)
        its_vm->vpes = NULL;
 }
 
-int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db)
+int vgic_v4_put(struct kvm_vcpu *vcpu)
 {
        struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
 
        if (!vgic_supports_direct_msis(vcpu->kvm) || !vpe->resident)
                return 0;
 
-       return its_make_vpe_non_resident(vpe, need_db);
+       return its_make_vpe_non_resident(vpe, !!vcpu_get_flag(vcpu, IN_WFI));
 }
 
 int vgic_v4_load(struct kvm_vcpu *vcpu)
@@ -354,6 +354,9 @@ int vgic_v4_load(struct kvm_vcpu *vcpu)
        if (!vgic_supports_direct_msis(vcpu->kvm) || vpe->resident)
                return 0;
 
+       if (vcpu_get_flag(vcpu, IN_WFI))
+               return 0;
+
        /*
         * Before making the VPE resident, make sure the redistributor
         * corresponding to our current CPU expects us here. See the
index 4ea2eef..e9ad391 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/bug.h>
 #include <linux/mm.h>
 #include <linux/mmzone.h>
+#include <linux/kfence.h>
 
 static void *trans_alloc(struct trans_pgd_info *info)
 {
@@ -41,7 +42,8 @@ static void _copy_pte(pte_t *dst_ptep, pte_t *src_ptep, unsigned long addr)
                 * the temporary mappings we use during restore.
                 */
                set_pte(dst_ptep, pte_mkwrite(pte));
-       } else if (debug_pagealloc_enabled() && !pte_none(pte)) {
+       } else if ((debug_pagealloc_enabled() ||
+                  is_kfence_address((void *)addr)) && !pte_none(pte)) {
                /*
                 * debug_pagealloc will removed the PTE_VALID bit if
                 * the page isn't in use by the resume kernel. It may have
index 145b540..ec21748 100644 (file)
@@ -322,7 +322,13 @@ static int build_prologue(struct jit_ctx *ctx, bool ebpf_from_cbpf)
         *
         */
 
-       emit_bti(A64_BTI_C, ctx);
+       /* bpf function may be invoked by 3 instruction types:
+        * 1. bl, attached via freplace to bpf prog via short jump
+        * 2. br, attached via freplace to bpf prog via long jump
+        * 3. blr, working as a function pointer, used by emit_call.
+        * So BTI_JC should used here to support both br and blr.
+        */
+       emit_bti(A64_BTI_JC, ctx);
 
        emit(A64_MOV(1, A64_R(9), A64_LR), ctx);
        emit(A64_NOP, ctx);
index 1ea4a3d..65866bf 100644 (file)
@@ -2017,7 +2017,7 @@ Field     0       SM
 EndSysreg
 
 SysregFields   HFGxTR_EL2
-Field  63      nAMIAIR2_EL1
+Field  63      nAMAIR2_EL1
 Field  62      nMAIR2_EL1
 Field  61      nS2POR_EL1
 Field  60      nPOR_EL1
@@ -2032,9 +2032,9 @@ Field     52      nGCS_EL0
 Res0   51
 Field  50      nACCDATA_EL1
 Field  49      ERXADDR_EL1
-Field  48      EXRPFGCDN_EL1
-Field  47      EXPFGCTL_EL1
-Field  46      EXPFGF_EL1
+Field  48      ERXPFGCDN_EL1
+Field  47      ERXPFGCTL_EL1
+Field  46      ERXPFGF_EL1
 Field  45      ERXMISCn_EL1
 Field  44      ERXSTATUS_EL1
 Field  43      ERXCTLR_EL1
@@ -2049,8 +2049,8 @@ Field     35      TPIDR_EL0
 Field  34      TPIDRRO_EL0
 Field  33      TPIDR_EL1
 Field  32      TCR_EL1
-Field  31      SCTXNUM_EL0
-Field  30      SCTXNUM_EL1
+Field  31      SCXTNUM_EL0
+Field  30      SCXTNUM_EL1
 Field  29      SCTLR_EL1
 Field  28      REVIDR_EL1
 Field  27      PAR_EL1
index 3e1337a..7cb96db 100644 (file)
@@ -77,7 +77,7 @@ CONFIG_EXT3_FS=y
 CONFIG_XFS_FS=y
 CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
index f8033ba..4581240 100644 (file)
@@ -146,7 +146,7 @@ CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
index ffebe6c..c9e8066 100644 (file)
@@ -127,7 +127,7 @@ CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
index 45f5d6e..d7d8fb5 100644 (file)
@@ -110,7 +110,7 @@ CONFIG_REISERFS_FS_XATTR=y
 CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
index 6e948d0..eb561cc 100644 (file)
@@ -63,7 +63,7 @@ arch_get_unmapped_area (struct file *filp, unsigned long addr, unsigned long len
        info.low_limit = addr;
        info.high_limit = TASK_SIZE;
        info.align_mask = align_mask;
-       info.align_offset = 0;
+       info.align_offset = pgoff << PAGE_SHIFT;
        return vm_unmapped_area(&info);
 }
 
index e55511a..e71d5bf 100644 (file)
@@ -14,6 +14,7 @@ config LOONGARCH
        select ARCH_HAS_CPU_FINALIZE_INIT
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
+       select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE
        select ARCH_HAS_PTE_SPECIAL
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_INLINE_READ_LOCK if !PREEMPTION
index 09ba338..b1e5db5 100644 (file)
@@ -68,6 +68,8 @@ LDFLAGS_vmlinux                       += -static -n -nostdlib
 ifdef CONFIG_AS_HAS_EXPLICIT_RELOCS
 cflags-y                       += $(call cc-option,-mexplicit-relocs)
 KBUILD_CFLAGS_KERNEL           += $(call cc-option,-mdirect-extern-access)
+KBUILD_AFLAGS_MODULE           += $(call cc-option,-mno-relax) $(call cc-option,-Wa$(comma)-mno-relax)
+KBUILD_CFLAGS_MODULE           += $(call cc-option,-mno-relax) $(call cc-option,-Wa$(comma)-mno-relax)
 else
 cflags-y                       += $(call cc-option,-mno-explicit-relocs)
 KBUILD_AFLAGS_KERNEL           += -Wa,-mla-global-with-pcrel
@@ -111,7 +113,7 @@ KBUILD_CFLAGS += -isystem $(shell $(CC) -print-file-name=include)
 
 KBUILD_LDFLAGS += -m $(ld-emul)
 
-ifdef CONFIG_LOONGARCH
+ifdef need-compiler
 CHECKFLAGS += $(shell $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \
        grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \
        sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')
index 6cd26dd..d64849b 100644 (file)
@@ -769,7 +769,7 @@ CONFIG_QUOTA=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
 CONFIG_QFMT_V1=m
 CONFIG_QFMT_V2=m
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=m
 CONFIG_OVERLAY_FS=y
 CONFIG_OVERLAY_FS_INDEX=y
index e4193d6..b541f62 100644 (file)
@@ -218,15 +218,8 @@ static inline void restore_lsx(struct task_struct *t)
 
 static inline void init_lsx_upper(void)
 {
-       /*
-        * Check cpu_has_lsx only if it's a constant. This will allow the
-        * compiler to optimise out code for CPUs without LSX without adding
-        * an extra redundant check for CPUs with LSX.
-        */
-       if (__builtin_constant_p(cpu_has_lsx) && !cpu_has_lsx)
-               return;
-
-       _init_lsx_upper();
+       if (cpu_has_lsx)
+               _init_lsx_upper();
 }
 
 static inline void restore_lsx_upper(struct task_struct *t)
@@ -294,7 +287,7 @@ static inline void restore_lasx_upper(struct task_struct *t) {}
 
 static inline int thread_lsx_context_live(void)
 {
-       if (__builtin_constant_p(cpu_has_lsx) && !cpu_has_lsx)
+       if (!cpu_has_lsx)
                return 0;
 
        return test_thread_flag(TIF_LSX_CTX_LIVE);
@@ -302,7 +295,7 @@ static inline int thread_lsx_context_live(void)
 
 static inline int thread_lasx_context_live(void)
 {
-       if (__builtin_constant_p(cpu_has_lasx) && !cpu_has_lasx)
+       if (!cpu_has_lasx)
                return 0;
 
        return test_thread_flag(TIF_LASX_CTX_LIVE);
index 78a0035..9d830ab 100644 (file)
@@ -332,9 +332,25 @@ static void __init bootcmdline_init(char **cmdline_p)
                        strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
 
                strlcat(boot_command_line, init_command_line, COMMAND_LINE_SIZE);
+               goto out;
        }
 #endif
 
+       /*
+        * Append built-in command line to the bootloader command line if
+        * CONFIG_CMDLINE_EXTEND is enabled.
+        */
+       if (IS_ENABLED(CONFIG_CMDLINE_EXTEND) && CONFIG_CMDLINE[0]) {
+               strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+       }
+
+       /*
+        * Use built-in command line if the bootloader command line is empty.
+        */
+       if (IS_ENABLED(CONFIG_CMDLINE_BOOTLOADER) && !boot_command_line[0])
+               strscpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+
 out:
        *cmdline_p = boot_command_line;
 }
index fd1d62b..9dcf717 100644 (file)
@@ -108,6 +108,7 @@ SYM_FUNC_START(__clear_user_fast)
        addi.d  a3, a2, -8
        bgeu    a0, a3, .Llt8
 15:    st.d    zero, a0, 0
+       addi.d  a0, a0, 8
 
 .Llt8:
 16:    st.d    zero, a2, -8
@@ -188,7 +189,7 @@ SYM_FUNC_START(__clear_user_fast)
        _asm_extable 13b, .L_fixup_handle_0
        _asm_extable 14b, .L_fixup_handle_1
        _asm_extable 15b, .L_fixup_handle_0
-       _asm_extable 16b, .L_fixup_handle_1
+       _asm_extable 16b, .L_fixup_handle_0
        _asm_extable 17b, .L_fixup_handle_s0
        _asm_extable 18b, .L_fixup_handle_s0
        _asm_extable 19b, .L_fixup_handle_s0
index b21f6d5..fecd08c 100644 (file)
@@ -136,6 +136,7 @@ SYM_FUNC_START(__copy_user_fast)
        bgeu    a1, a4, .Llt8
 30:    ld.d    t0, a1, 0
 31:    st.d    t0, a0, 0
+       addi.d  a0, a0, 8
 
 .Llt8:
 32:    ld.d    t0, a3, -8
@@ -246,7 +247,7 @@ SYM_FUNC_START(__copy_user_fast)
        _asm_extable 30b, .L_fixup_handle_0
        _asm_extable 31b, .L_fixup_handle_0
        _asm_extable 32b, .L_fixup_handle_0
-       _asm_extable 33b, .L_fixup_handle_1
+       _asm_extable 33b, .L_fixup_handle_0
        _asm_extable 34b, .L_fixup_handle_s0
        _asm_extable 35b, .L_fixup_handle_s0
        _asm_extable 36b, .L_fixup_handle_s0
index c335dc4..6858633 100644 (file)
@@ -150,7 +150,7 @@ static inline void move_imm(struct jit_ctx *ctx, enum loongarch_gpr rd, long imm
                         * no need to call lu32id to do a new filled operation.
                         */
                        imm_51_31 = (imm >> 31) & 0x1fffff;
-                       if (imm_51_31 != 0 || imm_51_31 != 0x1fffff) {
+                       if (imm_51_31 != 0 && imm_51_31 != 0x1fffff) {
                                /* lu32id rd, imm_51_32 */
                                imm_51_32 = (imm >> 32) & 0xfffff;
                                emit_insn(ctx, lu32id, rd, imm_51_32);
index 439395a..081922c 100644 (file)
@@ -499,13 +499,13 @@ in_ea:
        dbf     %d0,morein
        rts
 
-       .section .fixup,#alloc,#execinstr
+       .section .fixup,"ax"
        .even
 1:
        jbsr    fpsp040_die
        jbra    .Lnotkern
 
-       .section __ex_table,#alloc
+       .section __ex_table,"a"
        .align  4
 
        .long   in_ea,1b
index 7a0d6e4..89e2ec2 100644 (file)
@@ -379,11 +379,11 @@ _060_real_access:
 
 
 | Execption handling for movs access to illegal memory
-       .section .fixup,#alloc,#execinstr
+       .section .fixup,"ax"
        .even
 1:     moveq           #-1,%d1
        rts
-.section __ex_table,#alloc
+.section __ex_table,"a"
        .align 4
        .long   dmrbuae,1b
        .long   dmrwuae,1b
index ab0f1e7..f766707 100644 (file)
@@ -26,7 +26,7 @@ ENTRY(relocate_new_kernel)
        lea %pc@(.Lcopy),%a4
 2:     addl #0x00000000,%a4            /* virt_to_phys() */
 
-       .section ".m68k_fixup","aw"
+       .section .m68k_fixup,"aw"
        .long M68K_FIXUP_MEMOFFSET, 2b+2
        .previous
 
@@ -49,7 +49,7 @@ ENTRY(relocate_new_kernel)
        lea %pc@(.Lcont040),%a4
 5:     addl #0x00000000,%a4            /* virt_to_phys() */
 
-       .section ".m68k_fixup","aw"
+       .section .m68k_fixup,"aw"
        .long M68K_FIXUP_MEMOFFSET, 5b+2
        .previous
 
index b0cbfa7..e463a9a 100644 (file)
@@ -153,7 +153,7 @@ CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
 CONFIG_QFMT_V2=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 5458573..1843468 100644 (file)
@@ -178,7 +178,7 @@ CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
 CONFIG_REISERFS_FS=m
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 897e555..44821f4 100644 (file)
@@ -245,7 +245,7 @@ CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
 CONFIG_QFMT_V2=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 418a418..930c5f6 100644 (file)
@@ -95,7 +95,7 @@ CONFIG_EXT3_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QFMT_V1=m
 CONFIG_QFMT_V2=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 6b5d7e9..fdf3745 100644 (file)
@@ -76,7 +76,7 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=m
 CONFIG_XFS_QUOTA=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 7e598d3..83d9a8f 100644 (file)
@@ -240,7 +240,7 @@ CONFIG_XFS_POSIX_ACL=y
 CONFIG_BTRFS_FS=m
 CONFIG_QUOTA=y
 CONFIG_QFMT_V2=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FSCACHE=m
 CONFIG_CACHEFILES=m
 CONFIG_ISO9660_FS=m
index 0ab029e..ec3ee8d 100644 (file)
@@ -296,7 +296,7 @@ CONFIG_XFS_QUOTA=y
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_QUOTA=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 3087e64..1294263 100644 (file)
@@ -352,7 +352,7 @@ CONFIG_QUOTA=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
 CONFIG_QFMT_V1=m
 CONFIG_QFMT_V2=m
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=m
 CONFIG_VIRTIO_FS=m
 CONFIG_FSCACHE=m
index b641721..935585d 100644 (file)
@@ -601,7 +601,7 @@ CONFIG_EXT3_FS=m
 CONFIG_EXT3_FS_POSIX_ACL=y
 CONFIG_EXT3_FS_SECURITY=y
 CONFIG_QUOTA=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 8397f28..0e494c2 100644 (file)
@@ -66,7 +66,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_FSCACHE=m
 CONFIG_ISO9660_FS=m
index 7475c2c..e0e312d 100644 (file)
@@ -317,7 +317,7 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=m
 CONFIG_XFS_QUOTA=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
index 9651f43..ee4febb 100644 (file)
@@ -237,7 +237,7 @@ CONFIG_EXT3_FS_SECURITY=y
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_VFAT_FS=y
index 6758c03..f6ded71 100644 (file)
@@ -259,7 +259,7 @@ CONFIG_BTRFS_FS=m
 CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V2=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=y
 CONFIG_ISO9660_FS=y
index 9915062..ca2d537 100644 (file)
 #include <linux/elf-randomize.h>
 
 /*
- * Construct an artificial page offset for the mapping based on the physical
+ * Construct an artificial page offset for the mapping based on the virtual
  * address of the kernel file mapping variable.
+ * If filp is zero the calculated pgoff value aliases the memory of the given
+ * address. This is useful for io_uring where the mapping shall alias a kernel
+ * address and a userspace adress where both the kernel and the userspace
+ * access the same memory region.
  */
-#define GET_FILP_PGOFF(filp)           \
-       (filp ? (((unsigned long) filp->f_mapping) >> 8)        \
-                & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL)
+#define GET_FILP_PGOFF(filp, addr)             \
+       ((filp ? (((unsigned long) filp->f_mapping) >> 8)       \
+                & ((SHM_COLOUR-1) >> PAGE_SHIFT) : 0UL)        \
+         + (addr >> PAGE_SHIFT))
 
 static unsigned long shared_align_offset(unsigned long filp_pgoff,
                                         unsigned long pgoff)
@@ -112,7 +117,7 @@ static unsigned long arch_get_unmapped_area_common(struct file *filp,
        do_color_align = 0;
        if (filp || (flags & MAP_SHARED))
                do_color_align = 1;
-       filp_pgoff = GET_FILP_PGOFF(filp);
+       filp_pgoff = GET_FILP_PGOFF(filp, addr);
 
        if (flags & MAP_FIXED) {
                /* Even MAP_FIXED mappings must reside within TASK_SIZE */
index ef09786..51499ee 100644 (file)
@@ -79,7 +79,7 @@ CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
index ecbcc85..e708049 100644 (file)
@@ -50,7 +50,7 @@ CONFIG_DRM=m
 CONFIG_SOUND=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=m
index 06391cc..53f43a3 100644 (file)
@@ -172,7 +172,7 @@ CONFIG_EDAC_CELL=y
 CONFIG_UIO=m
 CONFIG_EXT2_FS=y
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
index b9dfa3a..0d8d3f4 100644 (file)
@@ -47,7 +47,7 @@ CONFIG_SERIAL_CPM_CONSOLE=y
 # CONFIG_USB_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_CRAMFS=y
index ce220ce..2101bfe 100644 (file)
@@ -60,7 +60,7 @@ CONFIG_USB_FSL_USB2=y
 CONFIG_USB_G_SERIAL=y
 CONFIG_UIO=y
 CONFIG_EXT2_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
index 96aa535..6199394 100644 (file)
@@ -143,7 +143,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT4_FS=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_UDF_FS=y
 CONFIG_MSDOS_FS=y
index 019163c..05ed585 100644 (file)
@@ -254,7 +254,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
index e02ab94..ee84ade 100644 (file)
@@ -270,7 +270,7 @@ CONFIG_BTRFS_FS=m
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_NILFS2_FS=m
 CONFIG_FANOTIFY=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_OVERLAY_FS=m
 CONFIG_ISO9660_FS=y
index 268fa36..c0f4bbc 100644 (file)
@@ -327,7 +327,7 @@ CONFIG_BTRFS_FS=m
 CONFIG_BTRFS_FS_POSIX_ACL=y
 CONFIG_NILFS2_FS=m
 CONFIG_FS_DAX=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_OVERLAY_FS=m
 CONFIG_ISO9660_FS=y
index 776c329..624c371 100644 (file)
@@ -185,7 +185,7 @@ CONFIG_JFS_SECURITY=y
 CONFIG_XFS_FS=m
 CONFIG_XFS_POSIX_ACL=y
 CONFIG_FS_DAX=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=y
 CONFIG_UDF_FS=m
 CONFIG_MSDOS_FS=y
index f21170b..1034aea 100644 (file)
@@ -969,7 +969,7 @@ CONFIG_XFS_POSIX_ACL=y
 CONFIG_GFS2_FS=m
 CONFIG_FS_DAX=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
index ea3ee07..1ea732c 100644 (file)
@@ -129,7 +129,7 @@ CONFIG_EXT2_FS=m
 CONFIG_EXT4_FS=y
 CONFIG_QUOTA=y
 CONFIG_QFMT_V2=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_UDF_FS=m
diff --git a/arch/powerpc/crypto/.gitignore b/arch/powerpc/crypto/.gitignore
new file mode 100644 (file)
index 0000000..e1094f0
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+aesp10-ppc.S
+ghashp10-ppc.S
index ef42adb..00c6b0b 100644 (file)
@@ -4,14 +4,13 @@
 #ifdef __KERNEL__
 
 #include <asm/asm-compat.h>
-#include <asm/extable.h>
 
 #ifdef CONFIG_BUG
 
 #ifdef __ASSEMBLY__
 #include <asm/asm-offsets.h>
 #ifdef CONFIG_DEBUG_BUGVERBOSE
-.macro __EMIT_BUG_ENTRY addr,file,line,flags
+.macro EMIT_BUG_ENTRY addr,file,line,flags
         .section __bug_table,"aw"
 5001:   .4byte \addr - .
         .4byte 5002f - .
@@ -23,7 +22,7 @@
         .previous
 .endm
 #else
-.macro __EMIT_BUG_ENTRY addr,file,line,flags
+.macro EMIT_BUG_ENTRY addr,file,line,flags
         .section __bug_table,"aw"
 5001:   .4byte \addr - .
         .short \flags
 .endm
 #endif /* verbose */
 
-.macro EMIT_WARN_ENTRY addr,file,line,flags
-       EX_TABLE(\addr,\addr+4)
-       __EMIT_BUG_ENTRY \addr,\file,\line,\flags
-.endm
-
-.macro EMIT_BUG_ENTRY addr,file,line,flags
-       .if \flags & 1 /* BUGFLAG_WARNING */
-       .err /* Use EMIT_WARN_ENTRY for warnings */
-       .endif
-       __EMIT_BUG_ENTRY \addr,\file,\line,\flags
-.endm
-
 #else /* !__ASSEMBLY__ */
 /* _EMIT_BUG_ENTRY expects args %0,%1,%2,%3 to be FILE, LINE, flags and
    sizeof(struct bug_entry), respectively */
                  "i" (sizeof(struct bug_entry)),       \
                  ##__VA_ARGS__)
 
-#define WARN_ENTRY(insn, flags, label, ...)            \
-       asm_volatile_goto(                              \
-               "1:     " insn "\n"                     \
-               EX_TABLE(1b, %l[label])                 \
-               _EMIT_BUG_ENTRY                         \
-               : : "i" (__FILE__), "i" (__LINE__),     \
-                 "i" (flags),                          \
-                 "i" (sizeof(struct bug_entry)),       \
-                 ##__VA_ARGS__ : : label)
-
 /*
  * BUG_ON() and WARN_ON() do their best to cooperate with compile-time
  * optimisations. However depending on the complexity of the condition
 } while (0)
 #define HAVE_ARCH_BUG
 
-#define __WARN_FLAGS(flags) do {                               \
-       __label__ __label_warn_on;                              \
-                                                               \
-       WARN_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags), __label_warn_on); \
-       barrier_before_unreachable();                           \
-       __builtin_unreachable();                                \
-                                                               \
-__label_warn_on:                                               \
-       break;                                                  \
-} while (0)
+#define __WARN_FLAGS(flags) BUG_ENTRY("twi 31, 0, 0", BUGFLAG_WARNING | (flags))
 
 #ifdef CONFIG_PPC64
 #define BUG_ON(x) do {                                         \
@@ -117,25 +85,15 @@ __label_warn_on:                                           \
 } while (0)
 
 #define WARN_ON(x) ({                                          \
-       bool __ret_warn_on = false;                             \
-       do {                                                    \
-               if (__builtin_constant_p((x))) {                \
-                       if (!(x))                               \
-                               break;                          \
+       int __ret_warn_on = !!(x);                              \
+       if (__builtin_constant_p(__ret_warn_on)) {              \
+               if (__ret_warn_on)                              \
                        __WARN();                               \
-                       __ret_warn_on = true;                   \
-               } else {                                        \
-                       __label__ __label_warn_on;              \
-                                                               \
-                       WARN_ENTRY(PPC_TLNEI " %4, 0",          \
-                                  BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN), \
-                                  __label_warn_on,             \
-                                  "r" ((__force long)(x)));    \
-                       break;                                  \
-__label_warn_on:                                               \
-                       __ret_warn_on = true;                   \
-               }                                               \
-       } while (0);                                            \
+       } else {                                                \
+               BUG_ENTRY(PPC_TLNEI " %4, 0",                   \
+                         BUGFLAG_WARNING | BUGFLAG_TAINT(TAINT_WARN),  \
+                         "r" (__ret_warn_on)); \
+       }                                                       \
        unlikely(__ret_warn_on);                                \
 })
 
@@ -148,14 +106,13 @@ __label_warn_on:                                          \
 #ifdef __ASSEMBLY__
 .macro EMIT_BUG_ENTRY addr,file,line,flags
 .endm
-.macro EMIT_WARN_ENTRY addr,file,line,flags
-.endm
 #else /* !__ASSEMBLY__ */
 #define _EMIT_BUG_ENTRY
-#define _EMIT_WARN_ENTRY
 #endif
 #endif /* CONFIG_BUG */
 
+#define EMIT_WARN_ENTRY EMIT_BUG_ENTRY
+
 #include <asm-generic/bug.h>
 
 #ifndef __ASSEMBLY__
index a26ca09..79f1c48 100644 (file)
 
 /*
  * This is used to ensure we don't load something for the wrong architecture.
- * 64le only supports ELFv2 64-bit binaries (64be supports v1 and v2).
  */
-#if defined(CONFIG_PPC64) && defined(CONFIG_CPU_LITTLE_ENDIAN)
-#define elf_check_arch(x) (((x)->e_machine == ELF_ARCH) && \
-                          (((x)->e_flags & 0x3) == 0x2))
-#else
 #define elf_check_arch(x) ((x)->e_machine == ELF_ARCH)
-#endif
 #define compat_elf_check_arch(x)       ((x)->e_machine == EM_PPC)
 
 #define CORE_DUMP_USE_REGSET
index bc5d39a..bf5dde1 100644 (file)
@@ -183,13 +183,9 @@ static inline bool test_thread_local_flags(unsigned int flags)
 #define clear_tsk_compat_task(tsk) do { } while (0)
 #endif
 
-#ifdef CONFIG_PPC64
-#ifdef CONFIG_CPU_BIG_ENDIAN
+#if defined(CONFIG_PPC64)
 #define is_elf2_task() (test_thread_flag(TIF_ELF2ABI))
 #else
-#define is_elf2_task() (1)
-#endif
-#else
 #define is_elf2_task() (0)
 #endif
 
index 46c31fb..30a12d2 100644 (file)
@@ -34,7 +34,7 @@ static inline long find_zero(unsigned long mask)
        return leading_zero_bits >> 3;
 }
 
-static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
+static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
 {
        unsigned long rhs = val | c->low_bits;
        *data = rhs;
index e59ec6d..7ef147e 100644 (file)
@@ -1508,13 +1508,8 @@ static void do_program_check(struct pt_regs *regs)
 
                if (!(regs->msr & MSR_PR) &&  /* not user-mode */
                    report_bug(bugaddr, regs) == BUG_TRAP_TYPE_WARN) {
-                       const struct exception_table_entry *entry;
-
-                       entry = search_exception_tables(bugaddr);
-                       if (entry) {
-                               regs_set_return_ip(regs, extable_fixup(entry) + regs->nip - bugaddr);
-                               return;
-                       }
+                       regs_add_return_ip(regs, 4);
+                       return;
                }
 
                if (cpu_has_feature(CPU_FTR_DEXCR_NPHIE) && user_mode(regs)) {
index 699eeff..f9522fd 100644 (file)
@@ -1,6 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 
 KASAN_SANITIZE := n
+KCOV_INSTRUMENT := n
 
 obj-$(CONFIG_PPC32)            += init_32.o
 obj-$(CONFIG_PPC_8xx)          += 8xx.o
index 1bfb295..c1e9816 100644 (file)
@@ -477,7 +477,7 @@ static int mpc512x_lpbfifo_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int mpc512x_lpbfifo_remove(struct platform_device *pdev)
+static void mpc512x_lpbfifo_remove(struct platform_device *pdev)
 {
        unsigned long flags;
        struct dma_device *dma_dev = lpbfifo.chan->device;
@@ -494,8 +494,6 @@ static int mpc512x_lpbfifo_remove(struct platform_device *pdev)
        free_irq(lpbfifo.irq, &pdev->dev);
        irq_dispose_mapping(lpbfifo.irq);
        dma_release_channel(lpbfifo.chan);
-
-       return 0;
 }
 
 static const struct of_device_id mpc512x_lpbfifo_match[] = {
@@ -506,7 +504,7 @@ MODULE_DEVICE_TABLE(of, mpc512x_lpbfifo_match);
 
 static struct platform_driver mpc512x_lpbfifo_driver = {
        .probe = mpc512x_lpbfifo_probe,
-       .remove = mpc512x_lpbfifo_remove,
+       .remove_new = mpc512x_lpbfifo_remove,
        .driver = {
                .name = DRV_NAME,
                .of_match_table = mpc512x_lpbfifo_match,
index 9a44a98..3fbc2a6 100644 (file)
@@ -744,6 +744,12 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
                }
 
                task_ref = &win->vas_win.task_ref;
+               /*
+                * VAS mmap (coproc_mmap()) and its fault handler
+                * (vas_mmap_fault()) are called after holding mmap lock.
+                * So hold mmap mutex after mmap_lock to avoid deadlock.
+                */
+               mmap_write_lock(task_ref->mm);
                mutex_lock(&task_ref->mmap_mutex);
                vma = task_ref->vma;
                /*
@@ -752,7 +758,6 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
                 */
                win->vas_win.status |= flag;
 
-               mmap_write_lock(task_ref->mm);
                /*
                 * vma is set in the original mapping. But this mapping
                 * is done with mmap() after the window is opened with ioctl.
@@ -762,8 +767,8 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
                if (vma)
                        zap_vma_pages(vma);
 
-               mmap_write_unlock(task_ref->mm);
                mutex_unlock(&task_ref->mmap_mutex);
+               mmap_write_unlock(task_ref->mm);
                /*
                 * Close VAS window in the hypervisor, but do not
                 * free vas_window struct since it may be reused
index 0a01074..ab86ec3 100644 (file)
@@ -192,7 +192,7 @@ CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_EXT4_FS_SECURITY=y
 CONFIG_BTRFS_FS=m
 CONFIG_BTRFS_FS_POSIX_ACL=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_OVERLAY_FS=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
index 38760e4..89b601e 100644 (file)
@@ -98,7 +98,7 @@ CONFIG_RPMSG_CTRL=y
 CONFIG_RPMSG_VIRTIO=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index aa95cf6..3a6a9a8 100644 (file)
@@ -116,7 +116,6 @@ CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=m
 CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=m
-CONFIG_NET_TC_SKB_EXT=y
 CONFIG_SMC=m
 CONFIG_SMC_DIAG=m
 CONFIG_INET=y
@@ -193,6 +192,7 @@ CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NFT_HASH=m
 CONFIG_NFT_FIB_INET=m
+CONFIG_NETFILTER_XTABLES_COMPAT=y
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -379,6 +379,7 @@ CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
 CONFIG_NET_ACT_GATE=m
+CONFIG_NET_TC_SKB_EXT=y
 CONFIG_DNS_RESOLVER=y
 CONFIG_OPENVSWITCH=m
 CONFIG_VSOCKETS=m
@@ -395,6 +396,7 @@ CONFIG_HOTPLUG_PCI=y
 CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_SAFE=y
+# CONFIG_FW_LOADER is not set
 CONFIG_CONNECTOR=y
 CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=m
@@ -502,7 +504,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_GOOGLE is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_LITEX is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
@@ -542,6 +543,7 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_TI is not set
 # CONFIG_NET_VENDOR_VERTEXCOM is not set
 # CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_NET_VENDOR_XILINX is not set
 CONFIG_PPP=m
@@ -624,7 +626,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QUOTA_DEBUG=y
 CONFIG_QFMT_V1=m
 CONFIG_QFMT_V2=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=m
 CONFIG_VIRTIO_FS=m
@@ -646,7 +648,6 @@ CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_TMPFS_INODE64=y
 CONFIG_HUGETLBFS=y
-CONFIG_CONFIGFS_FS=m
 CONFIG_ECRYPT_FS=m
 CONFIG_CRAMFS=m
 CONFIG_SQUASHFS=m
@@ -690,7 +691,6 @@ CONFIG_HARDENED_USERCOPY=y
 CONFIG_FORTIFY_SOURCE=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_SECURITY_LOCKDOWN_LSM=y
 CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
 CONFIG_SECURITY_LANDLOCK=y
@@ -744,7 +744,6 @@ CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_SM3_GENERIC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_WP512=m
@@ -844,6 +843,7 @@ CONFIG_PREEMPT_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
 CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_USER_EVENTS=y
 CONFIG_HIST_TRIGGERS=y
 CONFIG_FTRACE_STARTUP_TEST=y
 # CONFIG_EVENT_TRACE_STARTUP_TEST is not set
@@ -866,6 +866,7 @@ CONFIG_FAIL_MAKE_REQUEST=y
 CONFIG_FAIL_IO_TIMEOUT=y
 CONFIG_FAIL_FUTEX=y
 CONFIG_FAULT_INJECTION_DEBUG_FS=y
+CONFIG_FAULT_INJECTION_CONFIGFS=y
 CONFIG_FAULT_INJECTION_STACKTRACE_FILTER=y
 CONFIG_LKDTM=m
 CONFIG_TEST_MIN_HEAP=y
index f041945..b13a5a0 100644 (file)
@@ -107,7 +107,6 @@ CONFIG_UNIX=y
 CONFIG_UNIX_DIAG=m
 CONFIG_XFRM_USER=m
 CONFIG_NET_KEY=m
-CONFIG_NET_TC_SKB_EXT=y
 CONFIG_SMC=m
 CONFIG_SMC_DIAG=m
 CONFIG_INET=y
@@ -184,6 +183,7 @@ CONFIG_NFT_REJECT=m
 CONFIG_NFT_COMPAT=m
 CONFIG_NFT_HASH=m
 CONFIG_NFT_FIB_INET=m
+CONFIG_NETFILTER_XTABLES_COMPAT=y
 CONFIG_NETFILTER_XT_SET=m
 CONFIG_NETFILTER_XT_TARGET_AUDIT=m
 CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
@@ -369,6 +369,7 @@ CONFIG_NET_ACT_SIMP=m
 CONFIG_NET_ACT_SKBEDIT=m
 CONFIG_NET_ACT_CSUM=m
 CONFIG_NET_ACT_GATE=m
+CONFIG_NET_TC_SKB_EXT=y
 CONFIG_DNS_RESOLVER=y
 CONFIG_OPENVSWITCH=m
 CONFIG_VSOCKETS=m
@@ -385,6 +386,7 @@ CONFIG_HOTPLUG_PCI_S390=y
 CONFIG_UEVENT_HELPER=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_SAFE=y
+# CONFIG_FW_LOADER is not set
 CONFIG_CONNECTOR=y
 CONFIG_ZRAM=y
 CONFIG_BLK_DEV_LOOP=m
@@ -492,7 +494,6 @@ CONFIG_NLMON=m
 # CONFIG_NET_VENDOR_GOOGLE is not set
 # CONFIG_NET_VENDOR_HUAWEI is not set
 # CONFIG_NET_VENDOR_INTEL is not set
-# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_LITEX is not set
 # CONFIG_NET_VENDOR_MARVELL is not set
 CONFIG_MLX4_EN=m
@@ -532,6 +533,7 @@ CONFIG_MLX5_CORE_EN=y
 # CONFIG_NET_VENDOR_TI is not set
 # CONFIG_NET_VENDOR_VERTEXCOM is not set
 # CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WANGXUN is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 # CONFIG_NET_VENDOR_XILINX is not set
 CONFIG_PPP=m
@@ -609,7 +611,7 @@ CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 CONFIG_QFMT_V1=m
 CONFIG_QFMT_V2=m
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=m
 CONFIG_VIRTIO_FS=m
@@ -673,7 +675,6 @@ CONFIG_SECURITY=y
 CONFIG_SECURITY_NETWORK=y
 CONFIG_SECURITY_SELINUX=y
 CONFIG_SECURITY_SELINUX_BOOTPARAM=y
-CONFIG_SECURITY_SELINUX_DISABLE=y
 CONFIG_SECURITY_LOCKDOWN_LSM=y
 CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y
 CONFIG_SECURITY_LANDLOCK=y
@@ -729,7 +730,6 @@ CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_RMD160=m
-CONFIG_CRYPTO_SHA3=m
 CONFIG_CRYPTO_SM3_GENERIC=m
 CONFIG_CRYPTO_VMAC=m
 CONFIG_CRYPTO_WP512=m
@@ -793,6 +793,7 @@ CONFIG_STACK_TRACER=y
 CONFIG_SCHED_TRACER=y
 CONFIG_FTRACE_SYSCALLS=y
 CONFIG_BLK_DEV_IO_TRACE=y
+CONFIG_USER_EVENTS=y
 CONFIG_HIST_TRIGGERS=y
 CONFIG_SAMPLES=y
 CONFIG_SAMPLE_TRACE_PRINTK=m
index 6f68b39..e62fb20 100644 (file)
@@ -53,7 +53,6 @@ CONFIG_ZFCP=y
 # CONFIG_HVC_IUCV is not set
 # CONFIG_HW_RANDOM_S390 is not set
 # CONFIG_HMC_DRV is not set
-# CONFIG_S390_UV_UAPI is not set
 # CONFIG_S390_TAPE is not set
 # CONFIG_VMCP is not set
 # CONFIG_MONWRITER is not set
index d29a9d9..3834915 100644 (file)
@@ -103,7 +103,7 @@ static inline void _free_kb_keybuf(struct key_blob *kb)
 {
        if (kb->key && kb->key != kb->keybuf
            && kb->keylen > sizeof(kb->keybuf)) {
-               kfree(kb->key);
+               kfree_sensitive(kb->key);
                kb->key = NULL;
        }
 }
index f0fe3bc..bb08260 100644 (file)
@@ -8,6 +8,8 @@
 #ifndef _UAPI_S390_PTRACE_H
 #define _UAPI_S390_PTRACE_H
 
+#include <linux/const.h>
+
 /*
  * Offsets in the user_regs_struct. They are used for the ptrace
  * system call and in entry.S
index 4d141e2..2ea7f20 100644 (file)
@@ -459,9 +459,9 @@ static int sthyi_update_cache(u64 *rc)
  *
  * Fills the destination with system information returned by the STHYI
  * instruction. The data is generated by emulation or execution of STHYI,
- * if available. The return value is the condition code that would be
- * returned, the rc parameter is the return code which is passed in
- * register R2 + 1.
+ * if available. The return value is either a negative error value or
+ * the condition code that would be returned, the rc parameter is the
+ * return code which is passed in register R2 + 1.
  */
 int sthyi_fill(void *dst, u64 *rc)
 {
index 954d39a..341abaf 100644 (file)
@@ -389,8 +389,8 @@ static int handle_partial_execution(struct kvm_vcpu *vcpu)
  */
 int handle_sthyi(struct kvm_vcpu *vcpu)
 {
-       int reg1, reg2, r = 0;
-       u64 code, addr, cc = 0, rc = 0;
+       int reg1, reg2, cc = 0, r = 0;
+       u64 code, addr, rc = 0;
        struct sthyi_sctns *sctns = NULL;
 
        if (!test_kvm_facility(vcpu->kvm, 74))
@@ -421,7 +421,10 @@ int handle_sthyi(struct kvm_vcpu *vcpu)
                return -ENOMEM;
 
        cc = sthyi_fill(sctns, &rc);
-
+       if (cc < 0) {
+               free_page((unsigned long)sctns);
+               return cc;
+       }
 out:
        if (!cc) {
                if (kvm_s390_pv_cpu_is_protected(vcpu)) {
index 2f34c7c..bf1fdc7 100644 (file)
@@ -411,8 +411,12 @@ int kvm_s390_pv_deinit_cleanup_all(struct kvm *kvm, u16 *rc, u16 *rrc)
        u16 _rc, _rrc;
        int cc = 0;
 
-       /* Make sure the counter does not reach 0 before calling s390_uv_destroy_range */
-       atomic_inc(&kvm->mm->context.protected_count);
+       /*
+        * Nothing to do if the counter was already 0. Otherwise make sure
+        * the counter does not reach 0 before calling s390_uv_destroy_range.
+        */
+       if (!atomic_inc_not_zero(&kvm->mm->context.protected_count))
+               return 0;
 
        *rc = 1;
        /* If the current VM is protected, destroy it */
index dbe8394..2f12342 100644 (file)
@@ -421,6 +421,8 @@ static inline vm_fault_t do_exception(struct pt_regs *regs, int access)
        vma_end_read(vma);
        if (!(fault & VM_FAULT_RETRY)) {
                count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
+               if (likely(!(fault & VM_FAULT_ERROR)))
+                       fault = 0;
                goto out;
        }
        count_vm_vma_lock_event(VMA_LOCK_RETRY);
index 989ebd0..9c8af31 100644 (file)
@@ -2853,6 +2853,7 @@ int s390_replace_asce(struct gmap *gmap)
        page = alloc_pages(GFP_KERNEL_ACCOUNT, CRST_ALLOC_ORDER);
        if (!page)
                return -ENOMEM;
+       page->index = 0;
        table = page_to_virt(page);
        memcpy(table, gmap->table, 1UL << (CRST_ALLOC_ORDER + PAGE_SHIFT));
 
index b266492..24a6667 100644 (file)
@@ -763,6 +763,8 @@ void __init vmem_map_init(void)
        if (static_key_enabled(&cpu_has_bear))
                set_memory_nx(0, 1);
        set_memory_nx(PAGE_SIZE, 1);
+       if (debug_pagealloc_enabled())
+               set_memory_4k(0, ident_map_size >> PAGE_SHIFT);
 
        pr_info("Write protected kernel read-only data: %luk\n",
                (unsigned long)(__end_rodata - _stext) >> 10);
index 623012d..67716a4 100644 (file)
@@ -61,7 +61,7 @@ CONFIG_USB_STORAGE=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
index 41cb588..cd24cf0 100644 (file)
@@ -105,7 +105,7 @@ CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
index a080c5d..cf59b98 100644 (file)
@@ -168,7 +168,7 @@ CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS=y
 CONFIG_XFS_FS=y
 CONFIG_BTRFS_FS=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_FUSE_FS=y
 CONFIG_CUSE=m
 CONFIG_FSCACHE=m
index f661ef8..48f38ec 100644 (file)
@@ -60,7 +60,7 @@ CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 CONFIG_EXT3_FS_POSIX_ACL=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
index ae72674..57923c3 100644 (file)
@@ -63,7 +63,7 @@ CONFIG_MMC=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
index 7c489e7..5010164 100644 (file)
@@ -65,7 +65,7 @@ CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_PROC_KCORE=y
 CONFIG_ROMFS_FS=m
index 05ae535..630be79 100644 (file)
@@ -62,7 +62,7 @@ CONFIG_UML_NET_SLIRP=y
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=y
 CONFIG_QUOTA=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_PROC_KCORE=y
index 1c75723..8540d33 100644 (file)
@@ -60,7 +60,7 @@ CONFIG_UML_NET_SLIRP=y
 CONFIG_EXT4_FS=y
 CONFIG_REISERFS_FS=y
 CONFIG_QUOTA=y
-CONFIG_AUTOFS4_FS=m
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=m
 CONFIG_JOLIET=y
 CONFIG_PROC_KCORE=y
index 37d60e7..9e71794 100644 (file)
@@ -3,7 +3,6 @@
  * Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  */
 
-#include <linux/minmax.h>
 #include <unistd.h>
 #include <errno.h>
 #include <fcntl.h>
@@ -51,7 +50,7 @@ static struct pollfds all_sigio_fds;
 
 static int write_sigio_thread(void *unused)
 {
-       struct pollfds *fds;
+       struct pollfds *fds, tmp;
        struct pollfd *p;
        int i, n, respond_fd;
        char c;
@@ -78,7 +77,9 @@ static int write_sigio_thread(void *unused)
                                               "write_sigio_thread : "
                                               "read on socket failed, "
                                               "err = %d\n", errno);
-                               swap(current_poll, next_poll);
+                               tmp = current_poll;
+                               current_poll = next_poll;
+                               next_poll = tmp;
                                respond_fd = sigio_private[1];
                        }
                        else {
index 3cf3491..75a343f 100644 (file)
@@ -245,7 +245,7 @@ CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
 CONFIG_QFMT_V2=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
index 2775923..0902518 100644 (file)
@@ -242,7 +242,7 @@ CONFIG_QUOTA=y
 CONFIG_QUOTA_NETLINK_INTERFACE=y
 # CONFIG_PRINT_QUOTA_WARNING is not set
 CONFIG_QFMT_V2=y
-CONFIG_AUTOFS4_FS=y
+CONFIG_AUTOFS_FS=y
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
index 91f6818..43606de 100644 (file)
@@ -285,7 +285,15 @@ SYM_FUNC_END(__switch_to_asm)
  */
 .pushsection .text, "ax"
 SYM_CODE_START(ret_from_fork_asm)
-       UNWIND_HINT_REGS
+       /*
+        * This is the start of the kernel stack; even through there's a
+        * register set at the top, the regset isn't necessarily coherent
+        * (consider kthreads) and one cannot unwind further.
+        *
+        * This ensures stack unwinds of kernel threads terminate in a known
+        * good state.
+        */
+       UNWIND_HINT_END_OF_STACK
        ANNOTATE_NOENDBR // copy_thread
        CALL_DEPTH_ACCOUNT
 
@@ -295,6 +303,12 @@ SYM_CODE_START(ret_from_fork_asm)
        movq    %r12, %rcx              /* fn_arg */
        call    ret_from_fork
 
+       /*
+        * Set the stack state to what is expected for the target function
+        * -- at this point the register set should be a valid user set
+        * and unwind should work normally.
+        */
+       UNWIND_HINT_REGS
        jmp     swapgs_restore_regs_and_return_to_usermode
 SYM_CODE_END(ret_from_fork_asm)
 .popsection
index 13bc212..e3054e3 100644 (file)
@@ -37,6 +37,7 @@ KVM_X86_OP(get_segment)
 KVM_X86_OP(get_cpl)
 KVM_X86_OP(set_segment)
 KVM_X86_OP(get_cs_db_l_bits)
+KVM_X86_OP(is_valid_cr0)
 KVM_X86_OP(set_cr0)
 KVM_X86_OP_OPTIONAL(post_set_cr3)
 KVM_X86_OP(is_valid_cr4)
index 28bd383..3bc146d 100644 (file)
@@ -1566,9 +1566,10 @@ struct kvm_x86_ops {
        void (*set_segment)(struct kvm_vcpu *vcpu,
                            struct kvm_segment *var, int seg);
        void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
+       bool (*is_valid_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
        void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
        void (*post_set_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3);
-       bool (*is_valid_cr4)(struct kvm_vcpu *vcpu, unsigned long cr0);
+       bool (*is_valid_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
        void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
        int (*set_efer)(struct kvm_vcpu *vcpu, u64 efer);
        void (*get_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
index 320566a..66dbba1 100644 (file)
@@ -5,6 +5,7 @@
 #include <asm/cpu.h>
 #include <linux/earlycpio.h>
 #include <linux/initrd.h>
+#include <asm/microcode_amd.h>
 
 struct ucode_patch {
        struct list_head plist;
index e6662ad..9675c62 100644 (file)
@@ -48,11 +48,13 @@ extern void __init load_ucode_amd_bsp(unsigned int family);
 extern void load_ucode_amd_ap(unsigned int family);
 extern int __init save_microcode_in_initrd_amd(unsigned int family);
 void reload_ucode_amd(unsigned int cpu);
+extern void amd_check_microcode(void);
 #else
 static inline void __init load_ucode_amd_bsp(unsigned int family) {}
 static inline void load_ucode_amd_ap(unsigned int family) {}
 static inline int __init
 save_microcode_in_initrd_amd(unsigned int family) { return -EINVAL; }
 static inline void reload_ucode_amd(unsigned int cpu) {}
+static inline void amd_check_microcode(void) {}
 #endif
 #endif /* _ASM_X86_MICROCODE_AMD_H */
index 3aedae6..a00a53e 100644 (file)
 #define MSR_AMD64_DE_CFG               0xc0011029
 #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT   1
 #define MSR_AMD64_DE_CFG_LFENCE_SERIALIZE      BIT_ULL(MSR_AMD64_DE_CFG_LFENCE_SERIALIZE_BIT)
+#define MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT 9
 
 #define MSR_AMD64_BU_CFG2              0xc001102a
 #define MSR_AMD64_IBSFETCHCTL          0xc0011030
index 571abf8..26ad7ca 100644 (file)
 
 #include "cpu.h"
 
-static const int amd_erratum_383[];
-static const int amd_erratum_400[];
-static const int amd_erratum_1054[];
-static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
-
 /*
  * nodes_per_socket: Stores the number of nodes per socket.
  * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
@@ -39,6 +34,78 @@ static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum);
  */
 static u32 nodes_per_socket = 1;
 
+/*
+ * AMD errata checking
+ *
+ * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or
+ * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
+ * have an OSVW id assigned, which it takes as first argument. Both take a
+ * variable number of family-specific model-stepping ranges created by
+ * AMD_MODEL_RANGE().
+ *
+ * Example:
+ *
+ * const int amd_erratum_319[] =
+ *     AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2),
+ *                        AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0),
+ *                        AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
+ */
+
+#define AMD_LEGACY_ERRATUM(...)                { -1, __VA_ARGS__, 0 }
+#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 }
+#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
+       ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
+#define AMD_MODEL_RANGE_FAMILY(range)  (((range) >> 24) & 0xff)
+#define AMD_MODEL_RANGE_START(range)   (((range) >> 12) & 0xfff)
+#define AMD_MODEL_RANGE_END(range)     ((range) & 0xfff)
+
+static const int amd_erratum_400[] =
+       AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
+                           AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
+
+static const int amd_erratum_383[] =
+       AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
+
+/* #1054: Instructions Retired Performance Counter May Be Inaccurate */
+static const int amd_erratum_1054[] =
+       AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
+
+static const int amd_zenbleed[] =
+       AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x30, 0x0, 0x4f, 0xf),
+                          AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf),
+                          AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf));
+
+static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
+{
+       int osvw_id = *erratum++;
+       u32 range;
+       u32 ms;
+
+       if (osvw_id >= 0 && osvw_id < 65536 &&
+           cpu_has(cpu, X86_FEATURE_OSVW)) {
+               u64 osvw_len;
+
+               rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len);
+               if (osvw_id < osvw_len) {
+                       u64 osvw_bits;
+
+                       rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6),
+                           osvw_bits);
+                       return osvw_bits & (1ULL << (osvw_id & 0x3f));
+               }
+       }
+
+       /* OSVW unavailable or ID unknown, match family-model-stepping range */
+       ms = (cpu->x86_model << 4) | cpu->x86_stepping;
+       while ((range = *erratum++))
+               if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
+                   (ms >= AMD_MODEL_RANGE_START(range)) &&
+                   (ms <= AMD_MODEL_RANGE_END(range)))
+                       return true;
+
+       return false;
+}
+
 static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
 {
        u32 gprs[8] = { 0 };
@@ -916,6 +983,47 @@ static void init_amd_zn(struct cpuinfo_x86 *c)
        }
 }
 
+static bool cpu_has_zenbleed_microcode(void)
+{
+       u32 good_rev = 0;
+
+       switch (boot_cpu_data.x86_model) {
+       case 0x30 ... 0x3f: good_rev = 0x0830107a; break;
+       case 0x60 ... 0x67: good_rev = 0x0860010b; break;
+       case 0x68 ... 0x6f: good_rev = 0x08608105; break;
+       case 0x70 ... 0x7f: good_rev = 0x08701032; break;
+       case 0xa0 ... 0xaf: good_rev = 0x08a00008; break;
+
+       default:
+               return false;
+               break;
+       }
+
+       if (boot_cpu_data.microcode < good_rev)
+               return false;
+
+       return true;
+}
+
+static void zenbleed_check(struct cpuinfo_x86 *c)
+{
+       if (!cpu_has_amd_erratum(c, amd_zenbleed))
+               return;
+
+       if (cpu_has(c, X86_FEATURE_HYPERVISOR))
+               return;
+
+       if (!cpu_has(c, X86_FEATURE_AVX))
+               return;
+
+       if (!cpu_has_zenbleed_microcode()) {
+               pr_notice_once("Zenbleed: please update your microcode for the most optimal fix\n");
+               msr_set_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
+       } else {
+               msr_clear_bit(MSR_AMD64_DE_CFG, MSR_AMD64_DE_CFG_ZEN2_FP_BACKUP_FIX_BIT);
+       }
+}
+
 static void init_amd(struct cpuinfo_x86 *c)
 {
        early_init_amd(c);
@@ -1020,6 +1128,8 @@ static void init_amd(struct cpuinfo_x86 *c)
        if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
            cpu_has(c, X86_FEATURE_AUTOIBRS))
                WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS));
+
+       zenbleed_check(c);
 }
 
 #ifdef CONFIG_X86_32
@@ -1115,73 +1225,6 @@ static const struct cpu_dev amd_cpu_dev = {
 
 cpu_dev_register(amd_cpu_dev);
 
-/*
- * AMD errata checking
- *
- * Errata are defined as arrays of ints using the AMD_LEGACY_ERRATUM() or
- * AMD_OSVW_ERRATUM() macros. The latter is intended for newer errata that
- * have an OSVW id assigned, which it takes as first argument. Both take a
- * variable number of family-specific model-stepping ranges created by
- * AMD_MODEL_RANGE().
- *
- * Example:
- *
- * const int amd_erratum_319[] =
- *     AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0x4, 0x2),
- *                        AMD_MODEL_RANGE(0x10, 0x8, 0x0, 0x8, 0x0),
- *                        AMD_MODEL_RANGE(0x10, 0x9, 0x0, 0x9, 0x0));
- */
-
-#define AMD_LEGACY_ERRATUM(...)                { -1, __VA_ARGS__, 0 }
-#define AMD_OSVW_ERRATUM(osvw_id, ...) { osvw_id, __VA_ARGS__, 0 }
-#define AMD_MODEL_RANGE(f, m_start, s_start, m_end, s_end) \
-       ((f << 24) | (m_start << 16) | (s_start << 12) | (m_end << 4) | (s_end))
-#define AMD_MODEL_RANGE_FAMILY(range)  (((range) >> 24) & 0xff)
-#define AMD_MODEL_RANGE_START(range)   (((range) >> 12) & 0xfff)
-#define AMD_MODEL_RANGE_END(range)     ((range) & 0xfff)
-
-static const int amd_erratum_400[] =
-       AMD_OSVW_ERRATUM(1, AMD_MODEL_RANGE(0xf, 0x41, 0x2, 0xff, 0xf),
-                           AMD_MODEL_RANGE(0x10, 0x2, 0x1, 0xff, 0xf));
-
-static const int amd_erratum_383[] =
-       AMD_OSVW_ERRATUM(3, AMD_MODEL_RANGE(0x10, 0, 0, 0xff, 0xf));
-
-/* #1054: Instructions Retired Performance Counter May Be Inaccurate */
-static const int amd_erratum_1054[] =
-       AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0, 0, 0x2f, 0xf));
-
-static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
-{
-       int osvw_id = *erratum++;
-       u32 range;
-       u32 ms;
-
-       if (osvw_id >= 0 && osvw_id < 65536 &&
-           cpu_has(cpu, X86_FEATURE_OSVW)) {
-               u64 osvw_len;
-
-               rdmsrl(MSR_AMD64_OSVW_ID_LENGTH, osvw_len);
-               if (osvw_id < osvw_len) {
-                       u64 osvw_bits;
-
-                       rdmsrl(MSR_AMD64_OSVW_STATUS + (osvw_id >> 6),
-                           osvw_bits);
-                       return osvw_bits & (1ULL << (osvw_id & 0x3f));
-               }
-       }
-
-       /* OSVW unavailable or ID unknown, match family-model-stepping range */
-       ms = (cpu->x86_model << 4) | cpu->x86_stepping;
-       while ((range = *erratum++))
-               if ((cpu->x86 == AMD_MODEL_RANGE_FAMILY(range)) &&
-                   (ms >= AMD_MODEL_RANGE_START(range)) &&
-                   (ms <= AMD_MODEL_RANGE_END(range)))
-                       return true;
-
-       return false;
-}
-
 static DEFINE_PER_CPU_READ_MOSTLY(unsigned long[4], amd_dr_addr_mask);
 
 static unsigned int amd_msr_dr_addr_masks[] = {
@@ -1235,3 +1278,15 @@ u32 amd_get_highest_perf(void)
        return 255;
 }
 EXPORT_SYMBOL_GPL(amd_get_highest_perf);
+
+static void zenbleed_check_cpu(void *unused)
+{
+       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+
+       zenbleed_check(c);
+}
+
+void amd_check_microcode(void)
+{
+       on_each_cpu(zenbleed_check_cpu, NULL, 1);
+}
index 9e2a918..9550744 100644 (file)
@@ -1150,19 +1150,21 @@ spectre_v2_user_select_mitigation(void)
        }
 
        /*
-        * If no STIBP, enhanced IBRS is enabled, or SMT impossible, STIBP
+        * If no STIBP, Intel enhanced IBRS is enabled, or SMT impossible, STIBP
         * is not required.
         *
-        * Enhanced IBRS also protects against cross-thread branch target
+        * Intel's Enhanced IBRS also protects against cross-thread branch target
         * injection in user-mode as the IBRS bit remains always set which
         * implicitly enables cross-thread protections.  However, in legacy IBRS
         * mode, the IBRS bit is set only on kernel entry and cleared on return
-        * to userspace. This disables the implicit cross-thread protection,
-        * so allow for STIBP to be selected in that case.
+        * to userspace.  AMD Automatic IBRS also does not protect userspace.
+        * These modes therefore disable the implicit cross-thread protection,
+        * so allow for STIBP to be selected in those cases.
         */
        if (!boot_cpu_has(X86_FEATURE_STIBP) ||
            !smt_possible ||
-           spectre_v2_in_eibrs_mode(spectre_v2_enabled))
+           (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
+            !boot_cpu_has(X86_FEATURE_AUTOIBRS)))
                return;
 
        /*
@@ -2294,7 +2296,8 @@ static ssize_t mmio_stale_data_show_state(char *buf)
 
 static char *stibp_state(void)
 {
-       if (spectre_v2_in_eibrs_mode(spectre_v2_enabled))
+       if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
+           !boot_cpu_has(X86_FEATURE_AUTOIBRS))
                return "";
 
        switch (spectre_v2_user_stibp) {
index 52683fd..0ba1067 100644 (file)
@@ -2287,6 +2287,8 @@ void microcode_check(struct cpuinfo_x86 *prev_info)
 
        perf_check_microcode();
 
+       amd_check_microcode();
+
        store_cpu_caps(&curr_info);
 
        if (!memcmp(&prev_info->x86_capability, &curr_info.x86_capability,
index 5e74610..c4ec4ca 100644 (file)
@@ -1261,10 +1261,10 @@ static void __threshold_remove_blocks(struct threshold_bank *b)
        struct threshold_block *pos = NULL;
        struct threshold_block *tmp = NULL;
 
-       kobject_del(b->kobj);
+       kobject_put(b->kobj);
 
        list_for_each_entry_safe(pos, tmp, &b->blocks->miscj, miscj)
-               kobject_del(&pos->kobj);
+               kobject_put(b->kobj);
 }
 
 static void threshold_remove_bank(struct threshold_bank *bank)
index 58b1f20..4a817d2 100644 (file)
@@ -697,9 +697,10 @@ static bool try_fixup_enqcmd_gp(void)
 }
 
 static bool gp_try_fixup_and_notify(struct pt_regs *regs, int trapnr,
-                                   unsigned long error_code, const char *str)
+                                   unsigned long error_code, const char *str,
+                                   unsigned long address)
 {
-       if (fixup_exception(regs, trapnr, error_code, 0))
+       if (fixup_exception(regs, trapnr, error_code, address))
                return true;
 
        current->thread.error_code = error_code;
@@ -759,7 +760,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection)
                goto exit;
        }
 
-       if (gp_try_fixup_and_notify(regs, X86_TRAP_GP, error_code, desc))
+       if (gp_try_fixup_and_notify(regs, X86_TRAP_GP, error_code, desc, 0))
                goto exit;
 
        if (error_code)
@@ -1357,17 +1358,20 @@ DEFINE_IDTENTRY(exc_device_not_available)
 
 #define VE_FAULT_STR "VE fault"
 
-static void ve_raise_fault(struct pt_regs *regs, long error_code)
+static void ve_raise_fault(struct pt_regs *regs, long error_code,
+                          unsigned long address)
 {
        if (user_mode(regs)) {
                gp_user_force_sig_segv(regs, X86_TRAP_VE, error_code, VE_FAULT_STR);
                return;
        }
 
-       if (gp_try_fixup_and_notify(regs, X86_TRAP_VE, error_code, VE_FAULT_STR))
+       if (gp_try_fixup_and_notify(regs, X86_TRAP_VE, error_code,
+                                   VE_FAULT_STR, address)) {
                return;
+       }
 
-       die_addr(VE_FAULT_STR, regs, error_code, 0);
+       die_addr(VE_FAULT_STR, regs, error_code, address);
 }
 
 /*
@@ -1431,7 +1435,7 @@ DEFINE_IDTENTRY(exc_virtualization_exception)
         * it successfully, treat it as #GP(0) and handle it.
         */
        if (!tdx_handle_virt_exception(regs, &ve))
-               ve_raise_fault(regs, 0);
+               ve_raise_fault(regs, 0, ve.gla);
 
        cond_local_irq_disable(regs);
 }
index 113ca96..a983a16 100644 (file)
@@ -637,16 +637,22 @@ bool __kvm_apic_update_irr(u32 *pir, void *regs, int *max_irr)
        *max_irr = -1;
 
        for (i = vec = 0; i <= 7; i++, vec += 32) {
+               u32 *p_irr = (u32 *)(regs + APIC_IRR + i * 0x10);
+
+               irr_val = *p_irr;
                pir_val = READ_ONCE(pir[i]);
-               irr_val = *((u32 *)(regs + APIC_IRR + i * 0x10));
+
                if (pir_val) {
+                       pir_val = xchg(&pir[i], 0);
+
                        prev_irr_val = irr_val;
-                       irr_val |= xchg(&pir[i], 0);
-                       *((u32 *)(regs + APIC_IRR + i * 0x10)) = irr_val;
-                       if (prev_irr_val != irr_val) {
-                               max_updated_irr =
-                                       __fls(irr_val ^ prev_irr_val) + vec;
-                       }
+                       do {
+                               irr_val = prev_irr_val | pir_val;
+                       } while (prev_irr_val != irr_val &&
+                                !try_cmpxchg(p_irr, &prev_irr_val, irr_val));
+
+                       if (prev_irr_val != irr_val)
+                               max_updated_irr = __fls(irr_val ^ prev_irr_val) + vec;
                }
                if (irr_val)
                        *max_irr = __fls(irr_val) + vec;
@@ -660,8 +666,11 @@ EXPORT_SYMBOL_GPL(__kvm_apic_update_irr);
 bool kvm_apic_update_irr(struct kvm_vcpu *vcpu, u32 *pir, int *max_irr)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
+       bool irr_updated = __kvm_apic_update_irr(pir, apic->regs, max_irr);
 
-       return __kvm_apic_update_irr(pir, apic->regs, max_irr);
+       if (unlikely(!apic->apicv_active && irr_updated))
+               apic->irr_pending = true;
+       return irr_updated;
 }
 EXPORT_SYMBOL_GPL(kvm_apic_update_irr);
 
index d381ad4..956726d 100644 (file)
@@ -1786,6 +1786,11 @@ static void sev_post_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
        }
 }
 
+static bool svm_is_valid_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+       return true;
+}
+
 void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
        struct vcpu_svm *svm = to_svm(vcpu);
@@ -3986,14 +3991,8 @@ static int svm_vcpu_pre_run(struct kvm_vcpu *vcpu)
 
 static fastpath_t svm_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
 {
-       struct vmcb_control_area *control = &to_svm(vcpu)->vmcb->control;
-
-       /*
-        * Note, the next RIP must be provided as SRCU isn't held, i.e. KVM
-        * can't read guest memory (dereference memslots) to decode the WRMSR.
-        */
-       if (control->exit_code == SVM_EXIT_MSR && control->exit_info_1 &&
-           nrips && control->next_rip)
+       if (to_svm(vcpu)->vmcb->control.exit_code == SVM_EXIT_MSR &&
+           to_svm(vcpu)->vmcb->control.exit_info_1)
                return handle_fastpath_set_msr_irqoff(vcpu);
 
        return EXIT_FASTPATH_NONE;
@@ -4815,6 +4814,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
        .set_segment = svm_set_segment,
        .get_cpl = svm_get_cpl,
        .get_cs_db_l_bits = svm_get_cs_db_l_bits,
+       .is_valid_cr0 = svm_is_valid_cr0,
        .set_cr0 = svm_set_cr0,
        .post_set_cr3 = sev_post_set_cr3,
        .is_valid_cr4 = svm_is_valid_cr4,
index 07e927d..be275a0 100644 (file)
@@ -303,10 +303,8 @@ SYM_FUNC_START(vmx_do_nmi_irqoff)
        VMX_DO_EVENT_IRQOFF call asm_exc_nmi_kvm_vmx
 SYM_FUNC_END(vmx_do_nmi_irqoff)
 
-
-.section .text, "ax"
-
 #ifndef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
+
 /**
  * vmread_error_trampoline - Trampoline from inline asm to vmread_error()
  * @field:     VMCS field encoding that failed
@@ -335,7 +333,7 @@ SYM_FUNC_START(vmread_error_trampoline)
        mov 3*WORD_SIZE(%_ASM_BP), %_ASM_ARG2
        mov 2*WORD_SIZE(%_ASM_BP), %_ASM_ARG1
 
-       call vmread_error
+       call vmread_error_trampoline2
 
        /* Zero out @fault, which will be popped into the result register. */
        _ASM_MOV $0, 3*WORD_SIZE(%_ASM_BP)
@@ -357,6 +355,8 @@ SYM_FUNC_START(vmread_error_trampoline)
 SYM_FUNC_END(vmread_error_trampoline)
 #endif
 
+.section .text, "ax"
+
 SYM_FUNC_START(vmx_do_interrupt_irqoff)
        VMX_DO_EVENT_IRQOFF CALL_NOSPEC _ASM_ARG1
 SYM_FUNC_END(vmx_do_interrupt_irqoff)
index 0ecf4be..df461f3 100644 (file)
@@ -441,13 +441,23 @@ do {                                      \
        pr_warn_ratelimited(fmt);       \
 } while (0)
 
-void vmread_error(unsigned long field, bool fault)
+noinline void vmread_error(unsigned long field)
 {
-       if (fault)
+       vmx_insn_failed("vmread failed: field=%lx\n", field);
+}
+
+#ifndef CONFIG_CC_HAS_ASM_GOTO_OUTPUT
+noinstr void vmread_error_trampoline2(unsigned long field, bool fault)
+{
+       if (fault) {
                kvm_spurious_fault();
-       else
-               vmx_insn_failed("vmread failed: field=%lx\n", field);
+       } else {
+               instrumentation_begin();
+               vmread_error(field);
+               instrumentation_end();
+       }
 }
+#endif
 
 noinline void vmwrite_error(unsigned long field, unsigned long value)
 {
@@ -1503,6 +1513,11 @@ void vmx_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags)
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        unsigned long old_rflags;
 
+       /*
+        * Unlike CR0 and CR4, RFLAGS handling requires checking if the vCPU
+        * is an unrestricted guest in order to mark L2 as needing emulation
+        * if L1 runs L2 as a restricted guest.
+        */
        if (is_unrestricted_guest(vcpu)) {
                kvm_register_mark_available(vcpu, VCPU_EXREG_RFLAGS);
                vmx->rflags = rflags;
@@ -3037,6 +3052,15 @@ static void enter_rmode(struct kvm_vcpu *vcpu)
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        struct kvm_vmx *kvm_vmx = to_kvm_vmx(vcpu->kvm);
 
+       /*
+        * KVM should never use VM86 to virtualize Real Mode when L2 is active,
+        * as using VM86 is unnecessary if unrestricted guest is enabled, and
+        * if unrestricted guest is disabled, VM-Enter (from L1) with CR0.PG=0
+        * should VM-Fail and KVM should reject userspace attempts to stuff
+        * CR0.PG=0 when L2 is active.
+        */
+       WARN_ON_ONCE(is_guest_mode(vcpu));
+
        vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_TR], VCPU_SREG_TR);
        vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_ES], VCPU_SREG_ES);
        vmx_get_segment(vcpu, &vmx->rmode.segs[VCPU_SREG_DS], VCPU_SREG_DS);
@@ -3226,6 +3250,17 @@ void ept_save_pdptrs(struct kvm_vcpu *vcpu)
 #define CR3_EXITING_BITS (CPU_BASED_CR3_LOAD_EXITING | \
                          CPU_BASED_CR3_STORE_EXITING)
 
+static bool vmx_is_valid_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+       if (is_guest_mode(vcpu))
+               return nested_guest_cr0_valid(vcpu, cr0);
+
+       if (to_vmx(vcpu)->nested.vmxon)
+               return nested_host_cr0_valid(vcpu, cr0);
+
+       return true;
+}
+
 void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -3235,7 +3270,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        old_cr0_pg = kvm_read_cr0_bits(vcpu, X86_CR0_PG);
 
        hw_cr0 = (cr0 & ~KVM_VM_CR0_ALWAYS_OFF);
-       if (is_unrestricted_guest(vcpu))
+       if (enable_unrestricted_guest)
                hw_cr0 |= KVM_VM_CR0_ALWAYS_ON_UNRESTRICTED_GUEST;
        else {
                hw_cr0 |= KVM_VM_CR0_ALWAYS_ON;
@@ -3263,7 +3298,7 @@ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
        }
 #endif
 
-       if (enable_ept && !is_unrestricted_guest(vcpu)) {
+       if (enable_ept && !enable_unrestricted_guest) {
                /*
                 * Ensure KVM has an up-to-date snapshot of the guest's CR3.  If
                 * the below code _enables_ CR3 exiting, vmx_cache_reg() will
@@ -3394,7 +3429,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
         * this bit, even if host CR4.MCE == 0.
         */
        hw_cr4 = (cr4_read_shadow() & X86_CR4_MCE) | (cr4 & ~X86_CR4_MCE);
-       if (is_unrestricted_guest(vcpu))
+       if (enable_unrestricted_guest)
                hw_cr4 |= KVM_VM_CR4_ALWAYS_ON_UNRESTRICTED_GUEST;
        else if (vmx->rmode.vm86_active)
                hw_cr4 |= KVM_RMODE_VM_CR4_ALWAYS_ON;
@@ -3414,7 +3449,7 @@ void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
        vcpu->arch.cr4 = cr4;
        kvm_register_mark_available(vcpu, VCPU_EXREG_CR4);
 
-       if (!is_unrestricted_guest(vcpu)) {
+       if (!enable_unrestricted_guest) {
                if (enable_ept) {
                        if (!is_paging(vcpu)) {
                                hw_cr4 &= ~X86_CR4_PAE;
@@ -4651,7 +4686,8 @@ static int vmx_alloc_ipiv_pid_table(struct kvm *kvm)
        if (kvm_vmx->pid_table)
                return 0;
 
-       pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, vmx_get_pid_table_order(kvm));
+       pages = alloc_pages(GFP_KERNEL_ACCOUNT | __GFP_ZERO,
+                           vmx_get_pid_table_order(kvm));
        if (!pages)
                return -ENOMEM;
 
@@ -5364,18 +5400,11 @@ static int handle_set_cr0(struct kvm_vcpu *vcpu, unsigned long val)
                val = (val & ~vmcs12->cr0_guest_host_mask) |
                        (vmcs12->guest_cr0 & vmcs12->cr0_guest_host_mask);
 
-               if (!nested_guest_cr0_valid(vcpu, val))
-                       return 1;
-
                if (kvm_set_cr0(vcpu, val))
                        return 1;
                vmcs_writel(CR0_READ_SHADOW, orig_val);
                return 0;
        } else {
-               if (to_vmx(vcpu)->nested.vmxon &&
-                   !nested_host_cr0_valid(vcpu, val))
-                       return 1;
-
                return kvm_set_cr0(vcpu, val);
        }
 }
@@ -8203,6 +8232,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
        .set_segment = vmx_set_segment,
        .get_cpl = vmx_get_cpl,
        .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
+       .is_valid_cr0 = vmx_is_valid_cr0,
        .set_cr0 = vmx_set_cr0,
        .is_valid_cr4 = vmx_is_valid_cr4,
        .set_cr4 = vmx_set_cr4,
index ce47dc2..33af7b4 100644 (file)
@@ -10,7 +10,7 @@
 #include "vmcs.h"
 #include "../x86.h"
 
-void vmread_error(unsigned long field, bool fault);
+void vmread_error(unsigned long field);
 void vmwrite_error(unsigned long field, unsigned long value);
 void vmclear_error(struct vmcs *vmcs, u64 phys_addr);
 void vmptrld_error(struct vmcs *vmcs, u64 phys_addr);
@@ -31,6 +31,13 @@ void invept_error(unsigned long ext, u64 eptp, gpa_t gpa);
  * void vmread_error_trampoline(unsigned long field, bool fault);
  */
 extern unsigned long vmread_error_trampoline;
+
+/*
+ * The second VMREAD error trampoline, called from the assembly trampoline,
+ * exists primarily to enable instrumentation for the VM-Fail path.
+ */
+void vmread_error_trampoline2(unsigned long field, bool fault);
+
 #endif
 
 static __always_inline void vmcs_check16(unsigned long field)
@@ -101,8 +108,7 @@ static __always_inline unsigned long __vmcs_readl(unsigned long field)
 
 do_fail:
        instrumentation_begin();
-       WARN_ONCE(1, KBUILD_MODNAME ": vmread failed: field=%lx\n", field);
-       pr_warn_ratelimited(KBUILD_MODNAME ": vmread failed: field=%lx\n", field);
+       vmread_error(field);
        instrumentation_end();
        return 0;
 
index a6b9bea..278dbd3 100644 (file)
@@ -906,6 +906,22 @@ int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3)
 }
 EXPORT_SYMBOL_GPL(load_pdptrs);
 
+static bool kvm_is_valid_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+{
+#ifdef CONFIG_X86_64
+       if (cr0 & 0xffffffff00000000UL)
+               return false;
+#endif
+
+       if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD))
+               return false;
+
+       if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE))
+               return false;
+
+       return static_call(kvm_x86_is_valid_cr0)(vcpu, cr0);
+}
+
 void kvm_post_set_cr0(struct kvm_vcpu *vcpu, unsigned long old_cr0, unsigned long cr0)
 {
        /*
@@ -952,20 +968,13 @@ int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
        unsigned long old_cr0 = kvm_read_cr0(vcpu);
 
-       cr0 |= X86_CR0_ET;
-
-#ifdef CONFIG_X86_64
-       if (cr0 & 0xffffffff00000000UL)
+       if (!kvm_is_valid_cr0(vcpu, cr0))
                return 1;
-#endif
 
-       cr0 &= ~CR0_RESERVED_BITS;
-
-       if ((cr0 & X86_CR0_NW) && !(cr0 & X86_CR0_CD))
-               return 1;
+       cr0 |= X86_CR0_ET;
 
-       if ((cr0 & X86_CR0_PG) && !(cr0 & X86_CR0_PE))
-               return 1;
+       /* Write to CR0 reserved bits are ignored, even on Intel. */
+       cr0 &= ~CR0_RESERVED_BITS;
 
 #ifdef CONFIG_X86_64
        if ((vcpu->arch.efer & EFER_LME) && !is_paging(vcpu) &&
@@ -2172,6 +2181,8 @@ fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu)
        u64 data;
        fastpath_t ret = EXIT_FASTPATH_NONE;
 
+       kvm_vcpu_srcu_read_lock(vcpu);
+
        switch (msr) {
        case APIC_BASE_MSR + (APIC_ICR >> 4):
                data = kvm_read_edx_eax(vcpu);
@@ -2194,6 +2205,8 @@ fastpath_t handle_fastpath_set_msr_irqoff(struct kvm_vcpu *vcpu)
        if (ret != EXIT_FASTPATH_NONE)
                trace_kvm_msr_write(msr, data);
 
+       kvm_vcpu_srcu_read_unlock(vcpu);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(handle_fastpath_set_msr_irqoff);
@@ -10203,9 +10216,13 @@ static int kvm_check_and_inject_events(struct kvm_vcpu *vcpu,
                if (r < 0)
                        goto out;
                if (r) {
-                       kvm_queue_interrupt(vcpu, kvm_cpu_get_interrupt(vcpu), false);
-                       static_call(kvm_x86_inject_irq)(vcpu, false);
-                       WARN_ON(static_call(kvm_x86_interrupt_allowed)(vcpu, true) < 0);
+                       int irq = kvm_cpu_get_interrupt(vcpu);
+
+                       if (!WARN_ON_ONCE(irq == -1)) {
+                               kvm_queue_interrupt(vcpu, irq, false);
+                               static_call(kvm_x86_inject_irq)(vcpu, false);
+                               WARN_ON(static_call(kvm_x86_interrupt_allowed)(vcpu, true) < 0);
+                       }
                }
                if (kvm_cpu_has_injectable_intr(vcpu))
                        static_call(kvm_x86_enable_irq_window)(vcpu);
@@ -11460,7 +11477,8 @@ static bool kvm_is_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
                        return false;
        }
 
-       return kvm_is_valid_cr4(vcpu, sregs->cr4);
+       return kvm_is_valid_cr4(vcpu, sregs->cr4) &&
+              kvm_is_valid_cr0(vcpu, sregs->cr0);
 }
 
 static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
@@ -13185,7 +13203,7 @@ EXPORT_SYMBOL_GPL(kvm_arch_has_noncoherent_dma);
 
 bool kvm_arch_has_irq_bypass(void)
 {
-       return true;
+       return enable_apicv && irq_remapping_cap(IRQ_POSTING_CAP);
 }
 
 int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
index 99d8b98..90de500 100644 (file)
@@ -1144,8 +1144,7 @@ void __blk_flush_plug(struct blk_plug *plug, bool from_schedule)
 {
        if (!list_empty(&plug->cb_list))
                flush_plug_callbacks(plug, from_schedule);
-       if (!rq_list_empty(plug->mq_list))
-               blk_mq_flush_plug_list(plug, from_schedule);
+       blk_mq_flush_plug_list(plug, from_schedule);
        /*
         * Unconditionally flush out cached requests, even if the unplug
         * event came from schedule. Since we know hold references to the
index 9dfcf54..dd64e20 100644 (file)
@@ -2516,6 +2516,10 @@ static void calc_vtime_cost_builtin(struct bio *bio, struct ioc_gq *iocg,
        u64 seek_pages = 0;
        u64 cost = 0;
 
+       /* Can't calculate cost for empty bio */
+       if (!bio->bi_iter.bi_size)
+               goto out;
+
        switch (bio_op(bio)) {
        case REQ_OP_READ:
                coef_seqio      = ioc->params.lcoefs[LCOEF_RSEQIO];
index d50b1d6..b04ff6f 100644 (file)
@@ -2754,7 +2754,14 @@ void blk_mq_flush_plug_list(struct blk_plug *plug, bool from_schedule)
 {
        struct request *rq;
 
-       if (rq_list_empty(plug->mq_list))
+       /*
+        * We may have been called recursively midway through handling
+        * plug->mq_list via a schedule() in the driver's queue_rq() callback.
+        * To avoid mq_list changing under our feet, clear rq_count early and
+        * bail out specifically if rq_count is 0 rather than checking
+        * whether the mq_list is empty.
+        */
+       if (plug->rq_count == 0)
                return;
        plug->rq_count = 0;
 
index d92ba2e..2f027d5 100644 (file)
@@ -3980,6 +3980,15 @@ static inline void hl_debugfs_fini(void)
 {
 }
 
+static inline int hl_debugfs_device_init(struct hl_device *hdev)
+{
+       return 0;
+}
+
+static inline void hl_debugfs_device_fini(struct hl_device *hdev)
+{
+}
+
 static inline void hl_debugfs_add_device(struct hl_device *hdev)
 {
 }
index 5c57f7b..cfbc92d 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mm.h>
 #include <linux/moduleparam.h>
 #include <linux/mutex.h>
+#include <linux/overflow.h>
 #include <linux/pci.h>
 #include <linux/scatterlist.h>
 #include <linux/types.h>
@@ -366,7 +367,7 @@ static int encode_passthrough(struct qaic_device *qdev, void *trans, struct wrap
        if (in_trans->hdr.len % 8 != 0)
                return -EINVAL;
 
-       if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_EXT_MSG_LENGTH)
+       if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_EXT_MSG_LENGTH)
                return -ENOSPC;
 
        trans_wrapper = add_wrapper(wrappers,
@@ -418,9 +419,12 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
        }
 
        ret = get_user_pages_fast(xfer_start_addr, nr_pages, 0, page_list);
-       if (ret < 0 || ret != nr_pages) {
-               ret = -EFAULT;
+       if (ret < 0)
                goto free_page_list;
+       if (ret != nr_pages) {
+               nr_pages = ret;
+               ret = -EFAULT;
+               goto put_pages;
        }
 
        sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
@@ -557,11 +561,8 @@ static int encode_dma(struct qaic_device *qdev, void *trans, struct wrapper_list
        msg = &wrapper->msg;
        msg_hdr_len = le32_to_cpu(msg->hdr.len);
 
-       if (msg_hdr_len > (UINT_MAX - QAIC_MANAGE_EXT_MSG_LENGTH))
-               return -EINVAL;
-
        /* There should be enough space to hold at least one ASP entry. */
-       if (msg_hdr_len + sizeof(*out_trans) + sizeof(struct wire_addr_size_pair) >
+       if (size_add(msg_hdr_len, sizeof(*out_trans) + sizeof(struct wire_addr_size_pair)) >
            QAIC_MANAGE_EXT_MSG_LENGTH)
                return -ENOMEM;
 
@@ -634,7 +635,7 @@ static int encode_activate(struct qaic_device *qdev, void *trans, struct wrapper
        msg = &wrapper->msg;
        msg_hdr_len = le32_to_cpu(msg->hdr.len);
 
-       if (msg_hdr_len + sizeof(*out_trans) > QAIC_MANAGE_MAX_MSG_LENGTH)
+       if (size_add(msg_hdr_len, sizeof(*out_trans)) > QAIC_MANAGE_MAX_MSG_LENGTH)
                return -ENOSPC;
 
        if (!in_trans->queue_size)
@@ -718,7 +719,7 @@ static int encode_status(struct qaic_device *qdev, void *trans, struct wrapper_l
        msg = &wrapper->msg;
        msg_hdr_len = le32_to_cpu(msg->hdr.len);
 
-       if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_MAX_MSG_LENGTH)
+       if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_MAX_MSG_LENGTH)
                return -ENOSPC;
 
        trans_wrapper = add_wrapper(wrappers, sizeof(*trans_wrapper));
@@ -748,7 +749,8 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
        int ret;
        int i;
 
-       if (!user_msg->count) {
+       if (!user_msg->count ||
+           user_msg->len < sizeof(*trans_hdr)) {
                ret = -EINVAL;
                goto out;
        }
@@ -765,12 +767,13 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
        }
 
        for (i = 0; i < user_msg->count; ++i) {
-               if (user_len >= user_msg->len) {
+               if (user_len > user_msg->len - sizeof(*trans_hdr)) {
                        ret = -EINVAL;
                        break;
                }
                trans_hdr = (struct qaic_manage_trans_hdr *)(user_msg->data + user_len);
-               if (user_len + trans_hdr->len > user_msg->len) {
+               if (trans_hdr->len < sizeof(trans_hdr) ||
+                   size_add(user_len, trans_hdr->len) > user_msg->len) {
                        ret = -EINVAL;
                        break;
                }
@@ -953,15 +956,23 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
        int ret;
        int i;
 
-       if (msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
+       if (msg_hdr_len < sizeof(*trans_hdr) ||
+           msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
                return -EINVAL;
 
        user_msg->len = 0;
        user_msg->count = le32_to_cpu(msg->hdr.count);
 
        for (i = 0; i < user_msg->count; ++i) {
+               u32 hdr_len;
+
+               if (msg_len > msg_hdr_len - sizeof(*trans_hdr))
+                       return -EINVAL;
+
                trans_hdr = (struct wire_trans_hdr *)(msg->data + msg_len);
-               if (msg_len + le32_to_cpu(trans_hdr->len) > msg_hdr_len)
+               hdr_len = le32_to_cpu(trans_hdr->len);
+               if (hdr_len < sizeof(*trans_hdr) ||
+                   size_add(msg_len, hdr_len) > msg_hdr_len)
                        return -EINVAL;
 
                switch (le32_to_cpu(trans_hdr->type)) {
index 3631230..56d8873 100644 (file)
@@ -1007,9 +1007,6 @@ static void iort_node_get_rmr_info(struct acpi_iort_node *node,
        for (i = 0; i < node->mapping_count; i++, map++) {
                struct acpi_iort_node *parent;
 
-               if (!map->id_count)
-                       continue;
-
                parent = ACPI_ADD_PTR(struct acpi_iort_node, iort_table,
                                      map->output_reference);
                if (parent != iommu)
index d37ab60..04db0f2 100644 (file)
@@ -4938,8 +4938,8 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
                if (qc->result_tf.status & ATA_SENSE &&
                    ((ata_is_ncq(qc->tf.protocol) &&
                      dev->flags & ATA_DFLAG_CDL_ENABLED) ||
-                    (!(ata_is_ncq(qc->tf.protocol) &&
-                       ata_id_sense_reporting_enabled(dev->id))))) {
+                    (!ata_is_ncq(qc->tf.protocol) &&
+                     ata_id_sense_reporting_enabled(dev->id)))) {
                        /*
                         * Tell SCSI EH to not overwrite scmd->result even if
                         * this command is finished with result SAM_STAT_GOOD.
index 6ab2943..314eaa1 100644 (file)
@@ -529,7 +529,8 @@ static void data_xfer(struct work_struct *work)
        /* dma_request_channel may sleep, so calling from process context */
        acdev->dma_chan = dma_request_chan(acdev->host->dev, "data");
        if (IS_ERR(acdev->dma_chan)) {
-               dev_err(acdev->host->dev, "Unable to get dma_chan\n");
+               dev_err_probe(acdev->host->dev, PTR_ERR(acdev->dma_chan),
+                             "Unable to get dma_chan\n");
                acdev->dma_chan = NULL;
                goto chan_request_fail;
        }
index d60e1f6..c697219 100644 (file)
@@ -260,7 +260,7 @@ static u8 ns87560_check_status(struct ata_port *ap)
  *     LOCKING:
  *     Inherited from caller.
  */
-void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+static void ns87560_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
        struct ata_ioports *ioaddr = &ap->ioaddr;
 
index ff538b8..2884acf 100644 (file)
@@ -815,8 +815,8 @@ static int octeon_cf_probe(struct platform_device *pdev)
        irq_handler_t irq_handler = NULL;
        void __iomem *base;
        struct octeon_cf_port *cf_port;
-       int rv = -ENOMEM;
        u32 bus_width;
+       int rv;
 
        node = pdev->dev.of_node;
        if (node == NULL)
@@ -893,12 +893,12 @@ static int octeon_cf_probe(struct platform_device *pdev)
        cs0 = devm_ioremap(&pdev->dev, res_cs0->start,
                                   resource_size(res_cs0));
        if (!cs0)
-               return rv;
+               return -ENOMEM;
 
        /* allocate host */
        host = ata_host_alloc(&pdev->dev, 1);
        if (!host)
-               return rv;
+               return -ENOMEM;
 
        ap = host->ports[0];
        ap->private_data = cf_port;
index 8328a49..620ce6c 100644 (file)
@@ -139,4 +139,6 @@ static struct pi_protocol aten = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("ATEN EH-100 parallel port IDE adapter protocol driver");
 module_pata_parport_driver(aten);
index 9f4309f..bba1eda 100644 (file)
@@ -502,4 +502,6 @@ static struct pi_protocol bpck = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("MicroSolutions BACKPACK parallel port IDE adapter protocol driver");
 module_pata_parport_driver(bpck);
index c6dbd14..62c2b53 100644 (file)
@@ -459,5 +459,6 @@ static struct pi_protocol bpck6 = {
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Micro Solutions Inc.");
-MODULE_DESCRIPTION("BACKPACK Protocol module, compatible with PARIDE");
+MODULE_DESCRIPTION("Micro Solutions BACKPACK parallel port IDE adapter "
+                  "(version 6 drives) protocol driver");
 module_pata_parport_driver(bpck6);
index cc5485b..4839bec 100644 (file)
@@ -201,4 +201,6 @@ static struct pi_protocol comm = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("DataStor Commuter parallel port IDE adapter protocol driver");
 module_pata_parport_driver(comm);
index 368d7c7..88930bb 100644 (file)
@@ -230,4 +230,6 @@ static struct pi_protocol dstr = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("DataStor EP2000 parallel port IDE adapter protocol driver");
 module_pata_parport_driver(dstr);
index 016bd96..3cb54fc 100644 (file)
@@ -358,5 +358,8 @@ static void __exit epat_exit(void)
 }
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Shuttle Technologies EPAT parallel port IDE adapter "
+                  "protocol driver");
 module_init(epat_init)
 module_exit(epat_exit)
index 920e9f4..7aaba47 100644 (file)
@@ -306,4 +306,7 @@ static struct pi_protocol epia = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Shuttle Technologies EPIA parallel port IDE adapter "
+                  "protocol driver");
 module_pata_parport_driver(epia);
index 6524f30..de79cf9 100644 (file)
@@ -132,4 +132,7 @@ static struct pi_protocol fit2 = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Fidelity International Technology parallel port IDE adapter"
+                  "(older models) protocol driver");
 module_pata_parport_driver(fit2);
index c172a38..bad7aa9 100644 (file)
@@ -193,4 +193,7 @@ static struct pi_protocol fit3 = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Fidelity International Technology parallel port IDE adapter"
+                  "(newer models) protocol driver");
 module_pata_parport_driver(fit3);
index dc428f5..7abe2ff 100644 (file)
@@ -259,4 +259,6 @@ static struct pi_protocol friq = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Freecom IQ parallel port IDE adapter protocol driver");
 module_pata_parport_driver(friq);
index 28d9bb2..7fa9b98 100644 (file)
@@ -293,4 +293,6 @@ static struct pi_protocol frpw = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Freecom Power parallel port IDE adapter protocol driver");
 module_pata_parport_driver(frpw);
index 6023e07..fca3226 100644 (file)
@@ -301,5 +301,8 @@ static void __exit kbic_exit(void)
 }
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("KingByte Information Systems KBIC-951A and KBIC-971A "
+                  "parallel port IDE adapter protocol driver");
 module_init(kbic_init)
 module_exit(kbic_exit)
index bca6c20..c078d19 100644 (file)
@@ -106,4 +106,6 @@ static struct pi_protocol ktti = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("KT Technology parallel port IDE adapter protocol driver");
 module_pata_parport_driver(ktti);
index 34e69da..7c70e5b 100644 (file)
@@ -142,4 +142,6 @@ static struct pi_protocol on20 = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Onspec 90c20 parallel port IDE adapter protocol driver");
 module_pata_parport_driver(on20);
index 5da317b..c88e5d6 100644 (file)
@@ -310,4 +310,6 @@ static struct pi_protocol on26 = {
 };
 
 MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Grant R. Guenther <grant@torque.net>");
+MODULE_DESCRIPTION("Onspec 90c26 parallel port IDE adapter protocol driver");
 module_pata_parport_driver(on26);
index 0eb7f02..922ed45 100644 (file)
@@ -29,6 +29,7 @@ extern u64 pm_runtime_active_time(struct device *dev);
 #define WAKE_IRQ_DEDICATED_MASK                (WAKE_IRQ_DEDICATED_ALLOCATED | \
                                         WAKE_IRQ_DEDICATED_MANAGED | \
                                         WAKE_IRQ_DEDICATED_REVERSE)
+#define WAKE_IRQ_DEDICATED_ENABLED     BIT(3)
 
 struct wake_irq {
        struct device *dev;
index d487a6b..42171f7 100644 (file)
@@ -194,7 +194,6 @@ err_free:
        return err;
 }
 
-
 /**
  * dev_pm_set_dedicated_wake_irq - Request a dedicated wake-up interrupt
  * @dev: Device entry
@@ -206,11 +205,6 @@ err_free:
  * Sets up a threaded interrupt handler for a device that has
  * a dedicated wake-up interrupt in addition to the device IO
  * interrupt.
- *
- * The interrupt starts disabled, and needs to be managed for
- * the device by the bus code or the device driver using
- * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
- * functions.
  */
 int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq)
 {
@@ -232,11 +226,6 @@ EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq);
  * the status of WAKE_IRQ_DEDICATED_REVERSE to tell rpm_suspend()
  * to enable dedicated wake-up interrupt after running the runtime suspend
  * callback for @dev.
- *
- * The interrupt starts disabled, and needs to be managed for
- * the device by the bus code or the device driver using
- * dev_pm_enable_wake_irq*() and dev_pm_disable_wake_irq*()
- * functions.
  */
 int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
 {
@@ -245,44 +234,6 @@ int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq)
 EXPORT_SYMBOL_GPL(dev_pm_set_dedicated_wake_irq_reverse);
 
 /**
- * dev_pm_enable_wake_irq - Enable device wake-up interrupt
- * @dev: Device
- *
- * Optionally called from the bus code or the device driver for
- * runtime_resume() to override the PM runtime core managed wake-up
- * interrupt handling to enable the wake-up interrupt.
- *
- * Note that for runtime_suspend()) the wake-up interrupts
- * should be unconditionally enabled unlike for suspend()
- * that is conditional.
- */
-void dev_pm_enable_wake_irq(struct device *dev)
-{
-       struct wake_irq *wirq = dev->power.wakeirq;
-
-       if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
-               enable_irq(wirq->irq);
-}
-EXPORT_SYMBOL_GPL(dev_pm_enable_wake_irq);
-
-/**
- * dev_pm_disable_wake_irq - Disable device wake-up interrupt
- * @dev: Device
- *
- * Optionally called from the bus code or the device driver for
- * runtime_suspend() to override the PM runtime core managed wake-up
- * interrupt handling to disable the wake-up interrupt.
- */
-void dev_pm_disable_wake_irq(struct device *dev)
-{
-       struct wake_irq *wirq = dev->power.wakeirq;
-
-       if (wirq && (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED))
-               disable_irq_nosync(wirq->irq);
-}
-EXPORT_SYMBOL_GPL(dev_pm_disable_wake_irq);
-
-/**
  * dev_pm_enable_wake_irq_check - Checks and enables wake-up interrupt
  * @dev: Device
  * @can_change_status: Can change wake-up interrupt status
@@ -314,8 +265,10 @@ void dev_pm_enable_wake_irq_check(struct device *dev,
        return;
 
 enable:
-       if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
+       if (!can_change_status || !(wirq->status & WAKE_IRQ_DEDICATED_REVERSE)) {
                enable_irq(wirq->irq);
+               wirq->status |= WAKE_IRQ_DEDICATED_ENABLED;
+       }
 }
 
 /**
@@ -336,8 +289,10 @@ void dev_pm_disable_wake_irq_check(struct device *dev, bool cond_disable)
        if (cond_disable && (wirq->status & WAKE_IRQ_DEDICATED_REVERSE))
                return;
 
-       if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED)
+       if (wirq->status & WAKE_IRQ_DEDICATED_MANAGED) {
+               wirq->status &= ~WAKE_IRQ_DEDICATED_ENABLED;
                disable_irq_nosync(wirq->irq);
+       }
 }
 
 /**
@@ -376,7 +331,7 @@ void dev_pm_arm_wake_irq(struct wake_irq *wirq)
 
        if (device_may_wakeup(wirq->dev)) {
                if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
-                   !pm_runtime_status_suspended(wirq->dev))
+                   !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
                        enable_irq(wirq->irq);
 
                enable_irq_wake(wirq->irq);
@@ -399,7 +354,7 @@ void dev_pm_disarm_wake_irq(struct wake_irq *wirq)
                disable_irq_wake(wirq->irq);
 
                if (wirq->status & WAKE_IRQ_DEDICATED_ALLOCATED &&
-                   !pm_runtime_status_suspended(wirq->dev))
+                   !(wirq->status & WAKE_IRQ_DEDICATED_ENABLED))
                        disable_irq_nosync(wirq->irq);
        }
 }
index fabf870..584bcc5 100644 (file)
@@ -471,6 +471,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
        unsigned int start, end;
        int ret;
 
+       map->async = true;
+
        rbtree_ctx = map->cache;
        for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
                rbnode = rb_entry(node, struct regcache_rbtree_node, node);
@@ -499,6 +501,8 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
                        return ret;
        }
 
+       map->async = false;
+
        return regmap_async_complete(map);
 }
 
index 28bc3ae..7d3e474 100644 (file)
@@ -368,8 +368,6 @@ int regcache_sync(struct regmap *map)
        if (!map->cache_dirty)
                goto out;
 
-       map->async = true;
-
        /* Apply any patch first */
        map->cache_bypass = true;
        for (i = 0; i < map->patch_regs; i++) {
@@ -392,7 +390,6 @@ int regcache_sync(struct regmap *map)
 
 out:
        /* Restore the bypass state */
-       map->async = false;
        map->cache_bypass = bypass;
        map->no_sync_defaults = false;
        map->unlock(map->lock_arg);
index 980e5ce..3ec611d 100644 (file)
@@ -242,8 +242,8 @@ static int regmap_i2c_smbus_i2c_read(void *context, const void *reg,
 static const struct regmap_bus regmap_i2c_smbus_i2c_block = {
        .write = regmap_i2c_smbus_i2c_write,
        .read = regmap_i2c_smbus_i2c_read,
-       .max_raw_read = I2C_SMBUS_BLOCK_MAX,
-       .max_raw_write = I2C_SMBUS_BLOCK_MAX,
+       .max_raw_read = I2C_SMBUS_BLOCK_MAX - 1,
+       .max_raw_write = I2C_SMBUS_BLOCK_MAX - 1,
 };
 
 static int regmap_i2c_smbus_i2c_write_reg16(void *context, const void *data,
@@ -299,8 +299,8 @@ static int regmap_i2c_smbus_i2c_read_reg16(void *context, const void *reg,
 static const struct regmap_bus regmap_i2c_smbus_i2c_block_reg16 = {
        .write = regmap_i2c_smbus_i2c_write_reg16,
        .read = regmap_i2c_smbus_i2c_read_reg16,
-       .max_raw_read = I2C_SMBUS_BLOCK_MAX,
-       .max_raw_write = I2C_SMBUS_BLOCK_MAX,
+       .max_raw_read = I2C_SMBUS_BLOCK_MAX - 2,
+       .max_raw_write = I2C_SMBUS_BLOCK_MAX - 2,
 };
 
 static const struct regmap_bus *regmap_get_i2c_bus(struct i2c_client *i2c,
index 24257aa..9ff3018 100644 (file)
@@ -58,6 +58,9 @@ static struct regmap *gen_regmap(struct regmap_config *config,
        int i;
        struct reg_default *defaults;
 
+       config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
+                                       config->cache_type == REGCACHE_MAPLE;
+
        buf = kmalloc(size, GFP_KERNEL);
        if (!buf)
                return ERR_PTR(-ENOMEM);
@@ -889,6 +892,8 @@ static struct regmap *gen_raw_regmap(struct regmap_config *config,
 
        config->cache_type = test_type->cache_type;
        config->val_format_endian = test_type->val_endian;
+       config->disable_locking = config->cache_type == REGCACHE_RBTREE ||
+                                       config->cache_type == REGCACHE_MAPLE;
 
        buf = kmalloc(size, GFP_KERNEL);
        if (!buf)
index 6af6928..4c2b94b 100644 (file)
@@ -660,7 +660,7 @@ static const struct regmap_bus regmap_spi_avmm_bus = {
        .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
        .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
        .max_raw_read = SPI_AVMM_VAL_SIZE * MAX_READ_CNT,
-       .max_raw_write = SPI_AVMM_REG_SIZE + SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
+       .max_raw_write = SPI_AVMM_VAL_SIZE * MAX_WRITE_CNT,
        .free_context = spi_avmm_bridge_ctx_free,
 };
 
index 89a7f1c..1bfd172 100644 (file)
@@ -2082,8 +2082,6 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
        size_t val_count = val_len / val_bytes;
        size_t chunk_count, chunk_bytes;
        size_t chunk_regs = val_count;
-       size_t max_data = map->max_raw_write - map->format.reg_bytes -
-                       map->format.pad_bytes;
        int ret, i;
 
        if (!val_count)
@@ -2091,8 +2089,8 @@ int _regmap_raw_write(struct regmap *map, unsigned int reg,
 
        if (map->use_single_write)
                chunk_regs = 1;
-       else if (map->max_raw_write && val_len > max_data)
-               chunk_regs = max_data / val_bytes;
+       else if (map->max_raw_write && val_len > map->max_raw_write)
+               chunk_regs = map->max_raw_write / val_bytes;
 
        chunk_count = val_count / chunk_regs;
        chunk_bytes = chunk_regs * val_bytes;
index 37511d2..637c5bd 100644 (file)
@@ -1775,14 +1775,43 @@ static const struct block_device_operations lo_fops = {
 /*
  * If max_loop is specified, create that many devices upfront.
  * This also becomes a hard limit. If max_loop is not specified,
+ * the default isn't a hard limit (as before commit 85c50197716c
+ * changed the default value from 0 for max_loop=0 reasons), just
  * create CONFIG_BLK_DEV_LOOP_MIN_COUNT loop devices at module
  * init time. Loop devices can be requested on-demand with the
  * /dev/loop-control interface, or be instantiated by accessing
  * a 'dead' device node.
  */
 static int max_loop = CONFIG_BLK_DEV_LOOP_MIN_COUNT;
-module_param(max_loop, int, 0444);
+
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
+static bool max_loop_specified;
+
+static int max_loop_param_set_int(const char *val,
+                                 const struct kernel_param *kp)
+{
+       int ret;
+
+       ret = param_set_int(val, kp);
+       if (ret < 0)
+               return ret;
+
+       max_loop_specified = true;
+       return 0;
+}
+
+static const struct kernel_param_ops max_loop_param_ops = {
+       .set = max_loop_param_set_int,
+       .get = param_get_int,
+};
+
+module_param_cb(max_loop, &max_loop_param_ops, &max_loop, 0444);
 MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
+#else
+module_param(max_loop, int, 0444);
+MODULE_PARM_DESC(max_loop, "Initial number of loop devices");
+#endif
+
 module_param(max_part, int, 0444);
 MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
 
@@ -2093,14 +2122,18 @@ static void loop_remove(struct loop_device *lo)
        put_disk(lo->lo_disk);
 }
 
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
 static void loop_probe(dev_t dev)
 {
        int idx = MINOR(dev) >> part_shift;
 
-       if (max_loop && idx >= max_loop)
+       if (max_loop_specified && max_loop && idx >= max_loop)
                return;
        loop_add(idx);
 }
+#else
+#define loop_probe NULL
+#endif /* !CONFIG_BLOCK_LEGACY_AUTOLOAD */
 
 static int loop_control_remove(int idx)
 {
@@ -2281,6 +2314,9 @@ module_exit(loop_exit);
 static int __init max_loop_setup(char *str)
 {
        max_loop = simple_strtol(str, NULL, 0);
+#ifdef CONFIG_BLOCK_LEGACY_AUTOLOAD
+       max_loop_specified = true;
+#endif
        return 1;
 }
 
index bd0e075..24afcc9 100644 (file)
@@ -3849,51 +3849,82 @@ static void wake_lock_waiters(struct rbd_device *rbd_dev, int result)
        list_splice_tail_init(&rbd_dev->acquiring_list, &rbd_dev->running_list);
 }
 
-static int get_lock_owner_info(struct rbd_device *rbd_dev,
-                              struct ceph_locker **lockers, u32 *num_lockers)
+static bool locker_equal(const struct ceph_locker *lhs,
+                        const struct ceph_locker *rhs)
+{
+       return lhs->id.name.type == rhs->id.name.type &&
+              lhs->id.name.num == rhs->id.name.num &&
+              !strcmp(lhs->id.cookie, rhs->id.cookie) &&
+              ceph_addr_equal_no_type(&lhs->info.addr, &rhs->info.addr);
+}
+
+static void free_locker(struct ceph_locker *locker)
+{
+       if (locker)
+               ceph_free_lockers(locker, 1);
+}
+
+static struct ceph_locker *get_lock_owner_info(struct rbd_device *rbd_dev)
 {
        struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
+       struct ceph_locker *lockers;
+       u32 num_lockers;
        u8 lock_type;
        char *lock_tag;
+       u64 handle;
        int ret;
 
-       dout("%s rbd_dev %p\n", __func__, rbd_dev);
-
        ret = ceph_cls_lock_info(osdc, &rbd_dev->header_oid,
                                 &rbd_dev->header_oloc, RBD_LOCK_NAME,
-                                &lock_type, &lock_tag, lockers, num_lockers);
-       if (ret)
-               return ret;
+                                &lock_type, &lock_tag, &lockers, &num_lockers);
+       if (ret) {
+               rbd_warn(rbd_dev, "failed to retrieve lockers: %d", ret);
+               return ERR_PTR(ret);
+       }
 
-       if (*num_lockers == 0) {
+       if (num_lockers == 0) {
                dout("%s rbd_dev %p no lockers detected\n", __func__, rbd_dev);
+               lockers = NULL;
                goto out;
        }
 
        if (strcmp(lock_tag, RBD_LOCK_TAG)) {
                rbd_warn(rbd_dev, "locked by external mechanism, tag %s",
                         lock_tag);
-               ret = -EBUSY;
-               goto out;
+               goto err_busy;
        }
 
-       if (lock_type == CEPH_CLS_LOCK_SHARED) {
-               rbd_warn(rbd_dev, "shared lock type detected");
-               ret = -EBUSY;
-               goto out;
+       if (lock_type != CEPH_CLS_LOCK_EXCLUSIVE) {
+               rbd_warn(rbd_dev, "incompatible lock type detected");
+               goto err_busy;
        }
 
-       if (strncmp((*lockers)[0].id.cookie, RBD_LOCK_COOKIE_PREFIX,
-                   strlen(RBD_LOCK_COOKIE_PREFIX))) {
+       WARN_ON(num_lockers != 1);
+       ret = sscanf(lockers[0].id.cookie, RBD_LOCK_COOKIE_PREFIX " %llu",
+                    &handle);
+       if (ret != 1) {
                rbd_warn(rbd_dev, "locked by external mechanism, cookie %s",
-                        (*lockers)[0].id.cookie);
-               ret = -EBUSY;
-               goto out;
+                        lockers[0].id.cookie);
+               goto err_busy;
        }
+       if (ceph_addr_is_blank(&lockers[0].info.addr)) {
+               rbd_warn(rbd_dev, "locker has a blank address");
+               goto err_busy;
+       }
+
+       dout("%s rbd_dev %p got locker %s%llu@%pISpc/%u handle %llu\n",
+            __func__, rbd_dev, ENTITY_NAME(lockers[0].id.name),
+            &lockers[0].info.addr.in_addr,
+            le32_to_cpu(lockers[0].info.addr.nonce), handle);
 
 out:
        kfree(lock_tag);
-       return ret;
+       return lockers;
+
+err_busy:
+       kfree(lock_tag);
+       ceph_free_lockers(lockers, num_lockers);
+       return ERR_PTR(-EBUSY);
 }
 
 static int find_watcher(struct rbd_device *rbd_dev,
@@ -3947,51 +3978,68 @@ out:
 static int rbd_try_lock(struct rbd_device *rbd_dev)
 {
        struct ceph_client *client = rbd_dev->rbd_client->client;
-       struct ceph_locker *lockers;
-       u32 num_lockers;
+       struct ceph_locker *locker, *refreshed_locker;
        int ret;
 
        for (;;) {
+               locker = refreshed_locker = NULL;
+
                ret = rbd_lock(rbd_dev);
                if (ret != -EBUSY)
-                       return ret;
+                       goto out;
 
                /* determine if the current lock holder is still alive */
-               ret = get_lock_owner_info(rbd_dev, &lockers, &num_lockers);
-               if (ret)
-                       return ret;
-
-               if (num_lockers == 0)
+               locker = get_lock_owner_info(rbd_dev);
+               if (IS_ERR(locker)) {
+                       ret = PTR_ERR(locker);
+                       locker = NULL;
+                       goto out;
+               }
+               if (!locker)
                        goto again;
 
-               ret = find_watcher(rbd_dev, lockers);
+               ret = find_watcher(rbd_dev, locker);
                if (ret)
                        goto out; /* request lock or error */
 
+               refreshed_locker = get_lock_owner_info(rbd_dev);
+               if (IS_ERR(refreshed_locker)) {
+                       ret = PTR_ERR(refreshed_locker);
+                       refreshed_locker = NULL;
+                       goto out;
+               }
+               if (!refreshed_locker ||
+                   !locker_equal(locker, refreshed_locker))
+                       goto again;
+
                rbd_warn(rbd_dev, "breaking header lock owned by %s%llu",
-                        ENTITY_NAME(lockers[0].id.name));
+                        ENTITY_NAME(locker->id.name));
 
                ret = ceph_monc_blocklist_add(&client->monc,
-                                             &lockers[0].info.addr);
+                                             &locker->info.addr);
                if (ret) {
-                       rbd_warn(rbd_dev, "blocklist of %s%llu failed: %d",
-                                ENTITY_NAME(lockers[0].id.name), ret);
+                       rbd_warn(rbd_dev, "failed to blocklist %s%llu: %d",
+                                ENTITY_NAME(locker->id.name), ret);
                        goto out;
                }
 
                ret = ceph_cls_break_lock(&client->osdc, &rbd_dev->header_oid,
                                          &rbd_dev->header_oloc, RBD_LOCK_NAME,
-                                         lockers[0].id.cookie,
-                                         &lockers[0].id.name);
-               if (ret && ret != -ENOENT)
+                                         locker->id.cookie, &locker->id.name);
+               if (ret && ret != -ENOENT) {
+                       rbd_warn(rbd_dev, "failed to break header lock: %d",
+                                ret);
                        goto out;
+               }
 
 again:
-               ceph_free_lockers(lockers, num_lockers);
+               free_locker(refreshed_locker);
+               free_locker(locker);
        }
 
 out:
-       ceph_free_lockers(lockers, num_lockers);
+       free_locker(refreshed_locker);
+       free_locker(locker);
        return ret;
 }
 
index 1c82375..21d2e71 100644 (file)
@@ -1847,7 +1847,8 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
        if (ublksrv_pid <= 0)
                return -EINVAL;
 
-       wait_for_completion_interruptible(&ub->completion);
+       if (wait_for_completion_interruptible(&ub->completion) != 0)
+               return -EINTR;
 
        schedule_delayed_work(&ub->monitor_work, UBLK_DAEMON_MONITOR_PERIOD);
 
@@ -2125,8 +2126,8 @@ static int ublk_ctrl_del_dev(struct ublk_device **p_ub)
         * - the device number is freed already, we will not find this
         *   device via ublk_get_device_from_id()
         */
-       wait_event_interruptible(ublk_idr_wq, ublk_idr_freed(idx));
-
+       if (wait_event_interruptible(ublk_idr_wq, ublk_idr_freed(idx)))
+               return -EINTR;
        return 0;
 }
 
@@ -2323,7 +2324,9 @@ static int ublk_ctrl_end_recovery(struct ublk_device *ub,
        pr_devel("%s: Waiting for new ubq_daemons(nr: %d) are ready, dev id %d...\n",
                        __func__, ub->dev_info.nr_hw_queues, header->dev_id);
        /* wait until new ubq_daemon sending all FETCH_REQ */
-       wait_for_completion_interruptible(&ub->completion);
+       if (wait_for_completion_interruptible(&ub->completion))
+               return -EINTR;
+
        pr_devel("%s: All new ubq_daemons(nr: %d) are ready, dev id %d\n",
                        __func__, ub->dev_info.nr_hw_queues, header->dev_id);
 
index 5ec4ad0..764d176 100644 (file)
@@ -4104,6 +4104,7 @@ static int btusb_probe(struct usb_interface *intf,
        BT_DBG("intf %p id %p", intf, id);
 
        if ((id->driver_info & BTUSB_IFNUM_2) &&
+           (intf->cur_altsetting->desc.bInterfaceNumber != 0) &&
            (intf->cur_altsetting->desc.bInterfaceNumber != 2))
                return -ENODEV;
 
index 2d28f55..661574b 100644 (file)
@@ -160,7 +160,7 @@ static struct i2c_driver st33zp24_i2c_driver = {
                .of_match_table = of_match_ptr(of_st33zp24_i2c_match),
                .acpi_match_table = ACPI_PTR(st33zp24_i2c_acpi_match),
        },
-       .probe_new = st33zp24_i2c_probe,
+       .probe = st33zp24_i2c_probe,
        .remove = st33zp24_i2c_remove,
        .id_table = st33zp24_i2c_id
 };
index 8f77154..301a95b 100644 (file)
@@ -203,7 +203,7 @@ static SIMPLE_DEV_PM_OPS(i2c_atmel_pm_ops, tpm_pm_suspend, tpm_pm_resume);
 
 static struct i2c_driver i2c_atmel_driver = {
        .id_table = i2c_atmel_id,
-       .probe_new = i2c_atmel_probe,
+       .probe = i2c_atmel_probe,
        .remove = i2c_atmel_remove,
        .driver = {
                .name = I2C_DRIVER_NAME,
index 7cdaff5..81d8a78 100644 (file)
@@ -716,7 +716,7 @@ static void tpm_tis_i2c_remove(struct i2c_client *client)
 
 static struct i2c_driver tpm_tis_i2c_driver = {
        .id_table = tpm_tis_i2c_table,
-       .probe_new = tpm_tis_i2c_probe,
+       .probe = tpm_tis_i2c_probe,
        .remove = tpm_tis_i2c_remove,
        .driver = {
                   .name = "tpm_i2c_infineon",
index a026e98..d7be03c 100644 (file)
@@ -650,7 +650,7 @@ static SIMPLE_DEV_PM_OPS(i2c_nuvoton_pm_ops, tpm_pm_suspend, tpm_pm_resume);
 
 static struct i2c_driver i2c_nuvoton_driver = {
        .id_table = i2c_nuvoton_id,
-       .probe_new = i2c_nuvoton_probe,
+       .probe = i2c_nuvoton_probe,
        .remove = i2c_nuvoton_remove,
        .driver = {
                .name = "tpm_i2c_nuvoton",
index 88a5384..b959630 100644 (file)
@@ -366,8 +366,13 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
                goto out;
        }
 
-       size += recv_data(chip, &buf[TPM_HEADER_SIZE],
-                         expected - TPM_HEADER_SIZE);
+       rc = recv_data(chip, &buf[TPM_HEADER_SIZE],
+                      expected - TPM_HEADER_SIZE);
+       if (rc < 0) {
+               size = rc;
+               goto out;
+       }
+       size += rc;
        if (size < expected) {
                dev_err(&chip->dev, "Unable to read remainder of result\n");
                size = -ETIME;
index 82fda48..a897402 100644 (file)
@@ -394,7 +394,7 @@ static struct i2c_driver tpm_tis_i2c_driver = {
                .pm = &tpm_tis_pm,
                .of_match_table = of_match_ptr(of_tis_i2c_match),
        },
-       .probe_new = tpm_tis_i2c_probe,
+       .probe = tpm_tis_i2c_probe,
        .remove = tpm_tis_i2c_remove,
        .id_table = tpm_tis_i2c_id,
 };
index 376ae18..e70abd6 100644 (file)
@@ -779,7 +779,7 @@ static void tpm_cr50_i2c_remove(struct i2c_client *client)
 static SIMPLE_DEV_PM_OPS(cr50_i2c_pm, tpm_pm_suspend, tpm_pm_resume);
 
 static struct i2c_driver cr50_i2c_driver = {
-       .probe_new = tpm_cr50_i2c_probe,
+       .probe = tpm_cr50_i2c_probe,
        .remove = tpm_cr50_i2c_remove,
        .driver = {
                .name = "cr50_i2c",
index fcbf829..8ea1d34 100644 (file)
@@ -2,6 +2,8 @@
 menuconfig CXL_BUS
        tristate "CXL (Compute Express Link) Devices Support"
        depends on PCI
+       select FW_LOADER
+       select FW_UPLOAD
        select PCI_DOE
        help
          CXL is a bus that is electrically compatible with PCI Express, but
@@ -82,7 +84,6 @@ config CXL_PMEM
 config CXL_MEM
        tristate "CXL: Memory Expansion"
        depends on CXL_PCI
-       select FW_UPLOAD
        default CXL_BUS
        help
          The CXL.mem protocol allows a device to act as a provider of "System
index 658e6b8..d1c5598 100644 (file)
@@ -296,9 +296,8 @@ err_xormap:
        else
                rc = cxl_decoder_autoremove(dev, cxld);
        if (rc) {
-               dev_err(dev, "Failed to add decode range [%#llx - %#llx]\n",
-                       cxld->hpa_range.start, cxld->hpa_range.end);
-               return 0;
+               dev_err(dev, "Failed to add decode range: %pr", res);
+               return rc;
        }
        dev_dbg(dev, "add: %s node: %d range [%#llx - %#llx]\n",
                dev_name(&cxld->dev),
index d6d067f..ca60bb8 100644 (file)
@@ -121,6 +121,45 @@ static bool cxl_is_security_command(u16 opcode)
        return false;
 }
 
+static void cxl_set_security_cmd_enabled(struct cxl_security_state *security,
+                                        u16 opcode)
+{
+       switch (opcode) {
+       case CXL_MBOX_OP_SANITIZE:
+               set_bit(CXL_SEC_ENABLED_SANITIZE, security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_SECURE_ERASE:
+               set_bit(CXL_SEC_ENABLED_SECURE_ERASE,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_GET_SECURITY_STATE:
+               set_bit(CXL_SEC_ENABLED_GET_SECURITY_STATE,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_SET_PASSPHRASE:
+               set_bit(CXL_SEC_ENABLED_SET_PASSPHRASE,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_DISABLE_PASSPHRASE:
+               set_bit(CXL_SEC_ENABLED_DISABLE_PASSPHRASE,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_UNLOCK:
+               set_bit(CXL_SEC_ENABLED_UNLOCK, security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_FREEZE_SECURITY:
+               set_bit(CXL_SEC_ENABLED_FREEZE_SECURITY,
+                       security->enabled_cmds);
+               break;
+       case CXL_MBOX_OP_PASSPHRASE_SECURE_ERASE:
+               set_bit(CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE,
+                       security->enabled_cmds);
+               break;
+       default:
+               break;
+       }
+}
+
 static bool cxl_is_poison_command(u16 opcode)
 {
 #define CXL_MBOX_OP_POISON_CMDS 0x43
@@ -677,7 +716,8 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
                u16 opcode = le16_to_cpu(cel_entry[i].opcode);
                struct cxl_mem_command *cmd = cxl_mem_find_command(opcode);
 
-               if (!cmd && !cxl_is_poison_command(opcode)) {
+               if (!cmd && (!cxl_is_poison_command(opcode) ||
+                            !cxl_is_security_command(opcode))) {
                        dev_dbg(dev,
                                "Opcode 0x%04x unsupported by driver\n", opcode);
                        continue;
@@ -689,6 +729,9 @@ static void cxl_walk_cel(struct cxl_memdev_state *mds, size_t size, u8 *cel)
                if (cxl_is_poison_command(opcode))
                        cxl_set_poison_cmd_enabled(&mds->poison, opcode);
 
+               if (cxl_is_security_command(opcode))
+                       cxl_set_security_cmd_enabled(&mds->security, opcode);
+
                dev_dbg(dev, "Opcode 0x%04x enabled\n", opcode);
        }
 }
index f99e7ec..14b547c 100644 (file)
@@ -477,9 +477,28 @@ static struct attribute_group cxl_memdev_pmem_attribute_group = {
        .attrs = cxl_memdev_pmem_attributes,
 };
 
+static umode_t cxl_memdev_security_visible(struct kobject *kobj,
+                                          struct attribute *a, int n)
+{
+       struct device *dev = kobj_to_dev(kobj);
+       struct cxl_memdev *cxlmd = to_cxl_memdev(dev);
+       struct cxl_memdev_state *mds = to_cxl_memdev_state(cxlmd->cxlds);
+
+       if (a == &dev_attr_security_sanitize.attr &&
+           !test_bit(CXL_SEC_ENABLED_SANITIZE, mds->security.enabled_cmds))
+               return 0;
+
+       if (a == &dev_attr_security_erase.attr &&
+           !test_bit(CXL_SEC_ENABLED_SECURE_ERASE, mds->security.enabled_cmds))
+               return 0;
+
+       return a->mode;
+}
+
 static struct attribute_group cxl_memdev_security_attribute_group = {
        .name = "security",
        .attrs = cxl_memdev_security_attributes,
+       .is_visible = cxl_memdev_security_visible,
 };
 
 static const struct attribute_group *cxl_memdev_attribute_groups[] = {
index 79e99c8..706f8a6 100644 (file)
@@ -244,6 +244,19 @@ enum poison_cmd_enabled_bits {
        CXL_POISON_ENABLED_MAX
 };
 
+/* Device enabled security commands */
+enum security_cmd_enabled_bits {
+       CXL_SEC_ENABLED_SANITIZE,
+       CXL_SEC_ENABLED_SECURE_ERASE,
+       CXL_SEC_ENABLED_GET_SECURITY_STATE,
+       CXL_SEC_ENABLED_SET_PASSPHRASE,
+       CXL_SEC_ENABLED_DISABLE_PASSPHRASE,
+       CXL_SEC_ENABLED_UNLOCK,
+       CXL_SEC_ENABLED_FREEZE_SECURITY,
+       CXL_SEC_ENABLED_PASSPHRASE_SECURE_ERASE,
+       CXL_SEC_ENABLED_MAX
+};
+
 /**
  * struct cxl_poison_state - Driver poison state info
  *
@@ -323,7 +336,7 @@ struct cxl_mbox_activate_fw {
 
 /* FW state bits */
 #define CXL_FW_STATE_BITS              32
-#define CXL_FW_CANCEL          BIT(0)
+#define CXL_FW_CANCEL                  0
 
 /**
  * struct cxl_fw_state - Firmware upload / activation state
@@ -346,6 +359,7 @@ struct cxl_fw_state {
  * struct cxl_security_state - Device security state
  *
  * @state: state of last security operation
+ * @enabled_cmds: All security commands enabled in the CEL
  * @poll: polling for sanitization is enabled, device has no mbox irq support
  * @poll_tmo_secs: polling timeout
  * @poll_dwork: polling work item
@@ -353,6 +367,7 @@ struct cxl_fw_state {
  */
 struct cxl_security_state {
        unsigned long state;
+       DECLARE_BITMAP(enabled_cmds, CXL_SEC_ENABLED_MAX);
        bool poll;
        int poll_tmo_secs;
        struct delayed_work poll_dwork;
@@ -434,6 +449,7 @@ struct cxl_dev_state {
  * @next_persistent_bytes: persistent capacity change pending device reset
  * @event: event log driver state
  * @poison: poison driver state info
+ * @security: security driver state info
  * @fw: firmware upload / activation state
  * @mbox_send: @dev specific transport for transmitting mailbox commands
  *
index b6f71eb..38b4110 100644 (file)
@@ -571,6 +571,7 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
        dma_resv_for_each_fence_unlocked(&cursor, fence) {
 
                if (dma_resv_iter_is_restarted(&cursor)) {
+                       struct dma_fence **new_fences;
                        unsigned int count;
 
                        while (*num_fences)
@@ -579,13 +580,17 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
                        count = cursor.num_fences + 1;
 
                        /* Eventually re-allocate the array */
-                       *fences = krealloc_array(*fences, count,
-                                                sizeof(void *),
-                                                GFP_KERNEL);
-                       if (count && !*fences) {
+                       new_fences = krealloc_array(*fences, count,
+                                                   sizeof(void *),
+                                                   GFP_KERNEL);
+                       if (count && !new_fences) {
+                               kfree(*fences);
+                               *fences = NULL;
+                               *num_fences = 0;
                                dma_resv_iter_end(&cursor);
                                return -ENOMEM;
                        }
+                       *fences = new_fences;
                }
 
                (*fences)[(*num_fences)++] = dma_fence_get(fence);
index 1efa5e9..19246ed 100644 (file)
@@ -166,8 +166,10 @@ static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                return -ENOMEM;
 
        shmem = of_parse_phandle(cdev->of_node, "shmem", idx);
-       if (!of_device_is_compatible(shmem, "arm,scmi-shmem"))
+       if (!of_device_is_compatible(shmem, "arm,scmi-shmem")) {
+               of_node_put(shmem);
                return -ENXIO;
+       }
 
        ret = of_address_to_resource(shmem, 0, &res);
        of_node_put(shmem);
index 6971dcf..0493aa3 100644 (file)
@@ -818,10 +818,13 @@ static ssize_t scmi_dbg_raw_mode_common_write(struct file *filp,
         * before sending it with a single RAW xfer.
         */
        if (rd->tx_size < rd->tx_req_size) {
-               size_t cnt;
+               ssize_t cnt;
 
                cnt = simple_write_to_buffer(rd->tx.buf, rd->tx.len, ppos,
                                             buf, count);
+               if (cnt < 0)
+                       return cnt;
+
                rd->tx_size += cnt;
                if (cnt < count)
                        return cnt;
index 621c37e..c193516 100644 (file)
@@ -40,6 +40,7 @@
 /**
  * struct scmi_smc - Structure representing a SCMI smc transport
  *
+ * @irq: An optional IRQ for completion
  * @cinfo: SCMI channel info
  * @shmem: Transmit/Receive shared memory area
  * @shmem_lock: Lock to protect access to Tx/Rx shared memory area.
@@ -52,6 +53,7 @@
  */
 
 struct scmi_smc {
+       int irq;
        struct scmi_chan_info *cinfo;
        struct scmi_shared_mem __iomem *shmem;
        /* Protect access to shmem area */
@@ -127,7 +129,7 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
        struct resource res;
        struct device_node *np;
        u32 func_id;
-       int ret, irq;
+       int ret;
 
        if (!tx)
                return -ENODEV;
@@ -137,8 +139,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
                return -ENOMEM;
 
        np = of_parse_phandle(cdev->of_node, "shmem", 0);
-       if (!of_device_is_compatible(np, "arm,scmi-shmem"))
+       if (!of_device_is_compatible(np, "arm,scmi-shmem")) {
+               of_node_put(np);
                return -ENXIO;
+       }
 
        ret = of_address_to_resource(np, 0, &res);
        of_node_put(np);
@@ -167,11 +171,10 @@ static int smc_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
         * completion of a message is signaled by an interrupt rather than by
         * the return of the SMC call.
         */
-       irq = of_irq_get_byname(cdev->of_node, "a2p");
-       if (irq > 0) {
-               ret = devm_request_irq(dev, irq, smc_msg_done_isr,
-                                      IRQF_NO_SUSPEND,
-                                      dev_name(dev), scmi_info);
+       scmi_info->irq = of_irq_get_byname(cdev->of_node, "a2p");
+       if (scmi_info->irq > 0) {
+               ret = request_irq(scmi_info->irq, smc_msg_done_isr,
+                                 IRQF_NO_SUSPEND, dev_name(dev), scmi_info);
                if (ret) {
                        dev_err(dev, "failed to setup SCMI smc irq\n");
                        return ret;
@@ -193,6 +196,10 @@ static int smc_chan_free(int id, void *p, void *data)
        struct scmi_chan_info *cinfo = p;
        struct scmi_smc *scmi_info = cinfo->transport_info;
 
+       /* Ignore any possible further reception on the IRQ path */
+       if (scmi_info->irq > 0)
+               free_irq(scmi_info->irq, scmi_info);
+
        cinfo->transport_info = NULL;
        scmi_info->cinfo = NULL;
 
index 890eb45..1990263 100644 (file)
@@ -34,7 +34,6 @@ static struct soc_device_attribute *soc_dev_attr;
 
 static int __init smccc_soc_init(void)
 {
-       struct arm_smccc_res res;
        int soc_id_rev, soc_id_version;
        static char soc_id_str[20], soc_id_rev_str[12];
        static char soc_id_jep106_id_str[12];
@@ -49,13 +48,13 @@ static int __init smccc_soc_init(void)
        }
 
        if (soc_id_version < 0) {
-               pr_err("ARCH_SOC_ID(0) returned error: %lx\n", res.a0);
+               pr_err("Invalid SoC Version: %x\n", soc_id_version);
                return -EINVAL;
        }
 
        soc_id_rev = arm_smccc_get_soc_id_revision();
        if (soc_id_rev < 0) {
-               pr_err("ARCH_SOC_ID(1) returned error: %lx\n", res.a0);
+               pr_err("Invalid SoC Revision: %x\n", soc_id_rev);
                return -EINVAL;
        }
 
index a68f682..6749711 100644 (file)
@@ -874,7 +874,7 @@ static int mvebu_pwm_probe(struct platform_device *pdev,
 
        spin_lock_init(&mvpwm->lock);
 
-       return pwmchip_add(&mvpwm->chip);
+       return devm_pwmchip_add(dev, &mvpwm->chip);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -1112,6 +1112,13 @@ static int mvebu_gpio_probe_syscon(struct platform_device *pdev,
        return 0;
 }
 
+static void mvebu_gpio_remove_irq_domain(void *data)
+{
+       struct irq_domain *domain = data;
+
+       irq_domain_remove(domain);
+}
+
 static int mvebu_gpio_probe(struct platform_device *pdev)
 {
        struct mvebu_gpio_chip *mvchip;
@@ -1243,17 +1250,21 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        if (!mvchip->domain) {
                dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n",
                        mvchip->chip.label);
-               err = -ENODEV;
-               goto err_pwm;
+               return -ENODEV;
        }
 
+       err = devm_add_action_or_reset(&pdev->dev, mvebu_gpio_remove_irq_domain,
+                                      mvchip->domain);
+       if (err)
+               return err;
+
        err = irq_alloc_domain_generic_chips(
            mvchip->domain, ngpios, 2, np->name, handle_level_irq,
            IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0);
        if (err) {
                dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n",
                        mvchip->chip.label);
-               goto err_domain;
+               return err;
        }
 
        /*
@@ -1293,13 +1304,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        }
 
        return 0;
-
-err_domain:
-       irq_domain_remove(mvchip->domain);
-err_pwm:
-       pwmchip_remove(&mvchip->mvpwm->chip);
-
-       return err;
 }
 
 static struct platform_driver mvebu_gpio_driver = {
index aaddcab..532dead 100644 (file)
@@ -91,13 +91,13 @@ static int tps68470_gpio_output(struct gpio_chip *gc, unsigned int offset,
        struct tps68470_gpio_data *tps68470_gpio = gpiochip_get_data(gc);
        struct regmap *regmap = tps68470_gpio->tps68470_regmap;
 
+       /* Set the initial value */
+       tps68470_gpio_set(gc, offset, value);
+
        /* rest are always outputs */
        if (offset >= TPS68470_N_REGULAR_GPIO)
                return 0;
 
-       /* Set the initial value */
-       tps68470_gpio_set(gc, offset, value);
-
        return regmap_update_bits(regmap, TPS68470_GPIO_CTL_REG_A(offset),
                                 TPS68470_GPIO_MODE_MASK,
                                 TPS68470_GPIO_MODE_OUT_CMOS);
index a7f314d..d34c3ef 100644 (file)
@@ -1709,7 +1709,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu(
                        alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ?
                        AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED : 0;
                }
-               xcp_id = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id;
+               xcp_id = fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION ?
+                                       0 : fpriv->xcp_id;
        } else if (flags & KFD_IOC_ALLOC_MEM_FLAGS_GTT) {
                domain = alloc_domain = AMDGPU_GEM_DOMAIN_GTT;
                alloc_flags = 0;
index cca5a49..12414a7 100644 (file)
@@ -1229,13 +1229,13 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
                pasid = 0;
        }
 
-       r = amdgpu_vm_init(adev, &fpriv->vm);
+       r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
        if (r)
                goto error_pasid;
 
-       r = amdgpu_xcp_open_device(adev, fpriv, file_priv);
+       r = amdgpu_vm_init(adev, &fpriv->vm, fpriv->xcp_id);
        if (r)
-               goto error_vm;
+               goto error_pasid;
 
        r = amdgpu_vm_set_pasid(adev, &fpriv->vm, pasid);
        if (r)
index e9091eb..f808841 100644 (file)
@@ -1382,7 +1382,7 @@ int amdgpu_mes_self_test(struct amdgpu_device *adev)
                goto error_pasid;
        }
 
-       r = amdgpu_vm_init(adev, vm);
+       r = amdgpu_vm_init(adev, vm, -1);
        if (r) {
                DRM_ERROR("failed to initialize vm\n");
                goto error_pasid;
index 6d676bd..78d1ee7 100644 (file)
@@ -498,11 +498,11 @@ static int psp_sw_init(void *handle)
        return 0;
 
 failed2:
-       amdgpu_bo_free_kernel(&psp->fw_pri_bo,
-                             &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
-failed1:
        amdgpu_bo_free_kernel(&psp->fence_buf_bo,
                              &psp->fence_buf_mc_addr, &psp->fence_buf);
+failed1:
+       amdgpu_bo_free_kernel(&psp->fw_pri_bo,
+                             &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
        return ret;
 }
 
index 53ff91f..d0748bc 100644 (file)
@@ -55,8 +55,9 @@ static enum hrtimer_restart amdgpu_vkms_vblank_simulate(struct hrtimer *timer)
                DRM_WARN("%s: vblank timer overrun\n", __func__);
 
        ret = drm_crtc_handle_vblank(crtc);
+       /* Don't queue timer again when vblank is disabled. */
        if (!ret)
-               DRM_ERROR("amdgpu_vkms failure on handling vblank");
+               return HRTIMER_NORESTART;
 
        return HRTIMER_RESTART;
 }
@@ -81,7 +82,7 @@ static void amdgpu_vkms_disable_vblank(struct drm_crtc *crtc)
 {
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
-       hrtimer_cancel(&amdgpu_crtc->vblank_timer);
+       hrtimer_try_to_cancel(&amdgpu_crtc->vblank_timer);
 }
 
 static bool amdgpu_vkms_get_vblank_timestamp(struct drm_crtc *crtc,
index 291977b..ec1ec08 100644 (file)
@@ -2121,13 +2121,14 @@ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout)
  *
  * @adev: amdgpu_device pointer
  * @vm: requested vm
+ * @xcp_id: GPU partition selection id
  *
  * Init @vm fields.
  *
  * Returns:
  * 0 for success, error for failure.
  */
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id)
 {
        struct amdgpu_bo *root_bo;
        struct amdgpu_bo_vm *root;
@@ -2177,7 +2178,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        vm->evicting = false;
 
        r = amdgpu_vm_pt_create(adev, vm, adev->vm_manager.root_level,
-                               false, &root);
+                               false, &root, xcp_id);
        if (r)
                goto error_free_delayed;
        root_bo = &root->bo;
index 9c85d49..ffac741 100644 (file)
@@ -392,7 +392,7 @@ int amdgpu_vm_set_pasid(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                        u32 pasid);
 
 long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout);
-int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm);
+int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int32_t xcp_id);
 int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm);
@@ -475,7 +475,8 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm,
 int amdgpu_vm_pt_clear(struct amdgpu_device *adev, struct amdgpu_vm *vm,
                       struct amdgpu_bo_vm *vmbo, bool immediate);
 int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                       int level, bool immediate, struct amdgpu_bo_vm **vmbo);
+                       int level, bool immediate, struct amdgpu_bo_vm **vmbo,
+                       int32_t xcp_id);
 void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm);
 bool amdgpu_vm_pt_is_root_clean(struct amdgpu_device *adev,
                                struct amdgpu_vm *vm);
index dea1a64..5431332 100644 (file)
@@ -498,11 +498,12 @@ exit:
  * @level: the page table level
  * @immediate: use a immediate update
  * @vmbo: pointer to the buffer object pointer
+ * @xcp_id: GPU partition id
  */
 int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
-                       int level, bool immediate, struct amdgpu_bo_vm **vmbo)
+                       int level, bool immediate, struct amdgpu_bo_vm **vmbo,
+                       int32_t xcp_id)
 {
-       struct amdgpu_fpriv *fpriv = container_of(vm, struct amdgpu_fpriv, vm);
        struct amdgpu_bo_param bp;
        struct amdgpu_bo *bo;
        struct dma_resv *resv;
@@ -535,7 +536,7 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
 
        bp.type = ttm_bo_type_kernel;
        bp.no_wait_gpu = immediate;
-       bp.xcp_id_plus1 = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id + 1;
+       bp.xcp_id_plus1 = xcp_id + 1;
 
        if (vm->root.bo)
                bp.resv = vm->root.bo->tbo.base.resv;
@@ -561,7 +562,7 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        bp.type = ttm_bo_type_kernel;
        bp.resv = bo->tbo.base.resv;
        bp.bo_ptr_size = sizeof(struct amdgpu_bo);
-       bp.xcp_id_plus1 = fpriv->xcp_id == ~0 ? 0 : fpriv->xcp_id + 1;
+       bp.xcp_id_plus1 = xcp_id + 1;
 
        r = amdgpu_bo_create(adev, &bp, &(*vmbo)->shadow);
 
@@ -606,7 +607,8 @@ static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev,
                return 0;
 
        amdgpu_vm_eviction_unlock(vm);
-       r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt);
+       r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt,
+                               vm->root.bo->xcp_id);
        amdgpu_vm_eviction_lock(vm);
        if (r)
                return r;
index d175e86..9c9cca1 100644 (file)
@@ -363,7 +363,7 @@ int amdgpu_xcp_open_device(struct amdgpu_device *adev,
        if (!adev->xcp_mgr)
                return 0;
 
-       fpriv->xcp_id = ~0;
+       fpriv->xcp_id = AMDGPU_XCP_NO_PARTITION;
        for (i = 0; i < MAX_XCP; ++i) {
                if (!adev->xcp_mgr->xcp[i].ddev)
                        break;
@@ -381,7 +381,7 @@ int amdgpu_xcp_open_device(struct amdgpu_device *adev,
                }
        }
 
-       fpriv->vm.mem_id = fpriv->xcp_id == ~0 ? -1 :
+       fpriv->vm.mem_id = fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION ? -1 :
                                adev->xcp_mgr->xcp[fpriv->xcp_id].mem_id;
        return 0;
 }
index 0f8026d..9a1036a 100644 (file)
@@ -37,6 +37,8 @@
 #define AMDGPU_XCP_FL_NONE 0
 #define AMDGPU_XCP_FL_LOCKED (1 << 0)
 
+#define AMDGPU_XCP_NO_PARTITION (~0)
+
 struct amdgpu_fpriv;
 
 enum AMDGPU_XCP_IP_BLOCK {
index 16471b8..72b629a 100644 (file)
@@ -68,7 +68,7 @@ static void aqua_vanjaram_set_xcp_id(struct amdgpu_device *adev,
        enum AMDGPU_XCP_IP_BLOCK ip_blk;
        uint32_t inst_mask;
 
-       ring->xcp_id = ~0;
+       ring->xcp_id = AMDGPU_XCP_NO_PARTITION;
        if (adev->xcp_mgr->mode == AMDGPU_XCP_MODE_NONE)
                return;
 
@@ -177,7 +177,7 @@ static int aqua_vanjaram_select_scheds(
        u32 sel_xcp_id;
        int i;
 
-       if (fpriv->xcp_id == ~0) {
+       if (fpriv->xcp_id == AMDGPU_XCP_NO_PARTITION) {
                u32 least_ref_cnt = ~0;
 
                fpriv->xcp_id = 0;
index 9e3b835..4f883b9 100644 (file)
@@ -46,6 +46,7 @@ MODULE_FIRMWARE("amdgpu/gc_9_4_3_rlc.bin");
 #define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
 
 #define GOLDEN_GB_ADDR_CONFIG 0x2a114042
+#define CP_HQD_PERSISTENT_STATE_DEFAULT 0xbe05301
 
 struct amdgpu_gfx_ras gfx_v9_4_3_ras;
 
@@ -1736,7 +1737,7 @@ static int gfx_v9_4_3_xcc_q_fini_register(struct amdgpu_ring *ring,
 
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_IQ_TIMER, 0);
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_IB_CONTROL, 0);
-       WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PERSISTENT_STATE, 0);
+       WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PERSISTENT_STATE, CP_HQD_PERSISTENT_STATE_DEFAULT);
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL, 0x40000000);
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_DOORBELL_CONTROL, 0);
        WREG32_SOC15_RLC(GC, GET_INST(GC, xcc_id), regCP_HQD_PQ_RPTR, 0);
index 4dabf91..d9f14dc 100644 (file)
@@ -402,18 +402,15 @@ static void gfxhub_v1_2_xcc_program_invalidation(struct amdgpu_device *adev,
 static int gfxhub_v1_2_xcc_gart_enable(struct amdgpu_device *adev,
                                       uint32_t xcc_mask)
 {
-       uint32_t tmp_mask;
        int i;
 
-       tmp_mask = xcc_mask;
        /*
         * MC_VM_FB_LOCATION_BASE/TOP is NULL for VF, because they are
         * VF copy registers so vbios post doesn't program them, for
         * SRIOV driver need to program them
         */
        if (amdgpu_sriov_vf(adev)) {
-               for_each_inst(i, tmp_mask) {
-                       i = ffs(tmp_mask) - 1;
+               for_each_inst(i, xcc_mask) {
                        WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_BASE,
                                     adev->gmc.vram_start >> 24);
                        WREG32_SOC15_RLC(GC, GET_INST(GC, i), regMC_VM_FB_LOCATION_TOP,
index f9cb0d2..e1a392b 100644 (file)
@@ -49,6 +49,7 @@ MODULE_FIRMWARE("amdgpu/psp_13_0_10_ta.bin");
 MODULE_FIRMWARE("amdgpu/psp_13_0_11_toc.bin");
 MODULE_FIRMWARE("amdgpu/psp_13_0_11_ta.bin");
 MODULE_FIRMWARE("amdgpu/psp_13_0_6_sos.bin");
+MODULE_FIRMWARE("amdgpu/psp_13_0_6_ta.bin");
 
 /* For large FW files the time to complete can be very long */
 #define USBC_PD_POLLING_LIMIT_S 240
index fff3ccc..9766076 100644 (file)
@@ -302,8 +302,7 @@ static int kfd_dbg_set_queue_workaround(struct queue *q, bool enable)
        if (!q)
                return 0;
 
-       if (KFD_GC_VERSION(q->device) < IP_VERSION(11, 0, 0) ||
-           KFD_GC_VERSION(q->device) >= IP_VERSION(12, 0, 0))
+       if (!kfd_dbg_has_cwsr_workaround(q->device))
                return 0;
 
        if (enable && q->properties.is_user_cu_masked)
@@ -349,7 +348,7 @@ int kfd_dbg_set_mes_debug_mode(struct kfd_process_device *pdd)
 {
        uint32_t spi_dbg_cntl = pdd->spi_dbg_override | pdd->spi_dbg_launch_mode;
        uint32_t flags = pdd->process->dbg_flags;
-       bool sq_trap_en = !!spi_dbg_cntl;
+       bool sq_trap_en = !!spi_dbg_cntl || !kfd_dbg_has_cwsr_workaround(pdd->dev);
 
        if (!kfd_dbg_is_per_vmid_supported(pdd->dev))
                return 0;
index a289e59..662a13a 100644 (file)
@@ -100,6 +100,12 @@ static inline bool kfd_dbg_is_rlc_restore_supported(struct kfd_node *dev)
                 KFD_GC_VERSION(dev) == IP_VERSION(10, 1, 1));
 }
 
+static inline bool kfd_dbg_has_cwsr_workaround(struct kfd_node *dev)
+{
+       return KFD_GC_VERSION(dev) >= IP_VERSION(11, 0, 0) &&
+              KFD_GC_VERSION(dev) <= IP_VERSION(11, 0, 3);
+}
+
 static inline bool kfd_dbg_has_gws_support(struct kfd_node *dev)
 {
        if ((KFD_GC_VERSION(dev) == IP_VERSION(9, 0, 1)
index f515cb8..2df1538 100644 (file)
@@ -226,8 +226,7 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
        queue_input.paging = false;
        queue_input.tba_addr = qpd->tba_addr;
        queue_input.tma_addr = qpd->tma_addr;
-       queue_input.trap_en = KFD_GC_VERSION(q->device) < IP_VERSION(11, 0, 0) ||
-                             KFD_GC_VERSION(q->device) > IP_VERSION(11, 0, 3);
+       queue_input.trap_en = !kfd_dbg_has_cwsr_workaround(q->device);
        queue_input.skip_process_ctx_clear = qpd->pqm->process->debug_trap_enabled;
 
        queue_type = convert_to_mes_queue_type(q->properties.type);
@@ -1806,8 +1805,7 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q,
         */
        q->properties.is_evicted = !!qpd->evicted;
        q->properties.is_dbg_wa = qpd->pqm->process->debug_trap_enabled &&
-                       KFD_GC_VERSION(q->device) >= IP_VERSION(11, 0, 0) &&
-                       KFD_GC_VERSION(q->device) <= IP_VERSION(11, 0, 3);
+                                 kfd_dbg_has_cwsr_workaround(q->device);
 
        if (qd)
                mqd_mgr->restore_mqd(mqd_mgr, &q->mqd, q->mqd_mem_obj, &q->gart_mqd_addr,
index ff0a217..0fa739f 100644 (file)
@@ -424,12 +424,12 @@ static void dm_pflip_high_irq(void *interrupt_params)
 
        spin_lock_irqsave(&adev_to_drm(adev)->event_lock, flags);
 
-       if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED){
-               DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p] \n",
-                                                amdgpu_crtc->pflip_status,
-                                                AMDGPU_FLIP_SUBMITTED,
-                                                amdgpu_crtc->crtc_id,
-                                                amdgpu_crtc);
+       if (amdgpu_crtc->pflip_status != AMDGPU_FLIP_SUBMITTED) {
+               DC_LOG_PFLIP("amdgpu_crtc->pflip_status = %d !=AMDGPU_FLIP_SUBMITTED(%d) on crtc:%d[%p]\n",
+                            amdgpu_crtc->pflip_status,
+                            AMDGPU_FLIP_SUBMITTED,
+                            amdgpu_crtc->crtc_id,
+                            amdgpu_crtc);
                spin_unlock_irqrestore(&adev_to_drm(adev)->event_lock, flags);
                return;
        }
@@ -883,7 +883,7 @@ static int dm_set_powergating_state(void *handle,
 }
 
 /* Prototypes of private functions */
-static int dm_early_init(voidhandle);
+static int dm_early_init(void *handle);
 
 /* Allocate memory for FBC compressed data  */
 static void amdgpu_dm_fbc_init(struct drm_connector *connector)
@@ -1282,7 +1282,7 @@ static void mmhub_read_system_context(struct amdgpu_device *adev, struct dc_phy_
        pa_config->system_aperture.start_addr = (uint64_t)logical_addr_low << 18;
        pa_config->system_aperture.end_addr = (uint64_t)logical_addr_high << 18;
 
-       pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24 ;
+       pa_config->system_aperture.agp_base = (uint64_t)agp_base << 24;
        pa_config->system_aperture.agp_bot = (uint64_t)agp_bot << 24;
        pa_config->system_aperture.agp_top = (uint64_t)agp_top << 24;
 
@@ -1347,6 +1347,15 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
        if (amdgpu_in_reset(adev))
                goto skip;
 
+       if (offload_work->data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
+               offload_work->data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
+               dm_handle_mst_sideband_msg_ready_event(&aconnector->mst_mgr, DOWN_OR_UP_MSG_RDY_EVENT);
+               spin_lock_irqsave(&offload_work->offload_wq->offload_lock, flags);
+               offload_work->offload_wq->is_handling_mst_msg_rdy_event = false;
+               spin_unlock_irqrestore(&offload_work->offload_wq->offload_lock, flags);
+               goto skip;
+       }
+
        mutex_lock(&adev->dm.dc_lock);
        if (offload_work->data.bytes.device_service_irq.bits.AUTOMATED_TEST) {
                dc_link_dp_handle_automated_test(dc_link);
@@ -1365,8 +1374,7 @@ static void dm_handle_hpd_rx_offload_work(struct work_struct *work)
                DP_TEST_RESPONSE,
                &test_response.raw,
                sizeof(test_response));
-       }
-       else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
+       } else if ((dc_link->connector_signal != SIGNAL_TYPE_EDP) &&
                        dc_link_check_link_loss_status(dc_link, &offload_work->data) &&
                        dc_link_dp_allow_hpd_rx_irq(dc_link)) {
                /* offload_work->data is from handle_hpd_rx_irq->
@@ -1554,7 +1562,7 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        mutex_init(&adev->dm.dc_lock);
        mutex_init(&adev->dm.audio_lock);
 
-       if(amdgpu_dm_irq_init(adev)) {
+       if (amdgpu_dm_irq_init(adev)) {
                DRM_ERROR("amdgpu: failed to initialize DM IRQ support.\n");
                goto error;
        }
@@ -1696,9 +1704,8 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
        if (amdgpu_dc_debug_mask & DC_DISABLE_STUTTER)
                adev->dm.dc->debug.disable_stutter = true;
 
-       if (amdgpu_dc_debug_mask & DC_DISABLE_DSC) {
+       if (amdgpu_dc_debug_mask & DC_DISABLE_DSC)
                adev->dm.dc->debug.disable_dsc = true;
-       }
 
        if (amdgpu_dc_debug_mask & DC_DISABLE_CLOCK_GATING)
                adev->dm.dc->debug.disable_clock_gate = true;
@@ -1942,8 +1949,6 @@ static void amdgpu_dm_fini(struct amdgpu_device *adev)
        mutex_destroy(&adev->dm.audio_lock);
        mutex_destroy(&adev->dm.dc_lock);
        mutex_destroy(&adev->dm.dpia_aux_lock);
-
-       return;
 }
 
 static int load_dmcu_fw(struct amdgpu_device *adev)
@@ -1952,7 +1957,7 @@ static int load_dmcu_fw(struct amdgpu_device *adev)
        int r;
        const struct dmcu_firmware_header_v1_0 *hdr;
 
-       switch(adev->asic_type) {
+       switch (adev->asic_type) {
 #if defined(CONFIG_DRM_AMD_DC_SI)
        case CHIP_TAHITI:
        case CHIP_PITCAIRN:
@@ -2709,7 +2714,7 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
                struct dc_scaling_info scaling_infos[MAX_SURFACES];
                struct dc_flip_addrs flip_addrs[MAX_SURFACES];
                struct dc_stream_update stream_update;
-       } * bundle;
+       } *bundle;
        int k, m;
 
        bundle = kzalloc(sizeof(*bundle), GFP_KERNEL);
@@ -2739,8 +2744,6 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
 
 cleanup:
        kfree(bundle);
-
-       return;
 }
 
 static int dm_resume(void *handle)
@@ -2954,8 +2957,7 @@ static const struct amd_ip_funcs amdgpu_dm_funcs = {
        .set_powergating_state = dm_set_powergating_state,
 };
 
-const struct amdgpu_ip_block_version dm_ip_block =
-{
+const struct amdgpu_ip_block_version dm_ip_block = {
        .type = AMD_IP_BLOCK_TYPE_DCE,
        .major = 1,
        .minor = 0,
@@ -3000,9 +3002,12 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
        caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
        caps->aux_support = false;
 
-       if (caps->ext_caps->bits.oled == 1 /*||
-           caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
-           caps->ext_caps->bits.hdr_aux_backlight_control == 1*/)
+       if (caps->ext_caps->bits.oled == 1
+           /*
+            * ||
+            * caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
+            * caps->ext_caps->bits.hdr_aux_backlight_control == 1
+            */)
                caps->aux_support = true;
 
        if (amdgpu_backlight == 0)
@@ -3236,86 +3241,6 @@ static void handle_hpd_irq(void *param)
 
 }
 
-static void dm_handle_mst_sideband_msg(struct amdgpu_dm_connector *aconnector)
-{
-       u8 esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
-       u8 dret;
-       bool new_irq_handled = false;
-       int dpcd_addr;
-       int dpcd_bytes_to_read;
-
-       const int max_process_count = 30;
-       int process_count = 0;
-
-       const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
-
-       if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
-               dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
-               /* DPCD 0x200 - 0x201 for downstream IRQ */
-               dpcd_addr = DP_SINK_COUNT;
-       } else {
-               dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
-               /* DPCD 0x2002 - 0x2005 for downstream IRQ */
-               dpcd_addr = DP_SINK_COUNT_ESI;
-       }
-
-       dret = drm_dp_dpcd_read(
-               &aconnector->dm_dp_aux.aux,
-               dpcd_addr,
-               esi,
-               dpcd_bytes_to_read);
-
-       while (dret == dpcd_bytes_to_read &&
-               process_count < max_process_count) {
-               u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
-               u8 retry;
-               dret = 0;
-
-               process_count++;
-
-               DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
-               /* handle HPD short pulse irq */
-               if (aconnector->mst_mgr.mst_state)
-                       drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
-                                                       esi,
-                                                       ack,
-                                                       &new_irq_handled);
-
-               if (new_irq_handled) {
-                       /* ACK at DPCD to notify down stream */
-                       for (retry = 0; retry < 3; retry++) {
-                               ssize_t wret;
-
-                               wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
-                                                         dpcd_addr + 1,
-                                                         ack[1]);
-                               if (wret == 1)
-                                       break;
-                       }
-
-                       if (retry == 3) {
-                               DRM_ERROR("Failed to ack MST event.\n");
-                               return;
-                       }
-
-                       drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
-                       /* check if there is new irq to be handled */
-                       dret = drm_dp_dpcd_read(
-                               &aconnector->dm_dp_aux.aux,
-                               dpcd_addr,
-                               esi,
-                               dpcd_bytes_to_read);
-
-                       new_irq_handled = false;
-               } else {
-                       break;
-               }
-       }
-
-       if (process_count == max_process_count)
-               DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
-}
-
 static void schedule_hpd_rx_offload_work(struct hpd_rx_irq_offload_work_queue *offload_wq,
                                                        union hpd_irq_data hpd_irq_data)
 {
@@ -3377,7 +3302,23 @@ static void handle_hpd_rx_irq(void *param)
        if (dc_link_dp_allow_hpd_rx_irq(dc_link)) {
                if (hpd_irq_data.bytes.device_service_irq.bits.UP_REQ_MSG_RDY ||
                        hpd_irq_data.bytes.device_service_irq.bits.DOWN_REP_MSG_RDY) {
-                       dm_handle_mst_sideband_msg(aconnector);
+                       bool skip = false;
+
+                       /*
+                        * DOWN_REP_MSG_RDY is also handled by polling method
+                        * mgr->cbs->poll_hpd_irq()
+                        */
+                       spin_lock(&offload_wq->offload_lock);
+                       skip = offload_wq->is_handling_mst_msg_rdy_event;
+
+                       if (!skip)
+                               offload_wq->is_handling_mst_msg_rdy_event = true;
+
+                       spin_unlock(&offload_wq->offload_lock);
+
+                       if (!skip)
+                               schedule_hpd_rx_offload_work(offload_wq, hpd_irq_data);
+
                        goto out;
                }
 
@@ -3468,7 +3409,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
                aconnector = to_amdgpu_dm_connector(connector);
                dc_link = aconnector->dc_link;
 
-               if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
+               if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
                        int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
                        int_params.irq_source = dc_link->irq_source_hpd;
 
@@ -3477,7 +3418,7 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
                                        (void *) aconnector);
                }
 
-               if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
+               if (dc_link->irq_source_hpd_rx != DC_IRQ_SOURCE_INVALID) {
 
                        /* Also register for DP short pulse (hpd_rx). */
                        int_params.int_context = INTERRUPT_LOW_IRQ_CONTEXT;
@@ -3486,11 +3427,11 @@ static void register_hpd_handlers(struct amdgpu_device *adev)
                        amdgpu_dm_irq_register_interrupt(adev, &int_params,
                                        handle_hpd_rx_irq,
                                        (void *) aconnector);
-
-                       if (adev->dm.hpd_rx_offload_wq)
-                               adev->dm.hpd_rx_offload_wq[dc_link->link_index].aconnector =
-                                       aconnector;
                }
+
+               if (adev->dm.hpd_rx_offload_wq)
+                       adev->dm.hpd_rx_offload_wq[connector->index].aconnector =
+                               aconnector;
        }
 }
 
@@ -3503,7 +3444,7 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
        struct dc_interrupt_params int_params = {0};
        int r;
        int i;
-       unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+       unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
 
        int_params.requested_polarity = INTERRUPT_POLARITY_DEFAULT;
        int_params.current_polarity = INTERRUPT_POLARITY_DEFAULT;
@@ -3517,11 +3458,12 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
         *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
         *    coming from DC hardware.
         *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
-        *    for acknowledging and handling. */
+        *    for acknowledging and handling.
+        */
 
        /* Use VBLANK interrupt */
        for (i = 0; i < adev->mode_info.num_crtc; i++) {
-               r = amdgpu_irq_add_id(adev, client_id, i+1 , &adev->crtc_irq);
+               r = amdgpu_irq_add_id(adev, client_id, i + 1, &adev->crtc_irq);
                if (r) {
                        DRM_ERROR("Failed to add crtc irq id!\n");
                        return r;
@@ -3529,7 +3471,7 @@ static int dce60_register_irq_handlers(struct amdgpu_device *adev)
 
                int_params.int_context = INTERRUPT_HIGH_IRQ_CONTEXT;
                int_params.irq_source =
-                       dc_interrupt_to_irq_source(dc, i+1 , 0);
+                       dc_interrupt_to_irq_source(dc, i + 1, 0);
 
                c_irq_params = &adev->dm.vblank_params[int_params.irq_source - DC_IRQ_SOURCE_VBLANK1];
 
@@ -3585,7 +3527,7 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
        struct dc_interrupt_params int_params = {0};
        int r;
        int i;
-       unsigned client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
+       unsigned int client_id = AMDGPU_IRQ_CLIENTID_LEGACY;
 
        if (adev->family >= AMDGPU_FAMILY_AI)
                client_id = SOC15_IH_CLIENTID_DCE;
@@ -3602,7 +3544,8 @@ static int dce110_register_irq_handlers(struct amdgpu_device *adev)
         *    Base driver will call amdgpu_dm_irq_handler() for ALL interrupts
         *    coming from DC hardware.
         *    amdgpu_dm_irq_handler() will re-direct the interrupt to DC
-        *    for acknowledging and handling. */
+        *    for acknowledging and handling.
+        */
 
        /* Use VBLANK interrupt */
        for (i = VISLANDS30_IV_SRCID_D1_VERTICAL_INTERRUPT0; i <= VISLANDS30_IV_SRCID_D6_VERTICAL_INTERRUPT0; i++) {
@@ -4049,7 +3992,7 @@ static void amdgpu_dm_update_backlight_caps(struct amdgpu_display_manager *dm,
 }
 
 static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
-                               unsigned *min, unsigned *max)
+                               unsigned int *min, unsigned int *max)
 {
        if (!caps)
                return 0;
@@ -4069,7 +4012,7 @@ static int get_brightness_range(const struct amdgpu_dm_backlight_caps *caps,
 static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *caps,
                                        uint32_t brightness)
 {
-       unsigned min, max;
+       unsigned int min, max;
 
        if (!get_brightness_range(caps, &min, &max))
                return brightness;
@@ -4082,7 +4025,7 @@ static u32 convert_brightness_from_user(const struct amdgpu_dm_backlight_caps *c
 static u32 convert_brightness_to_user(const struct amdgpu_dm_backlight_caps *caps,
                                      uint32_t brightness)
 {
-       unsigned min, max;
+       unsigned int min, max;
 
        if (!get_brightness_range(caps, &min, &max))
                return brightness;
@@ -4562,7 +4505,6 @@ fail:
 static void amdgpu_dm_destroy_drm_device(struct amdgpu_display_manager *dm)
 {
        drm_atomic_private_obj_fini(&dm->atomic_obj);
-       return;
 }
 
 /******************************************************************************
@@ -5394,6 +5336,7 @@ static bool adjust_colour_depth_from_display_info(
 {
        enum dc_color_depth depth = timing_out->display_color_depth;
        int normalized_clk;
+
        do {
                normalized_clk = timing_out->pix_clk_100hz / 10;
                /* YCbCr 4:2:0 requires additional adjustment of 1/2 */
@@ -5609,6 +5552,7 @@ create_fake_sink(struct amdgpu_dm_connector *aconnector)
 {
        struct dc_sink_init_data sink_init_data = { 0 };
        struct dc_sink *sink = NULL;
+
        sink_init_data.link = aconnector->dc_link;
        sink_init_data.sink_signal = aconnector->dc_link->connector_signal;
 
@@ -5732,7 +5676,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
                return &aconnector->freesync_vid_base;
 
        /* Find the preferred mode */
-       list_for_each_entry (m, list_head, head) {
+       list_for_each_entry(m, list_head, head) {
                if (m->type & DRM_MODE_TYPE_PREFERRED) {
                        m_pref = m;
                        break;
@@ -5756,7 +5700,7 @@ get_highest_refresh_rate_mode(struct amdgpu_dm_connector *aconnector,
         * For some monitors, preferred mode is not the mode with highest
         * supported refresh rate.
         */
-       list_for_each_entry (m, list_head, head) {
+       list_for_each_entry(m, list_head, head) {
                current_refresh  = drm_mode_vrefresh(m);
 
                if (m->hdisplay == m_pref->hdisplay &&
@@ -6028,7 +5972,7 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                 * This may not be an error, the use case is when we have no
                 * usermode calls to reset and set mode upon hotplug. In this
                 * case, we call set mode ourselves to restore the previous mode
-                * and the modelist may not be filled in in time.
+                * and the modelist may not be filled in time.
                 */
                DRM_DEBUG_DRIVER("No preferred mode found\n");
        } else {
@@ -6051,9 +5995,9 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,
                drm_mode_set_crtcinfo(&mode, 0);
 
        /*
-       * If scaling is enabled and refresh rate didn't change
-       * we copy the vic and polarities of the old timings
-       */
+        * If scaling is enabled and refresh rate didn't change
+        * we copy the vic and polarities of the old timings
+        */
        if (!scale || mode_refresh != preferred_refresh)
                fill_stream_properties_from_drm_display_mode(
                        stream, &mode, &aconnector->base, con_state, NULL,
@@ -6817,6 +6761,7 @@ static int dm_encoder_helper_atomic_check(struct drm_encoder *encoder,
 
        if (!state->duplicated) {
                int max_bpc = conn_state->max_requested_bpc;
+
                is_y420 = drm_mode_is_420_also(&connector->display_info, adjusted_mode) &&
                          aconnector->force_yuv420_output;
                color_depth = convert_color_depth_from_display_info(connector,
@@ -7135,7 +7080,7 @@ static bool is_duplicate_mode(struct amdgpu_dm_connector *aconnector,
 {
        struct drm_display_mode *m;
 
-       list_for_each_entry (m, &aconnector->base.probed_modes, head) {
+       list_for_each_entry(m, &aconnector->base.probed_modes, head) {
                if (drm_mode_equal(m, mode))
                        return true;
        }
@@ -7295,6 +7240,7 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        aconnector->as_type = ADAPTIVE_SYNC_TYPE_NONE;
        memset(&aconnector->vsdb_info, 0, sizeof(aconnector->vsdb_info));
        mutex_init(&aconnector->hpd_lock);
+       mutex_init(&aconnector->handle_mst_msg_ready);
 
        /*
         * configure support HPD hot plug connector_>polled default value is 0
@@ -7454,7 +7400,6 @@ static int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
 
        link->priv = aconnector;
 
-       DRM_DEBUG_DRIVER("%s()\n", __func__);
 
        i2c = create_i2c(link->ddc, link->link_index, &res);
        if (!i2c) {
@@ -8125,7 +8070,15 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                 * Only allow immediate flips for fast updates that don't
                 * change memory domain, FB pitch, DCC state, rotation or
                 * mirroring.
+                *
+                * dm_crtc_helper_atomic_check() only accepts async flips with
+                * fast updates.
                 */
+               if (crtc->state->async_flip &&
+                   acrtc_state->update_type != UPDATE_TYPE_FAST)
+                       drm_warn_once(state->dev,
+                                     "[PLANE:%d:%s] async flip with non-fast update\n",
+                                     plane->base.id, plane->name);
                bundle->flip_addrs[planes_count].flip_immediate =
                        crtc->state->async_flip &&
                        acrtc_state->update_type == UPDATE_TYPE_FAST &&
@@ -8168,8 +8121,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
                         * DRI3/Present extension with defined target_msc.
                         */
                        last_flip_vblank = amdgpu_get_vblank_counter_kms(pcrtc);
-               }
-               else {
+               } else {
                        /* For variable refresh rate mode only:
                         * Get vblank of last completed flip to avoid > 1 vrr
                         * flips per video frame by use of throttling, but allow
@@ -8502,8 +8454,8 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                dc_resource_state_copy_construct_current(dm->dc, dc_state);
        }
 
-       for_each_oldnew_crtc_in_state (state, crtc, old_crtc_state,
-                                      new_crtc_state, i) {
+       for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state,
+                                     new_crtc_state, i) {
                struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
 
                dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
@@ -8526,9 +8478,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
                dm_old_crtc_state = to_dm_crtc_state(old_crtc_state);
 
                drm_dbg_state(state->dev,
-                       "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
-                       "planes_changed:%d, mode_changed:%d,active_changed:%d,"
-                       "connectors_changed:%d\n",
+                       "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
                        acrtc->crtc_id,
                        new_crtc_state->enable,
                        new_crtc_state->active,
@@ -9104,8 +9054,8 @@ static int do_aquire_global_lock(struct drm_device *dev,
                                        &commit->flip_done, 10*HZ);
 
                if (ret == 0)
-                       DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done "
-                                 "timed out\n", crtc->base.id, crtc->name);
+                       DRM_ERROR("[CRTC:%d:%s] hw_done or flip_done timed out\n",
+                                 crtc->base.id, crtc->name);
 
                drm_crtc_commit_put(commit);
        }
@@ -9190,7 +9140,8 @@ is_timing_unchanged_for_freesync(struct drm_crtc_state *old_crtc_state,
        return false;
 }
 
-static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state) {
+static void set_freesync_fixed_config(struct dm_crtc_state *dm_new_crtc_state)
+{
        u64 num, den, res;
        struct drm_crtc_state *new_crtc_state = &dm_new_crtc_state->base;
 
@@ -9312,9 +9263,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                goto skip_modeset;
 
        drm_dbg_state(state->dev,
-               "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, "
-               "planes_changed:%d, mode_changed:%d,active_changed:%d,"
-               "connectors_changed:%d\n",
+               "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, planes_changed:%d, mode_changed:%d,active_changed:%d,connectors_changed:%d\n",
                acrtc->crtc_id,
                new_crtc_state->enable,
                new_crtc_state->active,
@@ -9343,8 +9292,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                                                     old_crtc_state)) {
                        new_crtc_state->mode_changed = false;
                        DRM_DEBUG_DRIVER(
-                               "Mode change not required for front porch change, "
-                               "setting mode_changed to %d",
+                               "Mode change not required for front porch change, setting mode_changed to %d",
                                new_crtc_state->mode_changed);
 
                        set_freesync_fixed_config(dm_new_crtc_state);
@@ -9356,9 +9304,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
                        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)) {
+                       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);
@@ -9526,6 +9473,7 @@ static bool should_reset_plane(struct drm_atomic_state *state,
         */
        for_each_oldnew_plane_in_state(state, other, old_other_state, new_other_state, i) {
                struct amdgpu_framebuffer *old_afb, *new_afb;
+
                if (other->type == DRM_PLANE_TYPE_CURSOR)
                        continue;
 
@@ -9624,11 +9572,12 @@ static int dm_check_cursor_fb(struct amdgpu_crtc *new_acrtc,
        }
 
        /* Core DRM takes care of checking FB modifiers, so we only need to
-        * check tiling flags when the FB doesn't have a modifier. */
+        * check tiling flags when the FB doesn't have a modifier.
+        */
        if (!(fb->flags & DRM_MODE_FB_MODIFIERS)) {
                if (adev->family < AMDGPU_FAMILY_AI) {
                        linear = AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_2D_TILED_THIN1 &&
-                                AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
+                                AMDGPU_TILING_GET(afb->tiling_flags, ARRAY_MODE) != DC_ARRAY_1D_TILED_THIN1 &&
                                 AMDGPU_TILING_GET(afb->tiling_flags, MICRO_TILE_MODE) == 0;
                } else {
                        linear = AMDGPU_TILING_GET(afb->tiling_flags, SWIZZLE_MODE) == 0;
@@ -9850,12 +9799,12 @@ static int dm_check_crtc_cursor(struct drm_atomic_state *state,
        /* On DCE and DCN there is no dedicated hardware cursor plane. We get a
         * cursor per pipe but it's going to inherit the scaling and
         * positioning from the underlying pipe. Check the cursor plane's
-        * blending properties match the underlying planes'. */
+        * blending properties match the underlying planes'.
+        */
 
        new_cursor_state = drm_atomic_get_new_plane_state(state, cursor);
-       if (!new_cursor_state || !new_cursor_state->fb) {
+       if (!new_cursor_state || !new_cursor_state->fb)
                return 0;
-       }
 
        dm_get_oriented_plane_size(new_cursor_state, &cursor_src_w, &cursor_src_h);
        cursor_scale_w = new_cursor_state->crtc_w * 1000 / cursor_src_w;
@@ -9900,6 +9849,7 @@ static int add_affected_mst_dsc_crtcs(struct drm_atomic_state *state, struct drm
        struct drm_connector_state *conn_state, *old_conn_state;
        struct amdgpu_dm_connector *aconnector = NULL;
        int i;
+
        for_each_oldnew_connector_in_state(state, connector, old_conn_state, conn_state, i) {
                if (!conn_state->crtc)
                        conn_state = old_conn_state;
@@ -10334,7 +10284,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        }
 
        /* Store the overall update type for use later in atomic check. */
-       for_each_new_crtc_in_state (state, crtc, new_crtc_state, i) {
+       for_each_new_crtc_in_state(state, crtc, new_crtc_state, i) {
                struct dm_crtc_state *dm_new_crtc_state =
                        to_dm_crtc_state(new_crtc_state);
 
@@ -10356,7 +10306,7 @@ fail:
        else if (ret == -EINTR || ret == -EAGAIN || ret == -ERESTARTSYS)
                DRM_DEBUG_DRIVER("Atomic check stopped due to signal.\n");
        else
-               DRM_DEBUG_DRIVER("Atomic check failed with err: %d \n", ret);
+               DRM_DEBUG_DRIVER("Atomic check failed with err: %d\n", ret);
 
        trace_amdgpu_dm_atomic_check_finish(state, ret);
 
index 4561f55..9fb5bb3 100644 (file)
@@ -195,6 +195,11 @@ struct hpd_rx_irq_offload_work_queue {
         */
        bool is_handling_link_loss;
        /**
+        * @is_handling_mst_msg_rdy_event: Used to prevent inserting mst message
+        * ready event when we're already handling mst message ready event
+        */
+       bool is_handling_mst_msg_rdy_event;
+       /**
         * @aconnector: The aconnector that this work queue is attached to
         */
        struct amdgpu_dm_connector *aconnector;
@@ -638,6 +643,8 @@ struct amdgpu_dm_connector {
        struct drm_dp_mst_port *mst_output_port;
        struct amdgpu_dm_connector *mst_root;
        struct drm_dp_aux *dsc_aux;
+       struct mutex handle_mst_msg_ready;
+
        /* TODO see if we can merge with ddc_bus or make a dm_connector */
        struct amdgpu_i2c_adapter *i2c;
 
index 440fc08..30d4c6f 100644 (file)
@@ -398,6 +398,18 @@ static int dm_crtc_helper_atomic_check(struct drm_crtc *crtc,
                return -EINVAL;
        }
 
+       /*
+        * Only allow async flips for fast updates that don't change the FB
+        * pitch, the DCC state, rotation, etc.
+        */
+       if (crtc_state->async_flip &&
+           dm_crtc_state->update_type != UPDATE_TYPE_FAST) {
+               drm_dbg_atomic(crtc->dev,
+                              "[CRTC:%d:%s] async flips are only supported for fast updates\n",
+                              crtc->base.id, crtc->name);
+               return -EINVAL;
+       }
+
        /* In some use cases, like reset, no stream is attached */
        if (!dm_crtc_state->stream)
                return 0;
index 46d0a8f..9bc86de 100644 (file)
@@ -619,8 +619,118 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
        return connector;
 }
 
+void dm_handle_mst_sideband_msg_ready_event(
+       struct drm_dp_mst_topology_mgr *mgr,
+       enum mst_msg_ready_type msg_rdy_type)
+{
+       uint8_t esi[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = { 0 };
+       uint8_t dret;
+       bool new_irq_handled = false;
+       int dpcd_addr;
+       uint8_t dpcd_bytes_to_read;
+       const uint8_t max_process_count = 30;
+       uint8_t process_count = 0;
+       u8 retry;
+       struct amdgpu_dm_connector *aconnector =
+                       container_of(mgr, struct amdgpu_dm_connector, mst_mgr);
+
+
+       const struct dc_link_status *link_status = dc_link_get_status(aconnector->dc_link);
+
+       if (link_status->dpcd_caps->dpcd_rev.raw < 0x12) {
+               dpcd_bytes_to_read = DP_LANE0_1_STATUS - DP_SINK_COUNT;
+               /* DPCD 0x200 - 0x201 for downstream IRQ */
+               dpcd_addr = DP_SINK_COUNT;
+       } else {
+               dpcd_bytes_to_read = DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI;
+               /* DPCD 0x2002 - 0x2005 for downstream IRQ */
+               dpcd_addr = DP_SINK_COUNT_ESI;
+       }
+
+       mutex_lock(&aconnector->handle_mst_msg_ready);
+
+       while (process_count < max_process_count) {
+               u8 ack[DP_PSR_ERROR_STATUS - DP_SINK_COUNT_ESI] = {};
+
+               process_count++;
+
+               dret = drm_dp_dpcd_read(
+                       &aconnector->dm_dp_aux.aux,
+                       dpcd_addr,
+                       esi,
+                       dpcd_bytes_to_read);
+
+               if (dret != dpcd_bytes_to_read) {
+                       DRM_DEBUG_KMS("DPCD read and acked number is not as expected!");
+                       break;
+               }
+
+               DRM_DEBUG_DRIVER("ESI %02x %02x %02x\n", esi[0], esi[1], esi[2]);
+
+               switch (msg_rdy_type) {
+               case DOWN_REP_MSG_RDY_EVENT:
+                       /* Only handle DOWN_REP_MSG_RDY case*/
+                       esi[1] &= DP_DOWN_REP_MSG_RDY;
+                       break;
+               case UP_REQ_MSG_RDY_EVENT:
+                       /* Only handle UP_REQ_MSG_RDY case*/
+                       esi[1] &= DP_UP_REQ_MSG_RDY;
+                       break;
+               default:
+                       /* Handle both cases*/
+                       esi[1] &= (DP_DOWN_REP_MSG_RDY | DP_UP_REQ_MSG_RDY);
+                       break;
+               }
+
+               if (!esi[1])
+                       break;
+
+               /* handle MST irq */
+               if (aconnector->mst_mgr.mst_state)
+                       drm_dp_mst_hpd_irq_handle_event(&aconnector->mst_mgr,
+                                                esi,
+                                                ack,
+                                                &new_irq_handled);
+
+               if (new_irq_handled) {
+                       /* ACK at DPCD to notify down stream */
+                       for (retry = 0; retry < 3; retry++) {
+                               ssize_t wret;
+
+                               wret = drm_dp_dpcd_writeb(&aconnector->dm_dp_aux.aux,
+                                                         dpcd_addr + 1,
+                                                         ack[1]);
+                               if (wret == 1)
+                                       break;
+                       }
+
+                       if (retry == 3) {
+                               DRM_ERROR("Failed to ack MST event.\n");
+                               break;
+                       }
+
+                       drm_dp_mst_hpd_irq_send_new_request(&aconnector->mst_mgr);
+
+                       new_irq_handled = false;
+               } else {
+                       break;
+               }
+       }
+
+       mutex_unlock(&aconnector->handle_mst_msg_ready);
+
+       if (process_count == max_process_count)
+               DRM_DEBUG_DRIVER("Loop exceeded max iterations\n");
+}
+
+static void dm_handle_mst_down_rep_msg_ready(struct drm_dp_mst_topology_mgr *mgr)
+{
+       dm_handle_mst_sideband_msg_ready_event(mgr, DOWN_REP_MSG_RDY_EVENT);
+}
+
 static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
        .add_connector = dm_dp_add_mst_connector,
+       .poll_hpd_irq = dm_handle_mst_down_rep_msg_ready,
 };
 
 void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
index 1e4ede1..37c820a 100644 (file)
 #define PBN_FEC_OVERHEAD_MULTIPLIER_8B_10B     1031
 #define PBN_FEC_OVERHEAD_MULTIPLIER_128B_132B  1000
 
+enum mst_msg_ready_type {
+       NONE_MSG_RDY_EVENT = 0,
+       DOWN_REP_MSG_RDY_EVENT = 1,
+       UP_REQ_MSG_RDY_EVENT = 2,
+       DOWN_OR_UP_MSG_RDY_EVENT = 3
+};
+
 struct amdgpu_display_manager;
 struct amdgpu_dm_connector;
 
@@ -61,6 +68,10 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,
 void
 dm_dp_create_fake_mst_encoders(struct amdgpu_device *adev);
 
+void dm_handle_mst_sideband_msg_ready_event(
+       struct drm_dp_mst_topology_mgr *mgr,
+       enum mst_msg_ready_type msg_rdy_type);
+
 struct dsc_mst_fairness_vars {
        int pbn;
        bool dsc_enabled;
index 7ccd969..3db4ef5 100644 (file)
@@ -87,6 +87,11 @@ static int dcn31_get_active_display_cnt_wa(
                                stream->signal == SIGNAL_TYPE_DVI_SINGLE_LINK ||
                                stream->signal == SIGNAL_TYPE_DVI_DUAL_LINK)
                        tmds_present = true;
+
+               /* Checking stream / link detection ensuring that PHY is active*/
+               if (dc_is_dp_signal(stream->signal) && !stream->dpms_off)
+                       display_count++;
+
        }
 
        for (i = 0; i < dc->link_count; i++) {
index 6c9ca43..20d4d08 100644 (file)
@@ -1792,10 +1792,13 @@ void dce110_enable_accelerated_mode(struct dc *dc, struct dc_state *context)
                        hws->funcs.edp_backlight_control(edp_link_with_sink, false);
                }
                /*resume from S3, no vbios posting, no need to power down again*/
+               clk_mgr_exit_optimized_pwr_state(dc, dc->clk_mgr);
+
                power_down_all_hw_blocks(dc);
                disable_vga_and_power_gate_all_controllers(dc);
                if (edp_link_with_sink && !keep_edp_vdd_on)
                        dc->hwss.edp_power_control(edp_link_with_sink, false);
+               clk_mgr_optimize_pwr_state(dc, dc->clk_mgr);
        }
        bios_set_scratch_acc_mode_change(dc->ctx->dc_bios, 1);
 }
index a503090..9834b75 100644 (file)
@@ -3278,7 +3278,8 @@ void dcn10_wait_for_mpcc_disconnect(
                if (pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst]) {
                        struct hubp *hubp = get_hubp_by_inst(res_pool, mpcc_inst);
 
-                       if (pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
+                       if (pipe_ctx->stream_res.tg &&
+                               pipe_ctx->stream_res.tg->funcs->is_tg_enabled(pipe_ctx->stream_res.tg))
                                res_pool->mpc->funcs->wait_for_idle(res_pool->mpc, mpcc_inst);
                        pipe_ctx->stream_res.opp->mpcc_disconnect_pending[mpcc_inst] = false;
                        hubp->funcs->set_blank(hubp, true);
index dfb8f62..5bf4d0a 100644 (file)
@@ -215,7 +215,7 @@ void optc3_set_odm_bypass(struct timing_generator *optc,
        optc1->opp_count = 1;
 }
 
-static void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
+void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
                struct dc_crtc_timing *timing)
 {
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
@@ -293,7 +293,7 @@ static void optc3_set_timing_double_buffer(struct timing_generator *optc, bool e
                   OTG_DRR_TIMING_DBUF_UPDATE_MODE, mode);
 }
 
-static void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc)
+void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc)
 {
        struct optc *optc1 = DCN10TG_FROM_TG(optc);
 
index fb06dc9..d3a056c 100644 (file)
@@ -351,6 +351,9 @@ void optc3_set_timing_db_mode(struct timing_generator *optc, bool enable);
 
 void optc3_set_odm_bypass(struct timing_generator *optc,
                const struct dc_crtc_timing *dc_crtc_timing);
+void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt,
+               struct dc_crtc_timing *timing);
+void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc);
 void optc3_tg_init(struct timing_generator *optc);
 void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max);
 #endif /* __DC_OPTC_DCN30_H__ */
index 7aa628c..9002cb1 100644 (file)
@@ -11,7 +11,8 @@
 # Makefile for dcn30.
 
 DCN301 = dcn301_init.o dcn301_resource.o dcn301_dccg.o \
-               dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o
+               dcn301_dio_link_encoder.o dcn301_hwseq.o dcn301_panel_cntl.o dcn301_hubbub.o \
+               dcn301_optc.o
 
 AMD_DAL_DCN301 = $(addprefix $(AMDDALPATH)/dc/dcn301/,$(DCN301))
 
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.c
new file mode 100644 (file)
index 0000000..b3cfcb8
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, 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: AMD
+ *
+ */
+
+#include "reg_helper.h"
+#include "dcn301_optc.h"
+#include "dc.h"
+#include "dcn_calc_math.h"
+#include "dc_dmub_srv.h"
+
+#include "dml/dcn30/dcn30_fpu.h"
+#include "dc_trace.h"
+
+#define REG(reg)\
+       optc1->tg_regs->reg
+
+#define CTX \
+       optc1->base.ctx
+
+#undef FN
+#define FN(reg_name, field_name) \
+       optc1->tg_shift->field_name, optc1->tg_mask->field_name
+
+
+/**
+ * optc301_set_drr() - Program dynamic refresh rate registers m_OTGx_OTG_V_TOTAL_*.
+ *
+ * @optc: timing_generator instance.
+ * @params: parameters used for Dynamic Refresh Rate.
+ */
+void optc301_set_drr(
+       struct timing_generator *optc,
+       const struct drr_params *params)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       if (params != NULL &&
+               params->vertical_total_max > 0 &&
+               params->vertical_total_min > 0) {
+
+               if (params->vertical_total_mid != 0) {
+
+                       REG_SET(OTG_V_TOTAL_MID, 0,
+                               OTG_V_TOTAL_MID, params->vertical_total_mid - 1);
+
+                       REG_UPDATE_2(OTG_V_TOTAL_CONTROL,
+                                       OTG_VTOTAL_MID_REPLACING_MAX_EN, 1,
+                                       OTG_VTOTAL_MID_FRAME_NUM,
+                                       (uint8_t)params->vertical_total_mid_frame_num);
+
+               }
+
+               optc->funcs->set_vtotal_min_max(optc, params->vertical_total_min - 1, params->vertical_total_max - 1);
+
+               REG_UPDATE_5(OTG_V_TOTAL_CONTROL,
+                               OTG_V_TOTAL_MIN_SEL, 1,
+                               OTG_V_TOTAL_MAX_SEL, 1,
+                               OTG_FORCE_LOCK_ON_EVENT, 0,
+                               OTG_SET_V_TOTAL_MIN_MASK_EN, 0,
+                               OTG_SET_V_TOTAL_MIN_MASK, 0);
+               // Setup manual flow control for EOF via TRIG_A
+               optc->funcs->setup_manual_trigger(optc);
+
+       } else {
+               REG_UPDATE_4(OTG_V_TOTAL_CONTROL,
+                               OTG_SET_V_TOTAL_MIN_MASK, 0,
+                               OTG_V_TOTAL_MIN_SEL, 0,
+                               OTG_V_TOTAL_MAX_SEL, 0,
+                               OTG_FORCE_LOCK_ON_EVENT, 0);
+
+               optc->funcs->set_vtotal_min_max(optc, 0, 0);
+       }
+}
+
+
+void optc301_setup_manual_trigger(struct timing_generator *optc)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       REG_SET_8(OTG_TRIGA_CNTL, 0,
+                       OTG_TRIGA_SOURCE_SELECT, 21,
+                       OTG_TRIGA_SOURCE_PIPE_SELECT, optc->inst,
+                       OTG_TRIGA_RISING_EDGE_DETECT_CNTL, 1,
+                       OTG_TRIGA_FALLING_EDGE_DETECT_CNTL, 0,
+                       OTG_TRIGA_POLARITY_SELECT, 0,
+                       OTG_TRIGA_FREQUENCY_SELECT, 0,
+                       OTG_TRIGA_DELAY, 0,
+                       OTG_TRIGA_CLEAR, 1);
+}
+
+static struct timing_generator_funcs dcn30_tg_funcs = {
+               .validate_timing = optc1_validate_timing,
+               .program_timing = optc1_program_timing,
+               .setup_vertical_interrupt0 = optc1_setup_vertical_interrupt0,
+               .setup_vertical_interrupt1 = optc1_setup_vertical_interrupt1,
+               .setup_vertical_interrupt2 = optc1_setup_vertical_interrupt2,
+               .program_global_sync = optc1_program_global_sync,
+               .enable_crtc = optc2_enable_crtc,
+               .disable_crtc = optc1_disable_crtc,
+               /* used by enable_timing_synchronization. Not need for FPGA */
+               .is_counter_moving = optc1_is_counter_moving,
+               .get_position = optc1_get_position,
+               .get_frame_count = optc1_get_vblank_counter,
+               .get_scanoutpos = optc1_get_crtc_scanoutpos,
+               .get_otg_active_size = optc1_get_otg_active_size,
+               .set_early_control = optc1_set_early_control,
+               /* used by enable_timing_synchronization. Not need for FPGA */
+               .wait_for_state = optc1_wait_for_state,
+               .set_blank_color = optc3_program_blank_color,
+               .did_triggered_reset_occur = optc1_did_triggered_reset_occur,
+               .triplebuffer_lock = optc3_triplebuffer_lock,
+               .triplebuffer_unlock = optc2_triplebuffer_unlock,
+               .enable_reset_trigger = optc1_enable_reset_trigger,
+               .enable_crtc_reset = optc1_enable_crtc_reset,
+               .disable_reset_trigger = optc1_disable_reset_trigger,
+               .lock = optc3_lock,
+               .unlock = optc1_unlock,
+               .lock_doublebuffer_enable = optc3_lock_doublebuffer_enable,
+               .lock_doublebuffer_disable = optc3_lock_doublebuffer_disable,
+               .enable_optc_clock = optc1_enable_optc_clock,
+               .set_drr = optc301_set_drr,
+               .get_last_used_drr_vtotal = optc2_get_last_used_drr_vtotal,
+               .set_vtotal_min_max = optc3_set_vtotal_min_max,
+               .set_static_screen_control = optc1_set_static_screen_control,
+               .program_stereo = optc1_program_stereo,
+               .is_stereo_left_eye = optc1_is_stereo_left_eye,
+               .tg_init = optc3_tg_init,
+               .is_tg_enabled = optc1_is_tg_enabled,
+               .is_optc_underflow_occurred = optc1_is_optc_underflow_occurred,
+               .clear_optc_underflow = optc1_clear_optc_underflow,
+               .setup_global_swap_lock = NULL,
+               .get_crc = optc1_get_crc,
+               .configure_crc = optc2_configure_crc,
+               .set_dsc_config = optc3_set_dsc_config,
+               .get_dsc_status = optc2_get_dsc_status,
+               .set_dwb_source = NULL,
+               .set_odm_bypass = optc3_set_odm_bypass,
+               .set_odm_combine = optc3_set_odm_combine,
+               .get_optc_source = optc2_get_optc_source,
+               .set_out_mux = optc3_set_out_mux,
+               .set_drr_trigger_window = optc3_set_drr_trigger_window,
+               .set_vtotal_change_limit = optc3_set_vtotal_change_limit,
+               .set_gsl = optc2_set_gsl,
+               .set_gsl_source_select = optc2_set_gsl_source_select,
+               .set_vtg_params = optc1_set_vtg_params,
+               .program_manual_trigger = optc2_program_manual_trigger,
+               .setup_manual_trigger = optc301_setup_manual_trigger,
+               .get_hw_timing = optc1_get_hw_timing,
+               .wait_drr_doublebuffer_pending_clear = optc3_wait_drr_doublebuffer_pending_clear,
+};
+
+void dcn301_timing_generator_init(struct optc *optc1)
+{
+       optc1->base.funcs = &dcn30_tg_funcs;
+
+       optc1->max_h_total = optc1->tg_mask->OTG_H_TOTAL + 1;
+       optc1->max_v_total = optc1->tg_mask->OTG_V_TOTAL + 1;
+
+       optc1->min_h_blank = 32;
+       optc1->min_v_blank = 3;
+       optc1->min_v_blank_interlace = 5;
+       optc1->min_h_sync_width = 4;
+       optc1->min_v_sync_width = 1;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h b/drivers/gpu/drm/amd/display/dc/dcn301/dcn301_optc.h
new file mode 100644 (file)
index 0000000..b495856
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2020 Advanced Micro Devices, 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: AMD
+ *
+ */
+
+#ifndef __DC_OPTC_DCN301_H__
+#define __DC_OPTC_DCN301_H__
+
+#include "dcn20/dcn20_optc.h"
+#include "dcn30/dcn30_optc.h"
+
+void dcn301_timing_generator_init(struct optc *optc1);
+void optc301_setup_manual_trigger(struct timing_generator *optc);
+void optc301_set_drr(struct timing_generator *optc, const struct drr_params *params);
+
+#endif /* __DC_OPTC_DCN301_H__ */
index 3485fbb..1bee9a4 100644 (file)
@@ -42,7 +42,7 @@
 #include "dcn30/dcn30_hubp.h"
 #include "irq/dcn30/irq_service_dcn30.h"
 #include "dcn30/dcn30_dpp.h"
-#include "dcn30/dcn30_optc.h"
+#include "dcn301/dcn301_optc.h"
 #include "dcn20/dcn20_hwseq.h"
 #include "dcn30/dcn30_hwseq.h"
 #include "dce110/dce110_hw_sequencer.h"
@@ -855,7 +855,7 @@ static struct timing_generator *dcn301_timing_generator_create(
        tgn10->tg_shift = &optc_shift;
        tgn10->tg_mask = &optc_mask;
 
-       dcn30_timing_generator_init(tgn10);
+       dcn301_timing_generator_init(tgn10);
 
        return &tgn10->base;
 }
index 45956ef..131b8b8 100644 (file)
@@ -65,7 +65,7 @@ static const struct dc_debug_options debug_defaults_drv = {
                .timing_trace = false,
                .clock_trace = true,
                .disable_pplib_clock_request = true,
-               .pipe_split_policy = MPC_SPLIT_DYNAMIC,
+               .pipe_split_policy = MPC_SPLIT_AVOID,
                .force_single_disp_pipe_split = false,
                .disable_dcc = DCC_ENABLE,
                .vsr_support = true,
index 65c1d75..01cc679 100644 (file)
@@ -84,7 +84,8 @@ static enum phyd32clk_clock_source get_phy_mux_symclk(
                struct dcn_dccg *dccg_dcn,
                enum phyd32clk_clock_source src)
 {
-       if (dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
+       if (dccg_dcn->base.ctx->asic_id.chip_family == FAMILY_YELLOW_CARP &&
+                       dccg_dcn->base.ctx->asic_id.hw_internal_rev == YELLOW_CARP_B0) {
                if (src == PHYD32CLKC)
                        src = PHYD32CLKF;
                if (src == PHYD32CLKD)
index 11e28e0..61ceff6 100644 (file)
@@ -49,7 +49,10 @@ static void dccg32_trigger_dio_fifo_resync(
        uint32_t dispclk_rdivider_value = 0;
 
        REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_RDIVIDER, &dispclk_rdivider_value);
-       REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
+
+       /* Not valid for the WDIVIDER to be set to 0 */
+       if (dispclk_rdivider_value != 0)
+               REG_UPDATE(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, dispclk_rdivider_value);
 }
 
 static void dccg32_get_pixel_rate_div(
index d9e049e..ed8ddb7 100644 (file)
@@ -295,7 +295,11 @@ int dcn314_populate_dml_pipes_from_context_fpu(struct dc *dc, struct dc_state *c
                pipe = &res_ctx->pipe_ctx[i];
                timing = &pipe->stream->timing;
 
-               pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min;
+               if (pipe->stream->adjust.v_total_min != 0)
+                       pipes[pipe_cnt].pipe.dest.vtotal = pipe->stream->adjust.v_total_min;
+               else
+                       pipes[pipe_cnt].pipe.dest.vtotal = timing->v_total;
+
                pipes[pipe_cnt].pipe.dest.vblank_nom = timing->v_total - pipes[pipe_cnt].pipe.dest.vactive;
                pipes[pipe_cnt].pipe.dest.vblank_nom = min(pipes[pipe_cnt].pipe.dest.vblank_nom, dcn3_14_ip.VBlankNomDefaultUS);
                pipes[pipe_cnt].pipe.dest.vblank_nom = max(pipes[pipe_cnt].pipe.dest.vblank_nom, timing->v_sync_width);
index 6841a4b..1cb4022 100644 (file)
@@ -1798,17 +1798,6 @@ static int smu7_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
        return result;
 }
 
-static bool intel_core_rkl_chk(void)
-{
-#if IS_ENABLED(CONFIG_X86_64)
-       struct cpuinfo_x86 *c = &cpu_data(0);
-
-       return (c->x86 == 6 && c->x86_model == INTEL_FAM6_ROCKETLAKE);
-#else
-       return false;
-#endif
-}
-
 static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
 {
        struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
@@ -1835,7 +1824,8 @@ static void smu7_init_dpm_defaults(struct pp_hwmgr *hwmgr)
        data->mclk_dpm_key_disabled = hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
        data->sclk_dpm_key_disabled = hwmgr->feature_mask & PP_SCLK_DPM_MASK ? false : true;
        data->pcie_dpm_key_disabled =
-               intel_core_rkl_chk() || !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
+               !amdgpu_device_pcie_dynamic_switching_supported() ||
+               !(hwmgr->feature_mask & PP_PCIE_DPM_MASK);
        /* need to set voltage control types before EVV patching */
        data->voltage_control = SMU7_VOLTAGE_CONTROL_NONE;
        data->vddci_control = SMU7_VOLTAGE_CONTROL_NONE;
index f6599c0..0cda3b2 100644 (file)
@@ -1927,12 +1927,16 @@ static int sienna_cichlid_read_sensor(struct smu_context *smu,
                *size = 4;
                break;
        case AMDGPU_PP_SENSOR_GFX_MCLK:
-               ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_UCLK, (uint32_t *)data);
+               ret = sienna_cichlid_get_smu_metrics_data(smu,
+                                                         METRICS_CURR_UCLK,
+                                                         (uint32_t *)data);
                *(uint32_t *)data *= 100;
                *size = 4;
                break;
        case AMDGPU_PP_SENSOR_GFX_SCLK:
-               ret = sienna_cichlid_get_current_clk_freq_by_table(smu, SMU_GFXCLK, (uint32_t *)data);
+               ret = sienna_cichlid_get_smu_metrics_data(smu,
+                                                         METRICS_AVERAGE_GFXCLK,
+                                                         (uint32_t *)data);
                *(uint32_t *)data *= 100;
                *size = 4;
                break;
index b9bde5f..3d18861 100644 (file)
@@ -1734,7 +1734,7 @@ static ssize_t smu_v13_0_0_get_gpu_metrics(struct smu_context *smu,
        gpu_metrics->average_vclk1_frequency = metrics->AverageVclk1Frequency;
        gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
 
-       gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+       gpu_metrics->current_gfxclk = gpu_metrics->average_gfxclk_frequency;
        gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
        gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
        gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
index 3ba0213..b1f0937 100644 (file)
@@ -949,7 +949,7 @@ static int smu_v13_0_7_read_sensor(struct smu_context *smu,
                break;
        case AMDGPU_PP_SENSOR_GFX_MCLK:
                ret = smu_v13_0_7_get_smu_metrics_data(smu,
-                                                      METRICS_AVERAGE_UCLK,
+                                                      METRICS_CURR_UCLK,
                                                       (uint32_t *)data);
                *(uint32_t *)data *= 100;
                *size = 4;
index 2c45456..c277b19 100644 (file)
@@ -140,6 +140,12 @@ drm_atomic_state_init(struct drm_device *dev, struct drm_atomic_state *state)
        if (!state->planes)
                goto fail;
 
+       /*
+        * Because drm_atomic_state can be committed asynchronously we need our
+        * own reference and cannot rely on the on implied by drm_file in the
+        * ioctl call.
+        */
+       drm_dev_get(dev);
        state->dev = dev;
 
        drm_dbg_atomic(dev, "Allocated atomic state %p\n", state);
@@ -299,7 +305,8 @@ EXPORT_SYMBOL(drm_atomic_state_clear);
 void __drm_atomic_state_free(struct kref *ref)
 {
        struct drm_atomic_state *state = container_of(ref, typeof(*state), ref);
-       struct drm_mode_config *config = &state->dev->mode_config;
+       struct drm_device *dev = state->dev;
+       struct drm_mode_config *config = &dev->mode_config;
 
        drm_atomic_state_clear(state);
 
@@ -311,6 +318,8 @@ void __drm_atomic_state_free(struct kref *ref)
                drm_atomic_state_default_release(state);
                kfree(state);
        }
+
+       drm_dev_put(dev);
 }
 EXPORT_SYMBOL(__drm_atomic_state_free);
 
index 1b12a3c..871e4e2 100644 (file)
@@ -311,6 +311,9 @@ static bool drm_client_target_cloned(struct drm_device *dev,
        can_clone = true;
        dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
 
+       if (!dmt_mode)
+               goto fail;
+
        for (i = 0; i < connector_count; i++) {
                if (!enabled[i])
                        continue;
@@ -326,11 +329,13 @@ static bool drm_client_target_cloned(struct drm_device *dev,
                if (!modes[i])
                        can_clone = false;
        }
+       kfree(dmt_mode);
 
        if (can_clone) {
                DRM_DEBUG_KMS("can clone using 1024x768\n");
                return true;
        }
+fail:
        DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
        return false;
 }
@@ -862,6 +867,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
                                break;
                        }
 
+                       kfree(modeset->mode);
                        modeset->mode = drm_mode_duplicate(dev, mode);
                        drm_connector_get(connector);
                        modeset->connectors[modeset->num_connectors++] = connector;
index 789dce9..dcbda9b 100644 (file)
@@ -23,6 +23,11 @@ subdir-ccflags-y += $(call cc-option, -Wunused-but-set-variable)
 subdir-ccflags-y += $(call cc-disable-warning, frame-address)
 subdir-ccflags-$(CONFIG_DRM_I915_WERROR) += -Werror
 
+# Fine grained warnings disable
+CFLAGS_i915_pci.o = $(call cc-disable-warning, override-init)
+CFLAGS_display/intel_display_device.o = $(call cc-disable-warning, override-init)
+CFLAGS_display/intel_fbdev.o = $(call cc-disable-warning, override-init)
+
 subdir-ccflags-y += -I$(srctree)/$(src)
 
 # Please keep these build lists sorted!
index 3fd30e7..f0ee9bc 100644 (file)
@@ -16,9 +16,6 @@
 #include "intel_display_reg_defs.h"
 #include "intel_fbc.h"
 
-__diag_push();
-__diag_ignore_all("-Woverride-init", "Allow overriding inherited members");
-
 static const struct intel_display_device_info no_display = {};
 
 #define PIPE_A_OFFSET          0x70000
@@ -665,8 +662,6 @@ static const struct intel_display_device_info xe_lpdp_display = {
                BIT(TRANSCODER_C) | BIT(TRANSCODER_D),
 };
 
-__diag_pop();
-
 #undef INTEL_VGA_DEVICE
 #undef INTEL_QUANTA_VGA_DEVICE
 #define INTEL_VGA_DEVICE(id, info) { id, info }
index 7c5fddb..fbfd8f9 100644 (file)
@@ -166,6 +166,8 @@ struct i915_vma *intel_dpt_pin(struct i915_address_space *vm)
                i915_vma_get(vma);
        }
 
+       dpt->obj->mm.dirty = true;
+
        atomic_dec(&i915->gpu_error.pending_fb_pin);
        intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 
@@ -261,7 +263,7 @@ intel_dpt_create(struct intel_framebuffer *fb)
                dpt_obj = i915_gem_object_create_stolen(i915, size);
        if (IS_ERR(dpt_obj) && !HAS_LMEM(i915)) {
                drm_dbg_kms(&i915->drm, "Allocating dpt from smem\n");
-               dpt_obj = i915_gem_object_create_internal(i915, size);
+               dpt_obj = i915_gem_object_create_shmem(i915, size);
        }
        if (IS_ERR(dpt_obj))
                return ERR_CAST(dpt_obj);
index 1cc0ddc..80c3f88 100644 (file)
@@ -135,9 +135,6 @@ static int intel_fbdev_mmap(struct fb_info *info, struct vm_area_struct *vma)
        return i915_gem_fb_mmap(obj, vma);
 }
 
-__diag_push();
-__diag_ignore_all("-Woverride-init", "Allow overriding the default ops");
-
 static const struct fb_ops intelfb_ops = {
        .owner = THIS_MODULE,
        __FB_DEFAULT_DEFERRED_OPS_RDWR(intel_fbdev),
@@ -149,8 +146,6 @@ static const struct fb_ops intelfb_ops = {
        .fb_mmap = intel_fbdev_mmap,
 };
 
-__diag_pop();
-
 static int intelfb_alloc(struct drm_fb_helper *helper,
                         struct drm_fb_helper_surface_size *sizes)
 {
index df6c9a8..6b9f6cf 100644 (file)
@@ -1246,8 +1246,10 @@ static int igt_write_huge(struct drm_i915_private *i915,
         * times in succession a possibility by enlarging the permutation array.
         */
        order = i915_random_order(count * count, &prng);
-       if (!order)
-               return -ENOMEM;
+       if (!order) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        max_page_size = rounddown_pow_of_two(obj->mm.page_sizes.sg);
        max = div_u64(max - size, max_page_size);
index 3d7a5db..928975d 100644 (file)
@@ -38,9 +38,6 @@
 #include "i915_reg.h"
 #include "intel_pci_config.h"
 
-__diag_push();
-__diag_ignore_all("-Woverride-init", "Allow overriding inherited members");
-
 #define PLATFORM(x) .platform = (x)
 #define GEN(x) \
        .__runtime.graphics.ip.ver = (x), \
@@ -846,8 +843,6 @@ static const struct intel_device_info mtl_info = {
 
 #undef PLATFORM
 
-__diag_pop();
-
 /*
  * Make sure any device matches here are from most specific to most
  * general.  For example, since the Quanta match is based on the subsystem
index 7413c11..49c6f1f 100644 (file)
@@ -4431,6 +4431,7 @@ static const struct i915_range mtl_oam_b_counters[] = {
 static const struct i915_range xehp_oa_b_counters[] = {
        { .start = 0xdc48, .end = 0xdc48 },     /* OAA_ENABLE_REG */
        { .start = 0xdd00, .end = 0xdd48 },     /* OAG_LCE0_0 - OAA_LENABLE_REG */
+       {}
 };
 
 static const struct i915_range gen7_oa_mux_regs[] = {
index a99310b..bbb1bf3 100644 (file)
@@ -89,7 +89,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit
                         * since we've already mapped it once in
                         * submit_reloc()
                         */
-                       if (WARN_ON(!ptr))
+                       if (WARN_ON(IS_ERR_OR_NULL(ptr)))
                                return;
 
                        for (i = 0; i < dwords; i++) {
index 790f55e..e788ed7 100644 (file)
@@ -206,7 +206,7 @@ static const struct a6xx_shader_block {
        SHADER(A6XX_SP_LB_3_DATA, 0x800),
        SHADER(A6XX_SP_LB_4_DATA, 0x800),
        SHADER(A6XX_SP_LB_5_DATA, 0x200),
-       SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x2000),
+       SHADER(A6XX_SP_CB_BINDLESS_DATA, 0x800),
        SHADER(A6XX_SP_CB_LEGACY_DATA, 0x280),
        SHADER(A6XX_SP_UAV_DATA, 0x80),
        SHADER(A6XX_SP_INST_TAG, 0x80),
index cb94cfd..ce8d0b2 100644 (file)
@@ -369,8 +369,6 @@ static const struct adreno_info gpulist[] = {
                .hwcg = a640_hwcg,
        }, {
                .rev = ADRENO_REV(6, 9, 0, ANY_ID),
-               .revn = 690,
-               .name = "A690",
                .fw = {
                        [ADRENO_FW_SQE] = "a660_sqe.fw",
                        [ADRENO_FW_GMU] = "a690_gmu.bin",
index d8c9e8c..8450198 100644 (file)
@@ -149,7 +149,8 @@ bool adreno_cmp_rev(struct adreno_rev rev1, struct adreno_rev rev2);
 
 static inline bool adreno_is_revn(const struct adreno_gpu *gpu, uint32_t revn)
 {
-       WARN_ON_ONCE(!gpu->revn);
+       /* revn can be zero, but if not is set at same time as info */
+       WARN_ON_ONCE(!gpu->info);
 
        return gpu->revn == revn;
 }
@@ -161,14 +162,16 @@ static inline bool adreno_has_gmu_wrapper(const struct adreno_gpu *gpu)
 
 static inline bool adreno_is_a2xx(const struct adreno_gpu *gpu)
 {
-       WARN_ON_ONCE(!gpu->revn);
+       /* revn can be zero, but if not is set at same time as info */
+       WARN_ON_ONCE(!gpu->info);
 
        return (gpu->revn < 300);
 }
 
 static inline bool adreno_is_a20x(const struct adreno_gpu *gpu)
 {
-       WARN_ON_ONCE(!gpu->revn);
+       /* revn can be zero, but if not is set at same time as info */
+       WARN_ON_ONCE(!gpu->info);
 
        return (gpu->revn < 210);
 }
@@ -307,7 +310,8 @@ static inline int adreno_is_a680(const struct adreno_gpu *gpu)
 
 static inline int adreno_is_a690(const struct adreno_gpu *gpu)
 {
-       return adreno_is_revn(gpu, 690);
+       /* The order of args is important here to handle ANY_ID correctly */
+       return adreno_cmp_rev(ADRENO_REV(6, 9, 0, ANY_ID), gpu->rev);
 };
 
 /* check for a615, a616, a618, a619 or any derivatives */
index e379599..29bb8ee 100644 (file)
 #define        DPU_PERF_DEFAULT_MAX_CORE_CLK_RATE      412500000
 
 /**
- * enum dpu_core_perf_data_bus_id - data bus identifier
- * @DPU_CORE_PERF_DATA_BUS_ID_MNOC: DPU/MNOC data bus
- * @DPU_CORE_PERF_DATA_BUS_ID_LLCC: MNOC/LLCC data bus
- * @DPU_CORE_PERF_DATA_BUS_ID_EBI: LLCC/EBI data bus
- */
-enum dpu_core_perf_data_bus_id {
-       DPU_CORE_PERF_DATA_BUS_ID_MNOC,
-       DPU_CORE_PERF_DATA_BUS_ID_LLCC,
-       DPU_CORE_PERF_DATA_BUS_ID_EBI,
-       DPU_CORE_PERF_DATA_BUS_ID_MAX,
-};
-
-/**
  * struct dpu_core_perf_params - definition of performance parameters
  * @max_per_pipe_ib: maximum instantaneous bandwidth request
  * @bw_ctl: arbitrated bandwidth request
index c278fb9..86182c7 100644 (file)
@@ -51,7 +51,7 @@
 
 static const u32 fetch_tbl[SSPP_MAX] = {CTL_INVALID_BIT, 16, 17, 18, 19,
        CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, CTL_INVALID_BIT, 0,
-       1, 2, 3, CTL_INVALID_BIT, CTL_INVALID_BIT};
+       1, 2, 3, 4, 5};
 
 static int _mixer_stages(const struct dpu_lm_cfg *mixer, int count,
                enum dpu_lm lm)
@@ -198,6 +198,12 @@ static void dpu_hw_ctl_update_pending_flush_sspp(struct dpu_hw_ctl *ctx,
        case SSPP_DMA3:
                ctx->pending_flush_mask |= BIT(25);
                break;
+       case SSPP_DMA4:
+               ctx->pending_flush_mask |= BIT(13);
+               break;
+       case SSPP_DMA5:
+               ctx->pending_flush_mask |= BIT(14);
+               break;
        case SSPP_CURSOR0:
                ctx->pending_flush_mask |= BIT(22);
                break;
index 3ce45b0..31deda1 100644 (file)
@@ -1087,8 +1087,6 @@ const struct msm_dsi_phy_cfg dsi_phy_14nm_8953_cfgs = {
 
 const struct msm_dsi_phy_cfg dsi_phy_14nm_2290_cfgs = {
        .has_phy_lane = true,
-       .regulator_data = dsi_phy_14nm_17mA_regulators,
-       .num_regulators = ARRAY_SIZE(dsi_phy_14nm_17mA_regulators),
        .ops = {
                .enable = dsi_14nm_phy_enable,
                .disable = dsi_14nm_phy_disable,
index 96599ec..1a5d4f1 100644 (file)
@@ -191,6 +191,12 @@ msm_fence_init(struct dma_fence *fence, struct msm_fence_context *fctx)
 
        f->fctx = fctx;
 
+       /*
+        * Until this point, the fence was just some pre-allocated memory,
+        * no-one should have taken a reference to it yet.
+        */
+       WARN_ON(kref_read(&fence->refcount));
+
        dma_fence_init(&f->base, &msm_fence_ops, &fctx->spinlock,
                       fctx->context, ++fctx->last_fence);
 }
index 3f1aa4d..63c9641 100644 (file)
@@ -86,7 +86,19 @@ void __msm_gem_submit_destroy(struct kref *kref)
        }
 
        dma_fence_put(submit->user_fence);
-       dma_fence_put(submit->hw_fence);
+
+       /*
+        * If the submit is freed before msm_job_run(), then hw_fence is
+        * just some pre-allocated memory, not a reference counted fence.
+        * Once the job runs and the hw_fence is initialized, it will
+        * have a refcount of at least one, since the submit holds a ref
+        * to the hw_fence.
+        */
+       if (kref_read(&submit->hw_fence->refcount) == 0) {
+               kfree(submit->hw_fence);
+       } else {
+               dma_fence_put(submit->hw_fence);
+       }
 
        put_pid(submit->pid);
        msm_submitqueue_put(submit->queue);
@@ -889,7 +901,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
         * after the job is armed
         */
        if ((args->flags & MSM_SUBMIT_FENCE_SN_IN) &&
-                       idr_find(&queue->fence_idr, args->fence)) {
+                       (!args->fence || idr_find(&queue->fence_idr, args->fence))) {
                spin_unlock(&queue->idr_lock);
                idr_preload_end();
                ret = -EINVAL;
index 05648c9..798bd4f 100644 (file)
@@ -189,6 +189,7 @@ static int _msm_mdss_irq_domain_add(struct msm_mdss *msm_mdss)
 #define UBWC_2_0 0x20000000
 #define UBWC_3_0 0x30000000
 #define UBWC_4_0 0x40000000
+#define UBWC_4_3 0x40030000
 
 static void msm_mdss_setup_ubwc_dec_20(struct msm_mdss *msm_mdss)
 {
@@ -227,7 +228,10 @@ static void msm_mdss_setup_ubwc_dec_40(struct msm_mdss *msm_mdss)
                writel_relaxed(1, msm_mdss->mmio + UBWC_CTRL_2);
                writel_relaxed(0, msm_mdss->mmio + UBWC_PREDICTION_MODE);
        } else {
-               writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
+               if (data->ubwc_dec_version == UBWC_4_3)
+                       writel_relaxed(3, msm_mdss->mmio + UBWC_CTRL_2);
+               else
+                       writel_relaxed(2, msm_mdss->mmio + UBWC_CTRL_2);
                writel_relaxed(1, msm_mdss->mmio + UBWC_PREDICTION_MODE);
        }
 }
@@ -271,6 +275,7 @@ static int msm_mdss_enable(struct msm_mdss *msm_mdss)
                msm_mdss_setup_ubwc_dec_30(msm_mdss);
                break;
        case UBWC_4_0:
+       case UBWC_4_3:
                msm_mdss_setup_ubwc_dec_40(msm_mdss);
                break;
        default:
@@ -569,6 +574,16 @@ static const struct msm_mdss_data sm8250_data = {
        .macrotile_mode = 1,
 };
 
+static const struct msm_mdss_data sm8550_data = {
+       .ubwc_version = UBWC_4_0,
+       .ubwc_dec_version = UBWC_4_3,
+       .ubwc_swizzle = 6,
+       .ubwc_static = 1,
+       /* TODO: highest_bank_bit = 2 for LP_DDR4 */
+       .highest_bank_bit = 3,
+       .macrotile_mode = 1,
+};
+
 static const struct of_device_id mdss_dt_match[] = {
        { .compatible = "qcom,mdss" },
        { .compatible = "qcom,msm8998-mdss" },
@@ -585,7 +600,7 @@ static const struct of_device_id mdss_dt_match[] = {
        { .compatible = "qcom,sm8250-mdss", .data = &sm8250_data },
        { .compatible = "qcom,sm8350-mdss", .data = &sm8250_data },
        { .compatible = "qcom,sm8450-mdss", .data = &sm8250_data },
-       { .compatible = "qcom,sm8550-mdss", .data = &sm8250_data },
+       { .compatible = "qcom,sm8550-mdss", .data = &sm8550_data },
        {}
 };
 MODULE_DEVICE_TABLE(of, mdss_dt_match);
index 38d3fad..1bec819 100644 (file)
@@ -1877,6 +1877,8 @@ nv50_pior_destroy(struct drm_encoder *encoder)
        nvif_outp_dtor(&nv_encoder->outp);
 
        drm_encoder_cleanup(encoder);
+
+       mutex_destroy(&nv_encoder->dp.hpd_irq_lock);
        kfree(encoder);
 }
 
@@ -1921,6 +1923,8 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
        nv_encoder->i2c = ddc;
        nv_encoder->aux = aux;
 
+       mutex_init(&nv_encoder->dp.hpd_irq_lock);
+
        encoder = to_drm_encoder(nv_encoder);
        encoder->possible_crtcs = dcbe->heads;
        encoder->possible_clones = 0;
index 40a1065..ef441df 100644 (file)
@@ -16,7 +16,7 @@ struct nvkm_i2c_bus {
        const struct nvkm_i2c_bus_func *func;
        struct nvkm_i2c_pad *pad;
 #define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */                           (n)
-#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
+#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */  ((n) + 0x10)
 #define NVKM_I2C_BUS_PRI /* ccb primary comm. port */                        -1
 #define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */                      -2
        int id;
@@ -38,7 +38,7 @@ struct nvkm_i2c_aux {
        const struct nvkm_i2c_aux_func *func;
        struct nvkm_i2c_pad *pad;
 #define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */                           (n)
-#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
+#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */  ((n) + 0x10)
        int id;
 
        struct mutex mutex;
index dad942b..46b057f 100644 (file)
@@ -81,20 +81,29 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_
                return -ENOSYS;
 
        list_for_each_entry(outp, &conn->disp->outps, head) {
-               if (outp->info.connector == conn->index && outp->dp.aux) {
-                       if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG  ) bits |= NVKM_I2C_PLUG;
-                       if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
-                       if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ   ) bits |= NVKM_I2C_IRQ;
+               if (outp->info.connector == conn->index)
+                       break;
+       }
 
-                       return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
-                                              nvkm_uconn_uevent_aux);
-               }
+       if (&outp->head == &conn->disp->outps)
+               return -EINVAL;
+
+       if (outp->dp.aux && !outp->info.location) {
+               if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG  ) bits |= NVKM_I2C_PLUG;
+               if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
+               if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ   ) bits |= NVKM_I2C_IRQ;
+
+               return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
+                                      nvkm_uconn_uevent_aux);
        }
 
        if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG  ) bits |= NVKM_GPIO_HI;
        if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO;
-       if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ)
-               return -EINVAL;
+       if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) {
+               /* TODO: support DP IRQ on ANX9805 and remove this hack. */
+               if (!outp->info.location)
+                       return -EINVAL;
+       }
 
        return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits,
                               nvkm_uconn_uevent_gpio);
index 976539d..731b2f6 100644 (file)
@@ -260,10 +260,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
 {
        struct nvkm_bios *bios = device->bios;
        struct nvkm_i2c *i2c;
+       struct nvkm_i2c_aux *aux;
        struct dcb_i2c_entry ccbE;
        struct dcb_output dcbE;
        u8 ver, hdr;
-       int ret, i;
+       int ret, i, ids;
 
        if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL)))
                return -ENOMEM;
@@ -406,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
                }
        }
 
-       return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event);
+       ids = 0;
+       list_for_each_entry(aux, &i2c->aux, head)
+               ids = max(ids, aux->id + 1);
+       if (!ids)
+               return 0;
+
+       return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event);
 }
index a981f70..a997dbc 100644 (file)
@@ -1027,7 +1027,7 @@ static int aqc_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
                        if (ret < 0)
                                return ret;
 
-                       *val = aqc_percent_to_pwm(ret);
+                       *val = aqc_percent_to_pwm(*val);
                        break;
                }
                break;
index 7b177b9..a267b11 100644 (file)
@@ -77,6 +77,13 @@ static DEFINE_MUTEX(nb_smu_ind_mutex);
 #define ZEN_CUR_TEMP_RANGE_SEL_MASK            BIT(19)
 #define ZEN_CUR_TEMP_TJ_SEL_MASK               GENMASK(17, 16)
 
+/*
+ * AMD's Industrial processor 3255 supports temperature from -40 deg to 105 deg Celsius.
+ * Use the model name to identify 3255 CPUs and set a flag to display negative temperature.
+ * Do not round off to zero for negative Tctl or Tdie values if the flag is set
+ */
+#define AMD_I3255_STR                          "3255"
+
 struct k10temp_data {
        struct pci_dev *pdev;
        void (*read_htcreg)(struct pci_dev *pdev, u32 *regval);
@@ -86,6 +93,7 @@ struct k10temp_data {
        u32 show_temp;
        bool is_zen;
        u32 ccd_offset;
+       bool disp_negative;
 };
 
 #define TCTL_BIT       0
@@ -204,12 +212,12 @@ static int k10temp_read_temp(struct device *dev, u32 attr, int channel,
                switch (channel) {
                case 0:         /* Tctl */
                        *val = get_raw_temp(data);
-                       if (*val < 0)
+                       if (*val < 0 && !data->disp_negative)
                                *val = 0;
                        break;
                case 1:         /* Tdie */
                        *val = get_raw_temp(data) - data->temp_offset;
-                       if (*val < 0)
+                       if (*val < 0 && !data->disp_negative)
                                *val = 0;
                        break;
                case 2 ... 13:          /* Tccd{1-12} */
@@ -405,6 +413,11 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        data->pdev = pdev;
        data->show_temp |= BIT(TCTL_BIT);       /* Always show Tctl */
 
+       if (boot_cpu_data.x86 == 0x17 &&
+           strstr(boot_cpu_data.x86_model_id, AMD_I3255_STR)) {
+               data->disp_negative = true;
+       }
+
        if (boot_cpu_data.x86 == 0x15 &&
            ((boot_cpu_data.x86_model & 0xf0) == 0x60 ||
             (boot_cpu_data.x86_model & 0xf0) == 0x70)) {
index 236dc97..08ce498 100644 (file)
@@ -955,14 +955,25 @@ static const u16 scale_in[15] = {
        800, 800
 };
 
-static inline long in_from_reg(u8 reg, u8 nr)
+/*
+ * NCT6798 scaling:
+ *    CPUVC, IN1, AVSB, 3VCC, IN0, IN8, IN4, 3VSB, VBAT,  VTT,  IN5,  IN6, IN2,
+ *      IN3, IN7
+ * Additional scales to be added later: IN9 (800), VHIF (1600)
+ */
+static const u16 scale_in_6798[15] = {
+       800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 1600, 1600, 1600, 800,
+       800, 800
+};
+
+static inline long in_from_reg(u8 reg, u8 nr, const u16 *scales)
 {
-       return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
+       return DIV_ROUND_CLOSEST(reg * scales[nr], 100);
 }
 
-static inline u8 in_to_reg(u32 val, u8 nr)
+static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scales)
 {
-       return clamp_val(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, 255);
+       return clamp_val(DIV_ROUND_CLOSEST(val * 100, scales[nr]), 0, 255);
 }
 
 /* TSI temperatures are in 8.3 format */
@@ -1673,7 +1684,8 @@ show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
        if (IS_ERR(data))
                return PTR_ERR(data);
 
-       return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
+       return sprintf(buf, "%ld\n",
+                      in_from_reg(data->in[nr][index], nr, data->scale_in));
 }
 
 static ssize_t
@@ -1691,7 +1703,7 @@ store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
        if (err < 0)
                return err;
        mutex_lock(&data->update_lock);
-       data->in[nr][index] = in_to_reg(val, nr);
+       data->in[nr][index] = in_to_reg(val, nr, data->scale_in);
        err = nct6775_write_value(data, data->REG_IN_MINMAX[index - 1][nr], data->in[nr][index]);
        mutex_unlock(&data->update_lock);
        return err ? : count;
@@ -3462,6 +3474,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
        mutex_init(&data->update_lock);
        data->name = nct6775_device_names[data->kind];
        data->bank = 0xff;              /* Force initial bank selection */
+       data->scale_in = scale_in;
 
        switch (data->kind) {
        case nct6106:
@@ -3977,6 +3990,9 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data,
                        break;
                }
 
+               if (data->kind == nct6798 || data->kind == nct6799)
+                       data->scale_in = scale_in_6798;
+
                reg_temp = NCT6779_REG_TEMP;
                num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
                if (data->kind == nct6791) {
index ada867d..a409d7a 100644 (file)
@@ -586,7 +586,7 @@ nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio
                int creb;
                int cred;
 
-               cre6 = sio_data->sio_inb(sio_data, 0xe0);
+               cre6 = sio_data->sio_inb(sio_data, 0xe6);
 
                sio_data->sio_select(sio_data, NCT6775_LD_12);
                cre0 = sio_data->sio_inb(sio_data, 0xe0);
index 44f79c5..a84c6ce 100644 (file)
@@ -98,6 +98,7 @@ struct nct6775_data {
        u8 bank;                /* current register bank */
        u8 in_num;              /* number of in inputs we have */
        u8 in[15][3];           /* [0]=in, [1]=in_max, [2]=in_min */
+       const u16 *scale_in;    /* internal scaling factors */
        unsigned int rpm[NUM_FAN];
        u16 fan_min[NUM_FAN];
        u8 fan_pulses[NUM_FAN];
index 9339bfc..024cff1 100644 (file)
@@ -725,7 +725,7 @@ static umode_t nct7802_temp_is_visible(struct kobject *kobj,
        if (index >= 38 && index < 46 && !(reg & 0x01))         /* PECI 0 */
                return 0;
 
-       if (index >= 0x46 && (!(reg & 0x02)))                   /* PECI 1 */
+       if (index >= 46 && !(reg & 0x02))                       /* PECI 1 */
                return 0;
 
        return attr->mode;
index e1a907c..1e1cc67 100644 (file)
@@ -220,6 +220,20 @@ static int tt_toggle_disable(void)
 }
 
 /* Callbacks for turbo toggle attribute */
+static umode_t tt_toggle_is_visible(struct kobject *kobj,
+                                   struct attribute *attr, int n)
+{
+       switch (board) {
+       case aok_zoe_a1:
+       case oxp_mini_amd_a07:
+       case oxp_mini_amd_pro:
+               return attr->mode;
+       default:
+               break;
+       }
+       return 0;
+}
+
 static ssize_t tt_toggle_store(struct device *dev,
                               struct device_attribute *attr, const char *buf,
                               size_t count)
@@ -396,7 +410,15 @@ static struct attribute *oxp_ec_attrs[] = {
        NULL
 };
 
-ATTRIBUTE_GROUPS(oxp_ec);
+static struct attribute_group oxp_ec_attribute_group = {
+       .is_visible = tt_toggle_is_visible,
+       .attrs = oxp_ec_attrs,
+};
+
+static const struct attribute_group *oxp_ec_groups[] = {
+       &oxp_ec_attribute_group,
+       NULL
+};
 
 static const struct hwmon_ops oxp_ec_hwmon_ops = {
        .is_visible = oxp_ec_hwmon_is_visible,
@@ -415,7 +437,6 @@ static int oxp_platform_probe(struct platform_device *pdev)
        const struct dmi_system_id *dmi_entry;
        struct device *dev = &pdev->dev;
        struct device *hwdev;
-       int ret;
 
        /*
         * Have to check for AMD processor here because DMI strings are the
@@ -430,18 +451,6 @@ static int oxp_platform_probe(struct platform_device *pdev)
 
        board = (enum oxp_board)(unsigned long)dmi_entry->driver_data;
 
-       switch (board) {
-       case aok_zoe_a1:
-       case oxp_mini_amd_a07:
-       case oxp_mini_amd_pro:
-               ret = devm_device_add_groups(dev, oxp_ec_groups);
-               if (ret)
-                       return ret;
-               break;
-       default:
-               break;
-       }
-
        hwdev = devm_hwmon_device_register_with_info(dev, "oxpec", NULL,
                                                     &oxp_ec_chip_info, NULL);
 
@@ -451,6 +460,7 @@ static int oxp_platform_probe(struct platform_device *pdev)
 static struct platform_driver oxp_platform_driver = {
        .driver = {
                .name = "oxp-platform",
+               .dev_groups = oxp_ec_groups,
        },
        .probe = oxp_platform_probe,
 };
index fa06325..69a4e62 100644 (file)
@@ -2745,9 +2745,8 @@ static const struct pmbus_status_category __maybe_unused pmbus_status_flag_map[]
        },
 };
 
-static int _pmbus_is_enabled(struct device *dev, u8 page)
+static int _pmbus_is_enabled(struct i2c_client *client, u8 page)
 {
-       struct i2c_client *client = to_i2c_client(dev->parent);
        int ret;
 
        ret = _pmbus_read_byte_data(client, page, PMBUS_OPERATION);
@@ -2758,17 +2757,16 @@ static int _pmbus_is_enabled(struct device *dev, u8 page)
        return !!(ret & PB_OPERATION_CONTROL_ON);
 }
 
-static int __maybe_unused pmbus_is_enabled(struct device *dev, u8 page)
+static int __maybe_unused pmbus_is_enabled(struct i2c_client *client, u8 page)
 {
-       struct i2c_client *client = to_i2c_client(dev->parent);
        struct pmbus_data *data = i2c_get_clientdata(client);
        int ret;
 
        mutex_lock(&data->update_lock);
-       ret = _pmbus_is_enabled(dev, page);
+       ret = _pmbus_is_enabled(client, page);
        mutex_unlock(&data->update_lock);
 
-       return !!(ret & PB_OPERATION_CONTROL_ON);
+       return ret;
 }
 
 #define to_dev_attr(_dev_attr) \
@@ -2844,7 +2842,7 @@ static int _pmbus_get_flags(struct pmbus_data *data, u8 page, unsigned int *flag
        if (status < 0)
                return status;
 
-       if (_pmbus_is_enabled(dev, page)) {
+       if (_pmbus_is_enabled(client, page)) {
                if (status & PB_STATUS_OFF) {
                        *flags |= REGULATOR_ERROR_FAIL;
                        *event |= REGULATOR_EVENT_FAIL;
@@ -2898,7 +2896,10 @@ static int __maybe_unused pmbus_get_flags(struct pmbus_data *data, u8 page, unsi
 #if IS_ENABLED(CONFIG_REGULATOR)
 static int pmbus_regulator_is_enabled(struct regulator_dev *rdev)
 {
-       return pmbus_is_enabled(rdev_get_dev(rdev), rdev_get_id(rdev));
+       struct device *dev = rdev_get_dev(rdev);
+       struct i2c_client *client = to_i2c_client(dev->parent);
+
+       return pmbus_is_enabled(client, rdev_get_id(rdev));
 }
 
 static int _pmbus_regulator_on_off(struct regulator_dev *rdev, bool enable)
@@ -2945,6 +2946,7 @@ static int pmbus_regulator_get_status(struct regulator_dev *rdev)
        struct pmbus_data *data = i2c_get_clientdata(client);
        u8 page = rdev_get_id(rdev);
        int status, ret;
+       int event;
 
        mutex_lock(&data->update_lock);
        status = pmbus_get_status(client, page, PMBUS_STATUS_WORD);
@@ -2964,7 +2966,7 @@ static int pmbus_regulator_get_status(struct regulator_dev *rdev)
                goto unlock;
        }
 
-       ret = pmbus_regulator_get_error_flags(rdev, &status);
+       ret = _pmbus_get_flags(data, rdev_get_id(rdev), &status, &event, false);
        if (ret)
                goto unlock;
 
index b930036..256c2d4 100644 (file)
@@ -199,43 +199,6 @@ static __cpuidle int intel_idle_xstate(struct cpuidle_device *dev,
        return __intel_idle(dev, drv, index);
 }
 
-static __always_inline int __intel_idle_hlt(struct cpuidle_device *dev,
-                                       struct cpuidle_driver *drv, int index)
-{
-       raw_safe_halt();
-       raw_local_irq_disable();
-       return index;
-}
-
-/**
- * intel_idle_hlt - Ask the processor to enter the given idle state using hlt.
- * @dev: cpuidle device of the target CPU.
- * @drv: cpuidle driver (assumed to point to intel_idle_driver).
- * @index: Target idle state index.
- *
- * Use the HLT instruction to notify the processor that the CPU represented by
- * @dev is idle and it can try to enter the idle state corresponding to @index.
- *
- * Must be called under local_irq_disable().
- */
-static __cpuidle int intel_idle_hlt(struct cpuidle_device *dev,
-                               struct cpuidle_driver *drv, int index)
-{
-       return __intel_idle_hlt(dev, drv, index);
-}
-
-static __cpuidle int intel_idle_hlt_irq_on(struct cpuidle_device *dev,
-                                   struct cpuidle_driver *drv, int index)
-{
-       int ret;
-
-       raw_local_irq_enable();
-       ret = __intel_idle_hlt(dev, drv, index);
-       raw_local_irq_disable();
-
-       return ret;
-}
-
 /**
  * intel_idle_s2idle - Ask the processor to enter the given idle state.
  * @dev: cpuidle device of the target CPU.
@@ -1279,25 +1242,6 @@ static struct cpuidle_state snr_cstates[] __initdata = {
                .enter = NULL }
 };
 
-static struct cpuidle_state vmguest_cstates[] __initdata = {
-       {
-               .name = "C1",
-               .desc = "HLT",
-               .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_IRQ_ENABLE,
-               .exit_latency = 5,
-               .target_residency = 10,
-               .enter = &intel_idle_hlt, },
-       {
-               .name = "C1L",
-               .desc = "Long HLT",
-               .flags = MWAIT2flg(0x00) | CPUIDLE_FLAG_TLB_FLUSHED,
-               .exit_latency = 5,
-               .target_residency = 200,
-               .enter = &intel_idle_hlt, },
-       {
-               .enter = NULL }
-};
-
 static const struct idle_cpu idle_cpu_nehalem __initconst = {
        .state_table = nehalem_cstates,
        .auto_demotion_disable_flags = NHM_C1_AUTO_DEMOTE | NHM_C3_AUTO_DEMOTE,
@@ -1897,16 +1841,6 @@ static bool __init intel_idle_verify_cstate(unsigned int mwait_hint)
 
 static void state_update_enter_method(struct cpuidle_state *state, int cstate)
 {
-       if (state->enter == intel_idle_hlt) {
-               if (force_irq_on) {
-                       pr_info("forced intel_idle_irq for state %d\n", cstate);
-                       state->enter = intel_idle_hlt_irq_on;
-               }
-               return;
-       }
-       if (state->enter == intel_idle_hlt_irq_on)
-               return; /* no update scenarios */
-
        if (state->flags & CPUIDLE_FLAG_INIT_XSTATE) {
                /*
                 * Combining with XSTATE with IBRS or IRQ_ENABLE flags
@@ -1940,21 +1874,6 @@ static void state_update_enter_method(struct cpuidle_state *state, int cstate)
        }
 }
 
-/*
- * For mwait based states, we want to verify the cpuid data to see if the state
- * is actually supported by this specific CPU.
- * For non-mwait based states, this check should be skipped.
- */
-static bool should_verify_mwait(struct cpuidle_state *state)
-{
-       if (state->enter == intel_idle_hlt)
-               return false;
-       if (state->enter == intel_idle_hlt_irq_on)
-               return false;
-
-       return true;
-}
-
 static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
 {
        int cstate;
@@ -2003,7 +1922,7 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv)
                }
 
                mwait_hint = flg2MWAIT(cpuidle_state_table[cstate].flags);
-               if (should_verify_mwait(&cpuidle_state_table[cstate]) && !intel_idle_verify_cstate(mwait_hint))
+               if (!intel_idle_verify_cstate(mwait_hint))
                        continue;
 
                /* Structure copy. */
@@ -2137,93 +2056,6 @@ static void __init intel_idle_cpuidle_devices_uninit(void)
                cpuidle_unregister_device(per_cpu_ptr(intel_idle_cpuidle_devices, i));
 }
 
-/*
- * Match up the latency and break even point of the bare metal (cpu based)
- * states with the deepest VM available state.
- *
- * We only want to do this for the deepest state, the ones that has
- * the TLB_FLUSHED flag set on the .
- *
- * All our short idle states are dominated by vmexit/vmenter latencies,
- * not the underlying hardware latencies so we keep our values for these.
- */
-static void __init matchup_vm_state_with_baremetal(void)
-{
-       int cstate;
-
-       for (cstate = 0; cstate < CPUIDLE_STATE_MAX; ++cstate) {
-               int matching_cstate;
-
-               if (intel_idle_max_cstate_reached(cstate))
-                       break;
-
-               if (!cpuidle_state_table[cstate].enter)
-                       break;
-
-               if (!(cpuidle_state_table[cstate].flags & CPUIDLE_FLAG_TLB_FLUSHED))
-                       continue;
-
-               for (matching_cstate = 0; matching_cstate < CPUIDLE_STATE_MAX; ++matching_cstate) {
-                       if (!icpu->state_table[matching_cstate].enter)
-                               break;
-                       if (icpu->state_table[matching_cstate].exit_latency > cpuidle_state_table[cstate].exit_latency) {
-                               cpuidle_state_table[cstate].exit_latency = icpu->state_table[matching_cstate].exit_latency;
-                               cpuidle_state_table[cstate].target_residency = icpu->state_table[matching_cstate].target_residency;
-                       }
-               }
-
-       }
-}
-
-
-static int __init intel_idle_vminit(const struct x86_cpu_id *id)
-{
-       int retval;
-
-       cpuidle_state_table = vmguest_cstates;
-
-       icpu = (const struct idle_cpu *)id->driver_data;
-
-       pr_debug("v" INTEL_IDLE_VERSION " model 0x%X\n",
-                boot_cpu_data.x86_model);
-
-       intel_idle_cpuidle_devices = alloc_percpu(struct cpuidle_device);
-       if (!intel_idle_cpuidle_devices)
-               return -ENOMEM;
-
-       /*
-        * We don't know exactly what the host will do when we go idle, but as a worst estimate
-        * we can assume that the exit latency of the deepest host state will be hit for our
-        * deep (long duration) guest idle state.
-        * The same logic applies to the break even point for the long duration guest idle state.
-        * So lets copy these two properties from the table we found for the host CPU type.
-        */
-       matchup_vm_state_with_baremetal();
-
-       intel_idle_cpuidle_driver_init(&intel_idle_driver);
-
-       retval = cpuidle_register_driver(&intel_idle_driver);
-       if (retval) {
-               struct cpuidle_driver *drv = cpuidle_get_driver();
-               printk(KERN_DEBUG pr_fmt("intel_idle yielding to %s\n"),
-                      drv ? drv->name : "none");
-               goto init_driver_fail;
-       }
-
-       retval = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "idle/intel:online",
-                                  intel_idle_cpu_online, NULL);
-       if (retval < 0)
-               goto hp_setup_fail;
-
-       return 0;
-hp_setup_fail:
-       intel_idle_cpuidle_devices_uninit();
-       cpuidle_unregister_driver(&intel_idle_driver);
-init_driver_fail:
-       free_percpu(intel_idle_cpuidle_devices);
-       return retval;
-}
-
 static int __init intel_idle_init(void)
 {
        const struct x86_cpu_id *id;
@@ -2242,8 +2074,6 @@ static int __init intel_idle_init(void)
        id = x86_match_cpu(intel_idle_ids);
        if (id) {
                if (!boot_cpu_has(X86_FEATURE_MWAIT)) {
-                       if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
-                               return intel_idle_vminit(id);
                        pr_debug("Please enable MWAIT in BIOS SETUP\n");
                        return -ENODEV;
                }
index 1ee87c3..9891c7d 100644 (file)
@@ -4062,6 +4062,8 @@ static int resolve_prepare_src(struct rdma_id_private *id_priv,
                                           RDMA_CM_ADDR_QUERY)))
                        return -EINVAL;
 
+       } else {
+               memcpy(cma_dst_addr(id_priv), dst_addr, rdma_addr_size(dst_addr));
        }
 
        if (cma_family(id_priv) != dst_addr->sa_family) {
index abef0b8..03cc45a 100644 (file)
@@ -869,7 +869,10 @@ fail:
 int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
 {
        struct bnxt_re_qp *qp = container_of(ib_qp, struct bnxt_re_qp, ib_qp);
+       struct bnxt_qplib_qp *qplib_qp = &qp->qplib_qp;
        struct bnxt_re_dev *rdev = qp->rdev;
+       struct bnxt_qplib_nq *scq_nq = NULL;
+       struct bnxt_qplib_nq *rcq_nq = NULL;
        unsigned int flags;
        int rc;
 
@@ -903,6 +906,15 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
        ib_umem_release(qp->rumem);
        ib_umem_release(qp->sumem);
 
+       /* Flush all the entries of notification queue associated with
+        * given qp.
+        */
+       scq_nq = qplib_qp->scq->nq;
+       rcq_nq = qplib_qp->rcq->nq;
+       bnxt_re_synchronize_nq(scq_nq);
+       if (scq_nq != rcq_nq)
+               bnxt_re_synchronize_nq(rcq_nq);
+
        return 0;
 }
 
index 91aed77..a425556 100644 (file)
@@ -381,6 +381,24 @@ static void bnxt_qplib_service_nq(struct tasklet_struct *t)
        spin_unlock_bh(&hwq->lock);
 }
 
+/* bnxt_re_synchronize_nq - self polling notification queue.
+ * @nq      -     notification queue pointer
+ *
+ * This function will start polling entries of a given notification queue
+ * for all pending  entries.
+ * This function is useful to synchronize notification entries while resources
+ * are going away.
+ */
+
+void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq)
+{
+       int budget = nq->budget;
+
+       nq->budget = nq->hwq.max_elements;
+       bnxt_qplib_service_nq(&nq->nq_tasklet);
+       nq->budget = budget;
+}
+
 static irqreturn_t bnxt_qplib_nq_irq(int irq, void *dev_instance)
 {
        struct bnxt_qplib_nq *nq = dev_instance;
@@ -402,19 +420,19 @@ void bnxt_qplib_nq_stop_irq(struct bnxt_qplib_nq *nq, bool kill)
        if (!nq->requested)
                return;
 
-       tasklet_disable(&nq->nq_tasklet);
+       nq->requested = false;
        /* Mask h/w interrupt */
        bnxt_qplib_ring_nq_db(&nq->nq_db.dbinfo, nq->res->cctx, false);
        /* Sync with last running IRQ handler */
        synchronize_irq(nq->msix_vec);
-       if (kill)
-               tasklet_kill(&nq->nq_tasklet);
-
        irq_set_affinity_hint(nq->msix_vec, NULL);
        free_irq(nq->msix_vec, nq);
        kfree(nq->name);
        nq->name = NULL;
-       nq->requested = false;
+
+       if (kill)
+               tasklet_kill(&nq->nq_tasklet);
+       tasklet_disable(&nq->nq_tasklet);
 }
 
 void bnxt_qplib_disable_nq(struct bnxt_qplib_nq *nq)
index a428208..404b851 100644 (file)
@@ -553,6 +553,7 @@ int bnxt_qplib_process_flush_list(struct bnxt_qplib_cq *cq,
                                  struct bnxt_qplib_cqe *cqe,
                                  int num_cqes);
 void bnxt_qplib_flush_cqn_wq(struct bnxt_qplib_qp *qp);
+void bnxt_re_synchronize_nq(struct bnxt_qplib_nq *nq);
 
 static inline void *bnxt_qplib_get_swqe(struct bnxt_qplib_q *que, u32 *swq_idx)
 {
index b30e66b..bc3aea4 100644 (file)
@@ -989,19 +989,18 @@ void bnxt_qplib_rcfw_stop_irq(struct bnxt_qplib_rcfw *rcfw, bool kill)
        if (!creq->requested)
                return;
 
-       tasklet_disable(&creq->creq_tasklet);
+       creq->requested = false;
        /* Mask h/w interrupts */
        bnxt_qplib_ring_nq_db(&creq->creq_db.dbinfo, rcfw->res->cctx, false);
        /* Sync with last running IRQ-handler */
        synchronize_irq(creq->msix_vec);
-       if (kill)
-               tasklet_kill(&creq->creq_tasklet);
-
        free_irq(creq->msix_vec, rcfw);
        kfree(creq->irq_name);
        creq->irq_name = NULL;
-       creq->requested = false;
        atomic_set(&rcfw->rcfw_intr_enabled, 0);
+       if (kill)
+               tasklet_kill(&creq->creq_tasklet);
+       tasklet_disable(&creq->creq_tasklet);
 }
 
 void bnxt_qplib_disable_rcfw_channel(struct bnxt_qplib_rcfw *rcfw)
index d88c918..45e3344 100644 (file)
@@ -2712,13 +2712,13 @@ static int irdma_sc_cq_modify(struct irdma_sc_cq *cq,
  */
 void irdma_check_cqp_progress(struct irdma_cqp_timeout *timeout, struct irdma_sc_dev *dev)
 {
-       if (timeout->compl_cqp_cmds != dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]) {
-               timeout->compl_cqp_cmds = dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS];
+       u64 completed_ops = atomic64_read(&dev->cqp->completed_ops);
+
+       if (timeout->compl_cqp_cmds != completed_ops) {
+               timeout->compl_cqp_cmds = completed_ops;
                timeout->count = 0;
-       } else {
-               if (dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS] !=
-                   timeout->compl_cqp_cmds)
-                       timeout->count++;
+       } else if (timeout->compl_cqp_cmds != dev->cqp->requested_ops) {
+               timeout->count++;
        }
 }
 
@@ -2761,7 +2761,7 @@ static int irdma_cqp_poll_registers(struct irdma_sc_cqp *cqp, u32 tail,
                if (newtail != tail) {
                        /* SUCCESS */
                        IRDMA_RING_MOVE_TAIL(cqp->sq_ring);
-                       cqp->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]++;
+                       atomic64_inc(&cqp->completed_ops);
                        return 0;
                }
                udelay(cqp->dev->hw_attrs.max_sleep_count);
@@ -3121,8 +3121,8 @@ int irdma_sc_cqp_init(struct irdma_sc_cqp *cqp,
        info->dev->cqp = cqp;
 
        IRDMA_RING_INIT(cqp->sq_ring, cqp->sq_size);
-       cqp->dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS] = 0;
-       cqp->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS] = 0;
+       cqp->requested_ops = 0;
+       atomic64_set(&cqp->completed_ops, 0);
        /* for the cqp commands backlog. */
        INIT_LIST_HEAD(&cqp->dev->cqp_cmd_head);
 
@@ -3274,7 +3274,7 @@ __le64 *irdma_sc_cqp_get_next_send_wqe_idx(struct irdma_sc_cqp *cqp, u64 scratch
        if (ret_code)
                return NULL;
 
-       cqp->dev->cqp_cmd_stats[IRDMA_OP_REQ_CMDS]++;
+       cqp->requested_ops++;
        if (!*wqe_idx)
                cqp->polarity = !cqp->polarity;
        wqe = cqp->sq_base[*wqe_idx].elem;
@@ -3363,6 +3363,9 @@ int irdma_sc_ccq_get_cqe_info(struct irdma_sc_cq *ccq,
        if (polarity != ccq->cq_uk.polarity)
                return -ENOENT;
 
+       /* Ensure CEQE contents are read after valid bit is checked */
+       dma_rmb();
+
        get_64bit_val(cqe, 8, &qp_ctx);
        cqp = (struct irdma_sc_cqp *)(unsigned long)qp_ctx;
        info->error = (bool)FIELD_GET(IRDMA_CQ_ERROR, temp);
@@ -3397,7 +3400,7 @@ int irdma_sc_ccq_get_cqe_info(struct irdma_sc_cq *ccq,
        dma_wmb(); /* make sure shadow area is updated before moving tail */
 
        IRDMA_RING_MOVE_TAIL(cqp->sq_ring);
-       ccq->dev->cqp_cmd_stats[IRDMA_OP_CMPL_CMDS]++;
+       atomic64_inc(&cqp->completed_ops);
 
        return ret_code;
 }
@@ -4009,13 +4012,17 @@ int irdma_sc_get_next_aeqe(struct irdma_sc_aeq *aeq,
        u8 polarity;
 
        aeqe = IRDMA_GET_CURRENT_AEQ_ELEM(aeq);
-       get_64bit_val(aeqe, 0, &compl_ctx);
        get_64bit_val(aeqe, 8, &temp);
        polarity = (u8)FIELD_GET(IRDMA_AEQE_VALID, temp);
 
        if (aeq->polarity != polarity)
                return -ENOENT;
 
+       /* Ensure AEQE contents are read after valid bit is checked */
+       dma_rmb();
+
+       get_64bit_val(aeqe, 0, &compl_ctx);
+
        print_hex_dump_debug("WQE: AEQ_ENTRY WQE", DUMP_PREFIX_OFFSET, 16, 8,
                             aeqe, 16, false);
 
index 6014b9d..d06e45d 100644 (file)
@@ -191,32 +191,30 @@ enum irdma_cqp_op_type {
        IRDMA_OP_MANAGE_VF_PBLE_BP              = 25,
        IRDMA_OP_QUERY_FPM_VAL                  = 26,
        IRDMA_OP_COMMIT_FPM_VAL                 = 27,
-       IRDMA_OP_REQ_CMDS                       = 28,
-       IRDMA_OP_CMPL_CMDS                      = 29,
-       IRDMA_OP_AH_CREATE                      = 30,
-       IRDMA_OP_AH_MODIFY                      = 31,
-       IRDMA_OP_AH_DESTROY                     = 32,
-       IRDMA_OP_MC_CREATE                      = 33,
-       IRDMA_OP_MC_DESTROY                     = 34,
-       IRDMA_OP_MC_MODIFY                      = 35,
-       IRDMA_OP_STATS_ALLOCATE                 = 36,
-       IRDMA_OP_STATS_FREE                     = 37,
-       IRDMA_OP_STATS_GATHER                   = 38,
-       IRDMA_OP_WS_ADD_NODE                    = 39,
-       IRDMA_OP_WS_MODIFY_NODE                 = 40,
-       IRDMA_OP_WS_DELETE_NODE                 = 41,
-       IRDMA_OP_WS_FAILOVER_START              = 42,
-       IRDMA_OP_WS_FAILOVER_COMPLETE           = 43,
-       IRDMA_OP_SET_UP_MAP                     = 44,
-       IRDMA_OP_GEN_AE                         = 45,
-       IRDMA_OP_QUERY_RDMA_FEATURES            = 46,
-       IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY          = 47,
-       IRDMA_OP_ADD_LOCAL_MAC_ENTRY            = 48,
-       IRDMA_OP_DELETE_LOCAL_MAC_ENTRY         = 49,
-       IRDMA_OP_CQ_MODIFY                      = 50,
+       IRDMA_OP_AH_CREATE                      = 28,
+       IRDMA_OP_AH_MODIFY                      = 29,
+       IRDMA_OP_AH_DESTROY                     = 30,
+       IRDMA_OP_MC_CREATE                      = 31,
+       IRDMA_OP_MC_DESTROY                     = 32,
+       IRDMA_OP_MC_MODIFY                      = 33,
+       IRDMA_OP_STATS_ALLOCATE                 = 34,
+       IRDMA_OP_STATS_FREE                     = 35,
+       IRDMA_OP_STATS_GATHER                   = 36,
+       IRDMA_OP_WS_ADD_NODE                    = 37,
+       IRDMA_OP_WS_MODIFY_NODE                 = 38,
+       IRDMA_OP_WS_DELETE_NODE                 = 39,
+       IRDMA_OP_WS_FAILOVER_START              = 40,
+       IRDMA_OP_WS_FAILOVER_COMPLETE           = 41,
+       IRDMA_OP_SET_UP_MAP                     = 42,
+       IRDMA_OP_GEN_AE                         = 43,
+       IRDMA_OP_QUERY_RDMA_FEATURES            = 44,
+       IRDMA_OP_ALLOC_LOCAL_MAC_ENTRY          = 45,
+       IRDMA_OP_ADD_LOCAL_MAC_ENTRY            = 46,
+       IRDMA_OP_DELETE_LOCAL_MAC_ENTRY         = 47,
+       IRDMA_OP_CQ_MODIFY                      = 48,
 
        /* Must be last entry*/
-       IRDMA_MAX_CQP_OPS                       = 51,
+       IRDMA_MAX_CQP_OPS                       = 49,
 };
 
 /* CQP SQ WQES */
index 795f7fd..457368e 100644 (file)
@@ -191,6 +191,7 @@ static void irdma_set_flush_fields(struct irdma_sc_qp *qp,
        case IRDMA_AE_AMP_MWBIND_INVALID_RIGHTS:
        case IRDMA_AE_AMP_MWBIND_BIND_DISABLED:
        case IRDMA_AE_AMP_MWBIND_INVALID_BOUNDS:
+       case IRDMA_AE_AMP_MWBIND_VALID_STAG:
                qp->flush_code = FLUSH_MW_BIND_ERR;
                qp->event_type = IRDMA_QP_EVENT_ACCESS_ERR;
                break;
@@ -2075,7 +2076,7 @@ void irdma_cqp_ce_handler(struct irdma_pci_f *rf, struct irdma_sc_cq *cq)
                        cqp_request->compl_info.error = info.error;
 
                        if (cqp_request->waiting) {
-                               cqp_request->request_done = true;
+                               WRITE_ONCE(cqp_request->request_done, true);
                                wake_up(&cqp_request->waitq);
                                irdma_put_cqp_request(&rf->cqp, cqp_request);
                        } else {
index def6dd5..2323962 100644 (file)
@@ -161,8 +161,8 @@ struct irdma_cqp_request {
        void (*callback_fcn)(struct irdma_cqp_request *cqp_request);
        void *param;
        struct irdma_cqp_compl_info compl_info;
+       bool request_done; /* READ/WRITE_ONCE macros operate on it */
        bool waiting:1;
-       bool request_done:1;
        bool dynamic:1;
 };
 
index 4ec9639..5625317 100644 (file)
@@ -230,6 +230,9 @@ static int irdma_puda_poll_info(struct irdma_sc_cq *cq,
        if (valid_bit != cq_uk->polarity)
                return -ENOENT;
 
+       /* Ensure CQE contents are read after valid bit is checked */
+       dma_rmb();
+
        if (cq->dev->hw_attrs.uk_attrs.hw_rev >= IRDMA_GEN_2)
                ext_valid = (bool)FIELD_GET(IRDMA_CQ_EXTCQE, qword3);
 
@@ -243,6 +246,9 @@ static int irdma_puda_poll_info(struct irdma_sc_cq *cq,
                if (polarity != cq_uk->polarity)
                        return -ENOENT;
 
+               /* Ensure ext CQE contents are read after ext valid bit is checked */
+               dma_rmb();
+
                IRDMA_RING_MOVE_HEAD_NOCHECK(cq_uk->cq_ring);
                if (!IRDMA_RING_CURRENT_HEAD(cq_uk->cq_ring))
                        cq_uk->polarity = !cq_uk->polarity;
index 5ee6860..a207095 100644 (file)
@@ -365,6 +365,8 @@ struct irdma_sc_cqp {
        struct irdma_dcqcn_cc_params dcqcn_params;
        __le64 *host_ctx;
        u64 *scratch_array;
+       u64 requested_ops;
+       atomic64_t completed_ops;
        u32 cqp_id;
        u32 sq_size;
        u32 hw_sq_size;
index dd428d9..280d633 100644 (file)
@@ -1161,7 +1161,7 @@ int irdma_uk_cq_poll_cmpl(struct irdma_cq_uk *cq,
        }
        wqe_idx = (u32)FIELD_GET(IRDMA_CQ_WQEIDX, qword3);
        info->qp_handle = (irdma_qp_handle)(unsigned long)qp;
-       info->op_type = (u8)FIELD_GET(IRDMA_CQ_SQ, qword3);
+       info->op_type = (u8)FIELD_GET(IRDMACQ_OP, qword3);
 
        if (info->q_type == IRDMA_CQE_QTYPE_RQ) {
                u32 array_idx;
@@ -1527,6 +1527,9 @@ void irdma_uk_clean_cq(void *q, struct irdma_cq_uk *cq)
                if (polarity != temp)
                        break;
 
+               /* Ensure CQE contents are read after valid bit is checked */
+               dma_rmb();
+
                get_64bit_val(cqe, 8, &comp_ctx);
                if ((void *)(unsigned long)comp_ctx == q)
                        set_64bit_val(cqe, 8, 0);
index 71e1c5d..eb083f7 100644 (file)
@@ -481,7 +481,7 @@ void irdma_free_cqp_request(struct irdma_cqp *cqp,
        if (cqp_request->dynamic) {
                kfree(cqp_request);
        } else {
-               cqp_request->request_done = false;
+               WRITE_ONCE(cqp_request->request_done, false);
                cqp_request->callback_fcn = NULL;
                cqp_request->waiting = false;
 
@@ -515,7 +515,7 @@ irdma_free_pending_cqp_request(struct irdma_cqp *cqp,
 {
        if (cqp_request->waiting) {
                cqp_request->compl_info.error = true;
-               cqp_request->request_done = true;
+               WRITE_ONCE(cqp_request->request_done, true);
                wake_up(&cqp_request->waitq);
        }
        wait_event_timeout(cqp->remove_wq,
@@ -567,11 +567,11 @@ static int irdma_wait_event(struct irdma_pci_f *rf,
        bool cqp_error = false;
        int err_code = 0;
 
-       cqp_timeout.compl_cqp_cmds = rf->sc_dev.cqp_cmd_stats[IRDMA_OP_CMPL_CMDS];
+       cqp_timeout.compl_cqp_cmds = atomic64_read(&rf->sc_dev.cqp->completed_ops);
        do {
                irdma_cqp_ce_handler(rf, &rf->ccq.sc_cq);
                if (wait_event_timeout(cqp_request->waitq,
-                                      cqp_request->request_done,
+                                      READ_ONCE(cqp_request->request_done),
                                       msecs_to_jiffies(CQP_COMPL_WAIT_TIME_MS)))
                        break;
 
index 4566566..9d08aa9 100644 (file)
@@ -565,15 +565,15 @@ static int set_qp_rss(struct mlx4_ib_dev *dev, struct mlx4_ib_rss *rss_ctx,
                return (-EOPNOTSUPP);
        }
 
-       if (ucmd->rx_hash_fields_mask & ~(MLX4_IB_RX_HASH_SRC_IPV4      |
-                                         MLX4_IB_RX_HASH_DST_IPV4      |
-                                         MLX4_IB_RX_HASH_SRC_IPV6      |
-                                         MLX4_IB_RX_HASH_DST_IPV6      |
-                                         MLX4_IB_RX_HASH_SRC_PORT_TCP  |
-                                         MLX4_IB_RX_HASH_DST_PORT_TCP  |
-                                         MLX4_IB_RX_HASH_SRC_PORT_UDP  |
-                                         MLX4_IB_RX_HASH_DST_PORT_UDP  |
-                                         MLX4_IB_RX_HASH_INNER)) {
+       if (ucmd->rx_hash_fields_mask & ~(u64)(MLX4_IB_RX_HASH_SRC_IPV4 |
+                                              MLX4_IB_RX_HASH_DST_IPV4 |
+                                              MLX4_IB_RX_HASH_SRC_IPV6 |
+                                              MLX4_IB_RX_HASH_DST_IPV6 |
+                                              MLX4_IB_RX_HASH_SRC_PORT_TCP |
+                                              MLX4_IB_RX_HASH_DST_PORT_TCP |
+                                              MLX4_IB_RX_HASH_SRC_PORT_UDP |
+                                              MLX4_IB_RX_HASH_DST_PORT_UDP |
+                                              MLX4_IB_RX_HASH_INNER)) {
                pr_debug("RX Hash fields_mask has unsupported mask (0x%llx)\n",
                         ucmd->rx_hash_fields_mask);
                return (-EOPNOTSUPP);
index 69bba0e..53f4364 100644 (file)
@@ -1393,7 +1393,7 @@ int mthca_alloc_sqp(struct mthca_dev *dev,
        if (mthca_array_get(&dev->qp_table.qp, mqpn))
                err = -EBUSY;
        else
-               mthca_array_set(&dev->qp_table.qp, mqpn, qp->sqp);
+               mthca_array_set(&dev->qp_table.qp, mqpn, qp);
        spin_unlock_irq(&dev->qp_table.lock);
 
        if (err)
index d8a43d8..d9312b5 100644 (file)
@@ -199,7 +199,8 @@ int rxe_bind_mw(struct rxe_qp *qp, struct rxe_send_wqe *wqe)
 
        if (access & ~RXE_ACCESS_SUPPORTED_MW) {
                rxe_err_mw(mw, "access %#x not supported", access);
-               return -EOPNOTSUPP;
+               ret = -EOPNOTSUPP;
+               goto err_drop_mr;
        }
 
        spin_lock_bh(&mw->lock);
index 29d0566..ed2937a 100644 (file)
@@ -109,10 +109,7 @@ EXPORT_SYMBOL_NS_GPL(iommufd_device_bind, IOMMUFD);
  */
 void iommufd_device_unbind(struct iommufd_device *idev)
 {
-       bool was_destroyed;
-
-       was_destroyed = iommufd_object_destroy_user(idev->ictx, &idev->obj);
-       WARN_ON(!was_destroyed);
+       iommufd_object_destroy_user(idev->ictx, &idev->obj);
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_device_unbind, IOMMUFD);
 
@@ -382,7 +379,7 @@ void iommufd_device_detach(struct iommufd_device *idev)
        mutex_unlock(&hwpt->devices_lock);
 
        if (hwpt->auto_domain)
-               iommufd_object_destroy_user(idev->ictx, &hwpt->obj);
+               iommufd_object_deref_user(idev->ictx, &hwpt->obj);
        else
                refcount_dec(&hwpt->obj.users);
 
@@ -456,10 +453,7 @@ EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
  */
 void iommufd_access_destroy(struct iommufd_access *access)
 {
-       bool was_destroyed;
-
-       was_destroyed = iommufd_object_destroy_user(access->ictx, &access->obj);
-       WARN_ON(!was_destroyed);
+       iommufd_object_destroy_user(access->ictx, &access->obj);
 }
 EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
 
index b38e67d..f979098 100644 (file)
@@ -176,8 +176,19 @@ void iommufd_object_abort_and_destroy(struct iommufd_ctx *ictx,
                                      struct iommufd_object *obj);
 void iommufd_object_finalize(struct iommufd_ctx *ictx,
                             struct iommufd_object *obj);
-bool iommufd_object_destroy_user(struct iommufd_ctx *ictx,
-                                struct iommufd_object *obj);
+void __iommufd_object_destroy_user(struct iommufd_ctx *ictx,
+                                  struct iommufd_object *obj, bool allow_fail);
+static inline void iommufd_object_destroy_user(struct iommufd_ctx *ictx,
+                                              struct iommufd_object *obj)
+{
+       __iommufd_object_destroy_user(ictx, obj, false);
+}
+static inline void iommufd_object_deref_user(struct iommufd_ctx *ictx,
+                                            struct iommufd_object *obj)
+{
+       __iommufd_object_destroy_user(ictx, obj, true);
+}
+
 struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
                                             size_t size,
                                             enum iommufd_object_type type);
index 3fbe636..4cf5f73 100644 (file)
@@ -117,13 +117,55 @@ struct iommufd_object *iommufd_get_object(struct iommufd_ctx *ictx, u32 id,
 }
 
 /*
+ * Remove the given object id from the xarray if the only reference to the
+ * object is held by the xarray. The caller must call ops destroy().
+ */
+static struct iommufd_object *iommufd_object_remove(struct iommufd_ctx *ictx,
+                                                   u32 id, bool extra_put)
+{
+       struct iommufd_object *obj;
+       XA_STATE(xas, &ictx->objects, id);
+
+       xa_lock(&ictx->objects);
+       obj = xas_load(&xas);
+       if (xa_is_zero(obj) || !obj) {
+               obj = ERR_PTR(-ENOENT);
+               goto out_xa;
+       }
+
+       /*
+        * If the caller is holding a ref on obj we put it here under the
+        * spinlock.
+        */
+       if (extra_put)
+               refcount_dec(&obj->users);
+
+       if (!refcount_dec_if_one(&obj->users)) {
+               obj = ERR_PTR(-EBUSY);
+               goto out_xa;
+       }
+
+       xas_store(&xas, NULL);
+       if (ictx->vfio_ioas == container_of(obj, struct iommufd_ioas, obj))
+               ictx->vfio_ioas = NULL;
+
+out_xa:
+       xa_unlock(&ictx->objects);
+
+       /* The returned object reference count is zero */
+       return obj;
+}
+
+/*
  * The caller holds a users refcount and wants to destroy the object. Returns
  * true if the object was destroyed. In all cases the caller no longer has a
  * reference on obj.
  */
-bool iommufd_object_destroy_user(struct iommufd_ctx *ictx,
-                                struct iommufd_object *obj)
+void __iommufd_object_destroy_user(struct iommufd_ctx *ictx,
+                                  struct iommufd_object *obj, bool allow_fail)
 {
+       struct iommufd_object *ret;
+
        /*
         * The purpose of the destroy_rwsem is to ensure deterministic
         * destruction of objects used by external drivers and destroyed by this
@@ -131,22 +173,22 @@ bool iommufd_object_destroy_user(struct iommufd_ctx *ictx,
         * side of this, such as during ioctl execution.
         */
        down_write(&obj->destroy_rwsem);
-       xa_lock(&ictx->objects);
-       refcount_dec(&obj->users);
-       if (!refcount_dec_if_one(&obj->users)) {
-               xa_unlock(&ictx->objects);
-               up_write(&obj->destroy_rwsem);
-               return false;
-       }
-       __xa_erase(&ictx->objects, obj->id);
-       if (ictx->vfio_ioas && &ictx->vfio_ioas->obj == obj)
-               ictx->vfio_ioas = NULL;
-       xa_unlock(&ictx->objects);
+       ret = iommufd_object_remove(ictx, obj->id, true);
        up_write(&obj->destroy_rwsem);
 
+       if (allow_fail && IS_ERR(ret))
+               return;
+
+       /*
+        * If there is a bug and we couldn't destroy the object then we did put
+        * back the caller's refcount and will eventually try to free it again
+        * during close.
+        */
+       if (WARN_ON(IS_ERR(ret)))
+               return;
+
        iommufd_object_ops[obj->type].destroy(obj);
        kfree(obj);
-       return true;
 }
 
 static int iommufd_destroy(struct iommufd_ucmd *ucmd)
@@ -154,13 +196,11 @@ static int iommufd_destroy(struct iommufd_ucmd *ucmd)
        struct iommu_destroy *cmd = ucmd->cmd;
        struct iommufd_object *obj;
 
-       obj = iommufd_get_object(ucmd->ictx, cmd->id, IOMMUFD_OBJ_ANY);
+       obj = iommufd_object_remove(ucmd->ictx, cmd->id, false);
        if (IS_ERR(obj))
                return PTR_ERR(obj);
-       iommufd_ref_to_users(obj);
-       /* See iommufd_ref_to_users() */
-       if (!iommufd_object_destroy_user(ucmd->ictx, obj))
-               return -EBUSY;
+       iommufd_object_ops[obj->type].destroy(obj);
+       kfree(obj);
        return 0;
 }
 
index 412ca96..8d9aa29 100644 (file)
@@ -297,7 +297,7 @@ static void batch_clear_carry(struct pfn_batch *batch, unsigned int keep_pfns)
        batch->pfns[0] = batch->pfns[batch->end - 1] +
                         (batch->npfns[batch->end - 1] - keep_pfns);
        batch->npfns[0] = keep_pfns;
-       batch->end = 0;
+       batch->end = 1;
 }
 
 static void batch_skip_carry(struct pfn_batch *batch, unsigned int skip_pfns)
index fa113cb..6341c01 100644 (file)
@@ -82,6 +82,7 @@ struct bcm6345_l1_chip {
 };
 
 struct bcm6345_l1_cpu {
+       struct bcm6345_l1_chip  *intc;
        void __iomem            *map_base;
        unsigned int            parent_irq;
        u32                     enable_cache[];
@@ -115,17 +116,11 @@ static inline unsigned int cpu_for_irq(struct bcm6345_l1_chip *intc,
 
 static void bcm6345_l1_irq_handle(struct irq_desc *desc)
 {
-       struct bcm6345_l1_chip *intc = irq_desc_get_handler_data(desc);
-       struct bcm6345_l1_cpu *cpu;
+       struct bcm6345_l1_cpu *cpu = irq_desc_get_handler_data(desc);
+       struct bcm6345_l1_chip *intc = cpu->intc;
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int idx;
 
-#ifdef CONFIG_SMP
-       cpu = intc->cpus[cpu_logical_map(smp_processor_id())];
-#else
-       cpu = intc->cpus[0];
-#endif
-
        chained_irq_enter(chip, desc);
 
        for (idx = 0; idx < intc->n_words; idx++) {
@@ -253,6 +248,7 @@ static int __init bcm6345_l1_init_one(struct device_node *dn,
        if (!cpu)
                return -ENOMEM;
 
+       cpu->intc = intc;
        cpu->map_base = ioremap(res.start, sz);
        if (!cpu->map_base)
                return -ENOMEM;
@@ -271,7 +267,7 @@ static int __init bcm6345_l1_init_one(struct device_node *dn,
                return -EINVAL;
        }
        irq_set_chained_handler_and_data(cpu->parent_irq,
-                                               bcm6345_l1_irq_handle, intc);
+                                               bcm6345_l1_irq_handle, cpu);
 
        return 0;
 }
index 1994541..e0c2b10 100644 (file)
@@ -273,13 +273,23 @@ static void vpe_to_cpuid_unlock(struct its_vpe *vpe, unsigned long flags)
        raw_spin_unlock_irqrestore(&vpe->vpe_lock, flags);
 }
 
+static struct irq_chip its_vpe_irq_chip;
+
 static int irq_to_cpuid_lock(struct irq_data *d, unsigned long *flags)
 {
-       struct its_vlpi_map *map = get_vlpi_map(d);
+       struct its_vpe *vpe = NULL;
        int cpu;
 
-       if (map) {
-               cpu = vpe_to_cpuid_lock(map->vpe, flags);
+       if (d->chip == &its_vpe_irq_chip) {
+               vpe = irq_data_get_irq_chip_data(d);
+       } else {
+               struct its_vlpi_map *map = get_vlpi_map(d);
+               if (map)
+                       vpe = map->vpe;
+       }
+
+       if (vpe) {
+               cpu = vpe_to_cpuid_lock(vpe, flags);
        } else {
                /* Physical LPIs are already locked via the irq_desc lock */
                struct its_device *its_dev = irq_data_get_irq_chip_data(d);
@@ -293,10 +303,18 @@ static int irq_to_cpuid_lock(struct irq_data *d, unsigned long *flags)
 
 static void irq_to_cpuid_unlock(struct irq_data *d, unsigned long flags)
 {
-       struct its_vlpi_map *map = get_vlpi_map(d);
+       struct its_vpe *vpe = NULL;
+
+       if (d->chip == &its_vpe_irq_chip) {
+               vpe = irq_data_get_irq_chip_data(d);
+       } else {
+               struct its_vlpi_map *map = get_vlpi_map(d);
+               if (map)
+                       vpe = map->vpe;
+       }
 
-       if (map)
-               vpe_to_cpuid_unlock(map->vpe, flags);
+       if (vpe)
+               vpe_to_cpuid_unlock(vpe, flags);
 }
 
 static struct its_collection *valid_col(struct its_collection *col)
@@ -1433,14 +1451,29 @@ static void wait_for_syncr(void __iomem *rdbase)
                cpu_relax();
 }
 
-static void direct_lpi_inv(struct irq_data *d)
+static void __direct_lpi_inv(struct irq_data *d, u64 val)
 {
-       struct its_vlpi_map *map = get_vlpi_map(d);
        void __iomem *rdbase;
        unsigned long flags;
-       u64 val;
        int cpu;
 
+       /* Target the redistributor this LPI is currently routed to */
+       cpu = irq_to_cpuid_lock(d, &flags);
+       raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
+
+       rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
+       gic_write_lpir(val, rdbase + GICR_INVLPIR);
+       wait_for_syncr(rdbase);
+
+       raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
+       irq_to_cpuid_unlock(d, flags);
+}
+
+static void direct_lpi_inv(struct irq_data *d)
+{
+       struct its_vlpi_map *map = get_vlpi_map(d);
+       u64 val;
+
        if (map) {
                struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 
@@ -1453,15 +1486,7 @@ static void direct_lpi_inv(struct irq_data *d)
                val = d->hwirq;
        }
 
-       /* Target the redistributor this LPI is currently routed to */
-       cpu = irq_to_cpuid_lock(d, &flags);
-       raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
-       rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
-       gic_write_lpir(val, rdbase + GICR_INVLPIR);
-
-       wait_for_syncr(rdbase);
-       raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
-       irq_to_cpuid_unlock(d, flags);
+       __direct_lpi_inv(d, val);
 }
 
 static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
@@ -3953,18 +3978,10 @@ static void its_vpe_send_inv(struct irq_data *d)
 {
        struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
 
-       if (gic_rdists->has_direct_lpi) {
-               void __iomem *rdbase;
-
-               /* Target the redistributor this VPE is currently known on */
-               raw_spin_lock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
-               rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
-               gic_write_lpir(d->parent_data->hwirq, rdbase + GICR_INVLPIR);
-               wait_for_syncr(rdbase);
-               raw_spin_unlock(&gic_data_rdist_cpu(vpe->col_idx)->rd_lock);
-       } else {
+       if (gic_rdists->has_direct_lpi)
+               __direct_lpi_inv(d, d->parent_data->hwirq);
+       else
                its_vpe_send_cmd(vpe, its_send_inv);
-       }
 }
 
 static void its_vpe_mask_irq(struct irq_data *d)
@@ -4727,7 +4744,8 @@ static bool __maybe_unused its_enable_rk3588001(void *data)
 {
        struct its_node *its = data;
 
-       if (!of_machine_is_compatible("rockchip,rk3588"))
+       if (!of_machine_is_compatible("rockchip,rk3588") &&
+           !of_machine_is_compatible("rockchip,rk3588s"))
                return false;
 
        its->flags |= ITS_FLAGS_FORCE_NON_SHAREABLE;
index 0c6c1af..eedfa8e 100644 (file)
@@ -69,6 +69,8 @@ struct gic_chip_data {
 static void __iomem *t241_dist_base_alias[T241_CHIPS_MAX] __read_mostly;
 static DEFINE_STATIC_KEY_FALSE(gic_nvidia_t241_erratum);
 
+static DEFINE_STATIC_KEY_FALSE(gic_arm64_2941627_erratum);
+
 static struct gic_chip_data gic_data __read_mostly;
 static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
 
@@ -592,10 +594,39 @@ static void gic_irq_nmi_teardown(struct irq_data *d)
        gic_irq_set_prio(d, GICD_INT_DEF_PRI);
 }
 
+static bool gic_arm64_erratum_2941627_needed(struct irq_data *d)
+{
+       enum gic_intid_range range;
+
+       if (!static_branch_unlikely(&gic_arm64_2941627_erratum))
+               return false;
+
+       range = get_intid_range(d);
+
+       /*
+        * The workaround is needed if the IRQ is an SPI and
+        * the target cpu is different from the one we are
+        * executing on.
+        */
+       return (range == SPI_RANGE || range == ESPI_RANGE) &&
+               !cpumask_test_cpu(raw_smp_processor_id(),
+                                 irq_data_get_effective_affinity_mask(d));
+}
+
 static void gic_eoi_irq(struct irq_data *d)
 {
        write_gicreg(gic_irq(d), ICC_EOIR1_EL1);
        isb();
+
+       if (gic_arm64_erratum_2941627_needed(d)) {
+               /*
+                * Make sure the GIC stream deactivate packet
+                * issued by ICC_EOIR1_EL1 has completed before
+                * deactivating through GICD_IACTIVER.
+                */
+               dsb(sy);
+               gic_poke_irq(d, GICD_ICACTIVER);
+       }
 }
 
 static void gic_eoimode1_eoi_irq(struct irq_data *d)
@@ -606,7 +637,11 @@ static void gic_eoimode1_eoi_irq(struct irq_data *d)
         */
        if (gic_irq(d) >= 8192 || irqd_is_forwarded_to_vcpu(d))
                return;
-       gic_write_dir(gic_irq(d));
+
+       if (!gic_arm64_erratum_2941627_needed(d))
+               gic_write_dir(gic_irq(d));
+       else
+               gic_poke_irq(d, GICD_ICACTIVER);
 }
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -1816,6 +1851,12 @@ static bool gic_enable_quirk_asr8601(void *data)
        return true;
 }
 
+static bool gic_enable_quirk_arm64_2941627(void *data)
+{
+       static_branch_enable(&gic_arm64_2941627_erratum);
+       return true;
+}
+
 static const struct gic_quirk gic_quirks[] = {
        {
                .desc   = "GICv3: Qualcomm MSM8996 broken firmware",
@@ -1864,6 +1905,25 @@ static const struct gic_quirk gic_quirks[] = {
                .init   = gic_enable_quirk_nvidia_t241,
        },
        {
+               /*
+                * GIC-700: 2941627 workaround - IP variant [0,1]
+                *
+                */
+               .desc   = "GICv3: ARM64 erratum 2941627",
+               .iidr   = 0x0400043b,
+               .mask   = 0xff0e0fff,
+               .init   = gic_enable_quirk_arm64_2941627,
+       },
+       {
+               /*
+                * GIC-700: 2941627 workaround - IP variant [2]
+                */
+               .desc   = "GICv3: ARM64 erratum 2941627",
+               .iidr   = 0x0402043b,
+               .mask   = 0xff0f0fff,
+               .init   = gic_enable_quirk_arm64_2941627,
+       },
+       {
        }
 };
 
index c0331b2..fe391de 100644 (file)
@@ -839,7 +839,7 @@ hfcpci_fill_fifo(struct bchannel *bch)
                *z1t = cpu_to_le16(new_z1);     /* now send data */
                if (bch->tx_idx < bch->tx_skb->len)
                        return;
-               dev_kfree_skb(bch->tx_skb);
+               dev_kfree_skb_any(bch->tx_skb);
                if (get_next_bframe(bch))
                        goto next_t_frame;
                return;
@@ -895,7 +895,7 @@ hfcpci_fill_fifo(struct bchannel *bch)
        }
        bz->za[new_f1].z1 = cpu_to_le16(new_z1);        /* for next buffer */
        bz->f1 = new_f1;        /* next frame */
-       dev_kfree_skb(bch->tx_skb);
+       dev_kfree_skb_any(bch->tx_skb);
        get_next_bframe(bch);
 }
 
@@ -1119,7 +1119,7 @@ tx_birq(struct bchannel *bch)
        if (bch->tx_skb && bch->tx_idx < bch->tx_skb->len)
                hfcpci_fill_fifo(bch);
        else {
-               dev_kfree_skb(bch->tx_skb);
+               dev_kfree_skb_any(bch->tx_skb);
                if (get_next_bframe(bch))
                        hfcpci_fill_fifo(bch);
        }
@@ -2277,7 +2277,7 @@ _hfcpci_softirq(struct device *dev, void *unused)
                return 0;
 
        if (hc->hw.int_m2 & HFCPCI_IRQ_ENABLE) {
-               spin_lock(&hc->lock);
+               spin_lock_irq(&hc->lock);
                bch = Sel_BCS(hc, hc->hw.bswapped ? 2 : 1);
                if (bch && bch->state == ISDN_P_B_RAW) { /* B1 rx&tx */
                        main_rec_hfcpci(bch);
@@ -2288,7 +2288,7 @@ _hfcpci_softirq(struct device *dev, void *unused)
                        main_rec_hfcpci(bch);
                        tx_birq(bch);
                }
-               spin_unlock(&hc->lock);
+               spin_unlock_irq(&hc->lock);
        }
        return 0;
 }
index 493a871..8bd2ad7 100644 (file)
@@ -857,7 +857,13 @@ struct smq_policy {
 
        struct background_tracker *bg_work;
 
-       bool migrations_allowed;
+       bool migrations_allowed:1;
+
+       /*
+        * If this is set the policy will try and clean the whole cache
+        * even if the device is not idle.
+        */
+       bool cleaner:1;
 };
 
 /*----------------------------------------------------------------*/
@@ -1138,7 +1144,7 @@ static bool clean_target_met(struct smq_policy *mq, bool idle)
         * Cache entries may not be populated.  So we cannot rely on the
         * size of the clean queue.
         */
-       if (idle) {
+       if (idle || mq->cleaner) {
                /*
                 * We'd like to clean everything.
                 */
@@ -1722,11 +1728,9 @@ static void calc_hotspot_params(sector_t origin_size,
                *hotspot_block_size /= 2u;
 }
 
-static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size,
-                                           sector_t origin_size,
-                                           sector_t cache_block_size,
-                                           bool mimic_mq,
-                                           bool migrations_allowed)
+static struct dm_cache_policy *
+__smq_create(dm_cblock_t cache_size, sector_t origin_size, sector_t cache_block_size,
+            bool mimic_mq, bool migrations_allowed, bool cleaner)
 {
        unsigned int i;
        unsigned int nr_sentinels_per_queue = 2u * NR_CACHE_LEVELS;
@@ -1813,6 +1817,7 @@ static struct dm_cache_policy *__smq_create(dm_cblock_t cache_size,
                goto bad_btracker;
 
        mq->migrations_allowed = migrations_allowed;
+       mq->cleaner = cleaner;
 
        return &mq->policy;
 
@@ -1836,21 +1841,24 @@ static struct dm_cache_policy *smq_create(dm_cblock_t cache_size,
                                          sector_t origin_size,
                                          sector_t cache_block_size)
 {
-       return __smq_create(cache_size, origin_size, cache_block_size, false, true);
+       return __smq_create(cache_size, origin_size, cache_block_size,
+                           false, true, false);
 }
 
 static struct dm_cache_policy *mq_create(dm_cblock_t cache_size,
                                         sector_t origin_size,
                                         sector_t cache_block_size)
 {
-       return __smq_create(cache_size, origin_size, cache_block_size, true, true);
+       return __smq_create(cache_size, origin_size, cache_block_size,
+                           true, true, false);
 }
 
 static struct dm_cache_policy *cleaner_create(dm_cblock_t cache_size,
                                              sector_t origin_size,
                                              sector_t cache_block_size)
 {
-       return __smq_create(cache_size, origin_size, cache_block_size, false, false);
+       return __smq_create(cache_size, origin_size, cache_block_size,
+                           false, false, true);
 }
 
 /*----------------------------------------------------------------*/
index 3d5c56e..97a8d5f 100644 (file)
@@ -2676,6 +2676,7 @@ oom:
        recalc_tags = kvmalloc(recalc_tags_size, GFP_NOIO);
        if (!recalc_tags) {
                vfree(recalc_buffer);
+               recalc_buffer = NULL;
                goto oom;
        }
 
index 8846bf5..becdb68 100644 (file)
@@ -3251,8 +3251,7 @@ size_check:
        r = md_start(&rs->md);
        if (r) {
                ti->error = "Failed to start raid array";
-               mddev_unlock(&rs->md);
-               goto bad_md_start;
+               goto bad_unlock;
        }
 
        /* If raid4/5/6 journal mode explicitly requested (only possible with journal dev) -> set it */
@@ -3260,8 +3259,7 @@ size_check:
                r = r5c_journal_mode_set(&rs->md, rs->journal_dev.mode);
                if (r) {
                        ti->error = "Failed to set raid4/5/6 journal mode";
-                       mddev_unlock(&rs->md);
-                       goto bad_journal_mode_set;
+                       goto bad_unlock;
                }
        }
 
@@ -3272,14 +3270,14 @@ size_check:
        if (rs_is_raid456(rs)) {
                r = rs_set_raid456_stripe_cache(rs);
                if (r)
-                       goto bad_stripe_cache;
+                       goto bad_unlock;
        }
 
        /* Now do an early reshape check */
        if (test_bit(RT_FLAG_RESHAPE_RS, &rs->runtime_flags)) {
                r = rs_check_reshape(rs);
                if (r)
-                       goto bad_check_reshape;
+                       goto bad_unlock;
 
                /* Restore new, ctr requested layout to perform check */
                rs_config_restore(rs, &rs_layout);
@@ -3288,7 +3286,7 @@ size_check:
                        r = rs->md.pers->check_reshape(&rs->md);
                        if (r) {
                                ti->error = "Reshape check failed";
-                               goto bad_check_reshape;
+                               goto bad_unlock;
                        }
                }
        }
@@ -3299,11 +3297,9 @@ size_check:
        mddev_unlock(&rs->md);
        return 0;
 
-bad_md_start:
-bad_journal_mode_set:
-bad_stripe_cache:
-bad_check_reshape:
+bad_unlock:
        md_stop(&rs->md);
+       mddev_unlock(&rs->md);
 bad:
        raid_set_free(rs);
 
@@ -3314,7 +3310,9 @@ static void raid_dtr(struct dm_target *ti)
 {
        struct raid_set *rs = ti->private;
 
+       mddev_lock_nointr(&rs->md);
        md_stop(&rs->md);
+       mddev_unlock(&rs->md);
        raid_set_free(rs);
 }
 
index 2e38ef4..78be781 100644 (file)
@@ -6247,6 +6247,8 @@ static void __md_stop(struct mddev *mddev)
 
 void md_stop(struct mddev *mddev)
 {
+       lockdep_assert_held(&mddev->reconfig_mutex);
+
        /* stop the array and free an attached data structures.
         * This is called from dm-raid
         */
index 04b13cd..ba67587 100644 (file)
@@ -809,8 +809,11 @@ static void pulse8_ping_eeprom_work_handler(struct work_struct *work)
 
        mutex_lock(&pulse8->lock);
        cmd = MSGCODE_PING;
-       pulse8_send_and_wait(pulse8, &cmd, 1,
-                            MSGCODE_COMMAND_ACCEPTED, 0);
+       if (pulse8_send_and_wait(pulse8, &cmd, 1,
+                                MSGCODE_COMMAND_ACCEPTED, 0)) {
+               dev_warn(pulse8->dev, "failed to ping EEPROM\n");
+               goto unlock;
+       }
 
        if (pulse8->vers < 2)
                goto unlock;
index e9b2d90..3f7e147 100644 (file)
@@ -813,8 +813,8 @@ static unsigned long tc358746_find_pll_settings(struct tc358746 *tc358746,
        u32 min_delta = 0xffffffff;
        u16 prediv_max = 17;
        u16 prediv_min = 1;
-       u16 m_best, mul;
-       u16 p_best, p;
+       u16 m_best = 0, mul;
+       u16 p_best = 1, p;
        u8 postdiv;
 
        if (fout > 1000 * HZ_PER_MHZ) {
index 8fd5b6e..7551ca4 100644 (file)
@@ -2459,16 +2459,10 @@ static int dvb_register(struct cx23885_tsport *port)
                        request_module("%s", info.type);
                        client_tuner = i2c_new_client_device(&dev->i2c_bus[1].i2c_adap, &info);
                        if (!i2c_client_has_driver(client_tuner)) {
-                               module_put(client_demod->dev.driver->owner);
-                               i2c_unregister_device(client_demod);
-                               port->i2c_client_demod = NULL;
                                goto frontend_detach;
                        }
                        if (!try_module_get(client_tuner->dev.driver->owner)) {
                                i2c_unregister_device(client_tuner);
-                               module_put(client_demod->dev.driver->owner);
-                               i2c_unregister_device(client_demod);
-                               port->i2c_client_demod = NULL;
                                goto frontend_detach;
                        }
                        port->i2c_client_tuner = client_tuner;
@@ -2505,16 +2499,10 @@ static int dvb_register(struct cx23885_tsport *port)
                        request_module("%s", info.type);
                        client_tuner = i2c_new_client_device(&dev->i2c_bus[1].i2c_adap, &info);
                        if (!i2c_client_has_driver(client_tuner)) {
-                               module_put(client_demod->dev.driver->owner);
-                               i2c_unregister_device(client_demod);
-                               port->i2c_client_demod = NULL;
                                goto frontend_detach;
                        }
                        if (!try_module_get(client_tuner->dev.driver->owner)) {
                                i2c_unregister_device(client_tuner);
-                               module_put(client_demod->dev.driver->owner);
-                               i2c_unregister_device(client_demod);
-                               port->i2c_client_demod = NULL;
                                goto frontend_detach;
                        }
                        port->i2c_client_tuner = client_tuner;
index 43d85a5..7863b7b 100644 (file)
@@ -826,7 +826,7 @@ static const struct dev_pm_ops vpu_core_pm_ops = {
 
 static struct vpu_core_resources imx8q_enc = {
        .type = VPU_CORE_TYPE_ENC,
-       .fwname = "vpu/vpu_fw_imx8_enc.bin",
+       .fwname = "amphion/vpu/vpu_fw_imx8_enc.bin",
        .stride = 16,
        .max_width = 1920,
        .max_height = 1920,
@@ -841,7 +841,7 @@ static struct vpu_core_resources imx8q_enc = {
 
 static struct vpu_core_resources imx8q_dec = {
        .type = VPU_CORE_TYPE_DEC,
-       .fwname = "vpu/vpu_fw_imx8_dec.bin",
+       .fwname = "amphion/vpu/vpu_fw_imx8_dec.bin",
        .stride = 256,
        .max_width = 8188,
        .max_height = 8188,
index bf759eb..b6d5b48 100644 (file)
@@ -46,11 +46,10 @@ static int vpu_mbox_request_channel(struct device *dev, struct vpu_mbox *mbox)
        cl->rx_callback = vpu_mbox_rx_callback;
 
        ch = mbox_request_channel_byname(cl, mbox->name);
-       if (IS_ERR(ch)) {
-               dev_err(dev, "Failed to request mbox chan %s, ret : %ld\n",
-                       mbox->name, PTR_ERR(ch));
-               return PTR_ERR(ch);
-       }
+       if (IS_ERR(ch))
+               return dev_err_probe(dev, PTR_ERR(ch),
+                                    "Failed to request mbox chan %s\n",
+                                    mbox->name);
 
        mbox->ch = ch;
        return 0;
index 4768156..40cb3cb 100644 (file)
@@ -28,7 +28,6 @@
 #include "mtk_jpeg_core.h"
 #include "mtk_jpeg_dec_parse.h"
 
-#if defined(CONFIG_OF)
 static struct mtk_jpeg_fmt mtk_jpeg_enc_formats[] = {
        {
                .fourcc         = V4L2_PIX_FMT_JPEG,
@@ -102,7 +101,6 @@ static struct mtk_jpeg_fmt mtk_jpeg_dec_formats[] = {
                .flags          = MTK_JPEG_FMT_FLAG_CAPTURE,
        },
 };
-#endif
 
 #define MTK_JPEG_ENC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_enc_formats)
 #define MTK_JPEG_DEC_NUM_FORMATS ARRAY_SIZE(mtk_jpeg_dec_formats)
@@ -1455,7 +1453,6 @@ static const struct dev_pm_ops mtk_jpeg_pm_ops = {
        SET_RUNTIME_PM_OPS(mtk_jpeg_pm_suspend, mtk_jpeg_pm_resume, NULL)
 };
 
-#if defined(CONFIG_OF)
 static int mtk_jpegenc_get_hw(struct mtk_jpeg_ctx *ctx)
 {
        struct mtk_jpegenc_comp_dev *comp_jpeg;
@@ -1951,14 +1948,13 @@ static const struct of_device_id mtk_jpeg_match[] = {
 };
 
 MODULE_DEVICE_TABLE(of, mtk_jpeg_match);
-#endif
 
 static struct platform_driver mtk_jpeg_driver = {
        .probe = mtk_jpeg_probe,
        .remove_new = mtk_jpeg_remove,
        .driver = {
                .name           = MTK_JPEG_NAME,
-               .of_match_table = of_match_ptr(mtk_jpeg_match),
+               .of_match_table = mtk_jpeg_match,
                .pm             = &mtk_jpeg_pm_ops,
        },
 };
index 869068f..baa7be5 100644 (file)
@@ -39,7 +39,6 @@ enum mtk_jpeg_color {
        MTK_JPEG_COLOR_400              = 0x00110000
 };
 
-#if defined(CONFIG_OF)
 static const struct of_device_id mtk_jpegdec_hw_ids[] = {
        {
                .compatible = "mediatek,mt8195-jpgdec-hw",
@@ -47,7 +46,6 @@ static const struct of_device_id mtk_jpegdec_hw_ids[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, mtk_jpegdec_hw_ids);
-#endif
 
 static inline int mtk_jpeg_verify_align(u32 val, int align, u32 reg)
 {
@@ -653,7 +651,7 @@ static struct platform_driver mtk_jpegdec_hw_driver = {
        .probe = mtk_jpegdec_hw_probe,
        .driver = {
                .name = "mtk-jpegdec-hw",
-               .of_match_table = of_match_ptr(mtk_jpegdec_hw_ids),
+               .of_match_table = mtk_jpegdec_hw_ids,
        },
 };
 
index 71e85b4..2440183 100644 (file)
@@ -46,7 +46,6 @@ static const struct mtk_jpeg_enc_qlt mtk_jpeg_enc_quality[] = {
        {.quality_param = 97, .hardware_value = JPEG_ENC_QUALITY_Q97},
 };
 
-#if defined(CONFIG_OF)
 static const struct of_device_id mtk_jpegenc_drv_ids[] = {
        {
                .compatible = "mediatek,mt8195-jpgenc-hw",
@@ -54,7 +53,6 @@ static const struct of_device_id mtk_jpegenc_drv_ids[] = {
        {},
 };
 MODULE_DEVICE_TABLE(of, mtk_jpegenc_drv_ids);
-#endif
 
 void mtk_jpeg_enc_reset(void __iomem *base)
 {
@@ -377,7 +375,7 @@ static struct platform_driver mtk_jpegenc_hw_driver = {
        .probe = mtk_jpegenc_hw_probe,
        .driver = {
                .name = "mtk-jpegenc-hw",
-               .of_match_table = of_match_ptr(mtk_jpegenc_drv_ids),
+               .of_match_table = mtk_jpegenc_drv_ids,
        },
 };
 
index f555341..04e6dc6 100644 (file)
@@ -233,7 +233,8 @@ void vdec_msg_queue_deinit(struct vdec_msg_queue *msg_queue,
                kfree(lat_buf->private_data);
        }
 
-       cancel_work_sync(&msg_queue->core_work);
+       if (msg_queue->wdma_addr.size)
+               cancel_work_sync(&msg_queue->core_work);
 }
 
 static void vdec_msg_queue_core_work(struct work_struct *work)
index ed15ea3..a2b4fb9 100644 (file)
@@ -58,7 +58,6 @@
 #define CAST_OFBSIZE_LO                        CAST_STATUS18
 #define CAST_OFBSIZE_HI                        CAST_STATUS19
 
-#define MXC_MAX_SLOTS  1 /* TODO use all 4 slots*/
 /* JPEG-Decoder Wrapper Slot Registers 0..3 */
 #define SLOT_BASE                      0x10000
 #define SLOT_STATUS                    0x0
index c0e49be..9512c0a 100644 (file)
@@ -745,87 +745,77 @@ static void notify_src_chg(struct mxc_jpeg_ctx *ctx)
        v4l2_event_queue_fh(&ctx->fh, &ev);
 }
 
-static int mxc_get_free_slot(struct mxc_jpeg_slot_data slot_data[], int n)
+static int mxc_get_free_slot(struct mxc_jpeg_slot_data *slot_data)
 {
-       int free_slot = 0;
-
-       while (slot_data[free_slot].used && free_slot < n)
-               free_slot++;
-
-       return free_slot; /* >=n when there are no more free slots */
+       if (!slot_data->used)
+               return slot_data->slot;
+       return -1;
 }
 
-static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg,
-                                    unsigned int slot)
+static bool mxc_jpeg_alloc_slot_data(struct mxc_jpeg_dev *jpeg)
 {
        struct mxc_jpeg_desc *desc;
        struct mxc_jpeg_desc *cfg_desc;
        void *cfg_stm;
 
-       if (jpeg->slot_data[slot].desc)
+       if (jpeg->slot_data.desc)
                goto skip_alloc; /* already allocated, reuse it */
 
        /* allocate descriptor for decoding/encoding phase */
        desc = dma_alloc_coherent(jpeg->dev,
                                  sizeof(struct mxc_jpeg_desc),
-                                 &jpeg->slot_data[slot].desc_handle,
+                                 &jpeg->slot_data.desc_handle,
                                  GFP_ATOMIC);
        if (!desc)
                goto err;
-       jpeg->slot_data[slot].desc = desc;
+       jpeg->slot_data.desc = desc;
 
        /* allocate descriptor for configuration phase (encoder only) */
        cfg_desc = dma_alloc_coherent(jpeg->dev,
                                      sizeof(struct mxc_jpeg_desc),
-                                     &jpeg->slot_data[slot].cfg_desc_handle,
+                                     &jpeg->slot_data.cfg_desc_handle,
                                      GFP_ATOMIC);
        if (!cfg_desc)
                goto err;
-       jpeg->slot_data[slot].cfg_desc = cfg_desc;
+       jpeg->slot_data.cfg_desc = cfg_desc;
 
        /* allocate configuration stream */
        cfg_stm = dma_alloc_coherent(jpeg->dev,
                                     MXC_JPEG_MAX_CFG_STREAM,
-                                    &jpeg->slot_data[slot].cfg_stream_handle,
+                                    &jpeg->slot_data.cfg_stream_handle,
                                     GFP_ATOMIC);
        if (!cfg_stm)
                goto err;
-       jpeg->slot_data[slot].cfg_stream_vaddr = cfg_stm;
+       jpeg->slot_data.cfg_stream_vaddr = cfg_stm;
 
 skip_alloc:
-       jpeg->slot_data[slot].used = true;
+       jpeg->slot_data.used = true;
 
        return true;
 err:
-       dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", slot);
+       dev_err(jpeg->dev, "Could not allocate descriptors for slot %d", jpeg->slot_data.slot);
 
        return false;
 }
 
-static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg,
-                                   unsigned int slot)
+static void mxc_jpeg_free_slot_data(struct mxc_jpeg_dev *jpeg)
 {
-       if (slot >= MXC_MAX_SLOTS) {
-               dev_err(jpeg->dev, "Invalid slot %d, nothing to free.", slot);
-               return;
-       }
-
        /* free descriptor for decoding/encoding phase */
        dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
-                         jpeg->slot_data[slot].desc,
-                         jpeg->slot_data[slot].desc_handle);
+                         jpeg->slot_data.desc,
+                         jpeg->slot_data.desc_handle);
 
        /* free descriptor for encoder configuration phase / decoder DHT */
        dma_free_coherent(jpeg->dev, sizeof(struct mxc_jpeg_desc),
-                         jpeg->slot_data[slot].cfg_desc,
-                         jpeg->slot_data[slot].cfg_desc_handle);
+                         jpeg->slot_data.cfg_desc,
+                         jpeg->slot_data.cfg_desc_handle);
 
        /* free configuration stream */
        dma_free_coherent(jpeg->dev, MXC_JPEG_MAX_CFG_STREAM,
-                         jpeg->slot_data[slot].cfg_stream_vaddr,
-                         jpeg->slot_data[slot].cfg_stream_handle);
+                         jpeg->slot_data.cfg_stream_vaddr,
+                         jpeg->slot_data.cfg_stream_handle);
 
-       jpeg->slot_data[slot].used = false;
+       jpeg->slot_data.used = false;
 }
 
 static void mxc_jpeg_check_and_set_last_buffer(struct mxc_jpeg_ctx *ctx,
@@ -855,7 +845,7 @@ static void mxc_jpeg_job_finish(struct mxc_jpeg_ctx *ctx, enum vb2_buffer_state
        v4l2_m2m_buf_done(dst_buf, state);
 
        mxc_jpeg_disable_irq(reg, ctx->slot);
-       ctx->mxc_jpeg->slot_data[ctx->slot].used = false;
+       jpeg->slot_data.used = false;
        if (reset)
                mxc_jpeg_sw_reset(reg);
 }
@@ -919,7 +909,7 @@ static irqreturn_t mxc_jpeg_dec_irq(int irq, void *priv)
                goto job_unlock;
        }
 
-       if (!jpeg->slot_data[slot].used)
+       if (!jpeg->slot_data.used)
                goto job_unlock;
 
        dec_ret = readl(reg + MXC_SLOT_OFFSET(slot, SLOT_STATUS));
@@ -1179,13 +1169,13 @@ static void mxc_jpeg_config_dec_desc(struct vb2_buffer *out_buf,
        struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
        void __iomem *reg = jpeg->base_reg;
        unsigned int slot = ctx->slot;
-       struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
-       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
-       dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
-       dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
-       dma_addr_t cfg_stream_handle = jpeg->slot_data[slot].cfg_stream_handle;
-       unsigned int *cfg_size = &jpeg->slot_data[slot].cfg_stream_size;
-       void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
+       struct mxc_jpeg_desc *desc = jpeg->slot_data.desc;
+       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc;
+       dma_addr_t desc_handle = jpeg->slot_data.desc_handle;
+       dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle;
+       dma_addr_t cfg_stream_handle = jpeg->slot_data.cfg_stream_handle;
+       unsigned int *cfg_size = &jpeg->slot_data.cfg_stream_size;
+       void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr;
        struct mxc_jpeg_src_buf *jpeg_src_buf;
 
        jpeg_src_buf = vb2_to_mxc_buf(src_buf);
@@ -1245,18 +1235,18 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
        struct mxc_jpeg_dev *jpeg = ctx->mxc_jpeg;
        void __iomem *reg = jpeg->base_reg;
        unsigned int slot = ctx->slot;
-       struct mxc_jpeg_desc *desc = jpeg->slot_data[slot].desc;
-       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data[slot].cfg_desc;
-       dma_addr_t desc_handle = jpeg->slot_data[slot].desc_handle;
-       dma_addr_t cfg_desc_handle = jpeg->slot_data[slot].cfg_desc_handle;
-       void *cfg_stream_vaddr = jpeg->slot_data[slot].cfg_stream_vaddr;
+       struct mxc_jpeg_desc *desc = jpeg->slot_data.desc;
+       struct mxc_jpeg_desc *cfg_desc = jpeg->slot_data.cfg_desc;
+       dma_addr_t desc_handle = jpeg->slot_data.desc_handle;
+       dma_addr_t cfg_desc_handle = jpeg->slot_data.cfg_desc_handle;
+       void *cfg_stream_vaddr = jpeg->slot_data.cfg_stream_vaddr;
        struct mxc_jpeg_q_data *q_data;
        enum mxc_jpeg_image_format img_fmt;
        int w, h;
 
        q_data = mxc_jpeg_get_q_data(ctx, src_buf->vb2_queue->type);
 
-       jpeg->slot_data[slot].cfg_stream_size =
+       jpeg->slot_data.cfg_stream_size =
                        mxc_jpeg_setup_cfg_stream(cfg_stream_vaddr,
                                                  q_data->fmt->fourcc,
                                                  q_data->crop.width,
@@ -1265,7 +1255,7 @@ static void mxc_jpeg_config_enc_desc(struct vb2_buffer *out_buf,
        /* chain the config descriptor with the encoding descriptor */
        cfg_desc->next_descpt_ptr = desc_handle | MXC_NXT_DESCPT_EN;
 
-       cfg_desc->buf_base0 = jpeg->slot_data[slot].cfg_stream_handle;
+       cfg_desc->buf_base0 = jpeg->slot_data.cfg_stream_handle;
        cfg_desc->buf_base1 = 0;
        cfg_desc->line_pitch = 0;
        cfg_desc->stm_bufbase = 0; /* no output expected */
@@ -1408,7 +1398,7 @@ static void mxc_jpeg_device_run_timeout(struct work_struct *work)
        unsigned long flags;
 
        spin_lock_irqsave(&ctx->mxc_jpeg->hw_lock, flags);
-       if (ctx->slot < MXC_MAX_SLOTS && ctx->mxc_jpeg->slot_data[ctx->slot].used) {
+       if (ctx->mxc_jpeg->slot_data.used) {
                dev_warn(jpeg->dev, "%s timeout, cancel it\n",
                         ctx->mxc_jpeg->mode == MXC_JPEG_DECODE ? "decode" : "encode");
                mxc_jpeg_job_finish(ctx, VB2_BUF_STATE_ERROR, true);
@@ -1476,12 +1466,12 @@ static void mxc_jpeg_device_run(void *priv)
        mxc_jpeg_enable(reg);
        mxc_jpeg_set_l_endian(reg, 1);
 
-       ctx->slot = mxc_get_free_slot(jpeg->slot_data, MXC_MAX_SLOTS);
-       if (ctx->slot >= MXC_MAX_SLOTS) {
+       ctx->slot = mxc_get_free_slot(&jpeg->slot_data);
+       if (ctx->slot < 0) {
                dev_err(dev, "No more free slots\n");
                goto end;
        }
-       if (!mxc_jpeg_alloc_slot_data(jpeg, ctx->slot)) {
+       if (!mxc_jpeg_alloc_slot_data(jpeg)) {
                dev_err(dev, "Cannot allocate slot data\n");
                goto end;
        }
@@ -2101,7 +2091,7 @@ static int mxc_jpeg_open(struct file *file)
        }
        ctx->fh.ctrl_handler = &ctx->ctrl_handler;
        mxc_jpeg_set_default_params(ctx);
-       ctx->slot = MXC_MAX_SLOTS; /* slot not allocated yet */
+       ctx->slot = -1; /* slot not allocated yet */
        INIT_DELAYED_WORK(&ctx->task_timer, mxc_jpeg_device_run_timeout);
 
        if (mxc_jpeg->mode == MXC_JPEG_DECODE)
@@ -2677,6 +2667,11 @@ static int mxc_jpeg_attach_pm_domains(struct mxc_jpeg_dev *jpeg)
                dev_err(dev, "No power domains defined for jpeg node\n");
                return jpeg->num_domains;
        }
+       if (jpeg->num_domains == 1) {
+               /* genpd_dev_pm_attach() attach automatically if power domains count is 1 */
+               jpeg->num_domains = 0;
+               return 0;
+       }
 
        jpeg->pd_dev = devm_kmalloc_array(dev, jpeg->num_domains,
                                          sizeof(*jpeg->pd_dev), GFP_KERNEL);
@@ -2718,7 +2713,6 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
        int ret;
        int mode;
        const struct of_device_id *of_id;
-       unsigned int slot;
 
        of_id = of_match_node(mxc_jpeg_match, dev->of_node);
        if (!of_id)
@@ -2742,19 +2736,22 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
        if (IS_ERR(jpeg->base_reg))
                return PTR_ERR(jpeg->base_reg);
 
-       for (slot = 0; slot < MXC_MAX_SLOTS; slot++) {
-               dec_irq = platform_get_irq(pdev, slot);
-               if (dec_irq < 0) {
-                       ret = dec_irq;
-                       goto err_irq;
-               }
-               ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
-                                      0, pdev->name, jpeg);
-               if (ret) {
-                       dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
-                               dec_irq, ret);
-                       goto err_irq;
-               }
+       ret = of_property_read_u32_index(pdev->dev.of_node, "slot", 0, &jpeg->slot_data.slot);
+       if (ret)
+               jpeg->slot_data.slot = 0;
+       dev_info(&pdev->dev, "choose slot %d\n", jpeg->slot_data.slot);
+       dec_irq = platform_get_irq(pdev, 0);
+       if (dec_irq < 0) {
+               dev_err(&pdev->dev, "Failed to get irq %d\n", dec_irq);
+               ret = dec_irq;
+               goto err_irq;
+       }
+       ret = devm_request_irq(&pdev->dev, dec_irq, mxc_jpeg_dec_irq,
+                              0, pdev->name, jpeg);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to request irq %d (%d)\n",
+                       dec_irq, ret);
+               goto err_irq;
        }
 
        jpeg->pdev = pdev;
@@ -2914,11 +2911,9 @@ static const struct dev_pm_ops   mxc_jpeg_pm_ops = {
 
 static void mxc_jpeg_remove(struct platform_device *pdev)
 {
-       unsigned int slot;
        struct mxc_jpeg_dev *jpeg = platform_get_drvdata(pdev);
 
-       for (slot = 0; slot < MXC_MAX_SLOTS; slot++)
-               mxc_jpeg_free_slot_data(jpeg, slot);
+       mxc_jpeg_free_slot_data(jpeg);
 
        pm_runtime_disable(&pdev->dev);
        video_unregister_device(jpeg->dec_vdev);
index 87157db..d80e94c 100644 (file)
@@ -97,7 +97,7 @@ struct mxc_jpeg_ctx {
        struct mxc_jpeg_q_data          cap_q;
        struct v4l2_fh                  fh;
        enum mxc_jpeg_enc_state         enc_state;
-       unsigned int                    slot;
+       int                             slot;
        unsigned int                    source_change;
        bool                            header_parsed;
        struct v4l2_ctrl_handler        ctrl_handler;
@@ -106,6 +106,7 @@ struct mxc_jpeg_ctx {
 };
 
 struct mxc_jpeg_slot_data {
+       int slot;
        bool used;
        struct mxc_jpeg_desc *desc; // enc/dec descriptor
        struct mxc_jpeg_desc *cfg_desc; // configuration descriptor
@@ -128,7 +129,7 @@ struct mxc_jpeg_dev {
        struct v4l2_device              v4l2_dev;
        struct v4l2_m2m_dev             *m2m_dev;
        struct video_device             *dec_vdev;
-       struct mxc_jpeg_slot_data       slot_data[MXC_MAX_SLOTS];
+       struct mxc_jpeg_slot_data       slot_data;
        int                             num_domains;
        struct device                   **pd_dev;
        struct device_link              **pd_link;
index 6523ffb..77aee94 100644 (file)
@@ -370,26 +370,26 @@ extern int hantro_debug;
        pr_err("%s:%d: " fmt, __func__, __LINE__, ##args)
 
 /* Structure access helpers. */
-static inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh)
+static __always_inline struct hantro_ctx *fh_to_ctx(struct v4l2_fh *fh)
 {
        return container_of(fh, struct hantro_ctx, fh);
 }
 
 /* Register accessors. */
-static inline void vepu_write_relaxed(struct hantro_dev *vpu,
-                                     u32 val, u32 reg)
+static __always_inline void vepu_write_relaxed(struct hantro_dev *vpu,
+                                              u32 val, u32 reg)
 {
        vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
        writel_relaxed(val, vpu->enc_base + reg);
 }
 
-static inline void vepu_write(struct hantro_dev *vpu, u32 val, u32 reg)
+static __always_inline void vepu_write(struct hantro_dev *vpu, u32 val, u32 reg)
 {
        vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
        writel(val, vpu->enc_base + reg);
 }
 
-static inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
+static __always_inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
 {
        u32 val = readl(vpu->enc_base + reg);
 
@@ -397,27 +397,27 @@ static inline u32 vepu_read(struct hantro_dev *vpu, u32 reg)
        return val;
 }
 
-static inline void vdpu_write_relaxed(struct hantro_dev *vpu,
-                                     u32 val, u32 reg)
+static __always_inline void vdpu_write_relaxed(struct hantro_dev *vpu,
+                                              u32 val, u32 reg)
 {
        vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
        writel_relaxed(val, vpu->dec_base + reg);
 }
 
-static inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg)
+static __always_inline void vdpu_write(struct hantro_dev *vpu, u32 val, u32 reg)
 {
        vpu_debug(6, "0x%04x = 0x%08x\n", reg / 4, val);
        writel(val, vpu->dec_base + reg);
 }
 
-static inline void hantro_write_addr(struct hantro_dev *vpu,
-                                    unsigned long offset,
-                                    dma_addr_t addr)
+static __always_inline void hantro_write_addr(struct hantro_dev *vpu,
+                                             unsigned long offset,
+                                             dma_addr_t addr)
 {
        vdpu_write(vpu, addr & 0xffffffff, offset);
 }
 
-static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
+static __always_inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
 {
        u32 val = readl(vpu->dec_base + reg);
 
@@ -425,9 +425,9 @@ static inline u32 vdpu_read(struct hantro_dev *vpu, u32 reg)
        return val;
 }
 
-static inline u32 vdpu_read_mask(struct hantro_dev *vpu,
-                                const struct hantro_reg *reg,
-                                u32 val)
+static __always_inline u32 vdpu_read_mask(struct hantro_dev *vpu,
+                                         const struct hantro_reg *reg,
+                                         u32 val)
 {
        u32 v;
 
@@ -437,18 +437,18 @@ static inline u32 vdpu_read_mask(struct hantro_dev *vpu,
        return v;
 }
 
-static inline void hantro_reg_write(struct hantro_dev *vpu,
-                                   const struct hantro_reg *reg,
-                                   u32 val)
+static __always_inline void hantro_reg_write(struct hantro_dev *vpu,
+                                            const struct hantro_reg *reg,
+                                            u32 val)
 {
-       vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
+       vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
 }
 
-static inline void hantro_reg_write_s(struct hantro_dev *vpu,
-                                     const struct hantro_reg *reg,
-                                     u32 val)
+static __always_inline void hantro_reg_write_relaxed(struct hantro_dev *vpu,
+                                                    const struct hantro_reg *reg,
+                                                    u32 val)
 {
-       vdpu_write(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
+       vdpu_write_relaxed(vpu, vdpu_read_mask(vpu, reg, val), reg->base);
 }
 
 void *hantro_get_ctrl(struct hantro_ctx *ctx, u32 id);
index c977d64..0224ff6 100644 (file)
                         val); \
 }
 
-#define HANTRO_PP_REG_WRITE_S(vpu, reg_name, val) \
+#define HANTRO_PP_REG_WRITE_RELAXED(vpu, reg_name, val) \
 { \
-       hantro_reg_write_s(vpu, \
-                          &hantro_g1_postproc_regs.reg_name, \
-                          val); \
+       hantro_reg_write_relaxed(vpu, \
+                                &hantro_g1_postproc_regs.reg_name, \
+                                val); \
 }
 
 #define VPU_PP_IN_YUYV                 0x0
@@ -72,7 +72,7 @@ static void hantro_postproc_g1_enable(struct hantro_ctx *ctx)
        dma_addr_t dst_dma;
 
        /* Turn on pipeline mode. Must be done first. */
-       HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x1);
+       HANTRO_PP_REG_WRITE(vpu, pipeline_en, 0x1);
 
        src_pp_fmt = VPU_PP_IN_NV12;
 
@@ -242,7 +242,7 @@ static void hantro_postproc_g1_disable(struct hantro_ctx *ctx)
 {
        struct hantro_dev *vpu = ctx->dev;
 
-       HANTRO_PP_REG_WRITE_S(vpu, pipeline_en, 0x0);
+       HANTRO_PP_REG_WRITE(vpu, pipeline_en, 0x0);
 }
 
 static void hantro_postproc_g2_disable(struct hantro_ctx *ctx)
index 4a750da..deb6e65 100644 (file)
@@ -755,6 +755,43 @@ const char *const tegra_mc_error_names[8] = {
        [6] = "SMMU translation error",
 };
 
+struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data)
+{
+       struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
+       struct icc_node *node;
+
+       list_for_each_entry(node, &mc->provider.nodes, node_list) {
+               if (node->id == spec->args[0])
+                       return node;
+       }
+
+       /*
+        * If a client driver calls devm_of_icc_get() before the MC driver
+        * is probed, then return EPROBE_DEFER to the client driver.
+        */
+       return ERR_PTR(-EPROBE_DEFER);
+}
+
+static int tegra_mc_icc_get(struct icc_node *node, u32 *average, u32 *peak)
+{
+       *average = 0;
+       *peak = 0;
+
+       return 0;
+}
+
+static int tegra_mc_icc_set(struct icc_node *src, struct icc_node *dst)
+{
+       return 0;
+}
+
+const struct tegra_mc_icc_ops tegra_mc_icc_ops = {
+       .xlate = tegra_mc_icc_xlate,
+       .aggregate = icc_std_aggregate,
+       .get_bw = tegra_mc_icc_get,
+       .set = tegra_mc_icc_set,
+};
+
 /*
  * Memory Controller (MC) has few Memory Clients that are issuing memory
  * bandwidth allocation requests to the MC interconnect provider. The MC
index b2416ee..26035ac 100644 (file)
@@ -1355,6 +1355,7 @@ const struct tegra_mc_soc tegra194_mc_soc = {
                   MC_INT_SECURITY_VIOLATION | MC_INT_DECERR_EMEM,
        .has_addr_hi_reg = true,
        .ops = &tegra186_mc_ops,
+       .icc_ops = &tegra_mc_icc_ops,
        .ch_intmask = 0x00000f00,
        .global_intstatus_channel_shift = 8,
 };
index 8e873a7..8fb83b3 100644 (file)
@@ -827,7 +827,7 @@ static int tegra234_mc_icc_set(struct icc_node *src, struct icc_node *dst)
                return 0;
 
        if (!mc->bwmgr_mrq_supported)
-               return -EINVAL;
+               return 0;
 
        if (!mc->bpmp) {
                dev_err(mc->dev, "BPMP reference NULL\n");
@@ -874,7 +874,7 @@ static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
        struct tegra_mc *mc = icc_provider_to_tegra_mc(p);
 
        if (!mc->bwmgr_mrq_supported)
-               return -EINVAL;
+               return 0;
 
        if (node->id == TEGRA_ICC_MC_CPU_CLUSTER0 ||
            node->id == TEGRA_ICC_MC_CPU_CLUSTER1 ||
@@ -889,27 +889,6 @@ static int tegra234_mc_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
        return 0;
 }
 
-static struct icc_node*
-tegra234_mc_of_icc_xlate(struct of_phandle_args *spec, void *data)
-{
-       struct tegra_mc *mc = icc_provider_to_tegra_mc(data);
-       unsigned int cl_id = spec->args[0];
-       struct icc_node *node;
-
-       list_for_each_entry(node, &mc->provider.nodes, node_list) {
-               if (node->id != cl_id)
-                       continue;
-
-               return node;
-       }
-
-       /*
-        * If a client driver calls devm_of_icc_get() before the MC driver
-        * is probed, then return EPROBE_DEFER to the client driver.
-        */
-       return ERR_PTR(-EPROBE_DEFER);
-}
-
 static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *peak)
 {
        *avg = 0;
@@ -919,7 +898,7 @@ static int tegra234_mc_icc_get_init_bw(struct icc_node *node, u32 *avg, u32 *pea
 }
 
 static const struct tegra_mc_icc_ops tegra234_mc_icc_ops = {
-       .xlate = tegra234_mc_of_icc_xlate,
+       .xlate = tegra_mc_icc_xlate,
        .aggregate = tegra234_mc_icc_aggregate,
        .get_bw = tegra234_mc_icc_get_init_bw,
        .set = tegra234_mc_icc_set,
index 5757adf..6120973 100644 (file)
@@ -236,7 +236,7 @@ static int sram_reserve_regions(struct sram_dev *sram, struct resource *res)
                        }
                        if (!label)
                                block->label = devm_kasprintf(sram->dev, GFP_KERNEL,
-                                                             "%s", dev_name(sram->dev));
+                                                             "%s", of_node_full_name(child));
                        else
                                block->label = devm_kstrdup(sram->dev,
                                                            label, GFP_KERNEL);
index 7a0f253..484c9e3 100644 (file)
@@ -1508,6 +1508,11 @@ static void bond_setup_by_slave(struct net_device *bond_dev,
 
        memcpy(bond_dev->broadcast, slave_dev->broadcast,
                slave_dev->addr_len);
+
+       if (slave_dev->flags & IFF_POINTOPOINT) {
+               bond_dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+               bond_dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+       }
 }
 
 /* On bonding slaves other than the currently active slave, suppress
index 68df6d4..eebf967 100644 (file)
@@ -227,6 +227,8 @@ static int
 __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
                          const u8 mode_req, bool nowait)
 {
+       const struct can_bittiming *bt = &priv->can.bittiming;
+       unsigned long timeout_us = MCP251XFD_POLL_TIMEOUT_US;
        u32 con = 0, con_reqop, osc = 0;
        u8 mode;
        int err;
@@ -246,12 +248,16 @@ __mcp251xfd_chip_set_mode(const struct mcp251xfd_priv *priv,
        if (mode_req == MCP251XFD_REG_CON_MODE_SLEEP || nowait)
                return 0;
 
+       if (bt->bitrate)
+               timeout_us = max_t(unsigned long, timeout_us,
+                                  MCP251XFD_FRAME_LEN_MAX_BITS * USEC_PER_SEC /
+                                  bt->bitrate);
+
        err = regmap_read_poll_timeout(priv->map_reg, MCP251XFD_REG_CON, con,
                                       !mcp251xfd_reg_invalid(con) &&
                                       FIELD_GET(MCP251XFD_REG_CON_OPMOD_MASK,
                                                 con) == mode_req,
-                                      MCP251XFD_POLL_SLEEP_US,
-                                      MCP251XFD_POLL_TIMEOUT_US);
+                                      MCP251XFD_POLL_SLEEP_US, timeout_us);
        if (err != -ETIMEDOUT && err != -EBADMSG)
                return err;
 
index 7024ff0..24510b3 100644 (file)
@@ -387,6 +387,7 @@ static_assert(MCP251XFD_TIMESTAMP_WORK_DELAY_SEC <
 #define MCP251XFD_OSC_STAB_TIMEOUT_US (10 * MCP251XFD_OSC_STAB_SLEEP_US)
 #define MCP251XFD_POLL_SLEEP_US (10)
 #define MCP251XFD_POLL_TIMEOUT_US (USEC_PER_MSEC)
+#define MCP251XFD_FRAME_LEN_MAX_BITS (736)
 
 /* Misc */
 #define MCP251XFD_NAPI_WEIGHT 32
index d476c28..bd9eb06 100644 (file)
@@ -303,12 +303,6 @@ struct gs_can {
        struct can_bittiming_const bt_const, data_bt_const;
        unsigned int channel;   /* channel number */
 
-       /* time counter for hardware timestamps */
-       struct cyclecounter cc;
-       struct timecounter tc;
-       spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
-       struct delayed_work timestamp;
-
        u32 feature;
        unsigned int hf_size_tx;
 
@@ -325,6 +319,13 @@ struct gs_usb {
        struct gs_can *canch[GS_MAX_INTF];
        struct usb_anchor rx_submitted;
        struct usb_device *udev;
+
+       /* time counter for hardware timestamps */
+       struct cyclecounter cc;
+       struct timecounter tc;
+       spinlock_t tc_lock; /* spinlock to guard access tc->cycle_last */
+       struct delayed_work timestamp;
+
        unsigned int hf_size_rx;
        u8 active_channels;
 };
@@ -388,15 +389,15 @@ static int gs_cmd_reset(struct gs_can *dev)
                                    GFP_KERNEL);
 }
 
-static inline int gs_usb_get_timestamp(const struct gs_can *dev,
+static inline int gs_usb_get_timestamp(const struct gs_usb *parent,
                                       u32 *timestamp_p)
 {
        __le32 timestamp;
        int rc;
 
-       rc = usb_control_msg_recv(dev->udev, 0, GS_USB_BREQ_TIMESTAMP,
+       rc = usb_control_msg_recv(parent->udev, 0, GS_USB_BREQ_TIMESTAMP,
                                  USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE,
-                                 dev->channel, 0,
+                                 0, 0,
                                  &timestamp, sizeof(timestamp),
                                  USB_CTRL_GET_TIMEOUT,
                                  GFP_KERNEL);
@@ -410,20 +411,20 @@ static inline int gs_usb_get_timestamp(const struct gs_can *dev,
 
 static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev->tc_lock)
 {
-       struct gs_can *dev = container_of(cc, struct gs_can, cc);
+       struct gs_usb *parent = container_of(cc, struct gs_usb, cc);
        u32 timestamp = 0;
        int err;
 
-       lockdep_assert_held(&dev->tc_lock);
+       lockdep_assert_held(&parent->tc_lock);
 
        /* drop lock for synchronous USB transfer */
-       spin_unlock_bh(&dev->tc_lock);
-       err = gs_usb_get_timestamp(dev, &timestamp);
-       spin_lock_bh(&dev->tc_lock);
+       spin_unlock_bh(&parent->tc_lock);
+       err = gs_usb_get_timestamp(parent, &timestamp);
+       spin_lock_bh(&parent->tc_lock);
        if (err)
-               netdev_err(dev->netdev,
-                          "Error %d while reading timestamp. HW timestamps may be inaccurate.",
-                          err);
+               dev_err(&parent->udev->dev,
+                       "Error %d while reading timestamp. HW timestamps may be inaccurate.",
+                       err);
 
        return timestamp;
 }
@@ -431,14 +432,14 @@ static u64 gs_usb_timestamp_read(const struct cyclecounter *cc) __must_hold(&dev
 static void gs_usb_timestamp_work(struct work_struct *work)
 {
        struct delayed_work *delayed_work = to_delayed_work(work);
-       struct gs_can *dev;
+       struct gs_usb *parent;
 
-       dev = container_of(delayed_work, struct gs_can, timestamp);
-       spin_lock_bh(&dev->tc_lock);
-       timecounter_read(&dev->tc);
-       spin_unlock_bh(&dev->tc_lock);
+       parent = container_of(delayed_work, struct gs_usb, timestamp);
+       spin_lock_bh(&parent->tc_lock);
+       timecounter_read(&parent->tc);
+       spin_unlock_bh(&parent->tc_lock);
 
-       schedule_delayed_work(&dev->timestamp,
+       schedule_delayed_work(&parent->timestamp,
                              GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
 }
 
@@ -446,37 +447,38 @@ static void gs_usb_skb_set_timestamp(struct gs_can *dev,
                                     struct sk_buff *skb, u32 timestamp)
 {
        struct skb_shared_hwtstamps *hwtstamps = skb_hwtstamps(skb);
+       struct gs_usb *parent = dev->parent;
        u64 ns;
 
-       spin_lock_bh(&dev->tc_lock);
-       ns = timecounter_cyc2time(&dev->tc, timestamp);
-       spin_unlock_bh(&dev->tc_lock);
+       spin_lock_bh(&parent->tc_lock);
+       ns = timecounter_cyc2time(&parent->tc, timestamp);
+       spin_unlock_bh(&parent->tc_lock);
 
        hwtstamps->hwtstamp = ns_to_ktime(ns);
 }
 
-static void gs_usb_timestamp_init(struct gs_can *dev)
+static void gs_usb_timestamp_init(struct gs_usb *parent)
 {
-       struct cyclecounter *cc = &dev->cc;
+       struct cyclecounter *cc = &parent->cc;
 
        cc->read = gs_usb_timestamp_read;
        cc->mask = CYCLECOUNTER_MASK(32);
        cc->shift = 32 - bits_per(NSEC_PER_SEC / GS_USB_TIMESTAMP_TIMER_HZ);
        cc->mult = clocksource_hz2mult(GS_USB_TIMESTAMP_TIMER_HZ, cc->shift);
 
-       spin_lock_init(&dev->tc_lock);
-       spin_lock_bh(&dev->tc_lock);
-       timecounter_init(&dev->tc, &dev->cc, ktime_get_real_ns());
-       spin_unlock_bh(&dev->tc_lock);
+       spin_lock_init(&parent->tc_lock);
+       spin_lock_bh(&parent->tc_lock);
+       timecounter_init(&parent->tc, &parent->cc, ktime_get_real_ns());
+       spin_unlock_bh(&parent->tc_lock);
 
-       INIT_DELAYED_WORK(&dev->timestamp, gs_usb_timestamp_work);
-       schedule_delayed_work(&dev->timestamp,
+       INIT_DELAYED_WORK(&parent->timestamp, gs_usb_timestamp_work);
+       schedule_delayed_work(&parent->timestamp,
                              GS_USB_TIMESTAMP_WORK_DELAY_SEC * HZ);
 }
 
-static void gs_usb_timestamp_stop(struct gs_can *dev)
+static void gs_usb_timestamp_stop(struct gs_usb *parent)
 {
-       cancel_delayed_work_sync(&dev->timestamp);
+       cancel_delayed_work_sync(&parent->timestamp);
 }
 
 static void gs_update_state(struct gs_can *dev, struct can_frame *cf)
@@ -560,6 +562,9 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
        if (!netif_device_present(netdev))
                return;
 
+       if (!netif_running(netdev))
+               goto resubmit_urb;
+
        if (hf->echo_id == -1) { /* normal rx */
                if (hf->flags & GS_CAN_FLAG_FD) {
                        skb = alloc_canfd_skb(dev->netdev, &cfd);
@@ -833,6 +838,7 @@ static int gs_can_open(struct net_device *netdev)
                .mode = cpu_to_le32(GS_CAN_MODE_START),
        };
        struct gs_host_frame *hf;
+       struct urb *urb = NULL;
        u32 ctrlmode;
        u32 flags = 0;
        int rc, i;
@@ -855,14 +861,18 @@ static int gs_can_open(struct net_device *netdev)
        }
 
        if (!parent->active_channels) {
+               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+                       gs_usb_timestamp_init(parent);
+
                for (i = 0; i < GS_MAX_RX_URBS; i++) {
-                       struct urb *urb;
                        u8 *buf;
 
                        /* alloc rx urb */
                        urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (!urb)
-                               return -ENOMEM;
+                       if (!urb) {
+                               rc = -ENOMEM;
+                               goto out_usb_kill_anchored_urbs;
+                       }
 
                        /* alloc rx buffer */
                        buf = kmalloc(dev->parent->hf_size_rx,
@@ -870,8 +880,8 @@ static int gs_can_open(struct net_device *netdev)
                        if (!buf) {
                                netdev_err(netdev,
                                           "No memory left for USB buffer\n");
-                               usb_free_urb(urb);
-                               return -ENOMEM;
+                               rc = -ENOMEM;
+                               goto out_usb_free_urb;
                        }
 
                        /* fill, anchor, and submit rx urb */
@@ -894,9 +904,7 @@ static int gs_can_open(struct net_device *netdev)
                                netdev_err(netdev,
                                           "usb_submit failed (err=%d)\n", rc);
 
-                               usb_unanchor_urb(urb);
-                               usb_free_urb(urb);
-                               break;
+                               goto out_usb_unanchor_urb;
                        }
 
                        /* Drop reference,
@@ -926,13 +934,9 @@ static int gs_can_open(struct net_device *netdev)
                flags |= GS_CAN_MODE_FD;
 
        /* if hardware supports timestamps, enable it */
-       if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP) {
+       if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
                flags |= GS_CAN_MODE_HW_TIMESTAMP;
 
-               /* start polling timestamp */
-               gs_usb_timestamp_init(dev);
-       }
-
        /* finally start device */
        dev->can.state = CAN_STATE_ERROR_ACTIVE;
        dm.flags = cpu_to_le32(flags);
@@ -942,10 +946,9 @@ static int gs_can_open(struct net_device *netdev)
                                  GFP_KERNEL);
        if (rc) {
                netdev_err(netdev, "Couldn't start device (err=%d)\n", rc);
-               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
-                       gs_usb_timestamp_stop(dev);
                dev->can.state = CAN_STATE_STOPPED;
-               return rc;
+
+               goto out_usb_kill_anchored_urbs;
        }
 
        parent->active_channels++;
@@ -953,6 +956,22 @@ static int gs_can_open(struct net_device *netdev)
                netif_start_queue(netdev);
 
        return 0;
+
+out_usb_unanchor_urb:
+       usb_unanchor_urb(urb);
+out_usb_free_urb:
+       usb_free_urb(urb);
+out_usb_kill_anchored_urbs:
+       if (!parent->active_channels) {
+               usb_kill_anchored_urbs(&dev->tx_submitted);
+
+               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+                       gs_usb_timestamp_stop(parent);
+       }
+
+       close_candev(netdev);
+
+       return rc;
 }
 
 static int gs_usb_get_state(const struct net_device *netdev,
@@ -998,20 +1017,21 @@ static int gs_can_close(struct net_device *netdev)
 
        netif_stop_queue(netdev);
 
-       /* stop polling timestamp */
-       if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
-               gs_usb_timestamp_stop(dev);
-
        /* Stop polling */
        parent->active_channels--;
        if (!parent->active_channels) {
                usb_kill_anchored_urbs(&parent->rx_submitted);
+
+               if (dev->feature & GS_CAN_FEATURE_HW_TIMESTAMP)
+                       gs_usb_timestamp_stop(parent);
        }
 
        /* Stop sending URBs */
        usb_kill_anchored_urbs(&dev->tx_submitted);
        atomic_set(&dev->active_tx_urbs, 0);
 
+       dev->can.state = CAN_STATE_STOPPED;
+
        /* reset the device */
        rc = gs_cmd_reset(dev);
        if (rc < 0)
index cde253d..72374b0 100644 (file)
@@ -1436,7 +1436,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
        if (IS_ERR(priv->clk))
                return PTR_ERR(priv->clk);
 
-       clk_prepare_enable(priv->clk);
+       ret = clk_prepare_enable(priv->clk);
+       if (ret)
+               return ret;
 
        priv->clk_mdiv = devm_clk_get_optional(&pdev->dev, "sw_switch_mdiv");
        if (IS_ERR(priv->clk_mdiv)) {
@@ -1444,7 +1446,9 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
                goto out_clk;
        }
 
-       clk_prepare_enable(priv->clk_mdiv);
+       ret = clk_prepare_enable(priv->clk_mdiv);
+       if (ret)
+               goto out_clk;
 
        ret = bcm_sf2_sw_rst(priv);
        if (ret) {
index 84d5025..91aba47 100644 (file)
@@ -506,7 +506,13 @@ static int ksz8_r_sta_mac_table(struct ksz_device *dev, u16 addr,
                (data_hi & masks[STATIC_MAC_TABLE_FWD_PORTS]) >>
                        shifts[STATIC_MAC_FWD_PORTS];
        alu->is_override = (data_hi & masks[STATIC_MAC_TABLE_OVERRIDE]) ? 1 : 0;
-       data_hi >>= 1;
+
+       /* KSZ8795 family switches have STATIC_MAC_TABLE_USE_FID and
+        * STATIC_MAC_TABLE_FID definitions off by 1 when doing read on the
+        * static MAC table compared to doing write.
+        */
+       if (ksz_is_ksz87xx(dev))
+               data_hi >>= 1;
        alu->is_static = true;
        alu->is_use_fid = (data_hi & masks[STATIC_MAC_TABLE_USE_FID]) ? 1 : 0;
        alu->fid = (data_hi & masks[STATIC_MAC_TABLE_FID]) >>
index 813b91a..6c0623f 100644 (file)
@@ -331,13 +331,13 @@ static const u32 ksz8795_masks[] = {
        [STATIC_MAC_TABLE_VALID]        = BIT(21),
        [STATIC_MAC_TABLE_USE_FID]      = BIT(23),
        [STATIC_MAC_TABLE_FID]          = GENMASK(30, 24),
-       [STATIC_MAC_TABLE_OVERRIDE]     = BIT(26),
-       [STATIC_MAC_TABLE_FWD_PORTS]    = GENMASK(24, 20),
+       [STATIC_MAC_TABLE_OVERRIDE]     = BIT(22),
+       [STATIC_MAC_TABLE_FWD_PORTS]    = GENMASK(20, 16),
        [DYNAMIC_MAC_TABLE_ENTRIES_H]   = GENMASK(6, 0),
-       [DYNAMIC_MAC_TABLE_MAC_EMPTY]   = BIT(8),
+       [DYNAMIC_MAC_TABLE_MAC_EMPTY]   = BIT(7),
        [DYNAMIC_MAC_TABLE_NOT_READY]   = BIT(7),
        [DYNAMIC_MAC_TABLE_ENTRIES]     = GENMASK(31, 29),
-       [DYNAMIC_MAC_TABLE_FID]         = GENMASK(26, 20),
+       [DYNAMIC_MAC_TABLE_FID]         = GENMASK(22, 16),
        [DYNAMIC_MAC_TABLE_SRC_PORT]    = GENMASK(26, 24),
        [DYNAMIC_MAC_TABLE_TIMESTAMP]   = GENMASK(28, 27),
        [P_MII_TX_FLOW_CTRL]            = BIT(5),
@@ -635,10 +635,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x1030, 0x1030),
        regmap_reg_range(0x1100, 0x1115),
        regmap_reg_range(0x111a, 0x111f),
-       regmap_reg_range(0x1122, 0x1127),
-       regmap_reg_range(0x112a, 0x112b),
-       regmap_reg_range(0x1136, 0x1139),
-       regmap_reg_range(0x113e, 0x113f),
+       regmap_reg_range(0x1120, 0x112b),
+       regmap_reg_range(0x1134, 0x113b),
+       regmap_reg_range(0x113c, 0x113f),
        regmap_reg_range(0x1400, 0x1401),
        regmap_reg_range(0x1403, 0x1403),
        regmap_reg_range(0x1410, 0x1417),
@@ -669,10 +668,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x2030, 0x2030),
        regmap_reg_range(0x2100, 0x2115),
        regmap_reg_range(0x211a, 0x211f),
-       regmap_reg_range(0x2122, 0x2127),
-       regmap_reg_range(0x212a, 0x212b),
-       regmap_reg_range(0x2136, 0x2139),
-       regmap_reg_range(0x213e, 0x213f),
+       regmap_reg_range(0x2120, 0x212b),
+       regmap_reg_range(0x2134, 0x213b),
+       regmap_reg_range(0x213c, 0x213f),
        regmap_reg_range(0x2400, 0x2401),
        regmap_reg_range(0x2403, 0x2403),
        regmap_reg_range(0x2410, 0x2417),
@@ -703,10 +701,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x3030, 0x3030),
        regmap_reg_range(0x3100, 0x3115),
        regmap_reg_range(0x311a, 0x311f),
-       regmap_reg_range(0x3122, 0x3127),
-       regmap_reg_range(0x312a, 0x312b),
-       regmap_reg_range(0x3136, 0x3139),
-       regmap_reg_range(0x313e, 0x313f),
+       regmap_reg_range(0x3120, 0x312b),
+       regmap_reg_range(0x3134, 0x313b),
+       regmap_reg_range(0x313c, 0x313f),
        regmap_reg_range(0x3400, 0x3401),
        regmap_reg_range(0x3403, 0x3403),
        regmap_reg_range(0x3410, 0x3417),
@@ -737,10 +734,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x4030, 0x4030),
        regmap_reg_range(0x4100, 0x4115),
        regmap_reg_range(0x411a, 0x411f),
-       regmap_reg_range(0x4122, 0x4127),
-       regmap_reg_range(0x412a, 0x412b),
-       regmap_reg_range(0x4136, 0x4139),
-       regmap_reg_range(0x413e, 0x413f),
+       regmap_reg_range(0x4120, 0x412b),
+       regmap_reg_range(0x4134, 0x413b),
+       regmap_reg_range(0x413c, 0x413f),
        regmap_reg_range(0x4400, 0x4401),
        regmap_reg_range(0x4403, 0x4403),
        regmap_reg_range(0x4410, 0x4417),
@@ -771,10 +767,9 @@ static const struct regmap_range ksz9477_valid_regs[] = {
        regmap_reg_range(0x5030, 0x5030),
        regmap_reg_range(0x5100, 0x5115),
        regmap_reg_range(0x511a, 0x511f),
-       regmap_reg_range(0x5122, 0x5127),
-       regmap_reg_range(0x512a, 0x512b),
-       regmap_reg_range(0x5136, 0x5139),
-       regmap_reg_range(0x513e, 0x513f),
+       regmap_reg_range(0x5120, 0x512b),
+       regmap_reg_range(0x5134, 0x513b),
+       regmap_reg_range(0x513c, 0x513f),
        regmap_reg_range(0x5400, 0x5401),
        regmap_reg_range(0x5403, 0x5403),
        regmap_reg_range(0x5410, 0x5417),
index 28444e5..a4de588 100644 (file)
@@ -601,6 +601,13 @@ static inline void ksz_regmap_unlock(void *__mtx)
        mutex_unlock(mtx);
 }
 
+static inline bool ksz_is_ksz87xx(struct ksz_device *dev)
+{
+       return dev->chip_id == KSZ8795_CHIP_ID ||
+              dev->chip_id == KSZ8794_CHIP_ID ||
+              dev->chip_id == KSZ8765_CHIP_ID;
+}
+
 static inline bool ksz_is_ksz88x3(struct ksz_device *dev)
 {
        return dev->chip_id == KSZ8830_CHIP_ID;
index 8b51756..c7d51a5 100644 (file)
@@ -109,6 +109,13 @@ int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg,
                        usleep_range(1000, 2000);
        }
 
+       err = mv88e6xxx_read(chip, addr, reg, &data);
+       if (err)
+               return err;
+
+       if ((data & mask) == val)
+               return 0;
+
        dev_err(chip->dev, "Timeout while waiting for switch\n");
        return -ETIMEDOUT;
 }
index b2bf78a..3b09370 100644 (file)
@@ -1002,6 +1002,8 @@ static const struct regmap_config ar9331_mdio_regmap_config = {
        .val_bits = 32,
        .reg_stride = 4,
        .max_register = AR9331_SW_REG_PAGE,
+       .use_single_read = true,
+       .use_single_write = true,
 
        .ranges = ar9331_regmap_range,
        .num_ranges = ARRAY_SIZE(ar9331_regmap_range),
@@ -1018,8 +1020,6 @@ static struct regmap_bus ar9331_sw_bus = {
        .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
        .read = ar9331_mdio_read,
        .write = ar9331_sw_bus_write,
-       .max_raw_read = 4,
-       .max_raw_write = 4,
 };
 
 static int ar9331_sw_probe(struct mdio_device *mdiodev)
index 09b8064..efe9380 100644 (file)
@@ -576,8 +576,11 @@ static struct regmap_config qca8k_regmap_config = {
        .rd_table = &qca8k_readable_table,
        .disable_locking = true, /* Locking is handled by qca8k read/write */
        .cache_type = REGCACHE_NONE, /* Explicitly disable CACHE */
-       .max_raw_read = 32, /* mgmt eth can read/write up to 8 registers at time */
-       .max_raw_write = 32,
+       .max_raw_read = 32, /* mgmt eth can read up to 8 registers at time */
+       /* ATU regs suffer from a bug where some data are not correctly
+        * written. Disable bulk write to correctly write ATU entry.
+        */
+       .use_single_write = true,
 };
 
 static int
index 8c2dc0e..13b8452 100644 (file)
@@ -244,7 +244,7 @@ void qca8k_fdb_flush(struct qca8k_priv *priv)
 }
 
 static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
-                                      const u8 *mac, u16 vid)
+                                      const u8 *mac, u16 vid, u8 aging)
 {
        struct qca8k_fdb fdb = { 0 };
        int ret;
@@ -261,10 +261,12 @@ static int qca8k_fdb_search_and_insert(struct qca8k_priv *priv, u8 port_mask,
                goto exit;
 
        /* Rule exist. Delete first */
-       if (!fdb.aging) {
+       if (fdb.aging) {
                ret = qca8k_fdb_access(priv, QCA8K_FDB_PURGE, -1);
                if (ret)
                        goto exit;
+       } else {
+               fdb.aging = aging;
        }
 
        /* Add port to fdb portmask */
@@ -291,6 +293,10 @@ static int qca8k_fdb_search_and_del(struct qca8k_priv *priv, u8 port_mask,
        if (ret < 0)
                goto exit;
 
+       ret = qca8k_fdb_read(priv, &fdb);
+       if (ret < 0)
+               goto exit;
+
        /* Rule doesn't exist. Why delete? */
        if (!fdb.aging) {
                ret = -EINVAL;
@@ -810,7 +816,11 @@ int qca8k_port_mdb_add(struct dsa_switch *ds, int port,
        const u8 *addr = mdb->addr;
        u16 vid = mdb->vid;
 
-       return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid);
+       if (!vid)
+               vid = QCA8K_PORT_VID_DEF;
+
+       return qca8k_fdb_search_and_insert(priv, BIT(port), addr, vid,
+                                          QCA8K_ATU_STATUS_STATIC);
 }
 
 int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
@@ -821,6 +831,9 @@ int qca8k_port_mdb_del(struct dsa_switch *ds, int port,
        const u8 *addr = mdb->addr;
        u16 vid = mdb->vid;
 
+       if (!vid)
+               vid = QCA8K_PORT_VID_DEF;
+
        return qca8k_fdb_search_and_del(priv, BIT(port), addr, vid);
 }
 
index 4a28879..940c5d1 100644 (file)
@@ -2094,8 +2094,11 @@ static int atl1c_tso_csum(struct atl1c_adapter *adapter,
                        real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
                                        + ntohs(ip_hdr(skb)->tot_len));
 
-                       if (real_len < skb->len)
-                               pskb_trim(skb, real_len);
+                       if (real_len < skb->len) {
+                               err = pskb_trim(skb, real_len);
+                               if (err)
+                                       return err;
+                       }
 
                        hdr_len = skb_tcp_all_headers(skb);
                        if (unlikely(skb->len == hdr_len)) {
index 5db0f34..5935be1 100644 (file)
@@ -1641,8 +1641,11 @@ static int atl1e_tso_csum(struct atl1e_adapter *adapter,
                        real_len = (((unsigned char *)ip_hdr(skb) - skb->data)
                                        + ntohs(ip_hdr(skb)->tot_len));
 
-                       if (real_len < skb->len)
-                               pskb_trim(skb, real_len);
+                       if (real_len < skb->len) {
+                               err = pskb_trim(skb, real_len);
+                               if (err)
+                                       return err;
+                       }
 
                        hdr_len = skb_tcp_all_headers(skb);
                        if (unlikely(skb->len == hdr_len)) {
index c8444bc..02aa6fd 100644 (file)
@@ -2113,8 +2113,11 @@ static int atl1_tso(struct atl1_adapter *adapter, struct sk_buff *skb,
 
                        real_len = (((unsigned char *)iph - skb->data) +
                                ntohs(iph->tot_len));
-                       if (real_len < skb->len)
-                               pskb_trim(skb, real_len);
+                       if (real_len < skb->len) {
+                               err = pskb_trim(skb, real_len);
+                               if (err)
+                                       return err;
+                       }
                        hdr_len = skb_tcp_all_headers(skb);
                        if (skb->len == hdr_len) {
                                iph->check = 0;
index e5b54e6..1eb490c 100644 (file)
@@ -633,12 +633,13 @@ tx_kick_pending:
        return NETDEV_TX_OK;
 }
 
-static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
 {
        struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
        struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
        u16 cons = txr->tx_cons;
        struct pci_dev *pdev = bp->pdev;
+       int nr_pkts = bnapi->tx_pkts;
        int i;
        unsigned int tx_bytes = 0;
 
@@ -688,6 +689,7 @@ next_tx_int:
                dev_kfree_skb_any(skb);
        }
 
+       bnapi->tx_pkts = 0;
        WRITE_ONCE(txr->tx_cons, cons);
 
        __netif_txq_completed_wake(txq, nr_pkts, tx_bytes,
@@ -697,17 +699,24 @@ next_tx_int:
 
 static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
                                         struct bnxt_rx_ring_info *rxr,
+                                        unsigned int *offset,
                                         gfp_t gfp)
 {
        struct device *dev = &bp->pdev->dev;
        struct page *page;
 
-       page = page_pool_dev_alloc_pages(rxr->page_pool);
+       if (PAGE_SIZE > BNXT_RX_PAGE_SIZE) {
+               page = page_pool_dev_alloc_frag(rxr->page_pool, offset,
+                                               BNXT_RX_PAGE_SIZE);
+       } else {
+               page = page_pool_dev_alloc_pages(rxr->page_pool);
+               *offset = 0;
+       }
        if (!page)
                return NULL;
 
-       *mapping = dma_map_page_attrs(dev, page, 0, PAGE_SIZE, bp->rx_dir,
-                                     DMA_ATTR_WEAK_ORDERING);
+       *mapping = dma_map_page_attrs(dev, page, *offset, BNXT_RX_PAGE_SIZE,
+                                     bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
        if (dma_mapping_error(dev, *mapping)) {
                page_pool_recycle_direct(rxr->page_pool, page);
                return NULL;
@@ -747,15 +756,16 @@ int bnxt_alloc_rx_data(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
        dma_addr_t mapping;
 
        if (BNXT_RX_PAGE_MODE(bp)) {
+               unsigned int offset;
                struct page *page =
-                       __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
+                       __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp);
 
                if (!page)
                        return -ENOMEM;
 
                mapping += bp->rx_dma_offset;
                rx_buf->data = page;
-               rx_buf->data_ptr = page_address(page) + bp->rx_offset;
+               rx_buf->data_ptr = page_address(page) + offset + bp->rx_offset;
        } else {
                u8 *data = __bnxt_alloc_rx_frag(bp, &mapping, gfp);
 
@@ -815,7 +825,7 @@ static inline int bnxt_alloc_rx_page(struct bnxt *bp,
        unsigned int offset = 0;
 
        if (BNXT_RX_PAGE_MODE(bp)) {
-               page = __bnxt_alloc_rx_page(bp, &mapping, rxr, gfp);
+               page = __bnxt_alloc_rx_page(bp, &mapping, rxr, &offset, gfp);
 
                if (!page)
                        return -ENOMEM;
@@ -962,15 +972,15 @@ static struct sk_buff *bnxt_rx_multi_page_skb(struct bnxt *bp,
                return NULL;
        }
        dma_addr -= bp->rx_dma_offset;
-       dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
-                            DMA_ATTR_WEAK_ORDERING);
-       skb = build_skb(page_address(page), PAGE_SIZE);
+       dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
+                            bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
+       skb = build_skb(data_ptr - bp->rx_offset, BNXT_RX_PAGE_SIZE);
        if (!skb) {
                page_pool_recycle_direct(rxr->page_pool, page);
                return NULL;
        }
        skb_mark_for_recycle(skb);
-       skb_reserve(skb, bp->rx_dma_offset);
+       skb_reserve(skb, bp->rx_offset);
        __skb_put(skb, len);
 
        return skb;
@@ -996,8 +1006,8 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
                return NULL;
        }
        dma_addr -= bp->rx_dma_offset;
-       dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, PAGE_SIZE, bp->rx_dir,
-                            DMA_ATTR_WEAK_ORDERING);
+       dma_unmap_page_attrs(&bp->pdev->dev, dma_addr, BNXT_RX_PAGE_SIZE,
+                            bp->rx_dir, DMA_ATTR_WEAK_ORDERING);
 
        if (unlikely(!payload))
                payload = eth_get_headlen(bp->dev, data_ptr, len);
@@ -1010,7 +1020,7 @@ static struct sk_buff *bnxt_rx_page_skb(struct bnxt *bp,
 
        skb_mark_for_recycle(skb);
        off = (void *)data_ptr - page_address(page);
-       skb_add_rx_frag(skb, 0, page, off, len, PAGE_SIZE);
+       skb_add_rx_frag(skb, 0, page, off, len, BNXT_RX_PAGE_SIZE);
        memcpy(skb->data - NET_IP_ALIGN, data_ptr - NET_IP_ALIGN,
               payload + NET_IP_ALIGN);
 
@@ -1141,7 +1151,7 @@ static struct sk_buff *bnxt_rx_agg_pages_skb(struct bnxt *bp,
 
        skb->data_len += total_frag_len;
        skb->len += total_frag_len;
-       skb->truesize += PAGE_SIZE * agg_bufs;
+       skb->truesize += BNXT_RX_PAGE_SIZE * agg_bufs;
        return skb;
 }
 
@@ -2569,12 +2579,11 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
        return rx_pkts;
 }
 
-static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi)
+static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi,
+                                 int budget)
 {
-       if (bnapi->tx_pkts) {
-               bnapi->tx_int(bp, bnapi, bnapi->tx_pkts);
-               bnapi->tx_pkts = 0;
-       }
+       if (bnapi->tx_pkts)
+               bnapi->tx_int(bp, bnapi, budget);
 
        if ((bnapi->events & BNXT_RX_EVENT) && !(bnapi->in_reset)) {
                struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
@@ -2603,7 +2612,7 @@ static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
         */
        bnxt_db_cq(bp, &cpr->cp_db, cpr->cp_raw_cons);
 
-       __bnxt_poll_work_done(bp, bnapi);
+       __bnxt_poll_work_done(bp, bnapi, budget);
        return rx_pkts;
 }
 
@@ -2734,7 +2743,7 @@ static int __bnxt_poll_cqs(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
 }
 
 static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
-                                u64 dbr_type)
+                                u64 dbr_type, int budget)
 {
        struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
        int i;
@@ -2750,7 +2759,7 @@ static void __bnxt_poll_cqs_done(struct bnxt *bp, struct bnxt_napi *bnapi,
                        cpr2->had_work_done = 0;
                }
        }
-       __bnxt_poll_work_done(bp, bnapi);
+       __bnxt_poll_work_done(bp, bnapi, budget);
 }
 
 static int bnxt_poll_p5(struct napi_struct *napi, int budget)
@@ -2780,7 +2789,8 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
                        if (cpr->has_more_work)
                                break;
 
-                       __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL);
+                       __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ_ARMALL,
+                                            budget);
                        cpr->cp_raw_cons = raw_cons;
                        if (napi_complete_done(napi, work_done))
                                BNXT_DB_NQ_ARM_P5(&cpr->cp_db,
@@ -2810,7 +2820,7 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
                }
                raw_cons = NEXT_RAW_CMP(raw_cons);
        }
-       __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ);
+       __bnxt_poll_cqs_done(bp, bnapi, DBR_TYPE_CQ, budget);
        if (raw_cons != cpr->cp_raw_cons) {
                cpr->cp_raw_cons = raw_cons;
                BNXT_DB_NQ_P5(&cpr->cp_db, raw_cons);
@@ -2943,8 +2953,8 @@ skip_rx_tpa_free:
                rx_buf->data = NULL;
                if (BNXT_RX_PAGE_MODE(bp)) {
                        mapping -= bp->rx_dma_offset;
-                       dma_unmap_page_attrs(&pdev->dev, mapping, PAGE_SIZE,
-                                            bp->rx_dir,
+                       dma_unmap_page_attrs(&pdev->dev, mapping,
+                                            BNXT_RX_PAGE_SIZE, bp->rx_dir,
                                             DMA_ATTR_WEAK_ORDERING);
                        page_pool_recycle_direct(rxr->page_pool, data);
                } else {
@@ -3213,6 +3223,8 @@ static int bnxt_alloc_rx_page_pool(struct bnxt *bp,
        pp.napi = &rxr->bnapi->napi;
        pp.dev = &bp->pdev->dev;
        pp.dma_dir = DMA_BIDIRECTIONAL;
+       if (PAGE_SIZE > BNXT_RX_PAGE_SIZE)
+               pp.flags |= PP_FLAG_PAGE_FRAG;
 
        rxr->page_pool = page_pool_create(&pp);
        if (IS_ERR(rxr->page_pool)) {
@@ -3989,26 +4001,29 @@ void bnxt_set_ring_params(struct bnxt *bp)
  */
 int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode)
 {
+       struct net_device *dev = bp->dev;
+
        if (page_mode) {
                bp->flags &= ~BNXT_FLAG_AGG_RINGS;
                bp->flags |= BNXT_FLAG_RX_PAGE_MODE;
 
-               if (bp->dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
+               if (bp->xdp_prog->aux->xdp_has_frags)
+                       dev->max_mtu = min_t(u16, bp->max_mtu, BNXT_MAX_MTU);
+               else
+                       dev->max_mtu =
+                               min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
+               if (dev->mtu > BNXT_MAX_PAGE_MODE_MTU) {
                        bp->flags |= BNXT_FLAG_JUMBO;
                        bp->rx_skb_func = bnxt_rx_multi_page_skb;
-                       bp->dev->max_mtu =
-                               min_t(u16, bp->max_mtu, BNXT_MAX_MTU);
                } else {
                        bp->flags |= BNXT_FLAG_NO_AGG_RINGS;
                        bp->rx_skb_func = bnxt_rx_page_skb;
-                       bp->dev->max_mtu =
-                               min_t(u16, bp->max_mtu, BNXT_MAX_PAGE_MODE_MTU);
                }
                bp->rx_dir = DMA_BIDIRECTIONAL;
                /* Disable LRO or GRO_HW */
-               netdev_update_features(bp->dev);
+               netdev_update_features(dev);
        } else {
-               bp->dev->max_mtu = bp->max_mtu;
+               dev->max_mtu = bp->max_mtu;
                bp->flags &= ~BNXT_FLAG_RX_PAGE_MODE;
                bp->rx_dir = DMA_FROM_DEVICE;
                bp->rx_skb_func = bnxt_rx_skb;
@@ -9429,6 +9444,8 @@ static void bnxt_enable_napi(struct bnxt *bp)
                        cpr->sw_stats.rx.rx_resets++;
                bnapi->in_reset = false;
 
+               bnapi->tx_pkts = 0;
+
                if (bnapi->rx_ring) {
                        INIT_WORK(&cpr->dim.work, bnxt_dim_work);
                        cpr->dim.mode = DIM_CQ_PERIOD_MODE_START_FROM_EQE;
index 080e734..bb95c3d 100644 (file)
@@ -1005,7 +1005,7 @@ struct bnxt_napi {
        struct bnxt_tx_ring_info        *tx_ring;
 
        void                    (*tx_int)(struct bnxt *, struct bnxt_napi *,
-                                         int);
+                                         int budget);
        int                     tx_pkts;
        u8                      events;
 
index 4efa5fe..fb43232 100644 (file)
@@ -125,16 +125,20 @@ static void __bnxt_xmit_xdp_redirect(struct bnxt *bp,
        dma_unmap_len_set(tx_buf, len, 0);
 }
 
-void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
 {
        struct bnxt_tx_ring_info *txr = bnapi->tx_ring;
        struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;
        bool rx_doorbell_needed = false;
+       int nr_pkts = bnapi->tx_pkts;
        struct bnxt_sw_tx_bd *tx_buf;
        u16 tx_cons = txr->tx_cons;
        u16 last_tx_cons = tx_cons;
        int i, j, frags;
 
+       if (!budget)
+               return;
+
        for (i = 0; i < nr_pkts; i++) {
                tx_buf = &txr->tx_buf_ring[tx_cons];
 
@@ -161,6 +165,8 @@ void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
                }
                tx_cons = NEXT_TX(tx_cons);
        }
+
+       bnapi->tx_pkts = 0;
        WRITE_ONCE(txr->tx_cons, tx_cons);
        if (rx_doorbell_needed) {
                tx_buf = &txr->tx_buf_ring[last_tx_cons];
@@ -180,8 +186,8 @@ void bnxt_xdp_buff_init(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
                        u16 cons, u8 *data_ptr, unsigned int len,
                        struct xdp_buff *xdp)
 {
+       u32 buflen = BNXT_RX_PAGE_SIZE;
        struct bnxt_sw_rx_bd *rx_buf;
-       u32 buflen = PAGE_SIZE;
        struct pci_dev *pdev;
        dma_addr_t mapping;
        u32 offset;
@@ -297,7 +303,7 @@ bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
                rx_buf = &rxr->rx_buf_ring[cons];
                mapping = rx_buf->mapping - bp->rx_dma_offset;
                dma_unmap_page_attrs(&pdev->dev, mapping,
-                                    PAGE_SIZE, bp->rx_dir,
+                                    BNXT_RX_PAGE_SIZE, bp->rx_dir,
                                     DMA_ATTR_WEAK_ORDERING);
 
                /* if we are unable to allocate a new buffer, abort and reuse */
@@ -480,7 +486,7 @@ bnxt_xdp_build_skb(struct bnxt *bp, struct sk_buff *skb, u8 num_frags,
        }
        xdp_update_skb_shared_info(skb, num_frags,
                                   sinfo->xdp_frags_size,
-                                  PAGE_SIZE * sinfo->nr_frags,
+                                  BNXT_RX_PAGE_SIZE * sinfo->nr_frags,
                                   xdp_buff_is_frag_pfmemalloc(xdp));
        return skb;
 }
index ea430d6..5e412c5 100644 (file)
@@ -16,7 +16,7 @@ struct bnxt_sw_tx_bd *bnxt_xmit_bd(struct bnxt *bp,
                                   struct bnxt_tx_ring_info *txr,
                                   dma_addr_t mapping, u32 len,
                                   struct xdp_buff *xdp);
-void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts);
+void bnxt_tx_int_xdp(struct bnxt *bp, struct bnxt_napi *bnapi, int budget);
 bool bnxt_rx_xdp(struct bnxt *bp, struct bnxt_rx_ring_info *rxr, u16 cons,
                 struct xdp_buff xdp, struct page *page, u8 **data_ptr,
                 unsigned int *len, u8 *event);
index 04ad0f2..7246e13 100644 (file)
@@ -512,11 +512,6 @@ bnad_debugfs_init(struct bnad *bnad)
        if (!bnad->port_debugfs_root) {
                bnad->port_debugfs_root =
                        debugfs_create_dir(name, bna_debugfs_root);
-               if (!bnad->port_debugfs_root) {
-                       netdev_warn(bnad->netdev,
-                                   "debugfs root dir creation failed\n");
-                       return;
-               }
 
                atomic_inc(&bna_debugfs_port_count);
 
index 18c2fc8..0616b5f 100644 (file)
@@ -1138,7 +1138,8 @@ static struct sk_buff *be_lancer_xmit_workarounds(struct be_adapter *adapter,
            (lancer_chip(adapter) || BE3_chip(adapter) ||
             skb_vlan_tag_present(skb)) && is_ipv4_pkt(skb)) {
                ip = (struct iphdr *)ip_hdr(skb);
-               pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len));
+               if (unlikely(pskb_trim(skb, eth_hdr_len + ntohs(ip->tot_len))))
+                       goto tx_drop;
        }
 
        /* If vlan tag is already inlined in the packet, skip HW VLAN
index ec9e4bd..66b5cbd 100644 (file)
@@ -1372,7 +1372,7 @@ fec_enet_hwtstamp(struct fec_enet_private *fep, unsigned ts,
 }
 
 static void
-fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
+fec_enet_tx_queue(struct net_device *ndev, u16 queue_id, int budget)
 {
        struct  fec_enet_private *fep;
        struct xdp_frame *xdpf;
@@ -1416,6 +1416,14 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
                        if (!skb)
                                goto tx_buf_done;
                } else {
+                       /* Tx processing cannot call any XDP (or page pool) APIs if
+                        * the "budget" is 0. Because NAPI is called with budget of
+                        * 0 (such as netpoll) indicates we may be in an IRQ context,
+                        * however, we can't use the page pool from IRQ context.
+                        */
+                       if (unlikely(!budget))
+                               break;
+
                        xdpf = txq->tx_buf[index].xdp;
                        if (bdp->cbd_bufaddr)
                                dma_unmap_single(&fep->pdev->dev,
@@ -1508,14 +1516,14 @@ tx_buf_done:
                writel(0, txq->bd.reg_desc_active);
 }
 
-static void fec_enet_tx(struct net_device *ndev)
+static void fec_enet_tx(struct net_device *ndev, int budget)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
        int i;
 
        /* Make sure that AVB queues are processed first. */
        for (i = fep->num_tx_queues - 1; i >= 0; i--)
-               fec_enet_tx_queue(ndev, i);
+               fec_enet_tx_queue(ndev, i, budget);
 }
 
 static void fec_enet_update_cbd(struct fec_enet_priv_rx_q *rxq,
@@ -1858,7 +1866,7 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 
        do {
                done += fec_enet_rx(ndev, budget - done);
-               fec_enet_tx(ndev);
+               fec_enet_tx(ndev, budget);
        } while ((done < budget) && fec_enet_collect_events(fep));
 
        if (done < budget) {
@@ -3916,6 +3924,8 @@ static int fec_enet_xdp_xmit(struct net_device *dev,
 
        __netif_tx_lock(nq, cpu);
 
+       /* Avoid tx timeout as XDP shares the queue with kernel stack */
+       txq_trans_cond_update(nq);
        for (i = 0; i < num_frames; i++) {
                if (fec_enet_txq_xmit_frame(fep, txq, frames[i]) < 0)
                        break;
index b99d752..514a20b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/pci.h>
 #include <linux/pkt_sched.h>
 #include <linux/types.h>
+#include <linux/bitmap.h>
 #include <net/pkt_cls.h>
 #include <net/pkt_sched.h>
 
@@ -101,6 +102,7 @@ enum HNAE3_DEV_CAP_BITS {
        HNAE3_DEV_SUPPORT_FEC_STATS_B,
        HNAE3_DEV_SUPPORT_LANE_NUM_B,
        HNAE3_DEV_SUPPORT_WOL_B,
+       HNAE3_DEV_SUPPORT_TM_FLUSH_B,
 };
 
 #define hnae3_ae_dev_fd_supported(ae_dev) \
@@ -172,6 +174,9 @@ enum HNAE3_DEV_CAP_BITS {
 #define hnae3_ae_dev_wol_supported(ae_dev) \
        test_bit(HNAE3_DEV_SUPPORT_WOL_B, (ae_dev)->caps)
 
+#define hnae3_ae_dev_tm_flush_supported(hdev) \
+       test_bit(HNAE3_DEV_SUPPORT_TM_FLUSH_B, (hdev)->ae_dev->caps)
+
 enum HNAE3_PF_CAP_BITS {
        HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B = 0,
 };
@@ -407,7 +412,7 @@ struct hnae3_ae_dev {
        unsigned long hw_err_reset_req;
        struct hnae3_dev_specs dev_specs;
        u32 dev_version;
-       unsigned long caps[BITS_TO_LONGS(HNAE3_DEV_CAPS_MAX_NUM)];
+       DECLARE_BITMAP(caps, HNAE3_DEV_CAPS_MAX_NUM);
        void *priv;
 };
 
index b85c412..dcecb23 100644 (file)
@@ -156,6 +156,7 @@ static const struct hclge_comm_caps_bit_map hclge_pf_cmd_caps[] = {
        {HCLGE_COMM_CAP_FEC_STATS_B, HNAE3_DEV_SUPPORT_FEC_STATS_B},
        {HCLGE_COMM_CAP_LANE_NUM_B, HNAE3_DEV_SUPPORT_LANE_NUM_B},
        {HCLGE_COMM_CAP_WOL_B, HNAE3_DEV_SUPPORT_WOL_B},
+       {HCLGE_COMM_CAP_TM_FLUSH_B, HNAE3_DEV_SUPPORT_TM_FLUSH_B},
 };
 
 static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
@@ -172,6 +173,20 @@ static const struct hclge_comm_caps_bit_map hclge_vf_cmd_caps[] = {
 };
 
 static void
+hclge_comm_capability_to_bitmap(unsigned long *bitmap, __le32 *caps)
+{
+       const unsigned int words = HCLGE_COMM_QUERY_CAP_LENGTH;
+       u32 val[HCLGE_COMM_QUERY_CAP_LENGTH];
+       unsigned int i;
+
+       for (i = 0; i < words; i++)
+               val[i] = __le32_to_cpu(caps[i]);
+
+       bitmap_from_arr32(bitmap, val,
+                         HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32));
+}
+
+static void
 hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf,
                            struct hclge_comm_query_version_cmd *cmd)
 {
@@ -179,11 +194,12 @@ hclge_comm_parse_capability(struct hnae3_ae_dev *ae_dev, bool is_pf,
                                is_pf ? hclge_pf_cmd_caps : hclge_vf_cmd_caps;
        u32 size = is_pf ? ARRAY_SIZE(hclge_pf_cmd_caps) :
                                ARRAY_SIZE(hclge_vf_cmd_caps);
-       u32 caps, i;
+       DECLARE_BITMAP(caps, HCLGE_COMM_QUERY_CAP_LENGTH * BITS_PER_TYPE(u32));
+       u32 i;
 
-       caps = __le32_to_cpu(cmd->caps[0]);
+       hclge_comm_capability_to_bitmap(caps, cmd->caps);
        for (i = 0; i < size; i++)
-               if (hnae3_get_bit(caps, caps_map[i].imp_bit))
+               if (test_bit(caps_map[i].imp_bit, caps))
                        set_bit(caps_map[i].local_bit, ae_dev->caps);
 }
 
index 18f1b4b..2b7197c 100644 (file)
@@ -153,6 +153,7 @@ enum hclge_opcode_type {
        HCLGE_OPC_TM_INTERNAL_STS       = 0x0850,
        HCLGE_OPC_TM_INTERNAL_CNT       = 0x0851,
        HCLGE_OPC_TM_INTERNAL_STS_1     = 0x0852,
+       HCLGE_OPC_TM_FLUSH              = 0x0872,
 
        /* Packet buffer allocate commands */
        HCLGE_OPC_TX_BUFF_ALLOC         = 0x0901,
@@ -349,6 +350,7 @@ enum HCLGE_COMM_CAP_BITS {
        HCLGE_COMM_CAP_FEC_STATS_B = 25,
        HCLGE_COMM_CAP_LANE_NUM_B = 27,
        HCLGE_COMM_CAP_WOL_B = 28,
+       HCLGE_COMM_CAP_TM_FLUSH_B = 31,
 };
 
 enum HCLGE_COMM_API_CAP_BITS {
index 6546cfe..52546f6 100644 (file)
@@ -411,6 +411,9 @@ static struct hns3_dbg_cap_info hns3_dbg_cap[] = {
        }, {
                .name = "support wake on lan",
                .cap_bit = HNAE3_DEV_SUPPORT_WOL_B,
+       }, {
+               .name = "support tm flush",
+               .cap_bit = HNAE3_DEV_SUPPORT_TM_FLUSH_B,
        }
 };
 
index c4aded6..fad5a5f 100644 (file)
@@ -52,7 +52,10 @@ static void hclge_tm_info_to_ieee_ets(struct hclge_dev *hdev,
 
        for (i = 0; i < HNAE3_MAX_TC; i++) {
                ets->prio_tc[i] = hdev->tm_info.prio_tc[i];
-               ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
+               if (i < hdev->tm_info.num_tc)
+                       ets->tc_tx_bw[i] = hdev->tm_info.pg_info[0].tc_dwrr[i];
+               else
+                       ets->tc_tx_bw[i] = 0;
 
                if (hdev->tm_info.tc_info[i].tc_sch_mode ==
                    HCLGE_SCH_MODE_SP)
@@ -123,7 +126,8 @@ static u8 hclge_ets_tc_changed(struct hclge_dev *hdev, struct ieee_ets *ets,
 }
 
 static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
-                                      struct ieee_ets *ets, bool *changed)
+                                      struct ieee_ets *ets, bool *changed,
+                                      u8 tc_num)
 {
        bool has_ets_tc = false;
        u32 total_ets_bw = 0;
@@ -137,6 +141,13 @@ static int hclge_ets_sch_mode_validate(struct hclge_dev *hdev,
                                *changed = true;
                        break;
                case IEEE_8021QAZ_TSA_ETS:
+                       if (i >= tc_num) {
+                               dev_err(&hdev->pdev->dev,
+                                       "tc%u is disabled, cannot set ets bw\n",
+                                       i);
+                               return -EINVAL;
+                       }
+
                        /* The hardware will switch to sp mode if bandwidth is
                         * 0, so limit ets bandwidth must be greater than 0.
                         */
@@ -176,7 +187,7 @@ static int hclge_ets_validate(struct hclge_dev *hdev, struct ieee_ets *ets,
        if (ret)
                return ret;
 
-       ret = hclge_ets_sch_mode_validate(hdev, ets, changed);
+       ret = hclge_ets_sch_mode_validate(hdev, ets, changed, tc_num);
        if (ret)
                return ret;
 
@@ -216,6 +227,10 @@ static int hclge_notify_down_uinit(struct hclge_dev *hdev)
        if (ret)
                return ret;
 
+       ret = hclge_tm_flush_cfg(hdev, true);
+       if (ret)
+               return ret;
+
        return hclge_notify_client(hdev, HNAE3_UNINIT_CLIENT);
 }
 
@@ -227,6 +242,10 @@ static int hclge_notify_init_up(struct hclge_dev *hdev)
        if (ret)
                return ret;
 
+       ret = hclge_tm_flush_cfg(hdev, false);
+       if (ret)
+               return ret;
+
        return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
 }
 
@@ -313,6 +332,7 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
        struct net_device *netdev = h->kinfo.netdev;
        struct hclge_dev *hdev = vport->back;
        u8 i, j, pfc_map, *prio_tc;
+       int last_bad_ret = 0;
        int ret;
 
        if (!(hdev->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
@@ -350,13 +370,28 @@ static int hclge_ieee_setpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
        if (ret)
                return ret;
 
-       ret = hclge_buffer_alloc(hdev);
-       if (ret) {
-               hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+       ret = hclge_tm_flush_cfg(hdev, true);
+       if (ret)
                return ret;
-       }
 
-       return hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+       /* No matter whether the following operations are performed
+        * successfully or not, disabling the tm flush and notify
+        * the network status to up are necessary.
+        * Do not return immediately.
+        */
+       ret = hclge_buffer_alloc(hdev);
+       if (ret)
+               last_bad_ret = ret;
+
+       ret = hclge_tm_flush_cfg(hdev, false);
+       if (ret)
+               last_bad_ret = ret;
+
+       ret = hclge_notify_client(hdev, HNAE3_UP_CLIENT);
+       if (ret)
+               last_bad_ret = ret;
+
+       return last_bad_ret;
 }
 
 static int hclge_ieee_setapp(struct hnae3_handle *h, struct dcb_app *app)
index 233c132..409db2e 100644 (file)
@@ -693,8 +693,7 @@ static int hclge_dbg_dump_tc(struct hclge_dev *hdev, char *buf, int len)
        for (i = 0; i < HNAE3_MAX_TC; i++) {
                sch_mode_str = ets_weight->tc_weight[i] ? "dwrr" : "sp";
                pos += scnprintf(buf + pos, len - pos, "%u     %4s    %3u\n",
-                                i, sch_mode_str,
-                                hdev->tm_info.pg_info[0].tc_dwrr[i]);
+                                i, sch_mode_str, ets_weight->tc_weight[i]);
        }
 
        return 0;
index 922c0da..de509e5 100644 (file)
@@ -785,6 +785,7 @@ static void hclge_tm_tc_info_init(struct hclge_dev *hdev)
 static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
 {
 #define BW_PERCENT     100
+#define DEFAULT_BW_WEIGHT      1
 
        u8 i;
 
@@ -806,7 +807,7 @@ static void hclge_tm_pg_info_init(struct hclge_dev *hdev)
                for (k = 0; k < hdev->tm_info.num_tc; k++)
                        hdev->tm_info.pg_info[i].tc_dwrr[k] = BW_PERCENT;
                for (; k < HNAE3_MAX_TC; k++)
-                       hdev->tm_info.pg_info[i].tc_dwrr[k] = 0;
+                       hdev->tm_info.pg_info[i].tc_dwrr[k] = DEFAULT_BW_WEIGHT;
        }
 }
 
@@ -1484,7 +1485,11 @@ int hclge_tm_schd_setup_hw(struct hclge_dev *hdev)
                return ret;
 
        /* Cfg schd mode for each level schd */
-       return hclge_tm_schd_mode_hw(hdev);
+       ret = hclge_tm_schd_mode_hw(hdev);
+       if (ret)
+               return ret;
+
+       return hclge_tm_flush_cfg(hdev, false);
 }
 
 static int hclge_pause_param_setup_hw(struct hclge_dev *hdev)
@@ -2113,3 +2118,28 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev,
 
        return 0;
 }
+
+int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable)
+{
+       struct hclge_desc desc;
+       int ret;
+
+       if (!hnae3_ae_dev_tm_flush_supported(hdev))
+               return 0;
+
+       hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_TM_FLUSH, false);
+
+       desc.data[0] = cpu_to_le32(enable ? HCLGE_TM_FLUSH_EN_MSK : 0);
+
+       ret = hclge_cmd_send(&hdev->hw, &desc, 1);
+       if (ret) {
+               dev_err(&hdev->pdev->dev,
+                       "failed to config tm flush, ret = %d\n", ret);
+               return ret;
+       }
+
+       if (enable)
+               msleep(HCLGE_TM_FLUSH_TIME_MS);
+
+       return ret;
+}
index dd6f1fd..45dcfef 100644 (file)
@@ -33,6 +33,9 @@ enum hclge_opcode_type;
 #define HCLGE_DSCP_MAP_TC_BD_NUM       2
 #define HCLGE_DSCP_TC_SHIFT(n)         (((n) & 1) * 4)
 
+#define HCLGE_TM_FLUSH_TIME_MS 10
+#define HCLGE_TM_FLUSH_EN_MSK  BIT(0)
+
 struct hclge_pg_to_pri_link_cmd {
        u8 pg_id;
        u8 rsvd1[3];
@@ -272,4 +275,5 @@ int hclge_tm_get_port_shaper(struct hclge_dev *hdev,
                             struct hclge_tm_shaper_para *para);
 int hclge_up_to_tc_map(struct hclge_dev *hdev);
 int hclge_dscp_to_tc_map(struct hclge_dev *hdev);
+int hclge_tm_flush_cfg(struct hclge_dev *hdev, bool enable);
 #endif
index 9954493..62497f5 100644 (file)
@@ -1839,7 +1839,7 @@ void i40e_dbg_pf_exit(struct i40e_pf *pf)
 void i40e_dbg_init(void)
 {
        i40e_dbg_root = debugfs_create_dir(i40e_driver_name, NULL);
-       if (!i40e_dbg_root)
+       if (IS_ERR(i40e_dbg_root))
                pr_info("init of debugfs failed\n");
 }
 
index f80f273..8cbdebc 100644 (file)
@@ -255,8 +255,10 @@ struct iavf_adapter {
        struct workqueue_struct *wq;
        struct work_struct reset_task;
        struct work_struct adminq_task;
+       struct work_struct finish_config;
        struct delayed_work client_task;
        wait_queue_head_t down_waitqueue;
+       wait_queue_head_t reset_waitqueue;
        wait_queue_head_t vc_waitqueue;
        struct iavf_q_vector *q_vectors;
        struct list_head vlan_filter_list;
@@ -518,8 +520,9 @@ int iavf_up(struct iavf_adapter *adapter);
 void iavf_down(struct iavf_adapter *adapter);
 int iavf_process_config(struct iavf_adapter *adapter);
 int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter);
-void iavf_schedule_reset(struct iavf_adapter *adapter);
+void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags);
 void iavf_schedule_request_stats(struct iavf_adapter *adapter);
+void iavf_schedule_finish_config(struct iavf_adapter *adapter);
 void iavf_reset(struct iavf_adapter *adapter);
 void iavf_set_ethtool_ops(struct net_device *netdev);
 void iavf_update_stats(struct iavf_adapter *adapter);
@@ -582,4 +585,5 @@ void iavf_add_adv_rss_cfg(struct iavf_adapter *adapter);
 void iavf_del_adv_rss_cfg(struct iavf_adapter *adapter);
 struct iavf_mac_filter *iavf_add_filter(struct iavf_adapter *adapter,
                                        const u8 *macaddr);
+int iavf_wait_for_reset(struct iavf_adapter *adapter);
 #endif /* _IAVF_H_ */
index 6f171d1..2f47cfa 100644 (file)
@@ -484,6 +484,7 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
        u32 orig_flags, new_flags, changed_flags;
+       int ret = 0;
        u32 i;
 
        orig_flags = READ_ONCE(adapter->flags);
@@ -531,12 +532,14 @@ static int iavf_set_priv_flags(struct net_device *netdev, u32 flags)
        /* issue a reset to force legacy-rx change to take effect */
        if (changed_flags & IAVF_FLAG_LEGACY_RX) {
                if (netif_running(netdev)) {
-                       adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-                       queue_work(adapter->wq, &adapter->reset_task);
+                       iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+                       ret = iavf_wait_for_reset(adapter);
+                       if (ret)
+                               netdev_warn(netdev, "Changing private flags timeout or interrupted waiting for reset");
                }
        }
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -627,6 +630,7 @@ static int iavf_set_ringparam(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
        u32 new_rx_count, new_tx_count;
+       int ret = 0;
 
        if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
                return -EINVAL;
@@ -671,11 +675,13 @@ static int iavf_set_ringparam(struct net_device *netdev,
        }
 
        if (netif_running(netdev)) {
-               adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-               queue_work(adapter->wq, &adapter->reset_task);
+               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+               ret = iavf_wait_for_reset(adapter);
+               if (ret)
+                       netdev_warn(netdev, "Changing ring parameters timeout or interrupted waiting for reset");
        }
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -1830,7 +1836,7 @@ static int iavf_set_channels(struct net_device *netdev,
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
        u32 num_req = ch->combined_count;
-       int i;
+       int ret = 0;
 
        if ((adapter->vf_res->vf_cap_flags & VIRTCHNL_VF_OFFLOAD_ADQ) &&
            adapter->num_tc) {
@@ -1852,22 +1858,13 @@ static int iavf_set_channels(struct net_device *netdev,
 
        adapter->num_req_queues = num_req;
        adapter->flags |= IAVF_FLAG_REINIT_ITR_NEEDED;
-       iavf_schedule_reset(adapter);
+       iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
 
-       /* wait for the reset is done */
-       for (i = 0; i < IAVF_RESET_WAIT_COMPLETE_COUNT; i++) {
-               msleep(IAVF_RESET_WAIT_MS);
-               if (adapter->flags & IAVF_FLAG_RESET_PENDING)
-                       continue;
-               break;
-       }
-       if (i == IAVF_RESET_WAIT_COMPLETE_COUNT) {
-               adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
-               adapter->num_active_queues = num_req;
-               return -EOPNOTSUPP;
-       }
+       ret = iavf_wait_for_reset(adapter);
+       if (ret)
+               netdev_warn(netdev, "Changing channel count timeout or interrupted waiting for reset");
 
-       return 0;
+       return ret;
 }
 
 /**
index a483eb1..9610ca7 100644 (file)
@@ -167,6 +167,45 @@ static struct iavf_adapter *iavf_pdev_to_adapter(struct pci_dev *pdev)
 }
 
 /**
+ * iavf_is_reset_in_progress - Check if a reset is in progress
+ * @adapter: board private structure
+ */
+static bool iavf_is_reset_in_progress(struct iavf_adapter *adapter)
+{
+       if (adapter->state == __IAVF_RESETTING ||
+           adapter->flags & (IAVF_FLAG_RESET_PENDING |
+                             IAVF_FLAG_RESET_NEEDED))
+               return true;
+
+       return false;
+}
+
+/**
+ * iavf_wait_for_reset - Wait for reset to finish.
+ * @adapter: board private structure
+ *
+ * Returns 0 if reset finished successfully, negative on timeout or interrupt.
+ */
+int iavf_wait_for_reset(struct iavf_adapter *adapter)
+{
+       int ret = wait_event_interruptible_timeout(adapter->reset_waitqueue,
+                                       !iavf_is_reset_in_progress(adapter),
+                                       msecs_to_jiffies(5000));
+
+       /* If ret < 0 then it means wait was interrupted.
+        * If ret == 0 then it means we got a timeout while waiting
+        * for reset to finish.
+        * If ret > 0 it means reset has finished.
+        */
+       if (ret > 0)
+               return 0;
+       else if (ret < 0)
+               return -EINTR;
+       else
+               return -EBUSY;
+}
+
+/**
  * iavf_allocate_dma_mem_d - OS specific memory alloc for shared code
  * @hw:   pointer to the HW structure
  * @mem:  ptr to mem struct to fill out
@@ -262,12 +301,14 @@ static int iavf_lock_timeout(struct mutex *lock, unsigned int msecs)
 /**
  * iavf_schedule_reset - Set the flags and schedule a reset event
  * @adapter: board private structure
+ * @flags: IAVF_FLAG_RESET_PENDING or IAVF_FLAG_RESET_NEEDED
  **/
-void iavf_schedule_reset(struct iavf_adapter *adapter)
+void iavf_schedule_reset(struct iavf_adapter *adapter, u64 flags)
 {
-       if (!(adapter->flags &
-             (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
-               adapter->flags |= IAVF_FLAG_RESET_NEEDED;
+       if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
+           !(adapter->flags &
+           (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED))) {
+               adapter->flags |= flags;
                queue_work(adapter->wq, &adapter->reset_task);
        }
 }
@@ -295,7 +336,7 @@ static void iavf_tx_timeout(struct net_device *netdev, unsigned int txqueue)
        struct iavf_adapter *adapter = netdev_priv(netdev);
 
        adapter->tx_timeout_count++;
-       iavf_schedule_reset(adapter);
+       iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
 }
 
 /**
@@ -1651,10 +1692,10 @@ static int iavf_set_interrupt_capability(struct iavf_adapter *adapter)
                adapter->msix_entries[vector].entry = vector;
 
        err = iavf_acquire_msix_vectors(adapter, v_budget);
+       if (!err)
+               iavf_schedule_finish_config(adapter);
 
 out:
-       netif_set_real_num_rx_queues(adapter->netdev, pairs);
-       netif_set_real_num_tx_queues(adapter->netdev, pairs);
        return err;
 }
 
@@ -1828,19 +1869,16 @@ static int iavf_alloc_q_vectors(struct iavf_adapter *adapter)
 static void iavf_free_q_vectors(struct iavf_adapter *adapter)
 {
        int q_idx, num_q_vectors;
-       int napi_vectors;
 
        if (!adapter->q_vectors)
                return;
 
        num_q_vectors = adapter->num_msix_vectors - NONQ_VECS;
-       napi_vectors = adapter->num_active_queues;
 
        for (q_idx = 0; q_idx < num_q_vectors; q_idx++) {
                struct iavf_q_vector *q_vector = &adapter->q_vectors[q_idx];
 
-               if (q_idx < napi_vectors)
-                       netif_napi_del(&q_vector->napi);
+               netif_napi_del(&q_vector->napi);
        }
        kfree(adapter->q_vectors);
        adapter->q_vectors = NULL;
@@ -1877,9 +1915,7 @@ static int iavf_init_interrupt_scheme(struct iavf_adapter *adapter)
                goto err_alloc_queues;
        }
 
-       rtnl_lock();
        err = iavf_set_interrupt_capability(adapter);
-       rtnl_unlock();
        if (err) {
                dev_err(&adapter->pdev->dev,
                        "Unable to setup interrupt capabilities\n");
@@ -1932,15 +1968,16 @@ static void iavf_free_rss(struct iavf_adapter *adapter)
 /**
  * iavf_reinit_interrupt_scheme - Reallocate queues and vectors
  * @adapter: board private structure
+ * @running: true if adapter->state == __IAVF_RUNNING
  *
  * Returns 0 on success, negative on failure
  **/
-static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter)
+static int iavf_reinit_interrupt_scheme(struct iavf_adapter *adapter, bool running)
 {
        struct net_device *netdev = adapter->netdev;
        int err;
 
-       if (netif_running(netdev))
+       if (running)
                iavf_free_traffic_irqs(adapter);
        iavf_free_misc_irq(adapter);
        iavf_reset_interrupt_capability(adapter);
@@ -1965,6 +2002,78 @@ err:
 }
 
 /**
+ * iavf_finish_config - do all netdev work that needs RTNL
+ * @work: our work_struct
+ *
+ * Do work that needs both RTNL and crit_lock.
+ **/
+static void iavf_finish_config(struct work_struct *work)
+{
+       struct iavf_adapter *adapter;
+       int pairs, err;
+
+       adapter = container_of(work, struct iavf_adapter, finish_config);
+
+       /* Always take RTNL first to prevent circular lock dependency */
+       rtnl_lock();
+       mutex_lock(&adapter->crit_lock);
+
+       if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
+           adapter->netdev_registered &&
+           !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section)) {
+               netdev_update_features(adapter->netdev);
+               adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
+       }
+
+       switch (adapter->state) {
+       case __IAVF_DOWN:
+               if (!adapter->netdev_registered) {
+                       err = register_netdevice(adapter->netdev);
+                       if (err) {
+                               dev_err(&adapter->pdev->dev, "Unable to register netdev (%d)\n",
+                                       err);
+
+                               /* go back and try again.*/
+                               iavf_free_rss(adapter);
+                               iavf_free_misc_irq(adapter);
+                               iavf_reset_interrupt_capability(adapter);
+                               iavf_change_state(adapter,
+                                                 __IAVF_INIT_CONFIG_ADAPTER);
+                               goto out;
+                       }
+                       adapter->netdev_registered = true;
+               }
+
+               /* Set the real number of queues when reset occurs while
+                * state == __IAVF_DOWN
+                */
+               fallthrough;
+       case __IAVF_RUNNING:
+               pairs = adapter->num_active_queues;
+               netif_set_real_num_rx_queues(adapter->netdev, pairs);
+               netif_set_real_num_tx_queues(adapter->netdev, pairs);
+               break;
+
+       default:
+               break;
+       }
+
+out:
+       mutex_unlock(&adapter->crit_lock);
+       rtnl_unlock();
+}
+
+/**
+ * iavf_schedule_finish_config - Set the flags and schedule a reset event
+ * @adapter: board private structure
+ **/
+void iavf_schedule_finish_config(struct iavf_adapter *adapter)
+{
+       if (!test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section))
+               queue_work(adapter->wq, &adapter->finish_config);
+}
+
+/**
  * iavf_process_aq_command - process aq_required flags
  * and sends aq command
  * @adapter: pointer to iavf adapter structure
@@ -2371,7 +2480,7 @@ int iavf_parse_vf_resource_msg(struct iavf_adapter *adapter)
                        adapter->vsi_res->num_queue_pairs);
                adapter->flags |= IAVF_FLAG_REINIT_MSIX_NEEDED;
                adapter->num_req_queues = adapter->vsi_res->num_queue_pairs;
-               iavf_schedule_reset(adapter);
+               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
 
                return -EAGAIN;
        }
@@ -2601,22 +2710,8 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
 
        netif_carrier_off(netdev);
        adapter->link_up = false;
-
-       /* set the semaphore to prevent any callbacks after device registration
-        * up to time when state of driver will be set to __IAVF_DOWN
-        */
-       rtnl_lock();
-       if (!adapter->netdev_registered) {
-               err = register_netdevice(netdev);
-               if (err) {
-                       rtnl_unlock();
-                       goto err_register;
-               }
-       }
-
-       adapter->netdev_registered = true;
-
        netif_tx_stop_all_queues(netdev);
+
        if (CLIENT_ALLOWED(adapter)) {
                err = iavf_lan_add_device(adapter);
                if (err)
@@ -2629,7 +2724,6 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
 
        iavf_change_state(adapter, __IAVF_DOWN);
        set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
-       rtnl_unlock();
 
        iavf_misc_irq_enable(adapter);
        wake_up(&adapter->down_waitqueue);
@@ -2649,10 +2743,11 @@ static void iavf_init_config_adapter(struct iavf_adapter *adapter)
                /* request initial VLAN offload settings */
                iavf_set_vlan_offload_features(adapter, 0, netdev->features);
 
+       iavf_schedule_finish_config(adapter);
        return;
+
 err_mem:
        iavf_free_rss(adapter);
-err_register:
        iavf_free_misc_irq(adapter);
 err_sw_init:
        iavf_reset_interrupt_capability(adapter);
@@ -2679,26 +2774,9 @@ static void iavf_watchdog_task(struct work_struct *work)
                goto restart_watchdog;
        }
 
-       if ((adapter->flags & IAVF_FLAG_SETUP_NETDEV_FEATURES) &&
-           adapter->netdev_registered &&
-           !test_bit(__IAVF_IN_REMOVE_TASK, &adapter->crit_section) &&
-           rtnl_trylock()) {
-               netdev_update_features(adapter->netdev);
-               rtnl_unlock();
-               adapter->flags &= ~IAVF_FLAG_SETUP_NETDEV_FEATURES;
-       }
-
        if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
                iavf_change_state(adapter, __IAVF_COMM_FAILED);
 
-       if (adapter->flags & IAVF_FLAG_RESET_NEEDED) {
-               adapter->aq_required = 0;
-               adapter->current_op = VIRTCHNL_OP_UNKNOWN;
-               mutex_unlock(&adapter->crit_lock);
-               queue_work(adapter->wq, &adapter->reset_task);
-               return;
-       }
-
        switch (adapter->state) {
        case __IAVF_STARTUP:
                iavf_startup(adapter);
@@ -2826,11 +2904,10 @@ static void iavf_watchdog_task(struct work_struct *work)
        /* check for hw reset */
        reg_val = rd32(hw, IAVF_VF_ARQLEN1) & IAVF_VF_ARQLEN1_ARQENABLE_MASK;
        if (!reg_val) {
-               adapter->flags |= IAVF_FLAG_RESET_PENDING;
                adapter->aq_required = 0;
                adapter->current_op = VIRTCHNL_OP_UNKNOWN;
                dev_err(&adapter->pdev->dev, "Hardware reset detected\n");
-               queue_work(adapter->wq, &adapter->reset_task);
+               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
                mutex_unlock(&adapter->crit_lock);
                queue_delayed_work(adapter->wq,
                                   &adapter->watchdog_task, HZ * 2);
@@ -2940,11 +3017,6 @@ static void iavf_reset_task(struct work_struct *work)
        int i = 0, err;
        bool running;
 
-       /* Detach interface to avoid subsequent NDO callbacks */
-       rtnl_lock();
-       netif_device_detach(netdev);
-       rtnl_unlock();
-
        /* When device is being removed it doesn't make sense to run the reset
         * task, just return in such a case.
         */
@@ -2952,7 +3024,7 @@ static void iavf_reset_task(struct work_struct *work)
                if (adapter->state != __IAVF_REMOVE)
                        queue_work(adapter->wq, &adapter->reset_task);
 
-               goto reset_finish;
+               return;
        }
 
        while (!mutex_trylock(&adapter->client_lock))
@@ -3010,11 +3082,6 @@ static void iavf_reset_task(struct work_struct *work)
                iavf_disable_vf(adapter);
                mutex_unlock(&adapter->client_lock);
                mutex_unlock(&adapter->crit_lock);
-               if (netif_running(netdev)) {
-                       rtnl_lock();
-                       dev_close(netdev);
-                       rtnl_unlock();
-               }
                return; /* Do not attempt to reinit. It's dead, Jim. */
        }
 
@@ -3056,7 +3123,7 @@ continue_reset:
 
        if ((adapter->flags & IAVF_FLAG_REINIT_MSIX_NEEDED) ||
            (adapter->flags & IAVF_FLAG_REINIT_ITR_NEEDED)) {
-               err = iavf_reinit_interrupt_scheme(adapter);
+               err = iavf_reinit_interrupt_scheme(adapter, running);
                if (err)
                        goto reset_err;
        }
@@ -3151,10 +3218,11 @@ continue_reset:
 
        adapter->flags &= ~IAVF_FLAG_REINIT_ITR_NEEDED;
 
+       wake_up(&adapter->reset_waitqueue);
        mutex_unlock(&adapter->client_lock);
        mutex_unlock(&adapter->crit_lock);
 
-       goto reset_finish;
+       return;
 reset_err:
        if (running) {
                set_bit(__IAVF_VSI_DOWN, adapter->vsi.state);
@@ -3164,21 +3232,7 @@ reset_err:
 
        mutex_unlock(&adapter->client_lock);
        mutex_unlock(&adapter->crit_lock);
-
-       if (netif_running(netdev)) {
-               /* Close device to ensure that Tx queues will not be started
-                * during netif_device_attach() at the end of the reset task.
-                */
-               rtnl_lock();
-               dev_close(netdev);
-               rtnl_unlock();
-       }
-
        dev_err(&adapter->pdev->dev, "failed to allocate resources during reinit\n");
-reset_finish:
-       rtnl_lock();
-       netif_device_attach(netdev);
-       rtnl_unlock();
 }
 
 /**
@@ -3196,9 +3250,6 @@ static void iavf_adminq_task(struct work_struct *work)
        u32 val, oldval;
        u16 pending;
 
-       if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
-               goto out;
-
        if (!mutex_trylock(&adapter->crit_lock)) {
                if (adapter->state == __IAVF_REMOVE)
                        return;
@@ -3207,10 +3258,13 @@ static void iavf_adminq_task(struct work_struct *work)
                goto out;
        }
 
+       if (adapter->flags & IAVF_FLAG_PF_COMMS_FAILED)
+               goto unlock;
+
        event.buf_len = IAVF_MAX_AQ_BUF_SIZE;
        event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
        if (!event.msg_buf)
-               goto out;
+               goto unlock;
 
        do {
                ret = iavf_clean_arq_element(hw, &event, &pending);
@@ -3225,11 +3279,8 @@ static void iavf_adminq_task(struct work_struct *work)
                if (pending != 0)
                        memset(event.msg_buf, 0, IAVF_MAX_AQ_BUF_SIZE);
        } while (pending);
-       mutex_unlock(&adapter->crit_lock);
 
-       if ((adapter->flags &
-            (IAVF_FLAG_RESET_PENDING | IAVF_FLAG_RESET_NEEDED)) ||
-           adapter->state == __IAVF_RESETTING)
+       if (iavf_is_reset_in_progress(adapter))
                goto freedom;
 
        /* check for error indications */
@@ -3271,6 +3322,8 @@ static void iavf_adminq_task(struct work_struct *work)
 
 freedom:
        kfree(event.msg_buf);
+unlock:
+       mutex_unlock(&adapter->crit_lock);
 out:
        /* re-enable Admin queue interrupt cause */
        iavf_misc_irq_enable(adapter);
@@ -4315,6 +4368,7 @@ static int iavf_close(struct net_device *netdev)
 static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct iavf_adapter *adapter = netdev_priv(netdev);
+       int ret = 0;
 
        netdev_dbg(netdev, "changing MTU from %d to %d\n",
                   netdev->mtu, new_mtu);
@@ -4325,11 +4379,15 @@ static int iavf_change_mtu(struct net_device *netdev, int new_mtu)
        }
 
        if (netif_running(netdev)) {
-               adapter->flags |= IAVF_FLAG_RESET_NEEDED;
-               queue_work(adapter->wq, &adapter->reset_task);
+               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_NEEDED);
+               ret = iavf_wait_for_reset(adapter);
+               if (ret < 0)
+                       netdev_warn(netdev, "MTU change interrupted waiting for reset");
+               else if (ret)
+                       netdev_warn(netdev, "MTU change timed out waiting for reset");
        }
 
-       return 0;
+       return ret;
 }
 
 #define NETIF_VLAN_OFFLOAD_FEATURES    (NETIF_F_HW_VLAN_CTAG_RX | \
@@ -4922,6 +4980,7 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        INIT_WORK(&adapter->reset_task, iavf_reset_task);
        INIT_WORK(&adapter->adminq_task, iavf_adminq_task);
+       INIT_WORK(&adapter->finish_config, iavf_finish_config);
        INIT_DELAYED_WORK(&adapter->watchdog_task, iavf_watchdog_task);
        INIT_DELAYED_WORK(&adapter->client_task, iavf_client_task);
        queue_delayed_work(adapter->wq, &adapter->watchdog_task,
@@ -4930,6 +4989,9 @@ static int iavf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        /* Setup the wait queue for indicating transition to down status */
        init_waitqueue_head(&adapter->down_waitqueue);
 
+       /* Setup the wait queue for indicating transition to running state */
+       init_waitqueue_head(&adapter->reset_waitqueue);
+
        /* Setup the wait queue for indicating virtchannel events */
        init_waitqueue_head(&adapter->vc_waitqueue);
 
@@ -5061,13 +5123,15 @@ static void iavf_remove(struct pci_dev *pdev)
                usleep_range(500, 1000);
        }
        cancel_delayed_work_sync(&adapter->watchdog_task);
+       cancel_work_sync(&adapter->finish_config);
 
+       rtnl_lock();
        if (adapter->netdev_registered) {
-               rtnl_lock();
                unregister_netdevice(netdev);
                adapter->netdev_registered = false;
-               rtnl_unlock();
        }
+       rtnl_unlock();
+
        if (CLIENT_ALLOWED(adapter)) {
                err = iavf_lan_del_device(adapter);
                if (err)
index 7c0578b..be3c007 100644 (file)
@@ -1961,9 +1961,8 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
                case VIRTCHNL_EVENT_RESET_IMPENDING:
                        dev_info(&adapter->pdev->dev, "Reset indication received from the PF\n");
                        if (!(adapter->flags & IAVF_FLAG_RESET_PENDING)) {
-                               adapter->flags |= IAVF_FLAG_RESET_PENDING;
                                dev_info(&adapter->pdev->dev, "Scheduling reset task\n");
-                               queue_work(adapter->wq, &adapter->reset_task);
+                               iavf_schedule_reset(adapter, IAVF_FLAG_RESET_PENDING);
                        }
                        break;
                default:
@@ -2237,6 +2236,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
 
                iavf_process_config(adapter);
                adapter->flags |= IAVF_FLAG_SETUP_NETDEV_FEATURES;
+               iavf_schedule_finish_config(adapter);
 
                iavf_set_queue_vlan_tag_loc(adapter);
 
@@ -2285,6 +2285,7 @@ void iavf_virtchnl_completion(struct iavf_adapter *adapter,
        case VIRTCHNL_OP_ENABLE_QUEUES:
                /* enable transmits */
                iavf_irq_enable(adapter, true);
+               wake_up(&adapter->reset_waitqueue);
                adapter->flags &= ~IAVF_FLAG_QUEUES_DISABLED;
                break;
        case VIRTCHNL_OP_DISABLE_QUEUES:
index 4a12316..b678bdf 100644 (file)
@@ -800,6 +800,8 @@ void ice_vsi_free_q_vectors(struct ice_vsi *vsi)
 
        ice_for_each_q_vector(vsi, v_idx)
                ice_free_q_vector(vsi, v_idx);
+
+       vsi->num_q_vectors = 0;
 }
 
 /**
index 8d5cbbd..ad4d470 100644 (file)
@@ -2681,8 +2681,13 @@ ice_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
 
        ring->rx_max_pending = ICE_MAX_NUM_DESC;
        ring->tx_max_pending = ICE_MAX_NUM_DESC;
-       ring->rx_pending = vsi->rx_rings[0]->count;
-       ring->tx_pending = vsi->tx_rings[0]->count;
+       if (vsi->tx_rings && vsi->rx_rings) {
+               ring->rx_pending = vsi->rx_rings[0]->count;
+               ring->tx_pending = vsi->tx_rings[0]->count;
+       } else {
+               ring->rx_pending = 0;
+               ring->tx_pending = 0;
+       }
 
        /* Rx mini and jumbo rings are not supported */
        ring->rx_mini_max_pending = 0;
@@ -2716,6 +2721,10 @@ ice_set_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring,
                return -EINVAL;
        }
 
+       /* Return if there is no rings (device is reloading) */
+       if (!vsi->tx_rings || !vsi->rx_rings)
+               return -EBUSY;
+
        new_tx_cnt = ALIGN(ring->tx_pending, ICE_REQ_DESC_MULTIPLE);
        if (new_tx_cnt != ring->tx_pending)
                netdev_info(netdev, "Requested Tx descriptor count rounded up to %d\n",
index ead6d50..8c6e13f 100644 (file)
@@ -1281,16 +1281,21 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
                                     ICE_FLOW_FLD_OFF_INVAL);
        }
 
-       /* add filter for outer headers */
        fltr_idx = ice_ethtool_flow_to_fltr(fsp->flow_type & ~FLOW_EXT);
+
+       assign_bit(fltr_idx, hw->fdir_perfect_fltr, perfect_filter);
+
+       /* add filter for outer headers */
        ret = ice_fdir_set_hw_fltr_rule(pf, seg, fltr_idx,
                                        ICE_FD_HW_SEG_NON_TUN);
-       if (ret == -EEXIST)
-               /* Rule already exists, free memory and continue */
-               devm_kfree(dev, seg);
-       else if (ret)
+       if (ret == -EEXIST) {
+               /* Rule already exists, free memory and count as success */
+               ret = 0;
+               goto err_exit;
+       } else if (ret) {
                /* could not write filter, free memory */
                goto err_exit;
+       }
 
        /* make tunneled filter HW entries if possible */
        memcpy(&tun_seg[1], seg, sizeof(*seg));
@@ -1305,18 +1310,13 @@ ice_cfg_fdir_xtrct_seq(struct ice_pf *pf, struct ethtool_rx_flow_spec *fsp,
                devm_kfree(dev, tun_seg);
        }
 
-       if (perfect_filter)
-               set_bit(fltr_idx, hw->fdir_perfect_fltr);
-       else
-               clear_bit(fltr_idx, hw->fdir_perfect_fltr);
-
        return ret;
 
 err_exit:
        devm_kfree(dev, tun_seg);
        devm_kfree(dev, seg);
 
-       return -EOPNOTSUPP;
+       return ret;
 }
 
 /**
@@ -1914,7 +1914,9 @@ int ice_add_fdir_ethtool(struct ice_vsi *vsi, struct ethtool_rxnfc *cmd)
        input->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
 
        /* input struct is added to the HW filter list */
-       ice_fdir_update_list_entry(pf, input, fsp->location);
+       ret = ice_fdir_update_list_entry(pf, input, fsp->location);
+       if (ret)
+               goto release_lock;
 
        ret = ice_fdir_write_all_fltr(pf, input, true);
        if (ret)
index 00e3afd..0054d7e 100644 (file)
@@ -2972,39 +2972,12 @@ int ice_vsi_release(struct ice_vsi *vsi)
                return -ENODEV;
        pf = vsi->back;
 
-       /* do not unregister while driver is in the reset recovery pending
-        * state. Since reset/rebuild happens through PF service task workqueue,
-        * it's not a good idea to unregister netdev that is associated to the
-        * PF that is running the work queue items currently. This is done to
-        * avoid check_flush_dependency() warning on this wq
-        */
-       if (vsi->netdev && !ice_is_reset_in_progress(pf->state) &&
-           (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state))) {
-               unregister_netdev(vsi->netdev);
-               clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
-       }
-
-       if (vsi->type == ICE_VSI_PF)
-               ice_devlink_destroy_pf_port(pf);
-
        if (test_bit(ICE_FLAG_RSS_ENA, pf->flags))
                ice_rss_clean(vsi);
 
        ice_vsi_close(vsi);
        ice_vsi_decfg(vsi);
 
-       if (vsi->netdev) {
-               if (test_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state)) {
-                       unregister_netdev(vsi->netdev);
-                       clear_bit(ICE_VSI_NETDEV_REGISTERED, vsi->state);
-               }
-               if (test_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state)) {
-                       free_netdev(vsi->netdev);
-                       vsi->netdev = NULL;
-                       clear_bit(ICE_VSI_NETDEV_ALLOCD, vsi->state);
-               }
-       }
-
        /* retain SW VSI data structure since it is needed to unregister and
         * free VSI netdev when PF is not in reset recovery pending state,\
         * for ex: during rmmod.
index 19a5e7f..cf92c39 100644 (file)
@@ -4430,9 +4430,9 @@ static int ice_start_eth(struct ice_vsi *vsi)
        if (err)
                return err;
 
-       rtnl_lock();
        err = ice_vsi_open(vsi);
-       rtnl_unlock();
+       if (err)
+               ice_fltr_remove_all(vsi);
 
        return err;
 }
@@ -4895,6 +4895,7 @@ int ice_load(struct ice_pf *pf)
        params = ice_vsi_to_params(vsi);
        params.flags = ICE_VSI_FLAG_INIT;
 
+       rtnl_lock();
        err = ice_vsi_cfg(vsi, &params);
        if (err)
                goto err_vsi_cfg;
@@ -4902,6 +4903,7 @@ int ice_load(struct ice_pf *pf)
        err = ice_start_eth(ice_get_main_vsi(pf));
        if (err)
                goto err_start_eth;
+       rtnl_unlock();
 
        err = ice_init_rdma(pf);
        if (err)
@@ -4916,9 +4918,11 @@ int ice_load(struct ice_pf *pf)
 
 err_init_rdma:
        ice_vsi_close(ice_get_main_vsi(pf));
+       rtnl_lock();
 err_start_eth:
        ice_vsi_decfg(ice_get_main_vsi(pf));
 err_vsi_cfg:
+       rtnl_unlock();
        ice_deinit_dev(pf);
        return err;
 }
@@ -4931,8 +4935,10 @@ void ice_unload(struct ice_pf *pf)
 {
        ice_deinit_features(pf);
        ice_deinit_rdma(pf);
+       rtnl_lock();
        ice_stop_eth(ice_get_main_vsi(pf));
        ice_vsi_decfg(ice_get_main_vsi(pf));
+       rtnl_unlock();
        ice_deinit_dev(pf);
 }
 
@@ -8807,6 +8813,7 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
 {
        struct ice_netdev_priv *np = netdev_priv(netdev);
        struct ice_pf *pf = np->vsi->back;
+       bool locked = false;
        int err;
 
        switch (type) {
@@ -8816,10 +8823,27 @@ ice_setup_tc(struct net_device *netdev, enum tc_setup_type type,
                                                  ice_setup_tc_block_cb,
                                                  np, np, true);
        case TC_SETUP_QDISC_MQPRIO:
+               if (pf->adev) {
+                       mutex_lock(&pf->adev_mutex);
+                       device_lock(&pf->adev->dev);
+                       locked = true;
+                       if (pf->adev->dev.driver) {
+                               netdev_err(netdev, "Cannot change qdisc when RDMA is active\n");
+                               err = -EBUSY;
+                               goto adev_unlock;
+                       }
+               }
+
                /* setup traffic classifier for receive side */
                mutex_lock(&pf->tc_mutex);
                err = ice_setup_tc_mqprio_qdisc(netdev, type_data);
                mutex_unlock(&pf->tc_mutex);
+
+adev_unlock:
+               if (locked) {
+                       device_unlock(&pf->adev->dev);
+                       mutex_unlock(&pf->adev_mutex);
+               }
                return err;
        default:
                return -EOPNOTSUPP;
index 9f93f0f..bdeb367 100644 (file)
@@ -316,6 +316,33 @@ static void igc_clean_all_tx_rings(struct igc_adapter *adapter)
                        igc_clean_tx_ring(adapter->tx_ring[i]);
 }
 
+static void igc_disable_tx_ring_hw(struct igc_ring *ring)
+{
+       struct igc_hw *hw = &ring->q_vector->adapter->hw;
+       u8 idx = ring->reg_idx;
+       u32 txdctl;
+
+       txdctl = rd32(IGC_TXDCTL(idx));
+       txdctl &= ~IGC_TXDCTL_QUEUE_ENABLE;
+       txdctl |= IGC_TXDCTL_SWFLUSH;
+       wr32(IGC_TXDCTL(idx), txdctl);
+}
+
+/**
+ * igc_disable_all_tx_rings_hw - Disable all transmit queue operation
+ * @adapter: board private structure
+ */
+static void igc_disable_all_tx_rings_hw(struct igc_adapter *adapter)
+{
+       int i;
+
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+               igc_disable_tx_ring_hw(tx_ring);
+       }
+}
+
 /**
  * igc_setup_tx_resources - allocate Tx resources (Descriptors)
  * @tx_ring: tx descriptor ring (for a specific queue) to setup
@@ -2828,9 +2855,8 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
        struct netdev_queue *nq = txring_txq(ring);
        union igc_adv_tx_desc *tx_desc = NULL;
        int cpu = smp_processor_id();
-       u16 ntu = ring->next_to_use;
        struct xdp_desc xdp_desc;
-       u16 budget;
+       u16 budget, ntu;
 
        if (!netif_carrier_ok(ring->netdev))
                return;
@@ -2840,6 +2866,7 @@ static void igc_xdp_xmit_zc(struct igc_ring *ring)
        /* Avoid transmit queue timeout since we share it with the slow path */
        txq_trans_cond_update(nq);
 
+       ntu = ring->next_to_use;
        budget = igc_desc_unused(ring);
 
        while (xsk_tx_peek_desc(pool, &xdp_desc) && budget--) {
@@ -5058,6 +5085,7 @@ void igc_down(struct igc_adapter *adapter)
        /* clear VLAN promisc flag so VFTA will be updated if necessary */
        adapter->flags &= ~IGC_FLAG_VLAN_PROMISC;
 
+       igc_disable_all_tx_rings_hw(adapter);
        igc_clean_all_tx_rings(adapter);
        igc_clean_all_rx_rings(adapter);
 }
@@ -7290,18 +7318,6 @@ void igc_enable_rx_ring(struct igc_ring *ring)
                igc_alloc_rx_buffers(ring, igc_desc_unused(ring));
 }
 
-static void igc_disable_tx_ring_hw(struct igc_ring *ring)
-{
-       struct igc_hw *hw = &ring->q_vector->adapter->hw;
-       u8 idx = ring->reg_idx;
-       u32 txdctl;
-
-       txdctl = rd32(IGC_TXDCTL(idx));
-       txdctl &= ~IGC_TXDCTL_QUEUE_ENABLE;
-       txdctl |= IGC_TXDCTL_SWFLUSH;
-       wr32(IGC_TXDCTL(idx), txdctl);
-}
-
 void igc_disable_tx_ring(struct igc_ring *ring)
 {
        igc_disable_tx_ring_hw(ring);
index 1726297..8eb9839 100644 (file)
@@ -8479,7 +8479,7 @@ static void ixgbe_atr(struct ixgbe_ring *ring,
                struct ixgbe_adapter *adapter = q_vector->adapter;
 
                if (unlikely(skb_tail_pointer(skb) < hdr.network +
-                            VXLAN_HEADROOM))
+                            vxlan_headroom(0)))
                        return;
 
                /* verify the port is recognized as VXLAN */
index 2b9335c..8537578 100644 (file)
@@ -1302,11 +1302,10 @@ static int korina_probe(struct platform_device *pdev)
        else if (of_get_ethdev_address(pdev->dev.of_node, dev) < 0)
                eth_hw_addr_random(dev);
 
-       clk = devm_clk_get_optional(&pdev->dev, "mdioclk");
+       clk = devm_clk_get_optional_enabled(&pdev->dev, "mdioclk");
        if (IS_ERR(clk))
                return PTR_ERR(clk);
        if (clk) {
-               clk_prepare_enable(clk);
                lp->mii_clock_freq = clk_get_rate(clk);
        } else {
                lp->mii_clock_freq = 200000000; /* max possible input clk */
index 035ead7..dab61cc 100644 (file)
@@ -98,6 +98,9 @@ int octep_ctrl_mbox_init(struct octep_ctrl_mbox *mbox)
        writeq(OCTEP_CTRL_MBOX_STATUS_INIT,
               OCTEP_CTRL_MBOX_INFO_HOST_STATUS(mbox->barmem));
 
+       mutex_init(&mbox->h2fq_lock);
+       mutex_init(&mbox->f2hq_lock);
+
        mbox->h2fq.sz = readl(OCTEP_CTRL_MBOX_H2FQ_SZ(mbox->barmem));
        mbox->h2fq.hw_prod = OCTEP_CTRL_MBOX_H2FQ_PROD(mbox->barmem);
        mbox->h2fq.hw_cons = OCTEP_CTRL_MBOX_H2FQ_CONS(mbox->barmem);
index 6fe67f3..7e20282 100644 (file)
@@ -218,13 +218,54 @@ void npc_config_secret_key(struct rvu *rvu, int blkaddr)
 
 void npc_program_mkex_hash(struct rvu *rvu, int blkaddr)
 {
+       struct npc_mcam_kex_hash *mh = rvu->kpu.mkex_hash;
        struct hw_cap *hwcap = &rvu->hw->cap;
+       u8 intf, ld, hdr_offset, byte_len;
        struct rvu_hwinfo *hw = rvu->hw;
-       u8 intf;
+       u64 cfg;
 
+       /* Check if hardware supports hash extraction */
        if (!hwcap->npc_hash_extract)
                return;
 
+       /* Check if IPv6 source/destination address
+        * should be hash enabled.
+        * Hashing reduces 128bit SIP/DIP fields to 32bit
+        * so that 224 bit X2 key can be used for IPv6 based filters as well,
+        * which in turn results in more number of MCAM entries available for
+        * use.
+        *
+        * Hashing of IPV6 SIP/DIP is enabled in below scenarios
+        * 1. If the silicon variant supports hashing feature
+        * 2. If the number of bytes of IP addr being extracted is 4 bytes ie
+        *    32bit. The assumption here is that if user wants 8bytes of LSB of
+        *    IP addr or full 16 bytes then his intention is not to use 32bit
+        *    hash.
+        */
+       for (intf = 0; intf < hw->npc_intfs; intf++) {
+               for (ld = 0; ld < NPC_MAX_LD; ld++) {
+                       cfg = rvu_read64(rvu, blkaddr,
+                                        NPC_AF_INTFX_LIDX_LTX_LDX_CFG(intf,
+                                                                      NPC_LID_LC,
+                                                                      NPC_LT_LC_IP6,
+                                                                      ld));
+                       hdr_offset = FIELD_GET(NPC_HDR_OFFSET, cfg);
+                       byte_len = FIELD_GET(NPC_BYTESM, cfg);
+                       /* Hashing of IPv6 source/destination address should be
+                        * enabled if,
+                        * hdr_offset == 8 (offset of source IPv6 address) or
+                        * hdr_offset == 24 (offset of destination IPv6)
+                        * address) and the number of byte to be
+                        * extracted is 4. As per hardware configuration
+                        * byte_len should be == actual byte_len - 1.
+                        * Hence byte_len is checked against 3 but nor 4.
+                        */
+                       if ((hdr_offset == 8 || hdr_offset == 24) && byte_len == 3)
+                               mh->lid_lt_ld_hash_en[intf][NPC_LID_LC][NPC_LT_LC_IP6][ld] = true;
+               }
+       }
+
+       /* Update hash configuration if the field is hash enabled */
        for (intf = 0; intf < hw->npc_intfs; intf++) {
                npc_program_mkex_hash_rx(rvu, blkaddr, intf);
                npc_program_mkex_hash_tx(rvu, blkaddr, intf);
index a1c3d98..57a0932 100644 (file)
@@ -70,8 +70,8 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
        [NIX_INTF_RX] = {
                [NPC_LID_LC] = {
                        [NPC_LT_LC_IP6] = {
-                               true,
-                               true,
+                               false,
+                               false,
                        },
                },
        },
@@ -79,8 +79,8 @@ static struct npc_mcam_kex_hash npc_mkex_hash_default __maybe_unused = {
        [NIX_INTF_TX] = {
                [NPC_LID_LC] = {
                        [NPC_LT_LC_IP6] = {
-                               true,
-                               true,
+                               false,
+                               false,
                        },
                },
        },
index 6e2fb24..59b1382 100644 (file)
@@ -4,6 +4,7 @@
  * Copyright (C) 2022 Marvell.
  */
 
+#include <crypto/skcipher.h>
 #include <linux/rtnetlink.h>
 #include <linux/bitfield.h>
 #include "otx2_common.h"
 #define MCS_TCI_E                      0x08 /* encryption */
 #define MCS_TCI_C                      0x04 /* changed text */
 
+#define CN10K_MAX_HASH_LEN             16
+#define CN10K_MAX_SAK_LEN              32
+
+static int cn10k_ecb_aes_encrypt(struct otx2_nic *pfvf, u8 *sak,
+                                u16 sak_len, u8 *hash)
+{
+       u8 data[CN10K_MAX_HASH_LEN] = { 0 };
+       struct skcipher_request *req = NULL;
+       struct scatterlist sg_src, sg_dst;
+       struct crypto_skcipher *tfm;
+       DECLARE_CRYPTO_WAIT(wait);
+       int err;
+
+       tfm = crypto_alloc_skcipher("ecb(aes)", 0, 0);
+       if (IS_ERR(tfm)) {
+               dev_err(pfvf->dev, "failed to allocate transform for ecb-aes\n");
+               return PTR_ERR(tfm);
+       }
+
+       req = skcipher_request_alloc(tfm, GFP_KERNEL);
+       if (!req) {
+               dev_err(pfvf->dev, "failed to allocate request for skcipher\n");
+               err = -ENOMEM;
+               goto free_tfm;
+       }
+
+       err = crypto_skcipher_setkey(tfm, sak, sak_len);
+       if (err) {
+               dev_err(pfvf->dev, "failed to set key for skcipher\n");
+               goto free_req;
+       }
+
+       /* build sg list */
+       sg_init_one(&sg_src, data, CN10K_MAX_HASH_LEN);
+       sg_init_one(&sg_dst, hash, CN10K_MAX_HASH_LEN);
+
+       skcipher_request_set_callback(req, 0, crypto_req_done, &wait);
+       skcipher_request_set_crypt(req, &sg_src, &sg_dst,
+                                  CN10K_MAX_HASH_LEN, NULL);
+
+       err = crypto_skcipher_encrypt(req);
+       err = crypto_wait_req(err, &wait);
+
+free_req:
+       skcipher_request_free(req);
+free_tfm:
+       crypto_free_skcipher(tfm);
+       return err;
+}
+
 static struct cn10k_mcs_txsc *cn10k_mcs_get_txsc(struct cn10k_mcs_cfg *cfg,
                                                 struct macsec_secy *secy)
 {
@@ -330,19 +381,53 @@ fail:
        return ret;
 }
 
+static int cn10k_mcs_write_keys(struct otx2_nic *pfvf,
+                               struct macsec_secy *secy,
+                               struct mcs_sa_plcy_write_req *req,
+                               u8 *sak, u8 *salt, ssci_t ssci)
+{
+       u8 hash_rev[CN10K_MAX_HASH_LEN];
+       u8 sak_rev[CN10K_MAX_SAK_LEN];
+       u8 salt_rev[MACSEC_SALT_LEN];
+       u8 hash[CN10K_MAX_HASH_LEN];
+       u32 ssci_63_32;
+       int err, i;
+
+       err = cn10k_ecb_aes_encrypt(pfvf, sak, secy->key_len, hash);
+       if (err) {
+               dev_err(pfvf->dev, "Generating hash using ECB(AES) failed\n");
+               return err;
+       }
+
+       for (i = 0; i < secy->key_len; i++)
+               sak_rev[i] = sak[secy->key_len - 1 - i];
+
+       for (i = 0; i < CN10K_MAX_HASH_LEN; i++)
+               hash_rev[i] = hash[CN10K_MAX_HASH_LEN - 1 - i];
+
+       for (i = 0; i < MACSEC_SALT_LEN; i++)
+               salt_rev[i] = salt[MACSEC_SALT_LEN - 1 - i];
+
+       ssci_63_32 = (__force u32)cpu_to_be32((__force u32)ssci);
+
+       memcpy(&req->plcy[0][0], sak_rev, secy->key_len);
+       memcpy(&req->plcy[0][4], hash_rev, CN10K_MAX_HASH_LEN);
+       memcpy(&req->plcy[0][6], salt_rev, MACSEC_SALT_LEN);
+       req->plcy[0][7] |= (u64)ssci_63_32 << 32;
+
+       return 0;
+}
+
 static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
                                      struct macsec_secy *secy,
                                      struct cn10k_mcs_rxsc *rxsc,
                                      u8 assoc_num, bool sa_in_use)
 {
-       unsigned char *src = rxsc->sa_key[assoc_num];
        struct mcs_sa_plcy_write_req *plcy_req;
-       u8 *salt_p = rxsc->salt[assoc_num];
+       u8 *sak = rxsc->sa_key[assoc_num];
+       u8 *salt = rxsc->salt[assoc_num];
        struct mcs_rx_sc_sa_map *map_req;
        struct mbox *mbox = &pfvf->mbox;
-       u64 ssci_salt_95_64 = 0;
-       u8 reg, key_len;
-       u64 salt_63_0;
        int ret;
 
        mutex_lock(&mbox->lock);
@@ -360,20 +445,10 @@ static int cn10k_mcs_write_rx_sa_plcy(struct otx2_nic *pfvf,
                goto fail;
        }
 
-       for (reg = 0, key_len = 0; key_len < secy->key_len; key_len += 8) {
-               memcpy((u8 *)&plcy_req->plcy[0][reg],
-                      (src + reg * 8), 8);
-               reg++;
-       }
-
-       if (secy->xpn) {
-               memcpy((u8 *)&salt_63_0, salt_p, 8);
-               memcpy((u8 *)&ssci_salt_95_64, salt_p + 8, 4);
-               ssci_salt_95_64 |= (__force u64)rxsc->ssci[assoc_num] << 32;
-
-               plcy_req->plcy[0][6] = salt_63_0;
-               plcy_req->plcy[0][7] = ssci_salt_95_64;
-       }
+       ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
+                                  salt, rxsc->ssci[assoc_num]);
+       if (ret)
+               goto fail;
 
        plcy_req->sa_index[0] = rxsc->hw_sa_id[assoc_num];
        plcy_req->sa_cnt = 1;
@@ -586,13 +661,10 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
                                      struct cn10k_mcs_txsc *txsc,
                                      u8 assoc_num)
 {
-       unsigned char *src = txsc->sa_key[assoc_num];
        struct mcs_sa_plcy_write_req *plcy_req;
-       u8 *salt_p = txsc->salt[assoc_num];
+       u8 *sak = txsc->sa_key[assoc_num];
+       u8 *salt = txsc->salt[assoc_num];
        struct mbox *mbox = &pfvf->mbox;
-       u64 ssci_salt_95_64 = 0;
-       u8 reg, key_len;
-       u64 salt_63_0;
        int ret;
 
        mutex_lock(&mbox->lock);
@@ -603,19 +675,10 @@ static int cn10k_mcs_write_tx_sa_plcy(struct otx2_nic *pfvf,
                goto fail;
        }
 
-       for (reg = 0, key_len = 0; key_len < secy->key_len; key_len += 8) {
-               memcpy((u8 *)&plcy_req->plcy[0][reg], (src + reg * 8), 8);
-               reg++;
-       }
-
-       if (secy->xpn) {
-               memcpy((u8 *)&salt_63_0, salt_p, 8);
-               memcpy((u8 *)&ssci_salt_95_64, salt_p + 8, 4);
-               ssci_salt_95_64 |= (__force u64)txsc->ssci[assoc_num] << 32;
-
-               plcy_req->plcy[0][6] = salt_63_0;
-               plcy_req->plcy[0][7] = ssci_salt_95_64;
-       }
+       ret = cn10k_mcs_write_keys(pfvf, secy, plcy_req, sak,
+                                  salt, txsc->ssci[assoc_num]);
+       if (ret)
+               goto fail;
 
        plcy_req->plcy[0][8] = assoc_num;
        plcy_req->sa_index[0] = txsc->hw_sa_id[assoc_num];
index fe8ea4e..9551b42 100644 (file)
@@ -1454,8 +1454,9 @@ static int otx2_init_hw_resources(struct otx2_nic *pf)
        if (err)
                goto err_free_npa_lf;
 
-       /* Enable backpressure */
-       otx2_nix_config_bp(pf, true);
+       /* Enable backpressure for CGX mapped PF/VFs */
+       if (!is_otx2_lbkvf(pf->pdev))
+               otx2_nix_config_bp(pf, true);
 
        /* Init Auras and pools used by NIX RQ, for free buffer ptrs */
        err = otx2_rq_aura_pool_init(pf);
index f328d95..35857dc 100644 (file)
@@ -727,7 +727,8 @@ pick_fw_ver:
 
        err = request_firmware_direct(&fw->bin, fw_path, fw->dev.dev);
        if (err) {
-               if (ver_maj == PRESTERA_SUPP_FW_MAJ_VER) {
+               if (ver_maj != PRESTERA_PREV_FW_MAJ_VER ||
+                   ver_min != PRESTERA_PREV_FW_MIN_VER) {
                        ver_maj = PRESTERA_PREV_FW_MAJ_VER;
                        ver_min = PRESTERA_PREV_FW_MIN_VER;
 
index 834c644..2d15342 100644 (file)
@@ -3846,23 +3846,6 @@ static int mtk_hw_deinit(struct mtk_eth *eth)
        return 0;
 }
 
-static int __init mtk_init(struct net_device *dev)
-{
-       struct mtk_mac *mac = netdev_priv(dev);
-       struct mtk_eth *eth = mac->hw;
-       int ret;
-
-       ret = of_get_ethdev_address(mac->of_node, dev);
-       if (ret) {
-               /* If the mac address is invalid, use random mac address */
-               eth_hw_addr_random(dev);
-               dev_err(eth->dev, "generated random MAC address %pM\n",
-                       dev->dev_addr);
-       }
-
-       return 0;
-}
-
 static void mtk_uninit(struct net_device *dev)
 {
        struct mtk_mac *mac = netdev_priv(dev);
@@ -4278,7 +4261,6 @@ static const struct ethtool_ops mtk_ethtool_ops = {
 };
 
 static const struct net_device_ops mtk_netdev_ops = {
-       .ndo_init               = mtk_init,
        .ndo_uninit             = mtk_uninit,
        .ndo_open               = mtk_open,
        .ndo_stop               = mtk_stop,
@@ -4340,6 +4322,17 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
        mac->hw = eth;
        mac->of_node = np;
 
+       err = of_get_ethdev_address(mac->of_node, eth->netdev[id]);
+       if (err == -EPROBE_DEFER)
+               return err;
+
+       if (err) {
+               /* If the mac address is invalid, use random mac address */
+               eth_hw_addr_random(eth->netdev[id]);
+               dev_err(eth->dev, "generated random MAC address %pM\n",
+                       eth->netdev[id]->dev_addr);
+       }
+
        memset(mac->hwlro_ip, 0, sizeof(mac->hwlro_ip));
        mac->hwlro_ip_cnt = 0;
 
index 316fe2e..1a97fec 100644 (file)
@@ -98,7 +98,7 @@ mtk_ppe_debugfs_foe_show(struct seq_file *m, void *private, bool bind)
 
                acct = mtk_foe_entry_get_mib(ppe, i, NULL);
 
-               type = FIELD_GET(MTK_FOE_IB1_PACKET_TYPE, entry->ib1);
+               type = mtk_get_ib1_pkt_type(ppe->eth, entry->ib1);
                seq_printf(m, "%05x %s %7s", i,
                           mtk_foe_entry_state_str(state),
                           mtk_foe_pkt_type_str(type));
index f0c3464..0c88cf4 100644 (file)
@@ -1030,9 +1030,6 @@ int mlx5e_tc_tun_encap_dests_set(struct mlx5e_priv *priv,
        int out_index;
        int err = 0;
 
-       if (!mlx5e_is_eswitch_flow(flow))
-               return 0;
-
        parse_attr = attr->parse_attr;
        esw_attr = attr->esw_attr;
        *vf_tun = false;
index d97e6df..b8dd744 100644 (file)
@@ -323,8 +323,11 @@ struct sk_buff *mlx5e_xsk_skb_from_cqe_linear(struct mlx5e_rq *rq,
        net_prefetch(mxbuf->xdp.data);
 
        prog = rcu_dereference(rq->xdp_prog);
-       if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf)))
+       if (likely(prog && mlx5e_xdp_handle(rq, prog, mxbuf))) {
+               if (likely(__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)))
+                       wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
                return NULL; /* page/packet was consumed by XDP */
+       }
 
        /* XDP_PASS: copy the data from the UMEM to a new SKB. The frame reuse
         * will be handled by mlx5e_free_rx_wqe.
index dbe87bf..832d36b 100644 (file)
@@ -808,9 +808,9 @@ static void setup_fte_upper_proto_match(struct mlx5_flow_spec *spec, struct upsp
        }
 
        if (upspec->sport) {
-               MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_dport,
+               MLX5_SET(fte_match_set_lyr_2_4, spec->match_criteria, udp_sport,
                         upspec->sport_mask);
-               MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_dport, upspec->sport);
+               MLX5_SET(fte_match_set_lyr_2_4, spec->match_value, udp_sport, upspec->sport);
        }
 }
 
index eab5bc7..8d995e3 100644 (file)
@@ -58,7 +58,9 @@ static int mlx5e_ipsec_remove_trailer(struct sk_buff *skb, struct xfrm_state *x)
 
        trailer_len = alen + plen + 2;
 
-       pskb_trim(skb, skb->len - trailer_len);
+       ret = pskb_trim(skb, skb->len - trailer_len);
+       if (unlikely(ret))
+               return ret;
        if (skb->protocol == htons(ETH_P_IP)) {
                ipv4hdr->tot_len = htons(ntohs(ipv4hdr->tot_len) - trailer_len);
                ip_send_check(ipv4hdr);
index cf704f1..984fa04 100644 (file)
@@ -188,7 +188,6 @@ static void mlx5e_tls_debugfs_init(struct mlx5e_tls *tls,
 
 int mlx5e_ktls_init(struct mlx5e_priv *priv)
 {
-       struct mlx5_crypto_dek_pool *dek_pool;
        struct mlx5e_tls *tls;
 
        if (!mlx5e_is_ktls_device(priv->mdev))
@@ -199,12 +198,6 @@ int mlx5e_ktls_init(struct mlx5e_priv *priv)
                return -ENOMEM;
        tls->mdev = priv->mdev;
 
-       dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY);
-       if (IS_ERR(dek_pool)) {
-               kfree(tls);
-               return PTR_ERR(dek_pool);
-       }
-       tls->dek_pool = dek_pool;
        priv->tls = tls;
 
        mlx5e_tls_debugfs_init(tls, priv->dfs_root);
@@ -222,7 +215,6 @@ void mlx5e_ktls_cleanup(struct mlx5e_priv *priv)
        debugfs_remove_recursive(tls->debugfs.dfs);
        tls->debugfs.dfs = NULL;
 
-       mlx5_crypto_dek_pool_destroy(tls->dek_pool);
        kfree(priv->tls);
        priv->tls = NULL;
 }
index efb2cf7..d61be26 100644 (file)
@@ -908,28 +908,51 @@ static void mlx5e_tls_tx_debugfs_init(struct mlx5e_tls *tls,
 
 int mlx5e_ktls_init_tx(struct mlx5e_priv *priv)
 {
+       struct mlx5_crypto_dek_pool *dek_pool;
        struct mlx5e_tls *tls = priv->tls;
+       int err;
+
+       if (!mlx5e_is_ktls_device(priv->mdev))
+               return 0;
+
+       /* DEK pool could be used by either or both of TX and RX. But we have to
+        * put the creation here to avoid syndrome when doing devlink reload.
+        */
+       dek_pool = mlx5_crypto_dek_pool_create(priv->mdev, MLX5_ACCEL_OBJ_TLS_KEY);
+       if (IS_ERR(dek_pool))
+               return PTR_ERR(dek_pool);
+       tls->dek_pool = dek_pool;
 
        if (!mlx5e_is_ktls_tx(priv->mdev))
                return 0;
 
        priv->tls->tx_pool = mlx5e_tls_tx_pool_init(priv->mdev, &priv->tls->sw_stats);
-       if (!priv->tls->tx_pool)
-               return -ENOMEM;
+       if (!priv->tls->tx_pool) {
+               err = -ENOMEM;
+               goto err_tx_pool_init;
+       }
 
        mlx5e_tls_tx_debugfs_init(tls, tls->debugfs.dfs);
 
        return 0;
+
+err_tx_pool_init:
+       mlx5_crypto_dek_pool_destroy(dek_pool);
+       return err;
 }
 
 void mlx5e_ktls_cleanup_tx(struct mlx5e_priv *priv)
 {
        if (!mlx5e_is_ktls_tx(priv->mdev))
-               return;
+               goto dek_pool_destroy;
 
        debugfs_remove_recursive(priv->tls->debugfs.dfs_tx);
        priv->tls->debugfs.dfs_tx = NULL;
 
        mlx5e_tls_tx_pool_cleanup(priv->tls->tx_pool);
        priv->tls->tx_pool = NULL;
+
+dek_pool_destroy:
+       if (mlx5e_is_ktls_device(priv->mdev))
+               mlx5_crypto_dek_pool_destroy(priv->tls->dek_pool);
 }
index 7fc901a..414e285 100644 (file)
@@ -161,6 +161,7 @@ static int macsec_fs_tx_create_crypto_table_groups(struct mlx5e_flow_table *ft)
 
        if (!in) {
                kfree(ft->g);
+               ft->g = NULL;
                return -ENOMEM;
        }
 
index 933a777..5aa51d7 100644 (file)
@@ -135,6 +135,16 @@ static void arfs_del_rules(struct mlx5e_flow_steering *fs);
 
 int mlx5e_arfs_disable(struct mlx5e_flow_steering *fs)
 {
+       /* Moving to switchdev mode, fs->arfs is freed by mlx5e_nic_profile
+        * cleanup_rx callback and it is not recreated when
+        * mlx5e_uplink_rep_profile is loaded as mlx5e_create_flow_steering()
+        * is not called by the uplink_rep profile init_rx callback. Thus, if
+        * ntuple is set, moving to switchdev flow will enter this function
+        * with fs->arfs nullified.
+        */
+       if (!mlx5e_fs_get_arfs(fs))
+               return 0;
+
        arfs_del_rules(fs);
 
        return arfs_disable(fs);
index defb1ef..1c82011 100644 (file)
@@ -1036,7 +1036,23 @@ static int mlx5e_modify_rq_state(struct mlx5e_rq *rq, int curr_state, int next_s
        return err;
 }
 
-static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
+static void mlx5e_flush_rq_cq(struct mlx5e_rq *rq)
+{
+       struct mlx5_cqwq *cqwq = &rq->cq.wq;
+       struct mlx5_cqe64 *cqe;
+
+       if (test_bit(MLX5E_RQ_STATE_MINI_CQE_ENHANCED, &rq->state)) {
+               while ((cqe = mlx5_cqwq_get_cqe_enahnced_comp(cqwq)))
+                       mlx5_cqwq_pop(cqwq);
+       } else {
+               while ((cqe = mlx5_cqwq_get_cqe(cqwq)))
+                       mlx5_cqwq_pop(cqwq);
+       }
+
+       mlx5_cqwq_update_db_record(cqwq);
+}
+
+int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state)
 {
        struct net_device *dev = rq->netdev;
        int err;
@@ -1046,6 +1062,10 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
                netdev_err(dev, "Failed to move rq 0x%x to reset\n", rq->rqn);
                return err;
        }
+
+       mlx5e_free_rx_descs(rq);
+       mlx5e_flush_rq_cq(rq);
+
        err = mlx5e_modify_rq_state(rq, MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY);
        if (err) {
                netdev_err(dev, "Failed to move rq 0x%x to ready\n", rq->rqn);
@@ -1055,13 +1075,6 @@ static int mlx5e_rq_to_ready(struct mlx5e_rq *rq, int curr_state)
        return 0;
 }
 
-int mlx5e_flush_rq(struct mlx5e_rq *rq, int curr_state)
-{
-       mlx5e_free_rx_descs(rq);
-
-       return mlx5e_rq_to_ready(rq, curr_state);
-}
-
 static int mlx5e_modify_rq_vsd(struct mlx5e_rq *rq, bool vsd)
 {
        struct mlx5_core_dev *mdev = rq->mdev;
index 152b621..99b3843 100644 (file)
@@ -1012,7 +1012,7 @@ static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
        err = mlx5e_open_drop_rq(priv, &priv->drop_rq);
        if (err) {
                mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
-               return err;
+               goto err_rx_res_free;
        }
 
        err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0,
@@ -1046,6 +1046,7 @@ err_destroy_rx_res:
        mlx5e_rx_res_destroy(priv->rx_res);
 err_close_drop_rq:
        mlx5e_close_drop_rq(&priv->drop_rq);
+err_rx_res_free:
        mlx5e_rx_res_free(priv->rx_res);
        priv->rx_res = NULL;
 err_free_fs:
@@ -1159,6 +1160,10 @@ static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
                return err;
        }
 
+       err = mlx5e_rep_neigh_init(rpriv);
+       if (err)
+               goto err_neigh_init;
+
        if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
                err = mlx5e_init_uplink_rep_tx(rpriv);
                if (err)
@@ -1175,6 +1180,8 @@ err_ht_init:
        if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
                mlx5e_cleanup_uplink_rep_tx(rpriv);
 err_init_tx:
+       mlx5e_rep_neigh_cleanup(rpriv);
+err_neigh_init:
        mlx5e_destroy_tises(priv);
        return err;
 }
@@ -1188,22 +1195,17 @@ static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
        if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
                mlx5e_cleanup_uplink_rep_tx(rpriv);
 
+       mlx5e_rep_neigh_cleanup(rpriv);
        mlx5e_destroy_tises(priv);
 }
 
 static void mlx5e_rep_enable(struct mlx5e_priv *priv)
 {
-       struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
        mlx5e_set_netdev_mtu_boundaries(priv);
-       mlx5e_rep_neigh_init(rpriv);
 }
 
 static void mlx5e_rep_disable(struct mlx5e_priv *priv)
 {
-       struct mlx5e_rep_priv *rpriv = priv->ppriv;
-
-       mlx5e_rep_neigh_cleanup(rpriv);
 }
 
 static int mlx5e_update_rep_rx(struct mlx5e_priv *priv)
@@ -1253,7 +1255,6 @@ static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event
 
 static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
 {
-       struct mlx5e_rep_priv *rpriv = priv->ppriv;
        struct net_device *netdev = priv->netdev;
        struct mlx5_core_dev *mdev = priv->mdev;
        u16 max_mtu;
@@ -1275,7 +1276,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
        mlx5_notifier_register(mdev, &priv->events_nb);
        mlx5e_dcbnl_initialize(priv);
        mlx5e_dcbnl_init_app(priv);
-       mlx5e_rep_neigh_init(rpriv);
        mlx5e_rep_bridge_init(priv);
 
        netdev->wanted_features |= NETIF_F_HW_TC;
@@ -1290,7 +1290,6 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
 
 static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
 {
-       struct mlx5e_rep_priv *rpriv = priv->ppriv;
        struct mlx5_core_dev *mdev = priv->mdev;
 
        rtnl_lock();
@@ -1300,7 +1299,6 @@ static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
        rtnl_unlock();
 
        mlx5e_rep_bridge_cleanup(priv);
-       mlx5e_rep_neigh_cleanup(rpriv);
        mlx5e_dcbnl_delete_app(priv);
        mlx5_notifier_unregister(mdev, &priv->events_nb);
        mlx5e_rep_tc_disable(priv);
index 8d0a3f6..9237763 100644 (file)
@@ -1725,6 +1725,19 @@ verify_attr_actions(u32 actions, struct netlink_ext_ack *extack)
        return 0;
 }
 
+static bool
+has_encap_dests(struct mlx5_flow_attr *attr)
+{
+       struct mlx5_esw_flow_attr *esw_attr = attr->esw_attr;
+       int out_index;
+
+       for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++)
+               if (esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)
+                       return true;
+
+       return false;
+}
+
 static int
 post_process_attr(struct mlx5e_tc_flow *flow,
                  struct mlx5_flow_attr *attr,
@@ -1737,9 +1750,11 @@ post_process_attr(struct mlx5e_tc_flow *flow,
        if (err)
                goto err_out;
 
-       err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
-       if (err)
-               goto err_out;
+       if (mlx5e_is_eswitch_flow(flow) && has_encap_dests(attr)) {
+               err = mlx5e_tc_tun_encap_dests_set(flow->priv, flow, attr, extack, &vf_tun);
+               if (err)
+                       goto err_out;
+       }
 
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) {
                err = mlx5e_tc_attach_mod_hdr(flow->priv, flow, attr);
index b6a45ef..dbd7cbe 100644 (file)
@@ -64,7 +64,7 @@ void mlx5_esw_bridge_debugfs_init(struct net_device *br_netdev, struct mlx5_esw_
 
        bridge->debugfs_dir = debugfs_create_dir(br_netdev->name,
                                                 bridge->br_offloads->debugfs_root);
-       debugfs_create_file("fdb", 0444, bridge->debugfs_dir, bridge,
+       debugfs_create_file("fdb", 0400, bridge->debugfs_dir, bridge,
                            &mlx5_esw_bridge_debugfs_fops);
 }
 
index bdfe609..e59380e 100644 (file)
@@ -1436,7 +1436,6 @@ esw_chains_create(struct mlx5_eswitch *esw, struct mlx5_flow_table *miss_fdb)
 
        esw_init_chains_offload_flags(esw, &attr.flags);
        attr.ns = MLX5_FLOW_NAMESPACE_FDB;
-       attr.fs_base_prio = FDB_TC_OFFLOAD;
        attr.max_grp_num = esw->params.large_group_num;
        attr.default_ft = miss_fdb;
        attr.mapping = esw->offloads.reg_c0_obj_pool;
@@ -2779,9 +2778,9 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
                                         struct mlx5_eswitch *peer_esw,
                                         bool pair)
 {
-       u8 peer_idx = mlx5_get_dev_index(peer_esw->dev);
+       u16 peer_vhca_id = MLX5_CAP_GEN(peer_esw->dev, vhca_id);
+       u16 vhca_id = MLX5_CAP_GEN(esw->dev, vhca_id);
        struct mlx5_flow_root_namespace *peer_ns;
-       u8 idx = mlx5_get_dev_index(esw->dev);
        struct mlx5_flow_root_namespace *ns;
        int err;
 
@@ -2789,18 +2788,18 @@ static int mlx5_esw_offloads_set_ns_peer(struct mlx5_eswitch *esw,
        ns = esw->dev->priv.steering->fdb_root_ns;
 
        if (pair) {
-               err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_idx);
+               err = mlx5_flow_namespace_set_peer(ns, peer_ns, peer_vhca_id);
                if (err)
                        return err;
 
-               err = mlx5_flow_namespace_set_peer(peer_ns, ns, idx);
+               err = mlx5_flow_namespace_set_peer(peer_ns, ns, vhca_id);
                if (err) {
-                       mlx5_flow_namespace_set_peer(ns, NULL, peer_idx);
+                       mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id);
                        return err;
                }
        } else {
-               mlx5_flow_namespace_set_peer(ns, NULL, peer_idx);
-               mlx5_flow_namespace_set_peer(peer_ns, NULL, idx);
+               mlx5_flow_namespace_set_peer(ns, NULL, peer_vhca_id);
+               mlx5_flow_namespace_set_peer(peer_ns, NULL, vhca_id);
        }
 
        return 0;
@@ -4196,7 +4195,7 @@ int mlx5_devlink_port_fn_migratable_set(struct devlink_port *port, bool enable,
        }
 
        hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
-       MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, 1);
+       MLX5_SET(cmd_hca_cap_2, hca_caps, migratable, enable);
 
        err = mlx5_vport_set_other_func_cap(esw->dev, hca_caps, vport->vport,
                                            MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE2);
index 91dcb0d..aab7059 100644 (file)
@@ -140,7 +140,7 @@ static void mlx5_cmd_stub_modify_header_dealloc(struct mlx5_flow_root_namespace
 
 static int mlx5_cmd_stub_set_peer(struct mlx5_flow_root_namespace *ns,
                                  struct mlx5_flow_root_namespace *peer_ns,
-                                 u8 peer_idx)
+                                 u16 peer_vhca_id)
 {
        return 0;
 }
index b6b9a5a..7790ae5 100644 (file)
@@ -94,7 +94,7 @@ struct mlx5_flow_cmds {
 
        int (*set_peer)(struct mlx5_flow_root_namespace *ns,
                        struct mlx5_flow_root_namespace *peer_ns,
-                       u8 peer_idx);
+                       u16 peer_vhca_id);
 
        int (*create_ns)(struct mlx5_flow_root_namespace *ns);
        int (*destroy_ns)(struct mlx5_flow_root_namespace *ns);
index 4ef04aa..6b069fa 100644 (file)
@@ -889,7 +889,7 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node  *root,
        struct fs_node *iter = list_entry(start, struct fs_node, list);
        struct mlx5_flow_table *ft = NULL;
 
-       if (!root || root->type == FS_TYPE_PRIO_CHAINS)
+       if (!root)
                return NULL;
 
        list_for_each_advance_continue(iter, &root->children, reverse) {
@@ -905,20 +905,42 @@ static struct mlx5_flow_table *find_closest_ft_recursive(struct fs_node  *root,
        return ft;
 }
 
-/* If reverse is false then return the first flow table in next priority of
- * prio in the tree, else return the last flow table in the previous priority
- * of prio in the tree.
+static struct fs_node *find_prio_chains_parent(struct fs_node *parent,
+                                              struct fs_node **child)
+{
+       struct fs_node *node = NULL;
+
+       while (parent && parent->type != FS_TYPE_PRIO_CHAINS) {
+               node = parent;
+               parent = parent->parent;
+       }
+
+       if (child)
+               *child = node;
+
+       return parent;
+}
+
+/* If reverse is false then return the first flow table next to the passed node
+ * in the tree, else return the last flow table before the node in the tree.
+ * If skip is true, skip the flow tables in the same prio_chains prio.
  */
-static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool reverse)
+static struct mlx5_flow_table *find_closest_ft(struct fs_node *node, bool reverse,
+                                              bool skip)
 {
+       struct fs_node *prio_chains_parent = NULL;
        struct mlx5_flow_table *ft = NULL;
        struct fs_node *curr_node;
        struct fs_node *parent;
 
-       parent = prio->node.parent;
-       curr_node = &prio->node;
+       if (skip)
+               prio_chains_parent = find_prio_chains_parent(node, NULL);
+       parent = node->parent;
+       curr_node = node;
        while (!ft && parent) {
-               ft = find_closest_ft_recursive(parent, &curr_node->list, reverse);
+               if (parent != prio_chains_parent)
+                       ft = find_closest_ft_recursive(parent, &curr_node->list,
+                                                      reverse);
                curr_node = parent;
                parent = curr_node->parent;
        }
@@ -926,15 +948,15 @@ static struct mlx5_flow_table *find_closest_ft(struct fs_prio *prio, bool revers
 }
 
 /* Assuming all the tree is locked by mutex chain lock */
-static struct mlx5_flow_table *find_next_chained_ft(struct fs_prio *prio)
+static struct mlx5_flow_table *find_next_chained_ft(struct fs_node *node)
 {
-       return find_closest_ft(prio, false);
+       return find_closest_ft(node, false, true);
 }
 
 /* Assuming all the tree is locked by mutex chain lock */
-static struct mlx5_flow_table *find_prev_chained_ft(struct fs_prio *prio)
+static struct mlx5_flow_table *find_prev_chained_ft(struct fs_node *node)
 {
-       return find_closest_ft(prio, true);
+       return find_closest_ft(node, true, true);
 }
 
 static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
@@ -946,7 +968,7 @@ static struct mlx5_flow_table *find_next_fwd_ft(struct mlx5_flow_table *ft,
        next_ns = flow_act->action & MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_NS;
        fs_get_obj(prio, next_ns ? ft->ns->node.parent : ft->node.parent);
 
-       return find_next_chained_ft(prio);
+       return find_next_chained_ft(&prio->node);
 }
 
 static int connect_fts_in_prio(struct mlx5_core_dev *dev,
@@ -970,21 +992,55 @@ static int connect_fts_in_prio(struct mlx5_core_dev *dev,
        return 0;
 }
 
+static struct mlx5_flow_table *find_closet_ft_prio_chains(struct fs_node *node,
+                                                         struct fs_node *parent,
+                                                         struct fs_node **child,
+                                                         bool reverse)
+{
+       struct mlx5_flow_table *ft;
+
+       ft = find_closest_ft(node, reverse, false);
+
+       if (ft && parent == find_prio_chains_parent(&ft->node, child))
+               return ft;
+
+       return NULL;
+}
+
 /* Connect flow tables from previous priority of prio to ft */
 static int connect_prev_fts(struct mlx5_core_dev *dev,
                            struct mlx5_flow_table *ft,
                            struct fs_prio *prio)
 {
+       struct fs_node *prio_parent, *parent = NULL, *child, *node;
        struct mlx5_flow_table *prev_ft;
+       int err = 0;
+
+       prio_parent = find_prio_chains_parent(&prio->node, &child);
+
+       /* return directly if not under the first sub ns of prio_chains prio */
+       if (prio_parent && !list_is_first(&child->list, &prio_parent->children))
+               return 0;
 
-       prev_ft = find_prev_chained_ft(prio);
-       if (prev_ft) {
+       prev_ft = find_prev_chained_ft(&prio->node);
+       while (prev_ft) {
                struct fs_prio *prev_prio;
 
                fs_get_obj(prev_prio, prev_ft->node.parent);
-               return connect_fts_in_prio(dev, prev_prio, ft);
+               err = connect_fts_in_prio(dev, prev_prio, ft);
+               if (err)
+                       break;
+
+               if (!parent) {
+                       parent = find_prio_chains_parent(&prev_prio->node, &child);
+                       if (!parent)
+                               break;
+               }
+
+               node = child;
+               prev_ft = find_closet_ft_prio_chains(node, parent, &child, true);
        }
-       return 0;
+       return err;
 }
 
 static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
@@ -1123,7 +1179,7 @@ static int connect_flow_table(struct mlx5_core_dev *dev, struct mlx5_flow_table
                if (err)
                        return err;
 
-               next_ft = first_ft ? first_ft : find_next_chained_ft(prio);
+               next_ft = first_ft ? first_ft : find_next_chained_ft(&prio->node);
                err = connect_fwd_rules(dev, ft, next_ft);
                if (err)
                        return err;
@@ -1198,7 +1254,7 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
 
        tree_init_node(&ft->node, del_hw_flow_table, del_sw_flow_table);
        next_ft = unmanaged ? ft_attr->next_ft :
-                             find_next_chained_ft(fs_prio);
+                             find_next_chained_ft(&fs_prio->node);
        ft->def_miss_action = ns->def_miss_action;
        ft->ns = ns;
        err = root->cmds->create_flow_table(root, ft, ft_attr, next_ft);
@@ -2195,13 +2251,20 @@ EXPORT_SYMBOL(mlx5_del_flow_rules);
 /* Assuming prio->node.children(flow tables) is sorted by level */
 static struct mlx5_flow_table *find_next_ft(struct mlx5_flow_table *ft)
 {
+       struct fs_node *prio_parent, *child;
        struct fs_prio *prio;
 
        fs_get_obj(prio, ft->node.parent);
 
        if (!list_is_last(&ft->node.list, &prio->node.children))
                return list_next_entry(ft, node.list);
-       return find_next_chained_ft(prio);
+
+       prio_parent = find_prio_chains_parent(&prio->node, &child);
+
+       if (prio_parent && list_is_first(&child->list, &prio_parent->children))
+               return find_closest_ft(&prio->node, false, false);
+
+       return find_next_chained_ft(&prio->node);
 }
 
 static int update_root_ft_destroy(struct mlx5_flow_table *ft)
@@ -3621,7 +3684,7 @@ void mlx5_destroy_match_definer(struct mlx5_core_dev *dev,
 
 int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
                                 struct mlx5_flow_root_namespace *peer_ns,
-                                u8 peer_idx)
+                                u16 peer_vhca_id)
 {
        if (peer_ns && ns->mode != peer_ns->mode) {
                mlx5_core_err(ns->dev,
@@ -3629,7 +3692,7 @@ int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
                return -EINVAL;
        }
 
-       return ns->cmds->set_peer(ns, peer_ns, peer_idx);
+       return ns->cmds->set_peer(ns, peer_ns, peer_vhca_id);
 }
 
 /* This function should be called only at init stage of the namespace.
index 03e64c4..4aed176 100644 (file)
@@ -303,7 +303,7 @@ const struct mlx5_flow_cmds *mlx5_fs_cmd_get_fw_cmds(void);
 
 int mlx5_flow_namespace_set_peer(struct mlx5_flow_root_namespace *ns,
                                 struct mlx5_flow_root_namespace *peer_ns,
-                                u8 peer_idx);
+                                u16 peer_vhca_id);
 
 int mlx5_flow_namespace_set_mode(struct mlx5_flow_namespace *ns,
                                 enum mlx5_flow_steering_mode mode);
index db9df97..a80ecb6 100644 (file)
@@ -178,7 +178,7 @@ mlx5_chains_create_table(struct mlx5_fs_chains *chains,
        if (!mlx5_chains_ignore_flow_level_supported(chains) ||
            (chain == 0 && prio == 1 && level == 0)) {
                ft_attr.level = chains->fs_base_level;
-               ft_attr.prio = chains->fs_base_prio;
+               ft_attr.prio = chains->fs_base_prio + prio - 1;
                ns = (chains->ns == MLX5_FLOW_NAMESPACE_FDB) ?
                        mlx5_get_fdb_sub_ns(chains->dev, chain) :
                        mlx5_get_flow_namespace(chains->dev, chains->ns);
index 88dbea6..f42abc2 100644 (file)
@@ -1506,6 +1506,7 @@ void mlx5_uninit_one(struct mlx5_core_dev *dev)
        if (!test_bit(MLX5_INTERFACE_STATE_UP, &dev->intf_state)) {
                mlx5_core_warn(dev, "%s: interface is down, NOP\n",
                               __func__);
+               mlx5_devlink_params_unregister(priv_to_devlink(dev));
                mlx5_cleanup_once(dev);
                goto out;
        }
index e739ec6..54bb086 100644 (file)
@@ -2079,7 +2079,7 @@ mlx5dr_action_create_dest_vport(struct mlx5dr_domain *dmn,
 
        peer_vport = vhca_id_valid && mlx5_core_is_pf(dmn->mdev) &&
                (vhca_id != dmn->info.caps.gvmi);
-       vport_dmn = peer_vport ? dmn->peer_dmn[vhca_id] : dmn;
+       vport_dmn = peer_vport ? xa_load(&dmn->peer_dmn_xa, vhca_id) : dmn;
        if (!vport_dmn) {
                mlx5dr_dbg(dmn, "No peer vport domain for given vhca_id\n");
                return NULL;
index 7491911..8c2a34a 100644 (file)
@@ -564,11 +564,12 @@ int mlx5dr_cmd_create_reformat_ctx(struct mlx5_core_dev *mdev,
 
        err = mlx5_cmd_exec(mdev, in, inlen, out, sizeof(out));
        if (err)
-               return err;
+               goto err_free_in;
 
        *reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
-       kvfree(in);
 
+err_free_in:
+       kvfree(in);
        return err;
 }
 
index 75dc85d..3d74109 100644 (file)
@@ -475,6 +475,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
        mutex_init(&dmn->info.rx.mutex);
        mutex_init(&dmn->info.tx.mutex);
        xa_init(&dmn->definers_xa);
+       xa_init(&dmn->peer_dmn_xa);
 
        if (dr_domain_caps_init(mdev, dmn)) {
                mlx5dr_err(dmn, "Failed init domain, no caps\n");
@@ -507,6 +508,7 @@ mlx5dr_domain_create(struct mlx5_core_dev *mdev, enum mlx5dr_domain_type type)
 uninit_caps:
        dr_domain_caps_uninit(dmn);
 def_xa_destroy:
+       xa_destroy(&dmn->peer_dmn_xa);
        xa_destroy(&dmn->definers_xa);
        kfree(dmn);
        return NULL;
@@ -547,6 +549,7 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
        dr_domain_uninit_csum_recalc_fts(dmn);
        dr_domain_uninit_resources(dmn);
        dr_domain_caps_uninit(dmn);
+       xa_destroy(&dmn->peer_dmn_xa);
        xa_destroy(&dmn->definers_xa);
        mutex_destroy(&dmn->info.tx.mutex);
        mutex_destroy(&dmn->info.rx.mutex);
@@ -556,17 +559,21 @@ int mlx5dr_domain_destroy(struct mlx5dr_domain *dmn)
 
 void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
                            struct mlx5dr_domain *peer_dmn,
-                           u8 peer_idx)
+                           u16 peer_vhca_id)
 {
+       struct mlx5dr_domain *peer;
+
        mlx5dr_domain_lock(dmn);
 
-       if (dmn->peer_dmn[peer_idx])
-               refcount_dec(&dmn->peer_dmn[peer_idx]->refcount);
+       peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id);
+       if (peer)
+               refcount_dec(&peer->refcount);
 
-       dmn->peer_dmn[peer_idx] = peer_dmn;
+       WARN_ON(xa_err(xa_store(&dmn->peer_dmn_xa, peer_vhca_id, peer_dmn, GFP_KERNEL)));
 
-       if (dmn->peer_dmn[peer_idx])
-               refcount_inc(&dmn->peer_dmn[peer_idx]->refcount);
+       peer = xa_load(&dmn->peer_dmn_xa, peer_vhca_id);
+       if (peer)
+               refcount_inc(&peer->refcount);
 
        mlx5dr_domain_unlock(dmn);
 }
index 69d7a8f..f708b02 100644 (file)
@@ -1652,17 +1652,18 @@ dr_ste_v0_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
        struct mlx5dr_domain *dmn = sb->dmn;
        struct mlx5dr_domain *vport_dmn;
        u8 *bit_mask = sb->bit_mask;
+       struct mlx5dr_domain *peer;
        bool source_gvmi_set;
 
        DR_STE_SET_TAG(src_gvmi_qp, tag, source_qp, misc, source_sqn);
 
        if (sb->vhca_id_valid) {
+               peer = xa_load(&dmn->peer_dmn_xa, id);
                /* Find port GVMI based on the eswitch_owner_vhca_id */
                if (id == dmn->info.caps.gvmi)
                        vport_dmn = dmn;
-               else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] &&
-                        (id == dmn->peer_dmn[id]->info.caps.gvmi))
-                       vport_dmn = dmn->peer_dmn[id];
+               else if (peer && (id == peer->info.caps.gvmi))
+                       vport_dmn = peer;
                else
                        return -EINVAL;
 
index f4ef0b2..dd856cd 100644 (file)
@@ -1984,16 +1984,17 @@ static int dr_ste_v1_build_src_gvmi_qpn_tag(struct mlx5dr_match_param *value,
        struct mlx5dr_domain *dmn = sb->dmn;
        struct mlx5dr_domain *vport_dmn;
        u8 *bit_mask = sb->bit_mask;
+       struct mlx5dr_domain *peer;
 
        DR_STE_SET_TAG(src_gvmi_qp_v1, tag, source_qp, misc, source_sqn);
 
        if (sb->vhca_id_valid) {
+               peer = xa_load(&dmn->peer_dmn_xa, id);
                /* Find port GVMI based on the eswitch_owner_vhca_id */
                if (id == dmn->info.caps.gvmi)
                        vport_dmn = dmn;
-               else if (id < MLX5_MAX_PORTS && dmn->peer_dmn[id] &&
-                        (id == dmn->peer_dmn[id]->info.caps.gvmi))
-                       vport_dmn = dmn->peer_dmn[id];
+               else if (peer && (id == peer->info.caps.gvmi))
+                       vport_dmn = peer;
                else
                        return -EINVAL;
 
index 1622dbb..6c59de3 100644 (file)
@@ -935,7 +935,6 @@ struct mlx5dr_domain_info {
 };
 
 struct mlx5dr_domain {
-       struct mlx5dr_domain *peer_dmn[MLX5_MAX_PORTS];
        struct mlx5_core_dev *mdev;
        u32 pdn;
        struct mlx5_uars_page *uar;
@@ -956,6 +955,7 @@ struct mlx5dr_domain {
        struct list_head dbg_tbl_list;
        struct mlx5dr_dbg_dump_info dump_info;
        struct xarray definers_xa;
+       struct xarray peer_dmn_xa;
        /* memory management statistics */
        u32 num_buddies[DR_ICM_TYPE_MAX];
 };
index 6aac5f0..feb307f 100644 (file)
@@ -781,14 +781,14 @@ restore_fte:
 
 static int mlx5_cmd_dr_set_peer(struct mlx5_flow_root_namespace *ns,
                                struct mlx5_flow_root_namespace *peer_ns,
-                               u8 peer_idx)
+                               u16 peer_vhca_id)
 {
        struct mlx5dr_domain *peer_domain = NULL;
 
        if (peer_ns)
                peer_domain = peer_ns->fs_dr_domain.dr_domain;
        mlx5dr_domain_set_peer(ns->fs_dr_domain.dr_domain,
-                              peer_domain, peer_idx);
+                              peer_domain, peer_vhca_id);
        return 0;
 }
 
index 24cbb33..89fced8 100644 (file)
@@ -49,7 +49,7 @@ int mlx5dr_domain_sync(struct mlx5dr_domain *domain, u32 flags);
 
 void mlx5dr_domain_set_peer(struct mlx5dr_domain *dmn,
                            struct mlx5dr_domain *peer_dmn,
-                           u8 peer_idx);
+                           u16 peer_vhca_id);
 
 struct mlx5dr_table *
 mlx5dr_table_create(struct mlx5dr_domain *domain, u32 level, u32 flags,
index 8e3894c..83a3ce0 100644 (file)
@@ -368,7 +368,8 @@ static bool ocelot_fdma_receive_skb(struct ocelot *ocelot, struct sk_buff *skb)
        if (unlikely(!ndev))
                return false;
 
-       pskb_trim(skb, skb->len - ETH_FCS_LEN);
+       if (pskb_trim(skb, skb->len - ETH_FCS_LEN))
+               return false;
 
        skb->dev = ndev;
        skb->protocol = eth_type_trans(skb, skb->dev);
index f868235..94d4f94 100644 (file)
@@ -194,6 +194,22 @@ void qed_hw_remove(struct qed_dev *cdev);
 struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn);
 
 /**
+ * qed_ptt_acquire_context(): Allocate a PTT window honoring the context
+ *                           atomicy.
+ *
+ * @p_hwfn: HW device data.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: struct qed_ptt.
+ *
+ * Should be called at the entry point to the driver
+ * (at the beginning of an exported function).
+ */
+struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn,
+                                       bool is_atomic);
+
+/**
  * qed_ptt_release(): Release PTT Window.
  *
  * @p_hwfn: HW device data.
index 3764190..04602ac 100644 (file)
@@ -693,13 +693,14 @@ static void _qed_fcoe_get_pstats(struct qed_hwfn *p_hwfn,
 }
 
 static int qed_fcoe_get_stats(struct qed_hwfn *p_hwfn,
-                             struct qed_fcoe_stats *p_stats)
+                             struct qed_fcoe_stats *p_stats,
+                             bool is_atomic)
 {
        struct qed_ptt *p_ptt;
 
        memset(p_stats, 0, sizeof(*p_stats));
 
-       p_ptt = qed_ptt_acquire(p_hwfn);
+       p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic);
 
        if (!p_ptt) {
                DP_ERR(p_hwfn, "Failed to acquire ptt\n");
@@ -973,19 +974,27 @@ static int qed_fcoe_destroy_conn(struct qed_dev *cdev,
                                        QED_SPQ_MODE_EBLOCK, NULL);
 }
 
+static int qed_fcoe_stats_context(struct qed_dev *cdev,
+                                 struct qed_fcoe_stats *stats,
+                                 bool is_atomic)
+{
+       return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic);
+}
+
 static int qed_fcoe_stats(struct qed_dev *cdev, struct qed_fcoe_stats *stats)
 {
-       return qed_fcoe_get_stats(QED_AFFIN_HWFN(cdev), stats);
+       return qed_fcoe_stats_context(cdev, stats, false);
 }
 
 void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
-                                struct qed_mcp_fcoe_stats *stats)
+                                struct qed_mcp_fcoe_stats *stats,
+                                bool is_atomic)
 {
        struct qed_fcoe_stats proto_stats;
 
        /* Retrieve FW statistics */
        memset(&proto_stats, 0, sizeof(proto_stats));
-       if (qed_fcoe_stats(cdev, &proto_stats)) {
+       if (qed_fcoe_stats_context(cdev, &proto_stats, is_atomic)) {
                DP_VERBOSE(cdev, QED_MSG_STORAGE,
                           "Failed to collect FCoE statistics\n");
                return;
index 19c85ad..214e829 100644 (file)
@@ -28,8 +28,20 @@ int qed_fcoe_alloc(struct qed_hwfn *p_hwfn);
 void qed_fcoe_setup(struct qed_hwfn *p_hwfn);
 
 void qed_fcoe_free(struct qed_hwfn *p_hwfn);
+/**
+ * qed_get_protocol_stats_fcoe(): Fills provided statistics
+ *                               struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: Void.
+ */
 void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
-                                struct qed_mcp_fcoe_stats *stats);
+                                struct qed_mcp_fcoe_stats *stats,
+                                bool is_atomic);
 #else /* CONFIG_QED_FCOE */
 static inline int qed_fcoe_alloc(struct qed_hwfn *p_hwfn)
 {
@@ -40,7 +52,8 @@ static inline void qed_fcoe_setup(struct qed_hwfn *p_hwfn) {}
 static inline void qed_fcoe_free(struct qed_hwfn *p_hwfn) {}
 
 static inline void qed_get_protocol_stats_fcoe(struct qed_dev *cdev,
-                                              struct qed_mcp_fcoe_stats *stats)
+                                              struct qed_mcp_fcoe_stats *stats,
+                                              bool is_atomic)
 {
 }
 #endif /* CONFIG_QED_FCOE */
index 554f30b..6263f84 100644 (file)
 #include "qed_reg_addr.h"
 #include "qed_sriov.h"
 
-#define QED_BAR_ACQUIRE_TIMEOUT 1000
+#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT     1000
+#define QED_BAR_ACQUIRE_TIMEOUT_USLEEP         1000
+#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT     100000
+#define QED_BAR_ACQUIRE_TIMEOUT_UDELAY         10
 
 /* Invalid values */
 #define QED_BAR_INVALID_OFFSET          (cpu_to_le32(-1))
@@ -85,11 +88,21 @@ void qed_ptt_pool_free(struct qed_hwfn *p_hwfn)
 
 struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
 {
+       return qed_ptt_acquire_context(p_hwfn, false);
+}
+
+struct qed_ptt *qed_ptt_acquire_context(struct qed_hwfn *p_hwfn, bool is_atomic)
+{
        struct qed_ptt *p_ptt;
-       unsigned int i;
+       unsigned int i, count;
+
+       if (is_atomic)
+               count = QED_BAR_ACQUIRE_TIMEOUT_UDELAY_CNT;
+       else
+               count = QED_BAR_ACQUIRE_TIMEOUT_USLEEP_CNT;
 
        /* Take the free PTT from the list */
-       for (i = 0; i < QED_BAR_ACQUIRE_TIMEOUT; i++) {
+       for (i = 0; i < count; i++) {
                spin_lock_bh(&p_hwfn->p_ptt_pool->lock);
 
                if (!list_empty(&p_hwfn->p_ptt_pool->free_list)) {
@@ -105,7 +118,12 @@ struct qed_ptt *qed_ptt_acquire(struct qed_hwfn *p_hwfn)
                }
 
                spin_unlock_bh(&p_hwfn->p_ptt_pool->lock);
-               usleep_range(1000, 2000);
+
+               if (is_atomic)
+                       udelay(QED_BAR_ACQUIRE_TIMEOUT_UDELAY);
+               else
+                       usleep_range(QED_BAR_ACQUIRE_TIMEOUT_USLEEP,
+                                    QED_BAR_ACQUIRE_TIMEOUT_USLEEP * 2);
        }
 
        DP_NOTICE(p_hwfn, "PTT acquire timeout - failed to allocate PTT\n");
index 511ab21..980e728 100644 (file)
@@ -999,13 +999,14 @@ static void _qed_iscsi_get_pstats(struct qed_hwfn *p_hwfn,
 }
 
 static int qed_iscsi_get_stats(struct qed_hwfn *p_hwfn,
-                              struct qed_iscsi_stats *stats)
+                              struct qed_iscsi_stats *stats,
+                              bool is_atomic)
 {
        struct qed_ptt *p_ptt;
 
        memset(stats, 0, sizeof(*stats));
 
-       p_ptt = qed_ptt_acquire(p_hwfn);
+       p_ptt = qed_ptt_acquire_context(p_hwfn, is_atomic);
        if (!p_ptt) {
                DP_ERR(p_hwfn, "Failed to acquire ptt\n");
                return -EAGAIN;
@@ -1336,9 +1337,16 @@ static int qed_iscsi_destroy_conn(struct qed_dev *cdev,
                                           QED_SPQ_MODE_EBLOCK, NULL);
 }
 
+static int qed_iscsi_stats_context(struct qed_dev *cdev,
+                                  struct qed_iscsi_stats *stats,
+                                  bool is_atomic)
+{
+       return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats, is_atomic);
+}
+
 static int qed_iscsi_stats(struct qed_dev *cdev, struct qed_iscsi_stats *stats)
 {
-       return qed_iscsi_get_stats(QED_AFFIN_HWFN(cdev), stats);
+       return qed_iscsi_stats_context(cdev, stats, false);
 }
 
 static int qed_iscsi_change_mac(struct qed_dev *cdev,
@@ -1358,13 +1366,14 @@ static int qed_iscsi_change_mac(struct qed_dev *cdev,
 }
 
 void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
-                                 struct qed_mcp_iscsi_stats *stats)
+                                 struct qed_mcp_iscsi_stats *stats,
+                                 bool is_atomic)
 {
        struct qed_iscsi_stats proto_stats;
 
        /* Retrieve FW statistics */
        memset(&proto_stats, 0, sizeof(proto_stats));
-       if (qed_iscsi_stats(cdev, &proto_stats)) {
+       if (qed_iscsi_stats_context(cdev, &proto_stats, is_atomic)) {
                DP_VERBOSE(cdev, QED_MSG_STORAGE,
                           "Failed to collect ISCSI statistics\n");
                return;
index dec2b00..974cb8d 100644 (file)
@@ -39,11 +39,14 @@ void qed_iscsi_free(struct qed_hwfn *p_hwfn);
  *
  * @cdev: Qed dev pointer.
  * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
  *
+ * Context: The function should not sleep in case is_atomic == true.
  * Return: Void.
  */
 void qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
-                                 struct qed_mcp_iscsi_stats *stats);
+                                 struct qed_mcp_iscsi_stats *stats,
+                                 bool is_atomic);
 #else /* IS_ENABLED(CONFIG_QED_ISCSI) */
 static inline int qed_iscsi_alloc(struct qed_hwfn *p_hwfn)
 {
@@ -56,7 +59,8 @@ static inline void qed_iscsi_free(struct qed_hwfn *p_hwfn) {}
 
 static inline void
 qed_get_protocol_stats_iscsi(struct qed_dev *cdev,
-                            struct qed_mcp_iscsi_stats *stats) {}
+                            struct qed_mcp_iscsi_stats *stats,
+                            bool is_atomic) {}
 #endif /* IS_ENABLED(CONFIG_QED_ISCSI) */
 
 #endif
index 7776d3b..970b9aa 100644 (file)
@@ -1863,7 +1863,8 @@ static void __qed_get_vport_stats(struct qed_hwfn *p_hwfn,
 }
 
 static void _qed_get_vport_stats(struct qed_dev *cdev,
-                                struct qed_eth_stats *stats)
+                                struct qed_eth_stats *stats,
+                                bool is_atomic)
 {
        u8 fw_vport = 0;
        int i;
@@ -1872,10 +1873,11 @@ static void _qed_get_vport_stats(struct qed_dev *cdev,
 
        for_each_hwfn(cdev, i) {
                struct qed_hwfn *p_hwfn = &cdev->hwfns[i];
-               struct qed_ptt *p_ptt = IS_PF(cdev) ? qed_ptt_acquire(p_hwfn)
-                                                   :  NULL;
+               struct qed_ptt *p_ptt;
                bool b_get_port_stats;
 
+               p_ptt = IS_PF(cdev) ? qed_ptt_acquire_context(p_hwfn, is_atomic)
+                                   : NULL;
                if (IS_PF(cdev)) {
                        /* The main vport index is relative first */
                        if (qed_fw_vport(p_hwfn, 0, &fw_vport)) {
@@ -1901,6 +1903,13 @@ out:
 
 void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
 {
+       qed_get_vport_stats_context(cdev, stats, false);
+}
+
+void qed_get_vport_stats_context(struct qed_dev *cdev,
+                                struct qed_eth_stats *stats,
+                                bool is_atomic)
+{
        u32 i;
 
        if (!cdev || cdev->recov_in_prog) {
@@ -1908,7 +1917,7 @@ void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats)
                return;
        }
 
-       _qed_get_vport_stats(cdev, stats);
+       _qed_get_vport_stats(cdev, stats, is_atomic);
 
        if (!cdev->reset_stats)
                return;
@@ -1960,7 +1969,7 @@ void qed_reset_vport_stats(struct qed_dev *cdev)
        if (!cdev->reset_stats) {
                DP_INFO(cdev, "Reset stats not allocated\n");
        } else {
-               _qed_get_vport_stats(cdev, cdev->reset_stats);
+               _qed_get_vport_stats(cdev, cdev->reset_stats, false);
                cdev->reset_stats->common.link_change_count = 0;
        }
 }
index a538cf4..2d2f82c 100644 (file)
@@ -249,8 +249,32 @@ qed_sp_eth_rx_queues_update(struct qed_hwfn *p_hwfn,
                            enum spq_mode comp_mode,
                            struct qed_spq_comp_cb *p_comp_data);
 
+/**
+ * qed_get_vport_stats(): Fills provided statistics
+ *                       struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ *
+ * Return: Void.
+ */
 void qed_get_vport_stats(struct qed_dev *cdev, struct qed_eth_stats *stats);
 
+/**
+ * qed_get_vport_stats_context(): Fills provided statistics
+ *                               struct with statistics.
+ *
+ * @cdev: Qed dev pointer.
+ * @stats: Points to struct that will be filled with statistics.
+ * @is_atomic: Hint from the caller - if the func can sleep or not.
+ *
+ * Context: The function should not sleep in case is_atomic == true.
+ * Return: Void.
+ */
+void qed_get_vport_stats_context(struct qed_dev *cdev,
+                                struct qed_eth_stats *stats,
+                                bool is_atomic);
+
 void qed_reset_vport_stats(struct qed_dev *cdev);
 
 /**
index f5af833..c278f88 100644 (file)
@@ -3092,7 +3092,7 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
 
        switch (type) {
        case QED_MCP_LAN_STATS:
-               qed_get_vport_stats(cdev, &eth_stats);
+               qed_get_vport_stats_context(cdev, &eth_stats, true);
                stats->lan_stats.ucast_rx_pkts =
                                        eth_stats.common.rx_ucast_pkts;
                stats->lan_stats.ucast_tx_pkts =
@@ -3100,10 +3100,10 @@ void qed_get_protocol_stats(struct qed_dev *cdev,
                stats->lan_stats.fcs_err = -1;
                break;
        case QED_MCP_FCOE_STATS:
-               qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats);
+               qed_get_protocol_stats_fcoe(cdev, &stats->fcoe_stats, true);
                break;
        case QED_MCP_ISCSI_STATS:
-               qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats);
+               qed_get_protocol_stats_iscsi(cdev, &stats->iscsi_stats, true);
                break;
        default:
                DP_VERBOSE(cdev, QED_MSG_SP,
index 0d80447..d5c688a 100644 (file)
@@ -1260,8 +1260,11 @@ static int emac_tso_csum(struct emac_adapter *adpt,
                if (skb->protocol == htons(ETH_P_IP)) {
                        u32 pkt_len = ((unsigned char *)ip_hdr(skb) - skb->data)
                                       + ntohs(ip_hdr(skb)->tot_len);
-                       if (skb->len > pkt_len)
-                               pskb_trim(skb, pkt_len);
+                       if (skb->len > pkt_len) {
+                               ret = pskb_trim(skb, pkt_len);
+                               if (unlikely(ret))
+                                       return ret;
+                       }
                }
 
                hdr_len = skb_tcp_all_headers(skb);
index 9445f04..5eb50b2 100644 (file)
@@ -623,6 +623,7 @@ struct rtl8169_private {
        int cfg9346_usage_count;
 
        unsigned supports_gmii:1;
+       unsigned aspm_manageable:1;
        dma_addr_t counters_phys_addr;
        struct rtl8169_counters *counters;
        struct rtl8169_tc_offsets tc_offset;
@@ -2746,7 +2747,15 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
        if (tp->mac_version < RTL_GIGA_MAC_VER_32)
                return;
 
-       if (enable) {
+       /* Don't enable ASPM in the chip if OS can't control ASPM */
+       if (enable && tp->aspm_manageable) {
+               /* On these chip versions ASPM can even harm
+                * bus communication of other PCI devices.
+                */
+               if (tp->mac_version == RTL_GIGA_MAC_VER_42 ||
+                   tp->mac_version == RTL_GIGA_MAC_VER_43)
+                       return;
+
                rtl_mod_config5(tp, 0, ASPM_en);
                rtl_mod_config2(tp, 0, ClkReqEn);
 
@@ -4514,10 +4523,6 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
        }
 
        if (napi_schedule_prep(&tp->napi)) {
-               rtl_unlock_config_regs(tp);
-               rtl_hw_aspm_clkreq_enable(tp, false);
-               rtl_lock_config_regs(tp);
-
                rtl_irq_disable(tp);
                __napi_schedule(&tp->napi);
        }
@@ -4577,14 +4582,9 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
 
        work_done = rtl_rx(dev, tp, budget);
 
-       if (work_done < budget && napi_complete_done(napi, work_done)) {
+       if (work_done < budget && napi_complete_done(napi, work_done))
                rtl_irq_enable(tp);
 
-               rtl_unlock_config_regs(tp);
-               rtl_hw_aspm_clkreq_enable(tp, true);
-               rtl_lock_config_regs(tp);
-       }
-
        return work_done;
 }
 
@@ -5158,6 +5158,16 @@ done:
        rtl_rar_set(tp, mac_addr);
 }
 
+/* register is set if system vendor successfully tested ASPM 1.2 */
+static bool rtl_aspm_is_safe(struct rtl8169_private *tp)
+{
+       if (tp->mac_version >= RTL_GIGA_MAC_VER_61 &&
+           r8168_mac_ocp_read(tp, 0xc0b2) & 0xf)
+               return true;
+
+       return false;
+}
+
 static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct rtl8169_private *tp;
@@ -5227,6 +5237,19 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                                     xid);
        tp->mac_version = chipset;
 
+       /* Disable ASPM L1 as that cause random device stop working
+        * problems as well as full system hangs for some PCIe devices users.
+        * Chips from RTL8168h partially have issues with L1.2, but seem
+        * to work fine with L1 and L1.1.
+        */
+       if (rtl_aspm_is_safe(tp))
+               rc = 0;
+       else if (tp->mac_version >= RTL_GIGA_MAC_VER_46)
+               rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1_2);
+       else
+               rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L1);
+       tp->aspm_manageable = !rc;
+
        tp->dash_type = rtl_check_dash(tp);
 
        tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;
index 9e5ce2a..cf1d67b 100644 (file)
  */
 struct ef4_loopback_payload {
        char pad[2]; /* Ensures ip is 4-byte aligned */
-       struct ethhdr header;
-       struct iphdr ip;
-       struct udphdr udp;
-       __be16 iteration;
-       char msg[64];
+       struct_group_attr(packet, __packed,
+               struct ethhdr header;
+               struct iphdr ip;
+               struct udphdr udp;
+               __be16 iteration;
+               char msg[64];
+       );
 } __packed __aligned(4);
-#define EF4_LOOPBACK_PAYLOAD_LEN       (sizeof(struct ef4_loopback_payload) - \
-                                        offsetof(struct ef4_loopback_payload, \
-                                                 header))
+#define EF4_LOOPBACK_PAYLOAD_LEN       \
+               sizeof_field(struct ef4_loopback_payload, packet)
 
 /* Loopback test source MAC address */
 static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -299,7 +300,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
 
        payload = &state->payload;
 
-       memcpy(&received.header, buf_ptr,
+       memcpy(&received.packet, buf_ptr,
               min_t(int, pkt_len, EF4_LOOPBACK_PAYLOAD_LEN));
        received.ip.saddr = payload->ip.saddr;
        if (state->offload_csum)
@@ -370,7 +371,7 @@ void ef4_loopback_rx_packet(struct ef4_nic *efx,
                               buf_ptr, pkt_len, 0);
                netif_err(efx, drv, efx->net_dev, "expected packet:\n");
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
-                              &state->payload.header, EF4_LOOPBACK_PAYLOAD_LEN,
+                              &state->payload.packet, EF4_LOOPBACK_PAYLOAD_LEN,
                               0);
        }
 #endif
@@ -440,6 +441,8 @@ static int ef4_begin_loopback(struct ef4_tx_queue *tx_queue)
                payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
                /* Strip off the leading padding */
                skb_pull(skb, offsetof(struct ef4_loopback_payload, header));
+               /* Strip off the trailing padding */
+               skb_trim(skb, EF4_LOOPBACK_PAYLOAD_LEN);
 
                /* Ensure everything we've written is visible to the
                 * interrupt handler. */
index 96d856b..19a0b85 100644 (file)
  */
 struct efx_loopback_payload {
        char pad[2]; /* Ensures ip is 4-byte aligned */
-       struct ethhdr header;
-       struct iphdr ip;
-       struct udphdr udp;
-       __be16 iteration;
-       char msg[64];
+       struct_group_attr(packet, __packed,
+               struct ethhdr header;
+               struct iphdr ip;
+               struct udphdr udp;
+               __be16 iteration;
+               char msg[64];
+       );
 } __packed __aligned(4);
-#define EFX_LOOPBACK_PAYLOAD_LEN       (sizeof(struct efx_loopback_payload) - \
-                                        offsetof(struct efx_loopback_payload, \
-                                                 header))
+#define EFX_LOOPBACK_PAYLOAD_LEN       \
+               sizeof_field(struct efx_loopback_payload, packet)
 
 /* Loopback test source MAC address */
 static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -297,7 +298,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
 
        payload = &state->payload;
 
-       memcpy(&received.header, buf_ptr,
+       memcpy(&received.packet, buf_ptr,
               min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN));
        received.ip.saddr = payload->ip.saddr;
        if (state->offload_csum)
@@ -368,7 +369,7 @@ void efx_loopback_rx_packet(struct efx_nic *efx,
                               buf_ptr, pkt_len, 0);
                netif_err(efx, drv, efx->net_dev, "expected packet:\n");
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
-                              &state->payload.header, EFX_LOOPBACK_PAYLOAD_LEN,
+                              &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN,
                               0);
        }
 #endif
@@ -438,6 +439,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
                payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
                /* Strip off the leading padding */
                skb_pull(skb, offsetof(struct efx_loopback_payload, header));
+               /* Strip off the trailing padding */
+               skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN);
 
                /* Ensure everything we've written is visible to the
                 * interrupt handler. */
index 111ac17..b55fd33 100644 (file)
  */
 struct efx_loopback_payload {
        char pad[2]; /* Ensures ip is 4-byte aligned */
-       struct ethhdr header;
-       struct iphdr ip;
-       struct udphdr udp;
-       __be16 iteration;
-       char msg[64];
+       struct_group_attr(packet, __packed,
+               struct ethhdr header;
+               struct iphdr ip;
+               struct udphdr udp;
+               __be16 iteration;
+               char msg[64];
+       );
 } __packed __aligned(4);
-#define EFX_LOOPBACK_PAYLOAD_LEN       (sizeof(struct efx_loopback_payload) - \
-                                        offsetof(struct efx_loopback_payload, \
-                                                 header))
+#define EFX_LOOPBACK_PAYLOAD_LEN       \
+               sizeof_field(struct efx_loopback_payload, packet)
 
 /* Loopback test source MAC address */
 static const u8 payload_source[ETH_ALEN] __aligned(2) = {
@@ -297,7 +298,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
 
        payload = &state->payload;
 
-       memcpy(&received.header, buf_ptr,
+       memcpy(&received.packet, buf_ptr,
               min_t(int, pkt_len, EFX_LOOPBACK_PAYLOAD_LEN));
        received.ip.saddr = payload->ip.saddr;
        if (state->offload_csum)
@@ -368,7 +369,7 @@ void efx_siena_loopback_rx_packet(struct efx_nic *efx,
                               buf_ptr, pkt_len, 0);
                netif_err(efx, drv, efx->net_dev, "expected packet:\n");
                print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1,
-                              &state->payload.header, EFX_LOOPBACK_PAYLOAD_LEN,
+                              &state->payload.packet, EFX_LOOPBACK_PAYLOAD_LEN,
                               0);
        }
 #endif
@@ -438,6 +439,8 @@ static int efx_begin_loopback(struct efx_tx_queue *tx_queue)
                payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2));
                /* Strip off the leading padding */
                skb_pull(skb, offsetof(struct efx_loopback_payload, header));
+               /* Strip off the trailing padding */
+               skb_trim(skb, EFX_LOOPBACK_PAYLOAD_LEN);
 
                /* Ensure everything we've written is visible to the
                 * interrupt handler. */
index 2d7347b..0dcd6a5 100644 (file)
@@ -1851,6 +1851,17 @@ static int netsec_of_probe(struct platform_device *pdev,
                return err;
        }
 
+       /*
+        * SynQuacer is physically configured with TX and RX delays
+        * but the standard firmware claimed otherwise for a long
+        * time, ignore it.
+        */
+       if (of_machine_is_compatible("socionext,developer-box") &&
+           priv->phy_interface != PHY_INTERFACE_MODE_RGMII_ID) {
+               dev_warn(&pdev->dev, "Outdated firmware reports incorrect PHY mode, overriding\n");
+               priv->phy_interface = PHY_INTERFACE_MODE_RGMII_ID;
+       }
+
        priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
        if (!priv->phy_np) {
                dev_err(&pdev->dev, "missing required property 'phy-handle'\n");
index f8367c5..fbb0ccf 100644 (file)
@@ -234,7 +234,8 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
        res.addr = mgbe->regs;
        res.irq = irq;
 
-       mgbe->clks = devm_kzalloc(&pdev->dev, sizeof(*mgbe->clks), GFP_KERNEL);
+       mgbe->clks = devm_kcalloc(&pdev->dev, ARRAY_SIZE(mgbe_clks),
+                                 sizeof(*mgbe->clks), GFP_KERNEL);
        if (!mgbe->clks)
                return -ENOMEM;
 
index df41eac..03ceb6a 100644 (file)
@@ -240,13 +240,15 @@ void stmmac_dwmac4_set_mac_addr(void __iomem *ioaddr, const u8 addr[6],
 void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable)
 {
        u32 value = readl(ioaddr + GMAC_CONFIG);
+       u32 old_val = value;
 
        if (enable)
                value |= GMAC_CONFIG_RE | GMAC_CONFIG_TE;
        else
                value &= ~(GMAC_CONFIG_TE | GMAC_CONFIG_RE);
 
-       writel(value, ioaddr + GMAC_CONFIG);
+       if (value != old_val)
+               writel(value, ioaddr + GMAC_CONFIG);
 }
 
 void stmmac_dwmac4_get_mac_addr(void __iomem *ioaddr, unsigned char *addr,
index 0c5e783..64bf22c 100644 (file)
@@ -106,23 +106,37 @@ struct cpsw_ale_dev_id {
 
 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
 {
-       int idx;
+       int idx, idx2;
+       u32 hi_val = 0;
 
        idx    = start / 32;
+       idx2 = (start + bits - 1) / 32;
+       /* Check if bits to be fetched exceed a word */
+       if (idx != idx2) {
+               idx2 = 2 - idx2; /* flip */
+               hi_val = ale_entry[idx2] << ((idx2 * 32) - start);
+       }
        start -= idx * 32;
        idx    = 2 - idx; /* flip */
-       return (ale_entry[idx] >> start) & BITMASK(bits);
+       return (hi_val + (ale_entry[idx] >> start)) & BITMASK(bits);
 }
 
 static inline void cpsw_ale_set_field(u32 *ale_entry, u32 start, u32 bits,
                                      u32 value)
 {
-       int idx;
+       int idx, idx2;
 
        value &= BITMASK(bits);
-       idx    = start / 32;
+       idx = start / 32;
+       idx2 = (start + bits - 1) / 32;
+       /* Check if bits to be set exceed a word */
+       if (idx != idx2) {
+               idx2 = 2 - idx2; /* flip */
+               ale_entry[idx2] &= ~(BITMASK(bits + start - (idx2 * 32)));
+               ale_entry[idx2] |= (value >> ((idx2 * 32) - start));
+       }
        start -= idx * 32;
-       idx    = 2 - idx; /* flip */
+       idx = 2 - idx; /* flip */
        ale_entry[idx] &= ~(BITMASK(bits) << start);
        ale_entry[idx] |=  (value << start);
 }
index 39a9aee..6321178 100644 (file)
@@ -1511,7 +1511,6 @@ static void wx_configure_rx(struct wx *wx)
        psrtype = WX_RDB_PL_CFG_L4HDR |
                  WX_RDB_PL_CFG_L3HDR |
                  WX_RDB_PL_CFG_L2HDR |
-                 WX_RDB_PL_CFG_TUN_TUNHDR |
                  WX_RDB_PL_CFG_TUN_TUNHDR;
        wr32(wx, WX_RDB_PL_CFG(0), psrtype);
 
index e0ac1bc..49f3033 100644 (file)
@@ -1567,12 +1567,16 @@ static int temac_probe(struct platform_device *pdev)
        }
 
        /* Error handle returned DMA RX and TX interrupts */
-       if (lp->rx_irq < 0)
-               return dev_err_probe(&pdev->dev, lp->rx_irq,
+       if (lp->rx_irq <= 0) {
+               rc = lp->rx_irq ?: -EINVAL;
+               return dev_err_probe(&pdev->dev, rc,
                                     "could not get DMA RX irq\n");
-       if (lp->tx_irq < 0)
-               return dev_err_probe(&pdev->dev, lp->tx_irq,
+       }
+       if (lp->tx_irq <= 0) {
+               rc = lp->tx_irq ?: -EINVAL;
+               return dev_err_probe(&pdev->dev, rc,
                                     "could not get DMA TX irq\n");
+       }
 
        if (temac_np) {
                /* Retrieve the MAC address */
index f0529c3..7b637bb 100644 (file)
@@ -273,16 +273,15 @@ static int ipa_filter_reset(struct ipa *ipa, bool modem)
        if (ret)
                return ret;
 
-       ret = ipa_filter_reset_table(ipa, true, false, modem);
-       if (ret)
+       ret = ipa_filter_reset_table(ipa, false, true, modem);
+       if (ret || !ipa_table_hash_support(ipa))
                return ret;
 
-       ret = ipa_filter_reset_table(ipa, false, true, modem);
+       ret = ipa_filter_reset_table(ipa, true, false, modem);
        if (ret)
                return ret;
-       ret = ipa_filter_reset_table(ipa, true, true, modem);
 
-       return ret;
+       return ipa_filter_reset_table(ipa, true, true, modem);
 }
 
 /* The AP routes and modem routes are each contiguous within the
@@ -291,12 +290,13 @@ static int ipa_filter_reset(struct ipa *ipa, bool modem)
  * */
 static int ipa_route_reset(struct ipa *ipa, bool modem)
 {
+       bool hash_support = ipa_table_hash_support(ipa);
        u32 modem_route_count = ipa->modem_route_count;
        struct gsi_trans *trans;
        u16 first;
        u16 count;
 
-       trans = ipa_cmd_trans_alloc(ipa, 4);
+       trans = ipa_cmd_trans_alloc(ipa, hash_support ? 4 : 2);
        if (!trans) {
                dev_err(&ipa->pdev->dev,
                        "no transaction for %s route reset\n",
@@ -313,10 +313,12 @@ static int ipa_route_reset(struct ipa *ipa, bool modem)
        }
 
        ipa_table_reset_add(trans, false, false, false, first, count);
-       ipa_table_reset_add(trans, false, true, false, first, count);
-
        ipa_table_reset_add(trans, false, false, true, first, count);
-       ipa_table_reset_add(trans, false, true, true, first, count);
+
+       if (hash_support) {
+               ipa_table_reset_add(trans, false, true, false, first, count);
+               ipa_table_reset_add(trans, false, true, true, first, count);
+       }
 
        gsi_trans_commit_wait(trans);
 
index 4a53deb..ed90816 100644 (file)
@@ -1746,6 +1746,7 @@ static const struct nla_policy macvlan_policy[IFLA_MACVLAN_MAX + 1] = {
        [IFLA_MACVLAN_MACADDR_COUNT] = { .type = NLA_U32 },
        [IFLA_MACVLAN_BC_QUEUE_LEN] = { .type = NLA_U32 },
        [IFLA_MACVLAN_BC_QUEUE_LEN_USED] = { .type = NLA_REJECT },
+       [IFLA_MACVLAN_BC_CUTOFF] = { .type = NLA_S32 },
 };
 
 int macvlan_link_register(struct rtnl_link_ops *ops)
index 55d9d7a..d4bb90d 100644 (file)
@@ -328,6 +328,13 @@ static int mv3310_power_up(struct phy_device *phydev)
        ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
                                 MV_V2_PORT_CTRL_PWRDOWN);
 
+       /* Sometimes, the power down bit doesn't clear immediately, and
+        * a read of this register causes the bit not to clear. Delay
+        * 100us to allow the PHY to come out of power down mode before
+        * the next access.
+        */
+       udelay(100);
+
        if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
            priv->firmware_ver < 0x00030000)
                return ret;
index 0c2014a..61921d4 100644 (file)
@@ -3451,23 +3451,30 @@ static int __init phy_init(void)
 {
        int rc;
 
+       ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
+
        rc = mdio_bus_init();
        if (rc)
-               return rc;
+               goto err_ethtool_phy_ops;
 
-       ethtool_set_ethtool_phy_ops(&phy_ethtool_phy_ops);
        features_init();
 
        rc = phy_driver_register(&genphy_c45_driver, THIS_MODULE);
        if (rc)
-               goto err_c45;
+               goto err_mdio_bus;
 
        rc = phy_driver_register(&genphy_driver, THIS_MODULE);
-       if (rc) {
-               phy_driver_unregister(&genphy_c45_driver);
+       if (rc)
+               goto err_c45;
+
+       return 0;
+
 err_c45:
-               mdio_bus_exit();
-       }
+       phy_driver_unregister(&genphy_c45_driver);
+err_mdio_bus:
+       mdio_bus_exit();
+err_ethtool_phy_ops:
+       ethtool_set_ethtool_phy_ops(NULL);
 
        return rc;
 }
index 9137fb8..49d1d6a 100644 (file)
@@ -534,7 +534,7 @@ static int tap_open(struct inode *inode, struct file *file)
        q->sock.state = SS_CONNECTED;
        q->sock.file = file;
        q->sock.ops = &tap_socket_ops;
-       sock_init_data_uid(&q->sock, &q->sk, inode->i_uid);
+       sock_init_data_uid(&q->sock, &q->sk, current_fsuid());
        q->sk.sk_write_space = tap_sock_write_space;
        q->sk.sk_destruct = tap_sock_destruct;
        q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
index 555b0b1..d3dc225 100644 (file)
@@ -2135,6 +2135,15 @@ static void team_setup_by_port(struct net_device *dev,
        dev->mtu = port_dev->mtu;
        memcpy(dev->broadcast, port_dev->broadcast, port_dev->addr_len);
        eth_hw_addr_inherit(dev, port_dev);
+
+       if (port_dev->flags & IFF_POINTOPOINT) {
+               dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+               dev->flags |= (IFF_POINTOPOINT | IFF_NOARP);
+       } else if ((port_dev->flags & (IFF_BROADCAST | IFF_MULTICAST)) ==
+                   (IFF_BROADCAST | IFF_MULTICAST)) {
+               dev->flags |= (IFF_BROADCAST | IFF_MULTICAST);
+               dev->flags &= ~(IFF_POINTOPOINT | IFF_NOARP);
+       }
 }
 
 static int team_dev_type_check_change(struct net_device *dev,
index d75456a..25f0191 100644 (file)
@@ -3469,7 +3469,7 @@ static int tun_chr_open(struct inode *inode, struct file * file)
        tfile->socket.file = file;
        tfile->socket.ops = &tun_socket_ops;
 
-       sock_init_data_uid(&tfile->socket, &tfile->sk, inode->i_uid);
+       sock_init_data_uid(&tfile->socket, &tfile->sk, current_fsuid());
 
        tfile->sk.sk_write_space = tun_sock_write_space;
        tfile->sk.sk_sndbuf = INT_MAX;
index c00a89b..6d61052 100644 (file)
@@ -618,6 +618,13 @@ static const struct usb_device_id  products[] = {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                          | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
+       .idProduct              = 0x8005,   /* A-300 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info        = 0,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
        .idProduct              = 0x8006,       /* B-500/SL-5600 */
        ZAURUS_MASTER_INTERFACE,
        .driver_info            = 0,
@@ -625,11 +632,25 @@ static const struct usb_device_id products[] = {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                          | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
+       .idProduct              = 0x8006,   /* B-500/SL-5600 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info        = 0,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
        .idProduct              = 0x8007,       /* C-700 */
        ZAURUS_MASTER_INTERFACE,
        .driver_info            = 0,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
+       .idProduct              = 0x8007,   /* C-700 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info        = 0,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                 | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
        .idProduct              = 0x9031,       /* C-750 C-760 */
index c458c03..59cde06 100644 (file)
@@ -4224,8 +4224,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
        if (!dev)
                return;
 
-       set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
-
        netif_napi_del(&dev->napi);
 
        udev = interface_to_usbdev(intf);
@@ -4233,6 +4231,8 @@ static void lan78xx_disconnect(struct usb_interface *intf)
 
        unregister_netdev(net);
 
+       timer_shutdown_sync(&dev->stat_monitor);
+       set_bit(EVENT_DEV_DISCONNECT, &dev->flags);
        cancel_delayed_work_sync(&dev->wq);
 
        phydev = net->phydev;
@@ -4247,9 +4247,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
 
        usb_scuttle_anchored_urbs(&dev->deferred);
 
-       if (timer_pending(&dev->stat_monitor))
-               del_timer_sync(&dev->stat_monitor);
-
        lan78xx_unbind(dev, intf);
 
        lan78xx_free_tx_resources(dev);
index 417f7ea..344af3c 100644 (file)
@@ -1423,6 +1423,7 @@ static const struct usb_device_id products[] = {
        {QMI_QUIRK_SET_DTR(0x2c7c, 0x0191, 4)}, /* Quectel EG91 */
        {QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */
        {QMI_FIXED_INTF(0x2c7c, 0x0296, 4)},    /* Quectel BG96 */
+       {QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */
        {QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */
        {QMI_FIXED_INTF(0x0489, 0xe0b4, 0)},    /* Foxconn T77W968 LTE */
        {QMI_FIXED_INTF(0x0489, 0xe0b5, 0)},    /* Foxconn T77W968 LTE with eSIM support*/
index 283ffdd..2d14b0d 100644 (file)
@@ -1775,6 +1775,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
        } else if (!info->in || !info->out)
                status = usbnet_get_endpoints (dev, udev);
        else {
+               u8 ep_addrs[3] = {
+                       info->in + USB_DIR_IN, info->out + USB_DIR_OUT, 0
+               };
+
                dev->in = usb_rcvbulkpipe (xdev, info->in);
                dev->out = usb_sndbulkpipe (xdev, info->out);
                if (!(info->flags & FLAG_NO_SETINT))
@@ -1784,6 +1788,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
                else
                        status = 0;
 
+               if (status == 0 && !usb_check_bulk_endpoints(udev, ep_addrs))
+                       status = -EINVAL;
        }
        if (status >= 0 && dev->status)
                status = init_status (dev, udev);
index 7984f21..df3617c 100644 (file)
@@ -289,11 +289,25 @@ static const struct usb_device_id products [] = {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                          | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
+       .idProduct              = 0x8005,       /* A-300 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
        .idProduct              = 0x8006,       /* B-500/SL-5600 */
        ZAURUS_MASTER_INTERFACE,
        .driver_info = ZAURUS_PXA_INFO,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
+       .idProduct              = 0x8006,       /* B-500/SL-5600 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                  | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
        .idProduct              = 0x8007,       /* C-700 */
@@ -301,6 +315,13 @@ static const struct usb_device_id  products [] = {
        .driver_info = ZAURUS_PXA_INFO,
 }, {
        .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
+                         | USB_DEVICE_ID_MATCH_DEVICE,
+       .idVendor               = 0x04DD,
+       .idProduct              = 0x8007,       /* C-700 */
+       ZAURUS_FAKE_INTERFACE,
+       .driver_info = (unsigned long)&bogus_mdlm_info,
+}, {
+       .match_flags    =   USB_DEVICE_ID_MATCH_INT_INFO
                 | USB_DEVICE_ID_MATCH_DEVICE,
        .idVendor               = 0x04DD,
        .idProduct              = 0x9031,       /* C-750 C-760 */
index 0db14f6..1270c8d 100644 (file)
@@ -4219,6 +4219,8 @@ static int virtnet_probe(struct virtio_device *vdev)
        if (vi->has_rss || vi->has_rss_hash_report)
                virtnet_init_default_rss(vi);
 
+       _virtnet_set_queues(vi, vi->curr_queue_pairs);
+
        /* serialize netdev register + virtio_device_ready() with ndo_open() */
        rtnl_lock();
 
@@ -4257,8 +4259,6 @@ static int virtnet_probe(struct virtio_device *vdev)
                goto free_unregister_netdev;
        }
 
-       virtnet_set_queues(vi, vi->curr_queue_pairs);
-
        /* Assume link up if device can't report link status,
           otherwise get link status from config. */
        netif_carrier_off(dev);
index bdb3a76..6043e63 100644 (file)
@@ -664,7 +664,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
        skb->protocol = htons(ETH_P_IPV6);
        skb->dev = dev;
 
-       rcu_read_lock_bh();
+       rcu_read_lock();
        nexthop = rt6_nexthop((struct rt6_info *)dst, &ipv6_hdr(skb)->daddr);
        neigh = __ipv6_neigh_lookup_noref(dst->dev, nexthop);
        if (unlikely(!neigh))
@@ -672,10 +672,10 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
        if (!IS_ERR(neigh)) {
                sock_confirm_neigh(skb, neigh);
                ret = neigh_output(neigh, skb, false);
-               rcu_read_unlock_bh();
+               rcu_read_unlock();
                return ret;
        }
-       rcu_read_unlock_bh();
+       rcu_read_unlock();
 
        IP6_INC_STATS(dev_net(dst->dev),
                      ip6_dst_idev(dst), IPSTATS_MIB_OUTNOROUTES);
@@ -889,7 +889,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
                }
        }
 
-       rcu_read_lock_bh();
+       rcu_read_lock();
 
        neigh = ip_neigh_for_gw(rt, skb, &is_v6gw);
        if (!IS_ERR(neigh)) {
@@ -898,11 +898,11 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
                sock_confirm_neigh(skb, neigh);
                /* if crossing protocols, can not use the cached header */
                ret = neigh_output(neigh, skb, is_v6gw);
-               rcu_read_unlock_bh();
+               rcu_read_unlock();
                return ret;
        }
 
-       rcu_read_unlock_bh();
+       rcu_read_unlock();
        vrf_tx_error(skb->dev, skb);
        return -EINVAL;
 }
index 7874454..c9a9373 100644 (file)
@@ -623,6 +623,32 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
        return 1;
 }
 
+static bool vxlan_parse_gpe_proto(struct vxlanhdr *hdr, __be16 *protocol)
+{
+       struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
+
+       /* Need to have Next Protocol set for interfaces in GPE mode. */
+       if (!gpe->np_applied)
+               return false;
+       /* "The initial version is 0. If a receiver does not support the
+        * version indicated it MUST drop the packet.
+        */
+       if (gpe->version != 0)
+               return false;
+       /* "When the O bit is set to 1, the packet is an OAM packet and OAM
+        * processing MUST occur." However, we don't implement OAM
+        * processing, thus drop the packet.
+        */
+       if (gpe->oam_flag)
+               return false;
+
+       *protocol = tun_p_to_eth_p(gpe->next_protocol);
+       if (!*protocol)
+               return false;
+
+       return true;
+}
+
 static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
                                          unsigned int off,
                                          struct vxlanhdr *vh, size_t hdrlen,
@@ -649,26 +675,24 @@ static struct vxlanhdr *vxlan_gro_remcsum(struct sk_buff *skb,
        return vh;
 }
 
-static struct sk_buff *vxlan_gro_receive(struct sock *sk,
-                                        struct list_head *head,
-                                        struct sk_buff *skb)
+static struct vxlanhdr *vxlan_gro_prepare_receive(struct sock *sk,
+                                                 struct list_head *head,
+                                                 struct sk_buff *skb,
+                                                 struct gro_remcsum *grc)
 {
-       struct sk_buff *pp = NULL;
        struct sk_buff *p;
        struct vxlanhdr *vh, *vh2;
        unsigned int hlen, off_vx;
-       int flush = 1;
        struct vxlan_sock *vs = rcu_dereference_sk_user_data(sk);
        __be32 flags;
-       struct gro_remcsum grc;
 
-       skb_gro_remcsum_init(&grc);
+       skb_gro_remcsum_init(grc);
 
        off_vx = skb_gro_offset(skb);
        hlen = off_vx + sizeof(*vh);
        vh = skb_gro_header(skb, hlen, off_vx);
        if (unlikely(!vh))
-               goto out;
+               return NULL;
 
        skb_gro_postpull_rcsum(skb, vh, sizeof(struct vxlanhdr));
 
@@ -676,12 +700,12 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
 
        if ((flags & VXLAN_HF_RCO) && (vs->flags & VXLAN_F_REMCSUM_RX)) {
                vh = vxlan_gro_remcsum(skb, off_vx, vh, sizeof(struct vxlanhdr),
-                                      vh->vx_vni, &grc,
+                                      vh->vx_vni, grc,
                                       !!(vs->flags &
                                          VXLAN_F_REMCSUM_NOPARTIAL));
 
                if (!vh)
-                       goto out;
+                       return NULL;
        }
 
        skb_gro_pull(skb, sizeof(struct vxlanhdr)); /* pull vxlan header */
@@ -698,12 +722,48 @@ static struct sk_buff *vxlan_gro_receive(struct sock *sk,
                }
        }
 
-       pp = call_gro_receive(eth_gro_receive, head, skb);
-       flush = 0;
+       return vh;
+}
 
-out:
+static struct sk_buff *vxlan_gro_receive(struct sock *sk,
+                                        struct list_head *head,
+                                        struct sk_buff *skb)
+{
+       struct sk_buff *pp = NULL;
+       struct gro_remcsum grc;
+       int flush = 1;
+
+       if (vxlan_gro_prepare_receive(sk, head, skb, &grc)) {
+               pp = call_gro_receive(eth_gro_receive, head, skb);
+               flush = 0;
+       }
        skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
+       return pp;
+}
+
+static struct sk_buff *vxlan_gpe_gro_receive(struct sock *sk,
+                                            struct list_head *head,
+                                            struct sk_buff *skb)
+{
+       const struct packet_offload *ptype;
+       struct sk_buff *pp = NULL;
+       struct gro_remcsum grc;
+       struct vxlanhdr *vh;
+       __be16 protocol;
+       int flush = 1;
 
+       vh = vxlan_gro_prepare_receive(sk, head, skb, &grc);
+       if (vh) {
+               if (!vxlan_parse_gpe_proto(vh, &protocol))
+                       goto out;
+               ptype = gro_find_receive_by_type(protocol);
+               if (!ptype)
+                       goto out;
+               pp = call_gro_receive(ptype->callbacks.gro_receive, head, skb);
+               flush = 0;
+       }
+out:
+       skb_gro_flush_final_remcsum(skb, pp, flush, &grc);
        return pp;
 }
 
@@ -715,6 +775,21 @@ static int vxlan_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
        return eth_gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
 }
 
+static int vxlan_gpe_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff)
+{
+       struct vxlanhdr *vh = (struct vxlanhdr *)(skb->data + nhoff);
+       const struct packet_offload *ptype;
+       int err = -ENOSYS;
+       __be16 protocol;
+
+       if (!vxlan_parse_gpe_proto(vh, &protocol))
+               return err;
+       ptype = gro_find_complete_by_type(protocol);
+       if (ptype)
+               err = ptype->callbacks.gro_complete(skb, nhoff + sizeof(struct vxlanhdr));
+       return err;
+}
+
 static struct vxlan_fdb *vxlan_fdb_alloc(struct vxlan_dev *vxlan, const u8 *mac,
                                         __u16 state, __be32 src_vni,
                                         __u16 ndm_flags)
@@ -1525,35 +1600,6 @@ out:
        unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
 }
 
-static bool vxlan_parse_gpe_hdr(struct vxlanhdr *unparsed,
-                               __be16 *protocol,
-                               struct sk_buff *skb, u32 vxflags)
-{
-       struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)unparsed;
-
-       /* Need to have Next Protocol set for interfaces in GPE mode. */
-       if (!gpe->np_applied)
-               return false;
-       /* "The initial version is 0. If a receiver does not support the
-        * version indicated it MUST drop the packet.
-        */
-       if (gpe->version != 0)
-               return false;
-       /* "When the O bit is set to 1, the packet is an OAM packet and OAM
-        * processing MUST occur." However, we don't implement OAM
-        * processing, thus drop the packet.
-        */
-       if (gpe->oam_flag)
-               return false;
-
-       *protocol = tun_p_to_eth_p(gpe->next_protocol);
-       if (!*protocol)
-               return false;
-
-       unparsed->vx_flags &= ~VXLAN_GPE_USED_BITS;
-       return true;
-}
-
 static bool vxlan_set_mac(struct vxlan_dev *vxlan,
                          struct vxlan_sock *vs,
                          struct sk_buff *skb, __be32 vni)
@@ -1655,8 +1701,9 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
         * used by VXLAN extensions if explicitly requested.
         */
        if (vs->flags & VXLAN_F_GPE) {
-               if (!vxlan_parse_gpe_hdr(&unparsed, &protocol, skb, vs->flags))
+               if (!vxlan_parse_gpe_proto(&unparsed, &protocol))
                        goto drop;
+               unparsed.vx_flags &= ~VXLAN_GPE_USED_BITS;
                raw_proto = true;
        }
 
@@ -2516,7 +2563,7 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                }
 
                ndst = &rt->dst;
-               err = skb_tunnel_check_pmtu(skb, ndst, VXLAN_HEADROOM,
+               err = skb_tunnel_check_pmtu(skb, ndst, vxlan_headroom(flags & VXLAN_F_GPE),
                                            netif_is_any_bridge_port(dev));
                if (err < 0) {
                        goto tx_error;
@@ -2577,7 +2624,8 @@ void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev,
                                goto out_unlock;
                }
 
-               err = skb_tunnel_check_pmtu(skb, ndst, VXLAN6_HEADROOM,
+               err = skb_tunnel_check_pmtu(skb, ndst,
+                                           vxlan_headroom((flags & VXLAN_F_GPE) | VXLAN_F_IPV6),
                                            netif_is_any_bridge_port(dev));
                if (err < 0) {
                        goto tx_error;
@@ -2989,14 +3037,12 @@ static int vxlan_change_mtu(struct net_device *dev, int new_mtu)
        struct vxlan_rdst *dst = &vxlan->default_dst;
        struct net_device *lowerdev = __dev_get_by_index(vxlan->net,
                                                         dst->remote_ifindex);
-       bool use_ipv6 = !!(vxlan->cfg.flags & VXLAN_F_IPV6);
 
        /* This check is different than dev->max_mtu, because it looks at
         * the lowerdev->mtu, rather than the static dev->max_mtu
         */
        if (lowerdev) {
-               int max_mtu = lowerdev->mtu -
-                             (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
+               int max_mtu = lowerdev->mtu - vxlan_headroom(vxlan->cfg.flags);
                if (new_mtu > max_mtu)
                        return -EINVAL;
        }
@@ -3379,8 +3425,13 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
        tunnel_cfg.encap_rcv = vxlan_rcv;
        tunnel_cfg.encap_err_lookup = vxlan_err_lookup;
        tunnel_cfg.encap_destroy = NULL;
-       tunnel_cfg.gro_receive = vxlan_gro_receive;
-       tunnel_cfg.gro_complete = vxlan_gro_complete;
+       if (vs->flags & VXLAN_F_GPE) {
+               tunnel_cfg.gro_receive = vxlan_gpe_gro_receive;
+               tunnel_cfg.gro_complete = vxlan_gpe_gro_complete;
+       } else {
+               tunnel_cfg.gro_receive = vxlan_gro_receive;
+               tunnel_cfg.gro_complete = vxlan_gro_complete;
+       }
 
        setup_udp_tunnel_sock(net, sock, &tunnel_cfg);
 
@@ -3644,11 +3695,11 @@ static void vxlan_config_apply(struct net_device *dev,
        struct vxlan_dev *vxlan = netdev_priv(dev);
        struct vxlan_rdst *dst = &vxlan->default_dst;
        unsigned short needed_headroom = ETH_HLEN;
-       bool use_ipv6 = !!(conf->flags & VXLAN_F_IPV6);
        int max_mtu = ETH_MAX_MTU;
+       u32 flags = conf->flags;
 
        if (!changelink) {
-               if (conf->flags & VXLAN_F_GPE)
+               if (flags & VXLAN_F_GPE)
                        vxlan_raw_setup(dev);
                else
                        vxlan_ether_setup(dev);
@@ -3673,8 +3724,7 @@ static void vxlan_config_apply(struct net_device *dev,
 
                dev->needed_tailroom = lowerdev->needed_tailroom;
 
-               max_mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM :
-                                          VXLAN_HEADROOM);
+               max_mtu = lowerdev->mtu - vxlan_headroom(flags);
                if (max_mtu < ETH_MIN_MTU)
                        max_mtu = ETH_MIN_MTU;
 
@@ -3685,10 +3735,9 @@ static void vxlan_config_apply(struct net_device *dev,
        if (dev->mtu > max_mtu)
                dev->mtu = max_mtu;
 
-       if (use_ipv6 || conf->flags & VXLAN_F_COLLECT_METADATA)
-               needed_headroom += VXLAN6_HEADROOM;
-       else
-               needed_headroom += VXLAN_HEADROOM;
+       if (flags & VXLAN_F_COLLECT_METADATA)
+               flags |= VXLAN_F_IPV6;
+       needed_headroom += vxlan_headroom(flags);
        dev->needed_headroom = needed_headroom;
 
        memcpy(&vxlan->cfg, conf, sizeof(*conf));
index 1cebba7..139da57 100644 (file)
@@ -376,7 +376,6 @@ static void ath11k_ahb_ext_irq_enable(struct ath11k_base *ab)
                struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 
                if (!irq_grp->napi_enabled) {
-                       dev_set_threaded(&irq_grp->napi_ndev, true);
                        napi_enable(&irq_grp->napi);
                        irq_grp->napi_enabled = true;
                }
index c899616..c630836 100644 (file)
@@ -466,7 +466,6 @@ void ath11k_pcic_ext_irq_enable(struct ath11k_base *ab)
                struct ath11k_ext_irq_grp *irq_grp = &ab->ext_irq_grp[i];
 
                if (!irq_grp->napi_enabled) {
-                       dev_set_threaded(&irq_grp->napi_ndev, true);
                        napi_enable(&irq_grp->napi);
                        irq_grp->napi_enabled = true;
                }
index a75bfa9..dc2b3b4 100644 (file)
@@ -36,11 +36,6 @@ ath6kl_core-y += wmi.o
 ath6kl_core-y += core.o
 ath6kl_core-y += recovery.o
 
-# FIXME: temporarily silence -Wdangling-pointer on non W=1+ builds
-ifndef KBUILD_EXTRA_WARN
-CFLAGS_htc_mbox.o += $(call cc-disable-warning, dangling-pointer)
-endif
-
 ath6kl_core-$(CONFIG_NL80211_TESTMODE) += testmode.o
 ath6kl_core-$(CONFIG_ATH6KL_TRACING) += trace.o
 
index 792adaf..bece267 100644 (file)
@@ -398,7 +398,12 @@ struct brcmf_scan_params_le {
                                 * fixed parameter portion is assumed, otherwise
                                 * ssid in the fixed portion is ignored
                                 */
-       __le16 channel_list[1]; /* list of chanspecs */
+       union {
+               __le16 padding; /* Reserve space for at least 1 entry for abort
+                                * which uses an on stack brcmf_scan_params_le
+                                */
+               DECLARE_FLEX_ARRAY(__le16, channel_list);       /* chanspecs */
+       };
 };
 
 struct brcmf_scan_params_v2_le {
index 2b0f332..1f3bde8 100644 (file)
@@ -577,7 +577,7 @@ struct tx_msg {
     struct tib_structure tib;
     struct phy_header phy;
     struct mac_header mac;
-    UCHAR  var[1];
+    UCHAR  var[];
 };
 
 /****** ECF Receive Control Structure (RCS) Area at Shared RAM offset 0x0800  */
index 68e8822..ccedea7 100644 (file)
@@ -128,12 +128,12 @@ mt7615_eeprom_parse_hw_band_cap(struct mt7615_dev *dev)
        case MT_EE_5GHZ:
                dev->mphy.cap.has_5ghz = true;
                break;
-       case MT_EE_2GHZ:
-               dev->mphy.cap.has_2ghz = true;
-               break;
        case MT_EE_DBDC:
                dev->dbdc_support = true;
                fallthrough;
+       case MT_EE_2GHZ:
+               dev->mphy.cap.has_2ghz = true;
+               break;
        default:
                dev->mphy.cap.has_2ghz = true;
                dev->mphy.cap.has_5ghz = true;
index e40f10b..da9826a 100644 (file)
@@ -55,7 +55,7 @@ config OF_FLATTREE
 
 config OF_EARLY_FLATTREE
        bool
-       select DMA_DECLARE_COHERENT if HAS_DMA
+       select DMA_DECLARE_COHERENT if HAS_DMA && HAS_IOMEM
        select OF_FLATTREE
 
 config OF_PROMTREE
index 051e29b..0c3475e 100644 (file)
@@ -552,7 +552,7 @@ static int __init of_platform_default_populate_init(void)
                        if (!of_get_property(node, "linux,opened", NULL) ||
                            !of_get_property(node, "linux,boot-display", NULL))
                                continue;
-                       dev = of_platform_device_create(node, "of-display.0", NULL);
+                       dev = of_platform_device_create(node, "of-display", NULL);
                        of_node_put(node);
                        if (WARN_ON(!dev))
                                return -ENOMEM;
index 15dafe3..6ae6d50 100644 (file)
@@ -184,7 +184,7 @@ static int hisi_inno_phy_probe(struct platform_device *pdev)
                phy_set_drvdata(phy, &priv->ports[i]);
                i++;
 
-               if (i > INNO_PHY_PORT_NUM) {
+               if (i >= INNO_PHY_PORT_NUM) {
                        dev_warn(dev, "Support %d ports in maximum\n", i);
                        of_node_put(child);
                        break;
index 232fd3f..d7024a1 100644 (file)
@@ -169,7 +169,7 @@ static int mtk_dp_phy_probe(struct platform_device *pdev)
 
        regs = *(struct regmap **)dev->platform_data;
        if (!regs)
-               return dev_err_probe(dev, EINVAL,
+               return dev_err_probe(dev, -EINVAL,
                                     "No data passed, requires struct regmap**\n");
 
        dp_phy = devm_kzalloc(dev, sizeof(*dp_phy), GFP_KERNEL);
index 8aa7251..bbfe11d 100644 (file)
@@ -253,7 +253,7 @@ static int mtk_hdmi_pll_calc(struct mtk_hdmi_phy *hdmi_phy, struct clk_hw *hw,
        for (i = 0; i < ARRAY_SIZE(txpredivs); i++) {
                ns_hdmipll_ck = 5 * tmds_clk * txposdiv * txpredivs[i];
                if (ns_hdmipll_ck >= 5 * GIGA &&
-                   ns_hdmipll_ck <= 1 * GIGA)
+                   ns_hdmipll_ck <= 12 * GIGA)
                        break;
        }
        if (i == (ARRAY_SIZE(txpredivs) - 1) &&
index 6c237f3..d0319be 100644 (file)
@@ -110,11 +110,13 @@ struct phy_override_seq {
 /**
  * struct qcom_snps_hsphy - snps hs phy attributes
  *
+ * @dev: device structure
+ *
  * @phy: generic phy
  * @base: iomapped memory space for snps hs phy
  *
- * @cfg_ahb_clk: AHB2PHY interface clock
- * @ref_clk: phy reference clock
+ * @num_clks: number of clocks
+ * @clks: array of clocks
  * @phy_reset: phy reset control
  * @vregs: regulator supplies bulk data
  * @phy_initialized: if PHY has been initialized correctly
@@ -122,11 +124,13 @@ struct phy_override_seq {
  * @update_seq_cfg: tuning parameters for phy init
  */
 struct qcom_snps_hsphy {
+       struct device *dev;
+
        struct phy *phy;
        void __iomem *base;
 
-       struct clk *cfg_ahb_clk;
-       struct clk *ref_clk;
+       int num_clks;
+       struct clk_bulk_data *clks;
        struct reset_control *phy_reset;
        struct regulator_bulk_data vregs[SNPS_HS_NUM_VREGS];
 
@@ -135,6 +139,34 @@ struct qcom_snps_hsphy {
        struct phy_override_seq update_seq_cfg[NUM_HSPHY_TUNING_PARAMS];
 };
 
+static int qcom_snps_hsphy_clk_init(struct qcom_snps_hsphy *hsphy)
+{
+       struct device *dev = hsphy->dev;
+
+       hsphy->num_clks = 2;
+       hsphy->clks = devm_kcalloc(dev, hsphy->num_clks, sizeof(*hsphy->clks), GFP_KERNEL);
+       if (!hsphy->clks)
+               return -ENOMEM;
+
+       /*
+        * TODO: Currently no device tree instantiation of the PHY is using the clock.
+        * This needs to be fixed in order for this code to be able to use devm_clk_bulk_get().
+        */
+       hsphy->clks[0].id = "cfg_ahb";
+       hsphy->clks[0].clk = devm_clk_get_optional(dev, "cfg_ahb");
+       if (IS_ERR(hsphy->clks[0].clk))
+               return dev_err_probe(dev, PTR_ERR(hsphy->clks[0].clk),
+                                    "failed to get cfg_ahb clk\n");
+
+       hsphy->clks[1].id = "ref";
+       hsphy->clks[1].clk = devm_clk_get(dev, "ref");
+       if (IS_ERR(hsphy->clks[1].clk))
+               return dev_err_probe(dev, PTR_ERR(hsphy->clks[1].clk),
+                                    "failed to get ref clk\n");
+
+       return 0;
+}
+
 static inline void qcom_snps_hsphy_write_mask(void __iomem *base, u32 offset,
                                                u32 mask, u32 val)
 {
@@ -165,22 +197,13 @@ static int qcom_snps_hsphy_suspend(struct qcom_snps_hsphy *hsphy)
                                           0, USB2_AUTO_RESUME);
        }
 
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
        return 0;
 }
 
 static int qcom_snps_hsphy_resume(struct qcom_snps_hsphy *hsphy)
 {
-       int ret;
-
        dev_dbg(&hsphy->phy->dev, "Resume QCOM SNPS PHY, mode\n");
 
-       ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
-       if (ret) {
-               dev_err(&hsphy->phy->dev, "failed to enable cfg ahb clock\n");
-               return ret;
-       }
-
        return 0;
 }
 
@@ -191,8 +214,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_suspend(struct device *dev)
        if (!hsphy->phy_initialized)
                return 0;
 
-       qcom_snps_hsphy_suspend(hsphy);
-       return 0;
+       return qcom_snps_hsphy_suspend(hsphy);
 }
 
 static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
@@ -202,8 +224,7 @@ static int __maybe_unused qcom_snps_hsphy_runtime_resume(struct device *dev)
        if (!hsphy->phy_initialized)
                return 0;
 
-       qcom_snps_hsphy_resume(hsphy);
-       return 0;
+       return qcom_snps_hsphy_resume(hsphy);
 }
 
 static int qcom_snps_hsphy_set_mode(struct phy *phy, enum phy_mode mode,
@@ -374,16 +395,16 @@ static int qcom_snps_hsphy_init(struct phy *phy)
        if (ret)
                return ret;
 
-       ret = clk_prepare_enable(hsphy->cfg_ahb_clk);
+       ret = clk_bulk_prepare_enable(hsphy->num_clks, hsphy->clks);
        if (ret) {
-               dev_err(&phy->dev, "failed to enable cfg ahb clock, %d\n", ret);
+               dev_err(&phy->dev, "failed to enable clocks, %d\n", ret);
                goto poweroff_phy;
        }
 
        ret = reset_control_assert(hsphy->phy_reset);
        if (ret) {
                dev_err(&phy->dev, "failed to assert phy_reset, %d\n", ret);
-               goto disable_ahb_clk;
+               goto disable_clks;
        }
 
        usleep_range(100, 150);
@@ -391,7 +412,7 @@ static int qcom_snps_hsphy_init(struct phy *phy)
        ret = reset_control_deassert(hsphy->phy_reset);
        if (ret) {
                dev_err(&phy->dev, "failed to de-assert phy_reset, %d\n", ret);
-               goto disable_ahb_clk;
+               goto disable_clks;
        }
 
        qcom_snps_hsphy_write_mask(hsphy->base, USB2_PHY_USB_PHY_CFG0,
@@ -448,8 +469,8 @@ static int qcom_snps_hsphy_init(struct phy *phy)
 
        return 0;
 
-disable_ahb_clk:
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
+disable_clks:
+       clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
 poweroff_phy:
        regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
 
@@ -461,7 +482,7 @@ static int qcom_snps_hsphy_exit(struct phy *phy)
        struct qcom_snps_hsphy *hsphy = phy_get_drvdata(phy);
 
        reset_control_assert(hsphy->phy_reset);
-       clk_disable_unprepare(hsphy->cfg_ahb_clk);
+       clk_bulk_disable_unprepare(hsphy->num_clks, hsphy->clks);
        regulator_bulk_disable(ARRAY_SIZE(hsphy->vregs), hsphy->vregs);
        hsphy->phy_initialized = false;
 
@@ -554,14 +575,15 @@ static int qcom_snps_hsphy_probe(struct platform_device *pdev)
        if (!hsphy)
                return -ENOMEM;
 
+       hsphy->dev = dev;
+
        hsphy->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(hsphy->base))
                return PTR_ERR(hsphy->base);
 
-       hsphy->ref_clk = devm_clk_get(dev, "ref");
-       if (IS_ERR(hsphy->ref_clk))
-               return dev_err_probe(dev, PTR_ERR(hsphy->ref_clk),
-                                    "failed to get ref clk\n");
+       ret = qcom_snps_hsphy_clk_init(hsphy);
+       if (ret)
+               return dev_err_probe(dev, ret, "failed to initialize clocks\n");
 
        hsphy->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, NULL);
        if (IS_ERR(hsphy->phy_reset)) {
index 362e7c0..ad70246 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/dmi.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
-#include <linux/slab.h>
 
 #include "pmc.h"
 
@@ -135,12 +134,10 @@ static const struct dmi_system_id fwbug_list[] = {
  */
 static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
 {
-       struct resource *res;
        void __iomem *addr;
        u8 val;
 
-       res = request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80");
-       if (!res)
+       if (!request_mem_region_muxed(s2idle_bug_mmio, 1, "amd_pmc_pm80"))
                return;
 
        addr = ioremap(s2idle_bug_mmio, 1);
@@ -152,8 +149,7 @@ static void amd_pmc_skip_nvme_smi_handler(u32 s2idle_bug_mmio)
 
        iounmap(addr);
 cleanup_resource:
-       release_resource(res);
-       kfree(res);
+       release_mem_region(s2idle_bug_mmio, 1);
 }
 
 void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
index 081e84e..3fc5e45 100644 (file)
@@ -106,6 +106,27 @@ int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
                                                                         data, sizeof(*data));
 }
 
+int apmf_os_power_slider_update(struct amd_pmf_dev *pdev, u8 event)
+{
+       struct os_power_slider args;
+       struct acpi_buffer params;
+       union acpi_object *info;
+       int err = 0;
+
+       args.size = sizeof(args);
+       args.slider_event = event;
+
+       params.length = sizeof(args);
+       params.pointer = (void *)&args;
+
+       info = apmf_if_call(pdev, APMF_FUNC_OS_POWER_SLIDER_UPDATE, &params);
+       if (!info)
+               err = -EIO;
+
+       kfree(info);
+       return err;
+}
+
 static void apmf_sbios_heartbeat_notify(struct work_struct *work)
 {
        struct amd_pmf_dev *dev = container_of(work, struct amd_pmf_dev, heart_beat.work);
@@ -289,7 +310,7 @@ int apmf_acpi_init(struct amd_pmf_dev *pmf_dev)
 
        ret = apmf_get_system_params(pmf_dev);
        if (ret) {
-               dev_err(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
+               dev_dbg(pmf_dev->dev, "APMF apmf_get_system_params failed :%d\n", ret);
                goto out;
        }
 
index d873255..57bf1a9 100644 (file)
@@ -72,7 +72,11 @@ static int amd_pmf_pwr_src_notify_call(struct notifier_block *nb, unsigned long
                        return NOTIFY_DONE;
        }
 
-       amd_pmf_set_sps_power_limits(pmf);
+       if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR))
+               amd_pmf_set_sps_power_limits(pmf);
+
+       if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE))
+               amd_pmf_power_slider_update_event(pmf);
 
        return NOTIFY_OK;
 }
@@ -297,7 +301,8 @@ static void amd_pmf_init_features(struct amd_pmf_dev *dev)
        int ret;
 
        /* Enable Static Slider */
-       if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+       if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR) ||
+           is_apmf_func_supported(dev, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
                amd_pmf_init_sps(dev);
                dev->pwr_src_notifier.notifier_call = amd_pmf_pwr_src_notify_call;
                power_supply_reg_notifier(&dev->pwr_src_notifier);
index 06c30cd..deba88e 100644 (file)
@@ -21,6 +21,7 @@
 #define APMF_FUNC_SBIOS_HEARTBEAT                      4
 #define APMF_FUNC_AUTO_MODE                                    5
 #define APMF_FUNC_SET_FAN_IDX                          7
+#define APMF_FUNC_OS_POWER_SLIDER_UPDATE               8
 #define APMF_FUNC_STATIC_SLIDER_GRANULAR       9
 #define APMF_FUNC_DYN_SLIDER_AC                                11
 #define APMF_FUNC_DYN_SLIDER_DC                                12
 #define GET_STT_LIMIT_APU      0x20
 #define GET_STT_LIMIT_HS2      0x21
 
+/* OS slider update notification */
+#define DC_BEST_PERF           0
+#define DC_BETTER_PERF         1
+#define DC_BATTERY_SAVER       3
+#define AC_BEST_PERF           4
+#define AC_BETTER_PERF         5
+#define AC_BETTER_BATTERY      6
+
 /* Fan Index for Auto Mode */
 #define FAN_INDEX_AUTO         0xFFFFFFFF
 
@@ -193,6 +202,11 @@ struct amd_pmf_static_slider_granular {
        struct apmf_sps_prop_granular prop[POWER_SOURCE_MAX][POWER_MODE_MAX];
 };
 
+struct os_power_slider {
+       u16 size;
+       u8 slider_event;
+} __packed;
+
 struct fan_table_control {
        bool manual;
        unsigned long fan_id;
@@ -383,6 +397,7 @@ int amd_pmf_send_cmd(struct amd_pmf_dev *dev, u8 message, bool get, u32 arg, u32
 int amd_pmf_init_metrics_table(struct amd_pmf_dev *dev);
 int amd_pmf_get_power_source(void);
 int apmf_install_handler(struct amd_pmf_dev *pmf_dev);
+int apmf_os_power_slider_update(struct amd_pmf_dev *dev, u8 flag);
 
 /* SPS Layer */
 int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf);
@@ -393,6 +408,7 @@ void amd_pmf_deinit_sps(struct amd_pmf_dev *dev);
 int apmf_get_static_slider_granular(struct amd_pmf_dev *pdev,
                                    struct apmf_static_slider_granular_output *output);
 bool is_pprof_balanced(struct amd_pmf_dev *pmf);
+int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev);
 
 
 int apmf_update_fan_idx(struct amd_pmf_dev *pdev, bool manual, u32 idx);
index 445ff05..ab69d51 100644 (file)
@@ -174,14 +174,77 @@ int amd_pmf_get_pprof_modes(struct amd_pmf_dev *pmf)
        return mode;
 }
 
+int amd_pmf_power_slider_update_event(struct amd_pmf_dev *dev)
+{
+       u8 mode, flag = 0;
+       int src;
+
+       mode = amd_pmf_get_pprof_modes(dev);
+       if (mode < 0)
+               return mode;
+
+       src = amd_pmf_get_power_source();
+
+       if (src == POWER_SOURCE_AC) {
+               switch (mode) {
+               case POWER_MODE_PERFORMANCE:
+                       flag |= BIT(AC_BEST_PERF);
+                       break;
+               case POWER_MODE_BALANCED_POWER:
+                       flag |= BIT(AC_BETTER_PERF);
+                       break;
+               case POWER_MODE_POWER_SAVER:
+                       flag |= BIT(AC_BETTER_BATTERY);
+                       break;
+               default:
+                       dev_err(dev->dev, "unsupported platform profile\n");
+                       return -EOPNOTSUPP;
+               }
+
+       } else if (src == POWER_SOURCE_DC) {
+               switch (mode) {
+               case POWER_MODE_PERFORMANCE:
+                       flag |= BIT(DC_BEST_PERF);
+                       break;
+               case POWER_MODE_BALANCED_POWER:
+                       flag |= BIT(DC_BETTER_PERF);
+                       break;
+               case POWER_MODE_POWER_SAVER:
+                       flag |= BIT(DC_BATTERY_SAVER);
+                       break;
+               default:
+                       dev_err(dev->dev, "unsupported platform profile\n");
+                       return -EOPNOTSUPP;
+               }
+       }
+
+       apmf_os_power_slider_update(dev, flag);
+
+       return 0;
+}
+
 static int amd_pmf_profile_set(struct platform_profile_handler *pprof,
                               enum platform_profile_option profile)
 {
        struct amd_pmf_dev *pmf = container_of(pprof, struct amd_pmf_dev, pprof);
+       int ret = 0;
 
        pmf->current_profile = profile;
 
-       return amd_pmf_set_sps_power_limits(pmf);
+       /* Notify EC about the slider position change */
+       if (is_apmf_func_supported(pmf, APMF_FUNC_OS_POWER_SLIDER_UPDATE)) {
+               ret = amd_pmf_power_slider_update_event(pmf);
+               if (ret)
+                       return ret;
+       }
+
+       if (is_apmf_func_supported(pmf, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+               ret = amd_pmf_set_sps_power_limits(pmf);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
 }
 
 int amd_pmf_init_sps(struct amd_pmf_dev *dev)
@@ -189,10 +252,13 @@ int amd_pmf_init_sps(struct amd_pmf_dev *dev)
        int err;
 
        dev->current_profile = PLATFORM_PROFILE_BALANCED;
-       amd_pmf_load_defaults_sps(dev);
 
-       /* update SPS balanced power mode thermals */
-       amd_pmf_set_sps_power_limits(dev);
+       if (is_apmf_func_supported(dev, APMF_FUNC_STATIC_SLIDER_GRANULAR)) {
+               amd_pmf_load_defaults_sps(dev);
+
+               /* update SPS balanced power mode thermals */
+               amd_pmf_set_sps_power_limits(dev);
+       }
 
        dev->pprof.profile_get = amd_pmf_profile_get;
        dev->pprof.profile_set = amd_pmf_profile_set;
index 1038dfd..8bef66a 100644 (file)
@@ -738,13 +738,23 @@ static ssize_t kbd_rgb_mode_store(struct device *dev,
                                 struct device_attribute *attr,
                                 const char *buf, size_t count)
 {
-       u32 cmd, mode, r, g,  b,  speed;
+       u32 cmd, mode, r, g, b, speed;
        int err;
 
        if (sscanf(buf, "%d %d %d %d %d %d", &cmd, &mode, &r, &g, &b, &speed) != 6)
                return -EINVAL;
 
-       cmd = !!cmd;
+       /* B3 is set and B4 is save to BIOS */
+       switch (cmd) {
+       case 0:
+               cmd = 0xb3;
+               break;
+       case 1:
+               cmd = 0xb4;
+               break;
+       default:
+               return -EINVAL;
+       }
 
        /* These are the known usable modes across all TUF/ROG */
        if (mode >= 12 || mode == 9)
index 70e5c4c..0ef1c46 100644 (file)
@@ -85,6 +85,8 @@ static const struct key_entry huawei_wmi_keymap[] = {
        { KE_IGNORE, 0x293, { KEY_KBDILLUMTOGGLE } },
        { KE_IGNORE, 0x294, { KEY_KBDILLUMUP } },
        { KE_IGNORE, 0x295, { KEY_KBDILLUMUP } },
+       // Ignore Ambient Light Sensoring
+       { KE_KEY,    0x2c1, { KEY_RESERVED } },
        { KE_END,        0 }
 };
 
index 5632bd3..7457ca2 100644 (file)
@@ -150,6 +150,12 @@ static const struct dmi_system_id dmi_vgbs_allow_list[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Surface Go"),
                },
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Elite Dragonfly G2 Notebook PC"),
+               },
+       },
        { }
 };
 
@@ -620,7 +626,7 @@ static bool button_array_present(struct platform_device *device)
 static int intel_hid_probe(struct platform_device *device)
 {
        acpi_handle handle = ACPI_HANDLE(&device->dev);
-       unsigned long long mode;
+       unsigned long long mode, dummy;
        struct intel_hid_priv *priv;
        acpi_status status;
        int err;
@@ -692,18 +698,15 @@ static int intel_hid_probe(struct platform_device *device)
        if (err)
                goto err_remove_notify;
 
-       if (priv->array) {
-               unsigned long long dummy;
+       intel_button_array_enable(&device->dev, true);
 
-               intel_button_array_enable(&device->dev, true);
-
-               /* Call button load method to enable HID power button */
-               if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN,
-                                              &dummy)) {
-                       dev_warn(&device->dev,
-                                "failed to enable HID power button\n");
-               }
-       }
+       /*
+        * Call button load method to enable HID power button
+        * Always do this since it activates events on some devices without
+        * a button array too.
+        */
+       if (!intel_hid_evaluate_method(handle, INTEL_HID_DSM_BTNL_FN, &dummy))
+               dev_warn(&device->dev, "failed to enable HID power button\n");
 
        device_init_wakeup(&device->dev, true);
        /*
index 6b18ec5..f4c6c36 100644 (file)
@@ -208,7 +208,7 @@ static ssize_t set_device_state(const char *buf, size_t count, u8 mask)
                return -EINVAL;
 
        if (quirks->ec_read_only)
-               return -EOPNOTSUPP;
+               return 0;
 
        /* read current device state */
        result = ec_read(MSI_STANDARD_EC_COMMAND_ADDRESS, &rdata);
@@ -838,15 +838,15 @@ static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
 static void msi_init_rfkill(struct work_struct *ignored)
 {
        if (rfk_wlan) {
-               rfkill_set_sw_state(rfk_wlan, !wlan_s);
+               msi_rfkill_set_state(rfk_wlan, !wlan_s);
                rfkill_wlan_set(NULL, !wlan_s);
        }
        if (rfk_bluetooth) {
-               rfkill_set_sw_state(rfk_bluetooth, !bluetooth_s);
+               msi_rfkill_set_state(rfk_bluetooth, !bluetooth_s);
                rfkill_bluetooth_set(NULL, !bluetooth_s);
        }
        if (rfk_threeg) {
-               rfkill_set_sw_state(rfk_threeg, !threeg_s);
+               msi_rfkill_set_state(rfk_threeg, !threeg_s);
                rfkill_threeg_set(NULL, !threeg_s);
        }
 }
index f3dcbdd..2c2abf6 100644 (file)
@@ -21,6 +21,7 @@
 #define IRQ_RESOURCE_NONE      0
 #define IRQ_RESOURCE_GPIO      1
 #define IRQ_RESOURCE_APIC      2
+#define IRQ_RESOURCE_AUTO   3
 
 enum smi_bus_type {
        SMI_I2C,
@@ -52,6 +53,18 @@ static int smi_get_irq(struct platform_device *pdev, struct acpi_device *adev,
        int ret;
 
        switch (inst->flags & IRQ_RESOURCE_TYPE) {
+       case IRQ_RESOURCE_AUTO:
+               ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
+               if (ret > 0) {
+                       dev_dbg(&pdev->dev, "Using gpio irq\n");
+                       break;
+               }
+               ret = platform_get_irq(pdev, inst->irq_idx);
+               if (ret > 0) {
+                       dev_dbg(&pdev->dev, "Using platform irq\n");
+                       break;
+               }
+               break;
        case IRQ_RESOURCE_GPIO:
                ret = acpi_dev_gpio_irq_get(adev, inst->irq_idx);
                break;
@@ -307,10 +320,10 @@ static const struct smi_node int3515_data = {
 
 static const struct smi_node cs35l41_hda = {
        .instances = {
-               { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
-               { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
-               { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
-               { "cs35l41-hda", IRQ_RESOURCE_GPIO, 0 },
+               { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
+               { "cs35l41-hda", IRQ_RESOURCE_AUTO, 0 },
                {}
        },
        .bus_type = SMI_AUTO_DETECT,
index 52d1ce8..7934688 100644 (file)
@@ -719,12 +719,12 @@ static ssize_t cert_to_password_store(struct kobject *kobj,
        /* Format: 'Password,Signature' */
        auth_str = kasprintf(GFP_KERNEL, "%s,%s", passwd, setting->signature);
        if (!auth_str) {
-               kfree(passwd);
+               kfree_sensitive(passwd);
                return -ENOMEM;
        }
        ret = tlmi_simple_call(LENOVO_CERT_TO_PASSWORD_GUID, auth_str);
        kfree(auth_str);
-       kfree(passwd);
+       kfree_sensitive(passwd);
 
        return ret ?: count;
 }
index a5b687e..f9301a9 100644 (file)
@@ -27,11 +27,12 @@ struct ts_dmi_data {
 /* NOTE: Please keep all entries sorted alphabetically */
 
 static const struct property_entry archos_101_cesium_educ_props[] = {
-       PROPERTY_ENTRY_U32("touchscreen-size-x", 1280),
-       PROPERTY_ENTRY_U32("touchscreen-size-y", 1850),
-       PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1850),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1280),
+       PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
        PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
        PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
        PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-archos-101-cesium-educ.fw"),
        { }
 };
index c5dd77b..dfd5ec9 100644 (file)
@@ -778,6 +778,9 @@ static int da9063_check_xvp_constraints(struct regulator_config *config)
        const struct notification_limit *uv_l = &constr->under_voltage_limits;
        const struct notification_limit *ov_l = &constr->over_voltage_limits;
 
+       if (!config->init_data) /* No config in DT, pointers will be invalid */
+               return 0;
+
        /* make sure that only one severity is used to clarify if unchanged, enabled or disabled */
        if ((!!uv_l->prot + !!uv_l->err + !!uv_l->warn) > 1) {
                dev_err(config->dev, "%s: at most one voltage monitoring severity allowed!\n",
index 31a16fb..b9cda22 100644 (file)
@@ -661,7 +661,7 @@ static int mt6358_sync_vcn33_setting(struct device *dev)
        /* Disable VCN33_WIFI */
        ret = regmap_update_bits(mt6397->regmap, MT6358_LDO_VCN33_CON0_1, BIT(0), 0);
        if (ret) {
-               dev_err(dev, "Failed to disable VCN33_BT\n");
+               dev_err(dev, "Failed to disable VCN33_WIFI\n");
                return ret;
        }
 
@@ -676,10 +676,6 @@ static int mt6358_regulator_probe(struct platform_device *pdev)
        const struct mt6358_regulator_info *mt6358_info;
        int i, max_regulator, ret;
 
-       ret = mt6358_sync_vcn33_setting(&pdev->dev);
-       if (ret)
-               return ret;
-
        if (mt6397->chip_id == MT6366_CHIP_ID) {
                max_regulator = MT6366_MAX_REGULATOR;
                mt6358_info = mt6366_regulators;
@@ -688,6 +684,10 @@ static int mt6358_regulator_probe(struct platform_device *pdev)
                mt6358_info = mt6358_regulators;
        }
 
+       ret = mt6358_sync_vcn33_setting(&pdev->dev);
+       if (ret)
+               return ret;
+
        for (i = 0; i < max_regulator; i++) {
                config.dev = &pdev->dev;
                config.regmap = mt6397->regmap;
index edcbf77..50a5ff7 100644 (file)
@@ -2943,41 +2943,32 @@ static void _dasd_wake_block_flush_cb(struct dasd_ccw_req *cqr, void *data)
  * Requeue a request back to the block request queue
  * only works for block requests
  */
-static int _dasd_requeue_request(struct dasd_ccw_req *cqr)
+static void _dasd_requeue_request(struct dasd_ccw_req *cqr)
 {
-       struct dasd_block *block = cqr->block;
        struct request *req;
 
-       if (!block)
-               return -EINVAL;
        /*
         * If the request is an ERP request there is nothing to requeue.
         * This will be done with the remaining original request.
         */
        if (cqr->refers)
-               return 0;
+               return;
        spin_lock_irq(&cqr->dq->lock);
        req = (struct request *) cqr->callback_data;
        blk_mq_requeue_request(req, true);
        spin_unlock_irq(&cqr->dq->lock);
 
-       return 0;
+       return;
 }
 
-/*
- * Go through all request on the dasd_block request queue, cancel them
- * on the respective dasd_device, and return them to the generic
- * block layer.
- */
-static int dasd_flush_block_queue(struct dasd_block *block)
+static int _dasd_requests_to_flushqueue(struct dasd_block *block,
+                                       struct list_head *flush_queue)
 {
        struct dasd_ccw_req *cqr, *n;
-       int rc, i;
-       struct list_head flush_queue;
        unsigned long flags;
+       int rc, i;
 
-       INIT_LIST_HEAD(&flush_queue);
-       spin_lock_bh(&block->queue_lock);
+       spin_lock_irqsave(&block->queue_lock, flags);
        rc = 0;
 restart:
        list_for_each_entry_safe(cqr, n, &block->ccw_queue, blocklist) {
@@ -2992,13 +2983,32 @@ restart:
                 * is returned from the dasd_device layer.
                 */
                cqr->callback = _dasd_wake_block_flush_cb;
-               for (i = 0; cqr != NULL; cqr = cqr->refers, i++)
-                       list_move_tail(&cqr->blocklist, &flush_queue);
+               for (i = 0; cqr; cqr = cqr->refers, i++)
+                       list_move_tail(&cqr->blocklist, flush_queue);
                if (i > 1)
                        /* moved more than one request - need to restart */
                        goto restart;
        }
-       spin_unlock_bh(&block->queue_lock);
+       spin_unlock_irqrestore(&block->queue_lock, flags);
+
+       return rc;
+}
+
+/*
+ * Go through all request on the dasd_block request queue, cancel them
+ * on the respective dasd_device, and return them to the generic
+ * block layer.
+ */
+static int dasd_flush_block_queue(struct dasd_block *block)
+{
+       struct dasd_ccw_req *cqr, *n;
+       struct list_head flush_queue;
+       unsigned long flags;
+       int rc;
+
+       INIT_LIST_HEAD(&flush_queue);
+       rc = _dasd_requests_to_flushqueue(block, &flush_queue);
+
        /* Now call the callback function of flushed requests */
 restart_cb:
        list_for_each_entry_safe(cqr, n, &flush_queue, blocklist) {
@@ -3881,75 +3891,36 @@ EXPORT_SYMBOL_GPL(dasd_generic_space_avail);
  */
 int dasd_generic_requeue_all_requests(struct dasd_device *device)
 {
+       struct dasd_block *block = device->block;
        struct list_head requeue_queue;
        struct dasd_ccw_req *cqr, *n;
-       struct dasd_ccw_req *refers;
        int rc;
 
-       INIT_LIST_HEAD(&requeue_queue);
-       spin_lock_irq(get_ccwdev_lock(device->cdev));
-       rc = 0;
-       list_for_each_entry_safe(cqr, n, &device->ccw_queue, devlist) {
-               /* Check status and move request to flush_queue */
-               if (cqr->status == DASD_CQR_IN_IO) {
-                       rc = device->discipline->term_IO(cqr);
-                       if (rc) {
-                               /* unable to terminate requeust */
-                               dev_err(&device->cdev->dev,
-                                       "Unable to terminate request %p "
-                                       "on suspend\n", cqr);
-                               spin_unlock_irq(get_ccwdev_lock(device->cdev));
-                               dasd_put_device(device);
-                               return rc;
-                       }
-               }
-               list_move_tail(&cqr->devlist, &requeue_queue);
-       }
-       spin_unlock_irq(get_ccwdev_lock(device->cdev));
-
-       list_for_each_entry_safe(cqr, n, &requeue_queue, devlist) {
-               wait_event(dasd_flush_wq,
-                          (cqr->status != DASD_CQR_CLEAR_PENDING));
+       if (!block)
+               return 0;
 
-               /*
-                * requeue requests to blocklayer will only work
-                * for block device requests
-                */
-               if (_dasd_requeue_request(cqr))
-                       continue;
+       INIT_LIST_HEAD(&requeue_queue);
+       rc = _dasd_requests_to_flushqueue(block, &requeue_queue);
 
-               /* remove requests from device and block queue */
-               list_del_init(&cqr->devlist);
-               while (cqr->refers != NULL) {
-                       refers = cqr->refers;
-                       /* remove the request from the block queue */
-                       list_del(&cqr->blocklist);
-                       /* free the finished erp request */
-                       dasd_free_erp_request(cqr, cqr->memdev);
-                       cqr = refers;
+       /* Now call the callback function of flushed requests */
+restart_cb:
+       list_for_each_entry_safe(cqr, n, &requeue_queue, blocklist) {
+               wait_event(dasd_flush_wq, (cqr->status < DASD_CQR_QUEUED));
+               /* Process finished ERP request. */
+               if (cqr->refers) {
+                       spin_lock_bh(&block->queue_lock);
+                       __dasd_process_erp(block->base, cqr);
+                       spin_unlock_bh(&block->queue_lock);
+                       /* restart list_for_xx loop since dasd_process_erp
+                        * might remove multiple elements
+                        */
+                       goto restart_cb;
                }
-
-               /*
-                * _dasd_requeue_request already checked for a valid
-                * blockdevice, no need to check again
-                * all erp requests (cqr->refers) have a cqr->block
-                * pointer copy from the original cqr
-                */
+               _dasd_requeue_request(cqr);
                list_del_init(&cqr->blocklist);
                cqr->block->base->discipline->free_cp(
                        cqr, (struct request *) cqr->callback_data);
        }
-
-       /*
-        * if requests remain then they are internal request
-        * and go back to the device queue
-        */
-       if (!list_empty(&requeue_queue)) {
-               /* move freeze_queue to start of the ccw_queue */
-               spin_lock_irq(get_ccwdev_lock(device->cdev));
-               list_splice_tail(&requeue_queue, &device->ccw_queue);
-               spin_unlock_irq(get_ccwdev_lock(device->cdev));
-       }
        dasd_schedule_device_bh(device);
        return rc;
 }
index 9fd36c4..89957bb 100644 (file)
@@ -1050,7 +1050,7 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
                dev_err(&device->cdev->dev, "An I/O request was rejected"
                        " because writing is inhibited\n");
                erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
-       } else if (sense[7] & SNS7_INVALID_ON_SEC) {
+       } else if (sense[7] == SNS7_INVALID_ON_SEC) {
                dev_err(&device->cdev->dev, "An I/O request was rejected on a copy pair secondary device\n");
                /* suppress dump of sense data for this error */
                set_bit(DASD_CQR_SUPPRESS_CR, &erp->refers->flags);
@@ -2441,7 +2441,7 @@ static struct dasd_ccw_req *dasd_3990_erp_add_erp(struct dasd_ccw_req *cqr)
        erp->block    = cqr->block;
        erp->magic    = cqr->magic;
        erp->expires  = cqr->expires;
-       erp->retries  = 256;
+       erp->retries  = device->default_retries;
        erp->buildclk = get_tod_clock();
        erp->status = DASD_CQR_FILLED;
 
index 513a7e6..d558626 100644 (file)
@@ -131,6 +131,7 @@ static int dasd_ioctl_resume(struct dasd_block *block)
        spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags);
 
        dasd_schedule_block_bh(block);
+       dasd_schedule_device_bh(base);
        return 0;
 }
 
index 67fd2ec..e668ff5 100644 (file)
@@ -1101,23 +1101,36 @@ static long zcrypt_msgtype6_send_cprb(bool userspace, struct zcrypt_queue *zq,
                                      struct ica_xcRB *xcrb,
                                      struct ap_message *ap_msg)
 {
-       int rc;
        struct response_type *rtype = ap_msg->private;
        struct {
                struct type6_hdr hdr;
                struct CPRBX cprbx;
                /* ... more data blocks ... */
        } __packed * msg = ap_msg->msg;
-
-       /*
-        * Set the queue's reply buffer length minus 128 byte padding
-        * as reply limit for the card firmware.
-        */
-       msg->hdr.fromcardlen1 = min_t(unsigned int, msg->hdr.fromcardlen1,
-                                     zq->reply.bufsize - 128);
-       if (msg->hdr.fromcardlen2)
-               msg->hdr.fromcardlen2 =
-                       zq->reply.bufsize - msg->hdr.fromcardlen1 - 128;
+       unsigned int max_payload_size;
+       int rc, delta;
+
+       /* calculate maximum payload for this card and msg type */
+       max_payload_size = zq->reply.bufsize - sizeof(struct type86_fmt2_msg);
+
+       /* limit each of the two from fields to the maximum payload size */
+       msg->hdr.fromcardlen1 = min(msg->hdr.fromcardlen1, max_payload_size);
+       msg->hdr.fromcardlen2 = min(msg->hdr.fromcardlen2, max_payload_size);
+
+       /* calculate delta if the sum of both exceeds max payload size */
+       delta = msg->hdr.fromcardlen1 + msg->hdr.fromcardlen2
+               - max_payload_size;
+       if (delta > 0) {
+               /*
+                * Sum exceeds maximum payload size, prune fromcardlen1
+                * (always trust fromcardlen2)
+                */
+               if (delta > msg->hdr.fromcardlen1) {
+                       rc = -EINVAL;
+                       goto out;
+               }
+               msg->hdr.fromcardlen1 -= delta;
+       }
 
        init_completion(&rtype->work);
        rc = ap_queue_message(zq->queue, ap_msg);
index 1d19542..613eab7 100644 (file)
@@ -716,7 +716,6 @@ struct qeth_card_info {
        u16 chid;
        u8 ids_valid:1; /* cssid,iid,chid */
        u8 dev_addr_is_registered:1;
-       u8 open_when_online:1;
        u8 promisc_mode:1;
        u8 use_v1_blkt:1;
        u8 is_vm_nic:1;
index 1d5b207..cd78329 100644 (file)
@@ -5373,8 +5373,6 @@ int qeth_set_offline(struct qeth_card *card, const struct qeth_discipline *disc,
        qeth_clear_ipacmd_list(card);
 
        rtnl_lock();
-       card->info.open_when_online = card->dev->flags & IFF_UP;
-       dev_close(card->dev);
        netif_device_detach(card->dev);
        netif_carrier_off(card->dev);
        rtnl_unlock();
index 9f13ed1..75910c0 100644 (file)
@@ -2388,9 +2388,12 @@ static int qeth_l2_set_online(struct qeth_card *card, bool carrier_ok)
                qeth_enable_hw_features(dev);
                qeth_l2_enable_brport_features(card);
 
-               if (card->info.open_when_online) {
-                       card->info.open_when_online = 0;
-                       dev_open(dev, NULL);
+               if (netif_running(dev)) {
+                       local_bh_disable();
+                       napi_schedule(&card->napi);
+                       /* kick-start the NAPI softirq: */
+                       local_bh_enable();
+                       qeth_l2_set_rx_mode(dev);
                }
                rtnl_unlock();
        }
index af4e60d..b92a32b 100644 (file)
@@ -2018,9 +2018,11 @@ static int qeth_l3_set_online(struct qeth_card *card, bool carrier_ok)
                netif_device_attach(dev);
                qeth_enable_hw_features(dev);
 
-               if (card->info.open_when_online) {
-                       card->info.open_when_online = 0;
-                       dev_open(dev, NULL);
+               if (netif_running(dev)) {
+                       local_bh_disable();
+                       napi_schedule(&card->napi);
+                       /* kick-start the NAPI softirq: */
+                       local_bh_enable();
                }
                rtnl_unlock();
        }
index f213075..4f0d0e5 100644 (file)
@@ -534,8 +534,7 @@ static void zfcp_fc_adisc_handler(void *data)
 
        /* re-init to undo drop from zfcp_fc_adisc() */
        port->d_id = ntoh24(adisc_resp->adisc_port_id);
-       /* port is good, unblock rport without going through erp */
-       zfcp_scsi_schedule_rport_register(port);
+       /* port is still good, nothing to do */
  out:
        atomic_andnot(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
        put_device(&port->dev);
@@ -595,9 +594,6 @@ void zfcp_fc_link_test_work(struct work_struct *work)
        int retval;
 
        set_worker_desc("zadisc%16llx", port->wwpn); /* < WORKER_DESC_LEN=24 */
-       get_device(&port->dev);
-       port->rport_task = RPORT_DEL;
-       zfcp_scsi_rport_work(&port->rport_work);
 
        /* only issue one test command at one time per port */
        if (atomic_read(&port->status) & ZFCP_STATUS_PORT_LINK_TEST)
index 2e886c1..4995e1e 100644 (file)
@@ -1181,7 +1181,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
                pm80xx_set_thermal_config(pm8001_ha);
        }
 
-       if (pm8001_init_sas_add(pm8001_ha))
+       rc = pm8001_init_sas_add(pm8001_ha);
+       if (rc)
                goto err_out_shost;
        /* phy setting support for motherboard controller */
        rc = pm8001_configure_phy_settings(pm8001_ha);
index 89fa046..0d8afff 100644 (file)
@@ -1497,9 +1497,10 @@ sg_add_device(struct device *cl_dev)
        int error;
        unsigned long iflags;
 
-       error = blk_get_queue(scsidp->request_queue);
-       if (error)
-               return error;
+       if (!blk_get_queue(scsidp->request_queue)) {
+               pr_warn("%s: get scsi_device queue failed\n", __func__);
+               return -ENODEV;
+       }
 
        error = -ENOMEM;
        cdev = cdev_alloc();
index 7f12d93..f282321 100644 (file)
@@ -366,6 +366,7 @@ static void storvsc_on_channel_callback(void *context);
 #define STORVSC_FC_MAX_LUNS_PER_TARGET                 255
 #define STORVSC_FC_MAX_TARGETS                         128
 #define STORVSC_FC_MAX_CHANNELS                                8
+#define STORVSC_FC_MAX_XFER_SIZE                       ((u32)(512 * 1024))
 
 #define STORVSC_IDE_MAX_LUNS_PER_TARGET                        64
 #define STORVSC_IDE_MAX_TARGETS                                1
@@ -2006,6 +2007,9 @@ static int storvsc_probe(struct hv_device *device,
         * protecting it from any weird value.
         */
        max_xfer_bytes = round_down(stor_device->max_transfer_bytes, HV_HYP_PAGE_SIZE);
+       if (is_fc)
+               max_xfer_bytes = min(max_xfer_bytes, STORVSC_FC_MAX_XFER_SIZE);
+
        /* max_hw_sectors_kb */
        host->max_sectors = max_xfer_bytes >> 9;
        /*
index 870aecc..1c1fcab 100644 (file)
@@ -164,7 +164,7 @@ static int imx8mp_hsio_blk_ctrl_probe(struct imx8mp_blk_ctrl *bc)
        clk_hsio_pll->hw.init = &init;
 
        hw = &clk_hsio_pll->hw;
-       ret = devm_clk_hw_register(bc->dev, hw);
+       ret = devm_clk_hw_register(bc->bus_power_dev, hw);
        if (ret)
                return ret;
 
index 08aeb7e..3a99f6d 100644 (file)
@@ -910,9 +910,9 @@ static int amd_sdw_manager_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        amd_manager->acp_mmio = devm_ioremap(dev, res->start, resource_size(res));
-       if (IS_ERR(amd_manager->mmio)) {
+       if (!amd_manager->acp_mmio) {
                dev_err(dev, "mmio not found\n");
-               return PTR_ERR(amd_manager->mmio);
+               return -ENOMEM;
        }
        amd_manager->instance = pdata->instance;
        amd_manager->mmio = amd_manager->acp_mmio +
index dba920e..cf78839 100644 (file)
@@ -922,8 +922,8 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
                        "initializing enumeration and init completion for Slave %d\n",
                        slave->dev_num);
 
-               init_completion(&slave->enumeration_complete);
-               init_completion(&slave->initialization_complete);
+               reinit_completion(&slave->enumeration_complete);
+               reinit_completion(&slave->initialization_complete);
 
        } else if ((status == SDW_SLAVE_ATTACHED) &&
                   (slave->status == SDW_SLAVE_UNATTACHED)) {
@@ -931,7 +931,7 @@ static void sdw_modify_slave_status(struct sdw_slave *slave,
                        "signaling enumeration completion for Slave %d\n",
                        slave->dev_num);
 
-               complete(&slave->enumeration_complete);
+               complete_all(&slave->enumeration_complete);
        }
        slave->status = status;
        mutex_unlock(&bus->bus_lock);
@@ -1951,7 +1951,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,
                                "signaling initialization completion for Slave %d\n",
                                slave->dev_num);
 
-                       complete(&slave->initialization_complete);
+                       complete_all(&slave->initialization_complete);
 
                        /*
                         * If the manager became pm_runtime active, the peripherals will be
index 7970fdb..c029e4d 100644 (file)
@@ -540,7 +540,7 @@ static int qcom_swrm_get_alert_slave_dev_num(struct qcom_swrm_ctrl *ctrl)
                status = (val >> (dev_num * SWRM_MCP_SLV_STATUS_SZ));
 
                if ((status & SWRM_MCP_SLV_STATUS_MASK) == SDW_SLAVE_ALERT) {
-                       ctrl->status[dev_num] = status;
+                       ctrl->status[dev_num] = status & SWRM_MCP_SLV_STATUS_MASK;
                        return dev_num;
                }
        }
index a8a683d..1954c39 100644 (file)
@@ -69,7 +69,7 @@
                                 WR_FIFO_OVERRUN)
 #define QSPI_ALL_IRQS          (QSPI_ERR_IRQS | RESP_FIFO_RDY | \
                                 WR_FIFO_EMPTY | WR_FIFO_FULL | \
-                                TRANSACTION_DONE)
+                                TRANSACTION_DONE | DMA_CHAIN_DONE)
 
 #define PIO_XFER_CTRL          0x0014
 #define REQUEST_COUNT_MSK      0xffff
@@ -308,9 +308,11 @@ static int qcom_qspi_alloc_desc(struct qcom_qspi *ctrl, dma_addr_t dma_ptr,
        dma_addr_t dma_cmd_desc;
 
        /* allocate for dma cmd descriptor */
-       virt_cmd_desc = dma_pool_alloc(ctrl->dma_cmd_pool, GFP_KERNEL | __GFP_ZERO, &dma_cmd_desc);
-       if (!virt_cmd_desc)
-               return -ENOMEM;
+       virt_cmd_desc = dma_pool_alloc(ctrl->dma_cmd_pool, GFP_ATOMIC | __GFP_ZERO, &dma_cmd_desc);
+       if (!virt_cmd_desc) {
+               dev_warn_once(ctrl->dev, "Couldn't find memory for descriptor\n");
+               return -EAGAIN;
+       }
 
        ctrl->virt_cmd_desc[ctrl->n_cmd_desc] = virt_cmd_desc;
        ctrl->dma_cmd_desc[ctrl->n_cmd_desc] = dma_cmd_desc;
@@ -355,10 +357,22 @@ static int qcom_qspi_setup_dma_desc(struct qcom_qspi *ctrl,
 
        for (i = 0; i < sgt->nents; i++) {
                dma_ptr_sg = sg_dma_address(sgt->sgl + i);
+               dma_len_sg = sg_dma_len(sgt->sgl + i);
                if (!IS_ALIGNED(dma_ptr_sg, QSPI_ALIGN_REQ)) {
                        dev_warn_once(ctrl->dev, "dma_address not aligned to %d\n", QSPI_ALIGN_REQ);
                        return -EAGAIN;
                }
+               /*
+                * When reading with DMA the controller writes to memory 1 word
+                * at a time. If the length isn't a multiple of 4 bytes then
+                * the controller can clobber the things later in memory.
+                * Fallback to PIO to be safe.
+                */
+               if (ctrl->xfer.dir == QSPI_READ && (dma_len_sg & 0x03)) {
+                       dev_warn_once(ctrl->dev, "fallback to PIO for read of size %#010x\n",
+                                     dma_len_sg);
+                       return -EAGAIN;
+               }
        }
 
        for (i = 0; i < sgt->nents; i++) {
@@ -441,8 +455,10 @@ static int qcom_qspi_transfer_one(struct spi_master *master,
 
                ret = qcom_qspi_setup_dma_desc(ctrl, xfer);
                if (ret != -EAGAIN) {
-                       if (!ret)
+                       if (!ret) {
+                               dma_wmb();
                                qcom_qspi_dma_xfer(ctrl);
+                       }
                        goto exit;
                }
                dev_warn_once(ctrl->dev, "DMA failure, falling back to PIO\n");
@@ -603,6 +619,9 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
        int_status = readl(ctrl->base + MSTR_INT_STATUS);
        writel(int_status, ctrl->base + MSTR_INT_STATUS);
 
+       /* Ignore disabled interrupts */
+       int_status &= readl(ctrl->base + MSTR_INT_EN);
+
        /* PIO mode handling */
        if (ctrl->xfer.dir == QSPI_WRITE) {
                if (int_status & WR_FIFO_EMPTY)
@@ -647,6 +666,30 @@ static irqreturn_t qcom_qspi_irq(int irq, void *dev_id)
        return ret;
 }
 
+static int qcom_qspi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
+{
+       /*
+        * If qcom_qspi_can_dma() is going to return false we don't need to
+        * adjust anything.
+        */
+       if (op->data.nbytes <= QSPI_MAX_BYTES_FIFO)
+               return 0;
+
+       /*
+        * When reading, the transfer needs to be a multiple of 4 bytes so
+        * shrink the transfer if that's not true. The caller will then do a
+        * second transfer to finish things up.
+        */
+       if (op->data.dir == SPI_MEM_DATA_IN && (op->data.nbytes & 0x3))
+               op->data.nbytes &= ~0x3;
+
+       return 0;
+}
+
+static const struct spi_controller_mem_ops qcom_qspi_mem_ops = {
+       .adjust_op_size = qcom_qspi_adjust_op_size,
+};
+
 static int qcom_qspi_probe(struct platform_device *pdev)
 {
        int ret;
@@ -731,6 +774,7 @@ static int qcom_qspi_probe(struct platform_device *pdev)
        if (of_property_read_bool(pdev->dev.of_node, "iommus"))
                master->can_dma = qcom_qspi_can_dma;
        master->auto_runtime_pm = true;
+       master->mem_ops = &qcom_qspi_mem_ops;
 
        ret = devm_pm_opp_set_clkname(&pdev->dev, "core");
        if (ret)
index 9ccd082..47e72b8 100644 (file)
@@ -145,7 +145,7 @@ static struct fbtft_display display = {
        },
 };
 
-FBTFT_REGISTER_DRIVER(DRVNAME, "ilitek,ili9341", &display);
+FBTFT_REGISTER_SPI_DRIVER(DRVNAME, "ilitek", "ili9341", &display);
 
 MODULE_ALIAS("spi:" DRVNAME);
 MODULE_ALIAS("platform:" DRVNAME);
index e03c87f..0fb97a7 100644 (file)
@@ -1583,8 +1583,10 @@ static int ks_wlan_set_encode_ext(struct net_device *dev,
                        commit |= SME_WEP_FLAG;
                }
                if (enc->key_len) {
-                       memcpy(&key->key_val[0], &enc->key[0], enc->key_len);
-                       key->key_len = enc->key_len;
+                       int key_len = clamp_val(enc->key_len, 0, IW_ENCODING_TOKEN_MAX);
+
+                       memcpy(&key->key_val[0], &enc->key[0], key_len);
+                       key->key_len = key_len;
                        commit |= (SME_WEP_VAL1 << index);
                }
                break;
index c9bff98..e9b168b 100644 (file)
@@ -13,6 +13,7 @@ config VIDEO_ATOMISP
        tristate "Intel Atom Image Signal Processor Driver"
        depends on VIDEO_DEV && INTEL_ATOMISP
        depends on PMIC_OPREGION
+       select V4L2_FWNODE
        select IOSF_MBI
        select VIDEOBUF2_VMALLOC
        select VIDEO_V4L2_SUBDEV_API
index 090345b..6353dbe 100644 (file)
@@ -21,6 +21,7 @@
 #include "osdep_intf.h"
 #include "usb_ops.h"
 
+#include <linux/usb.h>
 #include <linux/ieee80211.h>
 
 static const u8 P802_1H_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0xf8};
@@ -55,6 +56,7 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
        sint i;
        struct xmit_buf *pxmitbuf;
        struct xmit_frame *pxframe;
+       int j;
 
        memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv));
        spin_lock_init(&pxmitpriv->lock);
@@ -117,11 +119,8 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
        _init_queue(&pxmitpriv->pending_xmitbuf_queue);
        pxmitpriv->pallocated_xmitbuf =
                kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf) + 4, GFP_ATOMIC);
-       if (!pxmitpriv->pallocated_xmitbuf) {
-               kfree(pxmitpriv->pallocated_frame_buf);
-               pxmitpriv->pallocated_frame_buf = NULL;
-               return -ENOMEM;
-       }
+       if (!pxmitpriv->pallocated_xmitbuf)
+               goto clean_up_frame_buf;
        pxmitpriv->pxmitbuf = pxmitpriv->pallocated_xmitbuf + 4 -
                              ((addr_t)(pxmitpriv->pallocated_xmitbuf) & 3);
        pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
@@ -129,13 +128,17 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
                INIT_LIST_HEAD(&pxmitbuf->list);
                pxmitbuf->pallocated_buf =
                        kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC);
-               if (!pxmitbuf->pallocated_buf)
-                       return -ENOMEM;
+               if (!pxmitbuf->pallocated_buf) {
+                       j = 0;
+                       goto clean_up_alloc_buf;
+               }
                pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ -
                                 ((addr_t) (pxmitbuf->pallocated_buf) &
                                 (XMITBUF_ALIGN_SZ - 1));
-               if (r8712_xmit_resource_alloc(padapter, pxmitbuf))
-                       return -ENOMEM;
+               if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) {
+                       j = 1;
+                       goto clean_up_alloc_buf;
+               }
                list_add_tail(&pxmitbuf->list,
                                 &(pxmitpriv->free_xmitbuf_queue.queue));
                pxmitbuf++;
@@ -146,6 +149,28 @@ int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
        init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
        tasklet_setup(&pxmitpriv->xmit_tasklet, r8712_xmit_bh);
        return 0;
+
+clean_up_alloc_buf:
+       if (j) {
+               /* failure happened in r8712_xmit_resource_alloc()
+                * delete extra pxmitbuf->pallocated_buf
+                */
+               kfree(pxmitbuf->pallocated_buf);
+       }
+       for (j = 0; j < i; j++) {
+               int k;
+
+               pxmitbuf--;                     /* reset pointer */
+               kfree(pxmitbuf->pallocated_buf);
+               for (k = 0; k < 8; k++)         /* delete xmit urb's */
+                       usb_free_urb(pxmitbuf->pxmit_urb[k]);
+       }
+       kfree(pxmitpriv->pallocated_xmitbuf);
+       pxmitpriv->pallocated_xmitbuf = NULL;
+clean_up_frame_buf:
+       kfree(pxmitpriv->pallocated_frame_buf);
+       pxmitpriv->pallocated_frame_buf = NULL;
+       return -ENOMEM;
 }
 
 void _free_xmit_priv(struct xmit_priv *pxmitpriv)
index 132afbf..ceb6b59 100644 (file)
@@ -112,6 +112,12 @@ int r8712_xmit_resource_alloc(struct _adapter *padapter,
        for (i = 0; i < 8; i++) {
                pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
                if (!pxmitbuf->pxmit_urb[i]) {
+                       int k;
+
+                       for (k = i - 1; k >= 0; k--) {
+                               /* handle allocation errors part way through loop */
+                               usb_free_urb(pxmitbuf->pxmit_urb[k]);
+                       }
                        netdev_err(padapter->pnetdev, "pxmitbuf->pxmit_urb[i] == NULL\n");
                        return -ENOMEM;
                }
index 842f678..cc2b5e8 100644 (file)
@@ -1203,7 +1203,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_get_crit_temp);
 struct thermal_zone_device *
 thermal_zone_device_register_with_trips(const char *type, struct thermal_trip *trips, int num_trips, int mask,
                                        void *devdata, struct thermal_zone_device_ops *ops,
-                                       struct thermal_zone_params *tzp, int passive_delay,
+                                       const struct thermal_zone_params *tzp, int passive_delay,
                                        int polling_delay)
 {
        struct thermal_zone_device *tz;
@@ -1371,7 +1371,7 @@ EXPORT_SYMBOL_GPL(thermal_zone_device_register_with_trips);
 
 struct thermal_zone_device *thermal_zone_device_register(const char *type, int ntrips, int mask,
                                                         void *devdata, struct thermal_zone_device_ops *ops,
-                                                        struct thermal_zone_params *tzp, int passive_delay,
+                                                        const struct thermal_zone_params *tzp, int passive_delay,
                                                         int polling_delay)
 {
        return thermal_zone_device_register_with_trips(type, NULL, ntrips, mask,
index 6fb14e5..bc07ae1 100644 (file)
@@ -238,17 +238,13 @@ static int thermal_of_monitor_init(struct device_node *np, int *delay, int *pdel
        return 0;
 }
 
-static struct thermal_zone_params *thermal_of_parameters_init(struct device_node *np)
+static void thermal_of_parameters_init(struct device_node *np,
+                                      struct thermal_zone_params *tzp)
 {
-       struct thermal_zone_params *tzp;
        int coef[2];
        int ncoef = ARRAY_SIZE(coef);
        int prop, ret;
 
-       tzp = kzalloc(sizeof(*tzp), GFP_KERNEL);
-       if (!tzp)
-               return ERR_PTR(-ENOMEM);
-
        tzp->no_hwmon = true;
 
        if (!of_property_read_u32(np, "sustainable-power", &prop))
@@ -267,8 +263,6 @@ static struct thermal_zone_params *thermal_of_parameters_init(struct device_node
 
        tzp->slope = coef[0];
        tzp->offset = coef[1];
-
-       return tzp;
 }
 
 static struct device_node *thermal_of_zone_get_by_name(struct thermal_zone_device *tz)
@@ -442,13 +436,11 @@ static int thermal_of_unbind(struct thermal_zone_device *tz,
 static void thermal_of_zone_unregister(struct thermal_zone_device *tz)
 {
        struct thermal_trip *trips = tz->trips;
-       struct thermal_zone_params *tzp = tz->tzp;
        struct thermal_zone_device_ops *ops = tz->ops;
 
        thermal_zone_device_disable(tz);
        thermal_zone_device_unregister(tz);
        kfree(trips);
-       kfree(tzp);
        kfree(ops);
 }
 
@@ -477,7 +469,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
 {
        struct thermal_zone_device *tz;
        struct thermal_trip *trips;
-       struct thermal_zone_params *tzp;
+       struct thermal_zone_params tzp = {};
        struct thermal_zone_device_ops *of_ops;
        struct device_node *np;
        int delay, pdelay;
@@ -509,12 +501,7 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
                goto out_kfree_trips;
        }
 
-       tzp = thermal_of_parameters_init(np);
-       if (IS_ERR(tzp)) {
-               ret = PTR_ERR(tzp);
-               pr_err("Failed to initialize parameter from %pOFn: %d\n", np, ret);
-               goto out_kfree_trips;
-       }
+       thermal_of_parameters_init(np, &tzp);
 
        of_ops->bind = thermal_of_bind;
        of_ops->unbind = thermal_of_unbind;
@@ -522,12 +509,12 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
        mask = GENMASK_ULL((ntrips) - 1, 0);
 
        tz = thermal_zone_device_register_with_trips(np->name, trips, ntrips,
-                                                    mask, data, of_ops, tzp,
+                                                    mask, data, of_ops, &tzp,
                                                     pdelay, delay);
        if (IS_ERR(tz)) {
                ret = PTR_ERR(tz);
                pr_err("Failed to register thermal zone %pOFn: %d\n", np, ret);
-               goto out_kfree_tzp;
+               goto out_kfree_trips;
        }
 
        ret = thermal_zone_device_enable(tz);
@@ -540,8 +527,6 @@ static struct thermal_zone_device *thermal_of_zone_register(struct device_node *
 
        return tz;
 
-out_kfree_tzp:
-       kfree(tzp);
 out_kfree_trips:
        kfree(trips);
 out_kfree_of_ops:
index b411a26..1cdefac 100644 (file)
@@ -3070,8 +3070,10 @@ static void gsm_cleanup_mux(struct gsm_mux *gsm, bool disc)
                gsm->has_devices = false;
        }
        for (i = NUM_DLCI - 1; i >= 0; i--)
-               if (gsm->dlci[i])
+               if (gsm->dlci[i]) {
                        gsm_dlci_release(gsm->dlci[i]);
+                       gsm->dlci[i] = NULL;
+               }
        mutex_unlock(&gsm->mutex);
        /* Now wipe the queues */
        tty_ldisc_flush(gsm->tty);
index 75f32f0..84843e2 100644 (file)
@@ -244,7 +244,7 @@ void dw8250_setup_port(struct uart_port *p)
        struct dw8250_port_data *pd = p->private_data;
        struct dw8250_data *data = to_dw8250_data(pd);
        struct uart_8250_port *up = up_to_u8250p(p);
-       u32 reg;
+       u32 reg, old_dlf;
 
        pd->hw_rs485_support = dw8250_detect_rs485_hw(p);
        if (pd->hw_rs485_support) {
@@ -270,9 +270,11 @@ void dw8250_setup_port(struct uart_port *p)
        dev_dbg(p->dev, "Designware UART version %c.%c%c\n",
                (reg >> 24) & 0xff, (reg >> 16) & 0xff, (reg >> 8) & 0xff);
 
+       /* Preserve value written by firmware or bootloader  */
+       old_dlf = dw8250_readl_ext(p, DW_UART_DLF);
        dw8250_writel_ext(p, DW_UART_DLF, ~0U);
        reg = dw8250_readl_ext(p, DW_UART_DLF);
-       dw8250_writel_ext(p, DW_UART_DLF, 0);
+       dw8250_writel_ext(p, DW_UART_DLF, old_dlf);
 
        if (reg) {
                pd->dlf_size = fls(reg);
index 444c74e..daaf2a6 100644 (file)
@@ -1681,13 +1681,6 @@ static int qcom_geni_serial_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       /*
-        * Set pm_runtime status as ACTIVE so that wakeup_irq gets
-        * enabled/disabled from dev_pm_arm_wake_irq during system
-        * suspend/resume respectively.
-        */
-       pm_runtime_set_active(&pdev->dev);
-
        if (port->wakeup_irq > 0) {
                device_init_wakeup(&pdev->dev, true);
                ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
index 7c94579..8b7a42e 100644 (file)
@@ -590,7 +590,7 @@ static void sci_start_tx(struct uart_port *port)
            dma_submit_error(s->cookie_tx)) {
                if (s->cfg->regtype == SCIx_RZ_SCIFA_REGTYPE)
                        /* Switch irq from SCIF to DMA */
-                       disable_irq(s->irqs[SCIx_TXI_IRQ]);
+                       disable_irq_nosync(s->irqs[SCIx_TXI_IRQ]);
 
                s->cookie_tx = 0;
                schedule_work(&s->work_tx);
index 1f565a2..a19db49 100644 (file)
@@ -811,7 +811,7 @@ static void sifive_serial_console_write(struct console *co, const char *s,
        local_irq_restore(flags);
 }
 
-static int __init sifive_serial_console_setup(struct console *co, char *options)
+static int sifive_serial_console_setup(struct console *co, char *options)
 {
        struct sifive_serial_port *ssp;
        int baud = SIFIVE_DEFAULT_BAUD_RATE;
index 404230c..0a370b9 100644 (file)
@@ -59,7 +59,7 @@ static int firmware_loaded;
 /* #define LOOPBACK */
 
 /* The major and minor device numbers are defined in
- * http://www.lanana.org/docs/device-list/devices-2.6+.txt.  For the QE
+ * Documentation/admin-guide/devices.txt.  For the QE
  * UART, we have major number 204 and minor numbers 46 - 49, which are the
  * same as for the CPM2.  This decision was made because no Freescale part
  * has both a CPM and a QE.
index 3959efc..63db04b 100644 (file)
@@ -2285,7 +2285,7 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
        char ch, mbz = 0;
        struct tty_ldisc *ld;
 
-       if (!tty_legacy_tiocsti)
+       if (!tty_legacy_tiocsti && !capable(CAP_SYS_ADMIN))
                return -EIO;
 
        if ((current->signal->tty != tty) && !capable(CAP_SYS_ADMIN))
index ea19253..aa0111b 100644 (file)
@@ -3015,12 +3015,14 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget)
 static int cdns3_gadget_check_config(struct usb_gadget *gadget)
 {
        struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget);
+       struct cdns3_endpoint *priv_ep;
        struct usb_ep *ep;
        int n_in = 0;
        int total;
 
        list_for_each_entry(ep, &gadget->ep_list, ep_list) {
-               if (ep->claimed && (ep->address & USB_DIR_IN))
+               priv_ep = ep_to_cdns3_ep(ep);
+               if ((priv_ep->flags & EP_CLAIMED) && (ep->address & USB_DIR_IN))
                        n_in++;
        }
 
index 934b3d9..15e9bd1 100644 (file)
@@ -436,6 +436,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        /* novation SoundControl XL */
        { USB_DEVICE(0x1235, 0x0061), .driver_info = USB_QUIRK_RESET_RESUME },
 
+       /* Focusrite Scarlett Solo USB */
+       { USB_DEVICE(0x1235, 0x8211), .driver_info =
+                       USB_QUIRK_DISCONNECT_SUSPEND },
+
        /* Huawei 4G LTE module */
        { USB_DEVICE(0x12d1, 0x15bb), .driver_info =
                        USB_QUIRK_DISCONNECT_SUSPEND },
index f6689b7..9c6bf05 100644 (file)
@@ -277,9 +277,9 @@ int dwc3_core_soft_reset(struct dwc3 *dwc)
        /*
         * We're resetting only the device side because, if we're in host mode,
         * XHCI driver will reset the host block. If dwc3 was configured for
-        * host-only mode, then we can return early.
+        * host-only mode or current role is host, then we can return early.
         */
-       if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
+       if (dwc->dr_mode == USB_DR_MODE_HOST || dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
                return 0;
 
        reg = dwc3_readl(dwc->regs, DWC3_DCTL);
@@ -1209,22 +1209,6 @@ static int dwc3_core_init(struct dwc3 *dwc)
                dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
        }
 
-       if (dwc->dr_mode == USB_DR_MODE_HOST ||
-           dwc->dr_mode == USB_DR_MODE_OTG) {
-               reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
-
-               /*
-                * Enable Auto retry Feature to make the controller operating in
-                * Host mode on seeing transaction errors(CRC errors or internal
-                * overrun scenerios) on IN transfers to reply to the device
-                * with a non-terminating retry ACK (i.e, an ACK transcation
-                * packet with Retry=1 & Nump != 0)
-                */
-               reg |= DWC3_GUCTL_HSTINAUTORETRY;
-
-               dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
-       }
-
        /*
         * Must config both number of packets and max burst settings to enable
         * RX and/or TX threshold.
index 8b1295e..a69ac67 100644 (file)
 #define DWC3_GCTL_GBLHIBERNATIONEN     BIT(1)
 #define DWC3_GCTL_DSBLCLKGTNG          BIT(0)
 
-/* Global User Control Register */
-#define DWC3_GUCTL_HSTINAUTORETRY      BIT(14)
-
 /* Global User Control 1 Register */
 #define DWC3_GUCTL1_DEV_DECOUPLE_L1L2_EVT      BIT(31)
 #define DWC3_GUCTL1_TX_IPGAP_LINECHECK_DIS     BIT(28)
index 44a04c9..6604845 100644 (file)
@@ -233,10 +233,12 @@ static int dwc3_pci_quirks(struct dwc3_pci *dwc,
 
                        /*
                         * A lot of BYT devices lack ACPI resource entries for
-                        * the GPIOs, add a fallback mapping to the reference
+                        * the GPIOs. If the ACPI entry for the GPIO controller
+                        * is present add a fallback mapping to the reference
                         * design GPIOs which all boards seem to use.
                         */
-                       gpiod_add_lookup_table(&platform_bytcr_gpios);
+                       if (acpi_dev_present("INT33FC", NULL, -1))
+                               gpiod_add_lookup_table(&platform_bytcr_gpios);
 
                        /*
                         * These GPIOs will turn on the USB2 PHY. Note that we have to
index 1b34891..dd9b904 100644 (file)
@@ -1125,6 +1125,10 @@ int usb_add_config(struct usb_composite_dev *cdev,
                goto done;
 
        status = bind(config);
+
+       if (status == 0)
+               status = usb_gadget_check_config(cdev->gadget);
+
        if (status < 0) {
                while (!list_empty(&config->functions)) {
                        struct usb_function             *f;
index 2acece1..e549022 100644 (file)
@@ -310,13 +310,15 @@ static int gadget_bind(struct usb_gadget *gadget,
        dev->eps_num = i;
        spin_unlock_irqrestore(&dev->lock, flags);
 
-       /* Matches kref_put() in gadget_unbind(). */
-       kref_get(&dev->count);
-
        ret = raw_queue_event(dev, USB_RAW_EVENT_CONNECT, 0, NULL);
-       if (ret < 0)
+       if (ret < 0) {
                dev_err(&gadget->dev, "failed to queue event\n");
+               set_gadget_data(gadget, NULL);
+               return ret;
+       }
 
+       /* Matches kref_put() in gadget_unbind(). */
+       kref_get(&dev->count);
        return ret;
 }
 
index 59188ea..cd58f2a 100644 (file)
@@ -878,7 +878,6 @@ int usb_gadget_activate(struct usb_gadget *gadget)
         */
        if (gadget->connected)
                ret = usb_gadget_connect_locked(gadget);
-       mutex_unlock(&gadget->udc->connect_lock);
 
 unlock:
        mutex_unlock(&gadget->udc->connect_lock);
index 83eaa65..df6028f 100644 (file)
@@ -3718,15 +3718,15 @@ static int tegra_xudc_powerdomain_init(struct tegra_xudc *xudc)
        int err;
 
        xudc->genpd_dev_device = dev_pm_domain_attach_by_name(dev, "dev");
-       if (IS_ERR_OR_NULL(xudc->genpd_dev_device)) {
-               err = PTR_ERR(xudc->genpd_dev_device) ? : -ENODATA;
+       if (IS_ERR(xudc->genpd_dev_device)) {
+               err = PTR_ERR(xudc->genpd_dev_device);
                dev_err(dev, "failed to get device power domain: %d\n", err);
                return err;
        }
 
        xudc->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "ss");
-       if (IS_ERR_OR_NULL(xudc->genpd_dev_ss)) {
-               err = PTR_ERR(xudc->genpd_dev_ss) ? : -ENODATA;
+       if (IS_ERR(xudc->genpd_dev_ss)) {
+               err = PTR_ERR(xudc->genpd_dev_ss);
                dev_err(dev, "failed to get SuperSpeed power domain: %d\n", err);
                return err;
        }
index b9ce8d8..b805c4b 100644 (file)
@@ -672,7 +672,13 @@ ohci_hcd_at91_drv_resume(struct device *dev)
        else
                at91_start_clock(ohci_at91);
 
-       ohci_resume(hcd, false);
+       /*
+        * According to the comment in ohci_hcd_at91_drv_suspend()
+        * we need to do a reset if the 48Mhz clock was stopped,
+        * that is, if ohci_at91->wakeup is clear. Tell ohci_resume()
+        * to reset in this case by setting its "hibernated" flag.
+        */
+       ohci_resume(hcd, !ohci_at91->wakeup);
 
        return 0;
 }
index 51d9d4d..bbdf1b0 100644 (file)
@@ -586,6 +586,7 @@ static int xhci_mtk_probe(struct platform_device *pdev)
        }
 
        device_init_wakeup(dev, true);
+       dma_set_max_seg_size(dev, UINT_MAX);
 
        xhci = hcd_to_xhci(hcd);
        xhci->main_hcd = hcd;
index c6742ba..b9ae5c2 100644 (file)
@@ -479,10 +479,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
                        pdev->device == 0x3432)
                xhci->quirks |= XHCI_BROKEN_STREAMS;
 
-       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483) {
+       if (pdev->vendor == PCI_VENDOR_ID_VIA && pdev->device == 0x3483)
                xhci->quirks |= XHCI_LPM_SUPPORT;
-               xhci->quirks |= XHCI_EP_CTX_BROKEN_DCS;
-       }
 
        if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA &&
                pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) {
index 646ff12..1dde53f 100644 (file)
@@ -626,11 +626,8 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
        struct xhci_ring *ep_ring;
        struct xhci_command *cmd;
        struct xhci_segment *new_seg;
-       struct xhci_segment *halted_seg = NULL;
        union xhci_trb *new_deq;
        int new_cycle;
-       union xhci_trb *halted_trb;
-       int index = 0;
        dma_addr_t addr;
        u64 hw_dequeue;
        bool cycle_found = false;
@@ -668,27 +665,7 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
        hw_dequeue = xhci_get_hw_deq(xhci, dev, ep_index, stream_id);
        new_seg = ep_ring->deq_seg;
        new_deq = ep_ring->dequeue;
-
-       /*
-        * Quirk: xHC write-back of the DCS field in the hardware dequeue
-        * pointer is wrong - use the cycle state of the TRB pointed to by
-        * the dequeue pointer.
-        */
-       if (xhci->quirks & XHCI_EP_CTX_BROKEN_DCS &&
-           !(ep->ep_state & EP_HAS_STREAMS))
-               halted_seg = trb_in_td(xhci, td->start_seg,
-                                      td->first_trb, td->last_trb,
-                                      hw_dequeue & ~0xf, false);
-       if (halted_seg) {
-               index = ((dma_addr_t)(hw_dequeue & ~0xf) - halted_seg->dma) /
-                        sizeof(*halted_trb);
-               halted_trb = &halted_seg->trbs[index];
-               new_cycle = halted_trb->generic.field[3] & 0x1;
-               xhci_dbg(xhci, "Endpoint DCS = %d TRB index = %d cycle = %d\n",
-                        (u8)(hw_dequeue & 0x1), index, new_cycle);
-       } else {
-               new_cycle = hw_dequeue & 0x1;
-       }
+       new_cycle = hw_dequeue & 0x1;
 
        /*
         * We want to find the pointer, segment and cycle state of the new trb
index 6ca8a37..4693d83 100644 (file)
@@ -1145,15 +1145,15 @@ static int tegra_xusb_powerdomain_init(struct device *dev,
        int err;
 
        tegra->genpd_dev_host = dev_pm_domain_attach_by_name(dev, "xusb_host");
-       if (IS_ERR_OR_NULL(tegra->genpd_dev_host)) {
-               err = PTR_ERR(tegra->genpd_dev_host) ? : -ENODATA;
+       if (IS_ERR(tegra->genpd_dev_host)) {
+               err = PTR_ERR(tegra->genpd_dev_host);
                dev_err(dev, "failed to get host pm-domain: %d\n", err);
                return err;
        }
 
        tegra->genpd_dev_ss = dev_pm_domain_attach_by_name(dev, "xusb_ss");
-       if (IS_ERR_OR_NULL(tegra->genpd_dev_ss)) {
-               err = PTR_ERR(tegra->genpd_dev_ss) ? : -ENODATA;
+       if (IS_ERR(tegra->genpd_dev_ss)) {
+               err = PTR_ERR(tegra->genpd_dev_ss);
                dev_err(dev, "failed to get superspeed pm-domain: %d\n", err);
                return err;
        }
index 986d658..36b6e9f 100644 (file)
@@ -77,7 +77,7 @@ static int ehset_probe(struct usb_interface *intf,
        switch (test_pid) {
        case TEST_SE0_NAK_PID:
                ret = ehset_prepare_port_for_testing(hub_udev, portnum);
-               if (!ret)
+               if (ret < 0)
                        break;
                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
@@ -86,7 +86,7 @@ static int ehset_probe(struct usb_interface *intf,
                break;
        case TEST_J_PID:
                ret = ehset_prepare_port_for_testing(hub_udev, portnum);
-               if (!ret)
+               if (ret < 0)
                        break;
                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
@@ -95,7 +95,7 @@ static int ehset_probe(struct usb_interface *intf,
                break;
        case TEST_K_PID:
                ret = ehset_prepare_port_for_testing(hub_udev, portnum);
-               if (!ret)
+               if (ret < 0)
                        break;
                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
@@ -104,7 +104,7 @@ static int ehset_probe(struct usb_interface *intf,
                break;
        case TEST_PACKET_PID:
                ret = ehset_prepare_port_for_testing(hub_udev, portnum);
-               if (!ret)
+               if (ret < 0)
                        break;
                ret = usb_control_msg_send(hub_udev, 0, USB_REQ_SET_FEATURE,
                                           USB_RT_PORT, USB_PORT_FEAT_TEST,
index 288a96a..8ac98e6 100644 (file)
@@ -251,6 +251,7 @@ static void option_instat_callback(struct urb *urb);
 #define QUECTEL_PRODUCT_EM061K_LTA             0x0123
 #define QUECTEL_PRODUCT_EM061K_LMS             0x0124
 #define QUECTEL_PRODUCT_EC25                   0x0125
+#define QUECTEL_PRODUCT_EM060K_128             0x0128
 #define QUECTEL_PRODUCT_EG91                   0x0191
 #define QUECTEL_PRODUCT_EG95                   0x0195
 #define QUECTEL_PRODUCT_BG96                   0x0296
@@ -268,6 +269,7 @@ static void option_instat_callback(struct urb *urb);
 #define QUECTEL_PRODUCT_RM520N                 0x0801
 #define QUECTEL_PRODUCT_EC200U                 0x0901
 #define QUECTEL_PRODUCT_EC200S_CN              0x6002
+#define QUECTEL_PRODUCT_EC200A                 0x6005
 #define QUECTEL_PRODUCT_EM061K_LWW             0x6008
 #define QUECTEL_PRODUCT_EM061K_LCN             0x6009
 #define QUECTEL_PRODUCT_EC200T                 0x6026
@@ -1197,6 +1199,9 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0x00, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K, 0xff, 0xff, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x30) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0x00, 0x40) },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM060K_128, 0xff, 0xff, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x30) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0x00, 0x40) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EM061K_LCN, 0xff, 0xff, 0x40) },
@@ -1225,6 +1230,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_RM520N, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, 0x0900, 0xff, 0, 0), /* RM500U-CN */
          .driver_info = ZLP },
+       { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200A, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200U, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200S_CN, 0xff, 0, 0) },
        { USB_DEVICE_AND_INTERFACE_INFO(QUECTEL_VENDOR_ID, QUECTEL_PRODUCT_EC200T, 0xff, 0, 0) },
index 4c67478..24b8772 100644 (file)
@@ -38,16 +38,6 @@ static struct usb_serial_driver vendor##_device = {          \
        { USB_DEVICE(0x0a21, 0x8001) }  /* MMT-7305WW */
 DEVICE(carelink, CARELINK_IDS);
 
-/* ZIO Motherboard USB driver */
-#define ZIO_IDS()                      \
-       { USB_DEVICE(0x1CBE, 0x0103) }
-DEVICE(zio, ZIO_IDS);
-
-/* Funsoft Serial USB driver */
-#define FUNSOFT_IDS()                  \
-       { USB_DEVICE(0x1404, 0xcddc) }
-DEVICE(funsoft, FUNSOFT_IDS);
-
 /* Infineon Flashloader driver */
 #define FLASHLOADER_IDS()              \
        { USB_DEVICE_INTERFACE_CLASS(0x058b, 0x0041, USB_CLASS_CDC_DATA) }, \
@@ -55,6 +45,11 @@ DEVICE(funsoft, FUNSOFT_IDS);
        { USB_DEVICE(0x8087, 0x0801) }
 DEVICE(flashloader, FLASHLOADER_IDS);
 
+/* Funsoft Serial USB driver */
+#define FUNSOFT_IDS()                  \
+       { USB_DEVICE(0x1404, 0xcddc) }
+DEVICE(funsoft, FUNSOFT_IDS);
+
 /* Google Serial USB SubClass */
 #define GOOGLE_IDS()                                           \
        { USB_VENDOR_AND_INTERFACE_INFO(0x18d1,                 \
@@ -63,16 +58,21 @@ DEVICE(flashloader, FLASHLOADER_IDS);
                                        0x01) }
 DEVICE(google, GOOGLE_IDS);
 
+/* HP4x (48/49) Generic Serial driver */
+#define HP4X_IDS()                     \
+       { USB_DEVICE(0x03f0, 0x0121) }
+DEVICE(hp4x, HP4X_IDS);
+
+/* KAUFMANN RKS+CAN VCP */
+#define KAUFMANN_IDS()                 \
+       { USB_DEVICE(0x16d0, 0x0870) }
+DEVICE(kaufmann, KAUFMANN_IDS);
+
 /* Libtransistor USB console */
 #define LIBTRANSISTOR_IDS()                    \
        { USB_DEVICE(0x1209, 0x8b00) }
 DEVICE(libtransistor, LIBTRANSISTOR_IDS);
 
-/* ViVOpay USB Serial Driver */
-#define VIVOPAY_IDS()                  \
-       { USB_DEVICE(0x1d5f, 0x1004) }  /* ViVOpay 8800 */
-DEVICE(vivopay, VIVOPAY_IDS);
-
 /* Motorola USB Phone driver */
 #define MOTO_IDS()                     \
        { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */    \
@@ -101,10 +101,10 @@ DEVICE(nokia, NOKIA_IDS);
        { USB_DEVICE(0x09d7, 0x0100) }  /* NovAtel FlexPack GPS */
 DEVICE_N(novatel_gps, NOVATEL_IDS, 3);
 
-/* HP4x (48/49) Generic Serial driver */
-#define HP4X_IDS()                     \
-       { USB_DEVICE(0x03f0, 0x0121) }
-DEVICE(hp4x, HP4X_IDS);
+/* Siemens USB/MPI adapter */
+#define SIEMENS_IDS()                  \
+       { USB_DEVICE(0x908, 0x0004) }
+DEVICE(siemens_mpi, SIEMENS_IDS);
 
 /* Suunto ANT+ USB Driver */
 #define SUUNTO_IDS()                   \
@@ -112,45 +112,52 @@ DEVICE(hp4x, HP4X_IDS);
        { USB_DEVICE(0x0fcf, 0x1009) } /* Dynastream ANT USB-m Stick */
 DEVICE(suunto, SUUNTO_IDS);
 
-/* Siemens USB/MPI adapter */
-#define SIEMENS_IDS()                  \
-       { USB_DEVICE(0x908, 0x0004) }
-DEVICE(siemens_mpi, SIEMENS_IDS);
+/* ViVOpay USB Serial Driver */
+#define VIVOPAY_IDS()                  \
+       { USB_DEVICE(0x1d5f, 0x1004) }  /* ViVOpay 8800 */
+DEVICE(vivopay, VIVOPAY_IDS);
+
+/* ZIO Motherboard USB driver */
+#define ZIO_IDS()                      \
+       { USB_DEVICE(0x1CBE, 0x0103) }
+DEVICE(zio, ZIO_IDS);
 
 /* All of the above structures mushed into two lists */
 static struct usb_serial_driver * const serial_drivers[] = {
        &carelink_device,
-       &zio_device,
-       &funsoft_device,
        &flashloader_device,
+       &funsoft_device,
        &google_device,
+       &hp4x_device,
+       &kaufmann_device,
        &libtransistor_device,
-       &vivopay_device,
        &moto_modem_device,
        &motorola_tetra_device,
        &nokia_device,
        &novatel_gps_device,
-       &hp4x_device,
-       &suunto_device,
        &siemens_mpi_device,
+       &suunto_device,
+       &vivopay_device,
+       &zio_device,
        NULL
 };
 
 static const struct usb_device_id id_table[] = {
        CARELINK_IDS(),
-       ZIO_IDS(),
-       FUNSOFT_IDS(),
        FLASHLOADER_IDS(),
+       FUNSOFT_IDS(),
        GOOGLE_IDS(),
+       HP4X_IDS(),
+       KAUFMANN_IDS(),
        LIBTRANSISTOR_IDS(),
-       VIVOPAY_IDS(),
        MOTO_IDS(),
        MOTOROLA_TETRA_IDS(),
        NOKIA_IDS(),
        NOVATEL_IDS(),
-       HP4X_IDS(),
-       SUUNTO_IDS(),
        SIEMENS_IDS(),
+       SUUNTO_IDS(),
+       VIVOPAY_IDS(),
+       ZIO_IDS(),
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index faa184a..9c1dbf3 100644 (file)
@@ -1277,8 +1277,7 @@ static ssize_t select_usb_power_delivery_show(struct device *dev,
 {
        struct typec_port *port = to_typec_port(dev);
        struct usb_power_delivery **pds;
-       struct usb_power_delivery *pd;
-       int ret = 0;
+       int i, ret = 0;
 
        if (!port->ops || !port->ops->pd_get)
                return -EOPNOTSUPP;
@@ -1287,11 +1286,11 @@ static ssize_t select_usb_power_delivery_show(struct device *dev,
        if (!pds)
                return 0;
 
-       for (pd = pds[0]; pd; pd++) {
-               if (pd == port->pd)
-                       ret += sysfs_emit(buf + ret, "[%s] ", dev_name(&pd->dev));
+       for (i = 0; pds[i]; i++) {
+               if (pds[i] == port->pd)
+                       ret += sysfs_emit_at(buf, ret, "[%s] ", dev_name(&pds[i]->dev));
                else
-                       ret += sysfs_emit(buf + ret, "%s ", dev_name(&pd->dev));
+                       ret += sysfs_emit_at(buf, ret, "%s ", dev_name(&pds[i]->dev));
        }
 
        buf[ret - 1] = '\n';
@@ -2288,6 +2287,8 @@ struct typec_port *typec_register_port(struct device *parent,
                return ERR_PTR(ret);
        }
 
+       port->pd = cap->pd;
+
        ret = device_add(&port->dev);
        if (ret) {
                dev_err(parent, "failed to register port (%d)\n", ret);
@@ -2295,7 +2296,7 @@ struct typec_port *typec_register_port(struct device *parent,
                return ERR_PTR(ret);
        }
 
-       ret = typec_port_set_usb_power_delivery(port, cap->pd);
+       ret = usb_power_delivery_link_device(port->pd, &port->dev);
        if (ret) {
                dev_err(&port->dev, "failed to link pd\n");
                device_unregister(&port->dev);
index a905160..9b467a3 100644 (file)
@@ -209,8 +209,8 @@ static int qcom_pmic_typec_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, tcpm);
 
        tcpm->tcpc.fwnode = device_get_named_child_node(tcpm->dev, "connector");
-       if (IS_ERR(tcpm->tcpc.fwnode))
-               return PTR_ERR(tcpm->tcpc.fwnode);
+       if (!tcpm->tcpc.fwnode)
+               return -EINVAL;
 
        tcpm->tcpm_port = tcpm_register_port(tcpm->dev, &tcpm->tcpc);
        if (IS_ERR(tcpm->tcpm_port)) {
index 9b6d6b1..f690131 100644 (file)
@@ -785,6 +785,8 @@ static void ucsi_unregister_partner(struct ucsi_connector *con)
        if (!con->partner)
                return;
 
+       typec_set_mode(con->port, TYPEC_STATE_SAFE);
+
        ucsi_unregister_partner_pdos(con);
        ucsi_unregister_altmodes(con, UCSI_RECIPIENT_SOP);
        typec_unregister_partner(con->partner);
@@ -825,8 +827,6 @@ static void ucsi_partner_change(struct ucsi_connector *con)
                                        UCSI_CONSTAT_PARTNER_FLAG_USB)
                                typec_set_mode(con->port, TYPEC_STATE_USB);
                }
-       } else {
-               typec_set_mode(con->port, TYPEC_STATE_SAFE);
        }
 
        /* Only notify USB controller if partner supports USB data */
index d11cfd2..992a4fa 100644 (file)
@@ -156,7 +156,7 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t,
     return false;
 }
 
-static int sticon_set_def_font(int unit, struct console_font *op)
+static void sticon_set_def_font(int unit)
 {
        if (font_data[unit] != STI_DEF_FONT) {
                if (--FNTREFCOUNT(font_data[unit]) == 0) {
@@ -165,8 +165,6 @@ static int sticon_set_def_font(int unit, struct console_font *op)
                }
                font_data[unit] = STI_DEF_FONT;
        }
-
-       return 0;
 }
 
 static int sticon_set_font(struct vc_data *vc, struct console_font *op,
@@ -246,7 +244,7 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op,
                  vc->vc_video_erase_char, font_data[vc->vc_num]);
 
        /* delete old font in case it is a user font */
-       sticon_set_def_font(unit, NULL);
+       sticon_set_def_font(unit);
 
        FNTREFCOUNT(cooked_font)++;
        font_data[unit] = cooked_font;
@@ -264,7 +262,9 @@ static int sticon_set_font(struct vc_data *vc, struct console_font *op,
 
 static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name)
 {
-       return sticon_set_def_font(vc->vc_num, op);
+       sticon_set_def_font(vc->vc_num);
+
+       return 0;
 }
 
 static int sticon_font_set(struct vc_data *vc, struct console_font *font,
@@ -297,7 +297,7 @@ static void sticon_deinit(struct vc_data *c)
 
     /* free memory used by user font */
     for (i = 0; i < MAX_NR_CONSOLES; i++)
-       sticon_set_def_font(i, NULL);
+       sticon_set_def_font(i);
 }
 
 static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
index e25ba52..7ad047b 100644 (file)
@@ -65,16 +65,8 @@ static struct vgastate vgastate;
  *  Interface used by the world
  */
 
-static const char *vgacon_startup(void);
-static void vgacon_init(struct vc_data *c, int init);
-static void vgacon_deinit(struct vc_data *c);
-static void vgacon_cursor(struct vc_data *c, int mode);
-static int vgacon_switch(struct vc_data *c);
-static int vgacon_blank(struct vc_data *c, int blank, int mode_switch);
-static void vgacon_scrolldelta(struct vc_data *c, int lines);
 static int vgacon_set_origin(struct vc_data *c);
-static void vgacon_save_screen(struct vc_data *c);
-static void vgacon_invert_region(struct vc_data *c, u16 * p, int count);
+
 static struct uni_pagedict *vgacon_uni_pagedir;
 static int vgacon_refcount;
 
@@ -142,12 +134,6 @@ static inline void vga_set_mem_top(struct vc_data *c)
        write_vga(12, (c->vc_visible_origin - vga_vram_base) / 2);
 }
 
-static void vgacon_restore_screen(struct vc_data *c)
-{
-       if (c->vc_origin != c->vc_visible_origin)
-               vgacon_scrolldelta(c, 0);
-}
-
 static void vgacon_scrolldelta(struct vc_data *c, int lines)
 {
        vc_scrolldelta_helper(c, lines, vga_rolled_over, (void *)vga_vram_base,
@@ -155,6 +141,12 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        vga_set_mem_top(c);
 }
 
+static void vgacon_restore_screen(struct vc_data *c)
+{
+       if (c->vc_origin != c->vc_visible_origin)
+               vgacon_scrolldelta(c, 0);
+}
+
 static const char *vgacon_startup(void)
 {
        const char *display_desc = NULL;
@@ -445,7 +437,7 @@ static void vgacon_invert_region(struct vc_data *c, u16 * p, int count)
        }
 }
 
-static void vgacon_set_cursor_size(int xpos, int from, int to)
+static void vgacon_set_cursor_size(int from, int to)
 {
        unsigned long flags;
        int curs, cure;
@@ -478,18 +470,22 @@ static void vgacon_set_cursor_size(int xpos, int from, int to)
 
 static void vgacon_cursor(struct vc_data *c, int mode)
 {
+       unsigned int c_height;
+
        if (c->vc_mode != KD_TEXT)
                return;
 
        vgacon_restore_screen(c);
 
+       c_height = c->vc_cell_height;
+
        switch (mode) {
        case CM_ERASE:
                write_vga(14, (c->vc_pos - vga_vram_base) / 2);
                if (vga_video_type >= VIDEO_TYPE_VGAC)
-                       vgacon_set_cursor_size(c->state.x, 31, 30);
+                       vgacon_set_cursor_size(31, 30);
                else
-                       vgacon_set_cursor_size(c->state.x, 31, 31);
+                       vgacon_set_cursor_size(31, 31);
                break;
 
        case CM_MOVE:
@@ -497,51 +493,38 @@ static void vgacon_cursor(struct vc_data *c, int mode)
                write_vga(14, (c->vc_pos - vga_vram_base) / 2);
                switch (CUR_SIZE(c->vc_cursor_type)) {
                case CUR_UNDERLINE:
-                       vgacon_set_cursor_size(c->state.x,
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 2 : 3),
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 1 : 2));
+                       vgacon_set_cursor_size(c_height -
+                                              (c_height < 10 ? 2 : 3),
+                                              c_height -
+                                              (c_height < 10 ? 1 : 2));
                        break;
                case CUR_TWO_THIRDS:
-                       vgacon_set_cursor_size(c->state.x,
-                                              c->vc_cell_height / 3,
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 1 : 2));
+                       vgacon_set_cursor_size(c_height / 3, c_height -
+                                              (c_height < 10 ? 1 : 2));
                        break;
                case CUR_LOWER_THIRD:
-                       vgacon_set_cursor_size(c->state.x,
-                                              (c->vc_cell_height * 2) / 3,
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 1 : 2));
+                       vgacon_set_cursor_size(c_height * 2 / 3, c_height -
+                                              (c_height < 10 ? 1 : 2));
                        break;
                case CUR_LOWER_HALF:
-                       vgacon_set_cursor_size(c->state.x,
-                                              c->vc_cell_height / 2,
-                                              c->vc_cell_height -
-                                              (c->vc_cell_height <
-                                               10 ? 1 : 2));
+                       vgacon_set_cursor_size(c_height / 2, c_height -
+                                              (c_height < 10 ? 1 : 2));
                        break;
                case CUR_NONE:
                        if (vga_video_type >= VIDEO_TYPE_VGAC)
-                               vgacon_set_cursor_size(c->state.x, 31, 30);
+                               vgacon_set_cursor_size(31, 30);
                        else
-                               vgacon_set_cursor_size(c->state.x, 31, 31);
+                               vgacon_set_cursor_size(31, 31);
                        break;
                default:
-                       vgacon_set_cursor_size(c->state.x, 1,
-                                              c->vc_cell_height);
+                       vgacon_set_cursor_size(1, c_height);
                        break;
                }
                break;
        }
 }
 
-static int vgacon_doresize(struct vc_data *c,
+static void vgacon_doresize(struct vc_data *c,
                unsigned int width, unsigned int height)
 {
        unsigned long flags;
@@ -600,7 +583,6 @@ static int vgacon_doresize(struct vc_data *c,
        }
 
        raw_spin_unlock_irqrestore(&vga_lock, flags);
-       return 0;
 }
 
 static int vgacon_switch(struct vc_data *c)
index 5c232eb..c137d6a 100644 (file)
@@ -1732,6 +1732,9 @@ static int au1200fb_drv_probe(struct platform_device *dev)
 
        /* Now hook interrupt too */
        irq = platform_get_irq(dev, 0);
+       if (irq < 0)
+               return irq;
+
        ret = request_irq(irq, au1200fb_handle_irq,
                          IRQF_SHARED, "lcd", (void *)dev);
        if (ret) {
index 025d663..39f438d 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index 832a82f..90fdc9d 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/fb.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index 6335cd3..98c60f7 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index 6884572..6427b85 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index c6c9d04..887fad4 100644 (file)
@@ -1612,8 +1612,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info,
        }
 }
 
-static void fbcon_redraw(struct vc_data *vc, struct fbcon_display *p,
-                        int line, int count, int offset)
+static void fbcon_redraw(struct vc_data *vc, int line, int count, int offset)
 {
        unsigned short *d = (unsigned short *)
            (vc->vc_origin + vc->vc_size_row * line);
@@ -1827,7 +1826,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
 
                case SCROLL_REDRAW:
                      redraw_up:
-                       fbcon_redraw(vc, p, t, b - t - count,
+                       fbcon_redraw(vc, t, b - t - count,
                                     count * vc->vc_cols);
                        fbcon_clear(vc, b - count, 0, count, vc->vc_cols);
                        scr_memsetw((unsigned short *) (vc->vc_origin +
@@ -1913,7 +1912,7 @@ static bool fbcon_scroll(struct vc_data *vc, unsigned int t, unsigned int b,
 
                case SCROLL_REDRAW:
                      redraw_down:
-                       fbcon_redraw(vc, p, b - 1, b - t - count,
+                       fbcon_redraw(vc, b - 1, b - t - count,
                                     -count * vc->vc_cols);
                        fbcon_clear(vc, t, 0, count, vc->vc_cols);
                        scr_memsetw((unsigned short *) (vc->vc_origin +
index 94fe529..22158d9 100644 (file)
@@ -548,7 +548,9 @@ static int ep93xxfb_probe(struct platform_device *pdev)
        }
 
        ep93xxfb_set_par(info);
-       clk_prepare_enable(fbi->clk);
+       err = clk_prepare_enable(fbi->clk);
+       if (err)
+               goto failed_check;
 
        err = register_framebuffer(info);
        if (err)
index c6d3111..c473841 100644 (file)
@@ -16,7 +16,8 @@
 #include <linux/fb.h>
 #include <linux/mm.h>
 #include <linux/timer.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/upa.h>
index 9aa15be..d4a9a58 100644 (file)
@@ -12,8 +12,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
-#include <linux/of_platform.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
index adf3669..77dedd2 100644 (file)
@@ -613,10 +613,10 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
        if (var->hsync_len < 1    || var->hsync_len > 64)
                printk(KERN_ERR "%s: invalid hsync_len %d\n",
                        info->fix.id, var->hsync_len);
-       if (var->left_margin > 255)
+       if (var->left_margin < 3  || var->left_margin > 255)
                printk(KERN_ERR "%s: invalid left_margin %d\n",
                        info->fix.id, var->left_margin);
-       if (var->right_margin > 255)
+       if (var->right_margin < 1 || var->right_margin > 255)
                printk(KERN_ERR "%s: invalid right_margin %d\n",
                        info->fix.id, var->right_margin);
        if (var->yres < 1 || var->yres > ymax_mask)
@@ -673,7 +673,8 @@ static int imxfb_init_fbinfo(struct platform_device *pdev)
 
        pr_debug("%s\n",__func__);
 
-       info->pseudo_palette = kmalloc_array(16, sizeof(u32), GFP_KERNEL);
+       info->pseudo_palette = devm_kmalloc_array(&pdev->dev, 16,
+                                                 sizeof(u32), GFP_KERNEL);
        if (!info->pseudo_palette)
                return -ENOMEM;
 
@@ -868,7 +869,6 @@ static int imxfb_probe(struct platform_device *pdev)
        struct imxfb_info *fbi;
        struct lcd_device *lcd;
        struct fb_info *info;
-       struct resource *res;
        struct imx_fb_videomode *m;
        const struct of_device_id *of_id;
        struct device_node *display_np;
@@ -885,10 +885,6 @@ static int imxfb_probe(struct platform_device *pdev)
        if (of_id)
                pdev->id_entry = of_id->data;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res)
-               return -ENODEV;
-
        info = framebuffer_alloc(sizeof(struct imxfb_info), &pdev->dev);
        if (!info)
                return -ENOMEM;
@@ -907,7 +903,7 @@ static int imxfb_probe(struct platform_device *pdev)
        if (!display_np) {
                dev_err(&pdev->dev, "No display defined in devicetree\n");
                ret = -EINVAL;
-               goto failed_of_parse;
+               goto failed_init;
        }
 
        /*
@@ -921,13 +917,13 @@ static int imxfb_probe(struct platform_device *pdev)
        if (!fbi->mode) {
                ret = -ENOMEM;
                of_node_put(display_np);
-               goto failed_of_parse;
+               goto failed_init;
        }
 
        ret = imxfb_of_read_mode(&pdev->dev, display_np, fbi->mode);
        of_node_put(display_np);
        if (ret)
-               goto failed_of_parse;
+               goto failed_init;
 
        /* Calculate maximum bytes used per pixel. In most cases this should
         * be the same as m->bpp/8 */
@@ -940,7 +936,7 @@ static int imxfb_probe(struct platform_device *pdev)
        fbi->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
        if (IS_ERR(fbi->clk_ipg)) {
                ret = PTR_ERR(fbi->clk_ipg);
-               goto failed_getclock;
+               goto failed_init;
        }
 
        /*
@@ -955,25 +951,25 @@ static int imxfb_probe(struct platform_device *pdev)
         */
        ret = clk_prepare_enable(fbi->clk_ipg);
        if (ret)
-               goto failed_getclock;
+               goto failed_init;
        clk_disable_unprepare(fbi->clk_ipg);
 
        fbi->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(fbi->clk_ahb)) {
                ret = PTR_ERR(fbi->clk_ahb);
-               goto failed_getclock;
+               goto failed_init;
        }
 
        fbi->clk_per = devm_clk_get(&pdev->dev, "per");
        if (IS_ERR(fbi->clk_per)) {
                ret = PTR_ERR(fbi->clk_per);
-               goto failed_getclock;
+               goto failed_init;
        }
 
-       fbi->regs = devm_ioremap_resource(&pdev->dev, res);
+       fbi->regs = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(fbi->regs)) {
                ret = PTR_ERR(fbi->regs);
-               goto failed_ioremap;
+               goto failed_init;
        }
 
        fbi->map_size = PAGE_ALIGN(info->fix.smem_len);
@@ -982,7 +978,7 @@ static int imxfb_probe(struct platform_device *pdev)
        if (!info->screen_buffer) {
                dev_err(&pdev->dev, "Failed to allocate video RAM\n");
                ret = -ENOMEM;
-               goto failed_map;
+               goto failed_init;
        }
 
        info->fix.smem_start = fbi->map_dma;
@@ -1034,18 +1030,11 @@ static int imxfb_probe(struct platform_device *pdev)
 
 failed_lcd:
        unregister_framebuffer(info);
-
 failed_register:
        fb_dealloc_cmap(&info->cmap);
 failed_cmap:
        dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer,
                    fbi->map_dma);
-failed_map:
-failed_ioremap:
-failed_getclock:
-       release_mem_region(res->start, resource_size(res));
-failed_of_parse:
-       kfree(info->pseudo_palette);
 failed_init:
        framebuffer_release(info);
        return ret;
@@ -1062,11 +1051,10 @@ static void imxfb_remove(struct platform_device *pdev)
        fb_dealloc_cmap(&info->cmap);
        dma_free_wc(&pdev->dev, fbi->map_size, info->screen_buffer,
                    fbi->map_dma);
-       kfree(info->pseudo_palette);
        framebuffer_release(info);
 }
 
-static int __maybe_unused imxfb_suspend(struct device *dev)
+static int imxfb_suspend(struct device *dev)
 {
        struct fb_info *info = dev_get_drvdata(dev);
        struct imxfb_info *fbi = info->par;
@@ -1076,7 +1064,7 @@ static int __maybe_unused imxfb_suspend(struct device *dev)
        return 0;
 }
 
-static int __maybe_unused imxfb_resume(struct device *dev)
+static int imxfb_resume(struct device *dev)
 {
        struct fb_info *info = dev_get_drvdata(dev);
        struct imxfb_info *fbi = info->par;
@@ -1086,13 +1074,13 @@ static int __maybe_unused imxfb_resume(struct device *dev)
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(imxfb_pm_ops, imxfb_suspend, imxfb_resume);
 
 static struct platform_driver imxfb_driver = {
        .driver         = {
                .name   = DRIVER_NAME,
                .of_match_table = imxfb_of_dev_id,
-               .pm     = &imxfb_pm_ops,
+               .pm     = pm_sleep_ptr(&imxfb_pm_ops),
        },
        .probe          = imxfb_probe,
        .remove_new     = imxfb_remove,
index edfa0a0..79886a2 100644 (file)
@@ -83,11 +83,11 @@ volatile u32 i,count=0; \
 static u32 InitSDRAMRegisters(volatile STG4000REG __iomem *pSTGReg,
                              u32 dwSubSysID, u32 dwRevID)
 {
-       u32 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
-       u32 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
-       u32 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
-       u32 adwSDRAMRsh[] = { 36, 39, 40 };
-       u32 adwChipSpeed[] = { 110, 120, 125 };
+       static const u8 adwSDRAMArgCfg0[] = { 0xa0, 0x80, 0xa0, 0xa0, 0xa0 };
+       static const u16 adwSDRAMCfg1[] = { 0x8732, 0x8732, 0xa732, 0xa732, 0x8732 };
+       static const u16 adwSDRAMCfg2[] = { 0x87d2, 0x87d2, 0xa7d2, 0x87d2, 0xa7d2 };
+       static const u8 adwSDRAMRsh[] = { 36, 39, 40 };
+       static const u8 adwChipSpeed[] = { 110, 120, 125 };
        u32 dwMemTypeIdx;
        u32 dwChipSpeedIdx;
 
index 3ffc0a7..89ca482 100644 (file)
@@ -16,8 +16,9 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/fbio.h>
 
index 61aed7f..c35a747 100644 (file)
@@ -15,9 +15,7 @@
 #include <linux/module.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#if defined(CONFIG_OF)
-#include <linux/of_platform.h>
-#endif
+
 #include "mb862xxfb.h"
 #include "mb862xx_reg.h"
 #include "mb862xxfb_accel.h"
index b5c8fca..9dc347d 100644 (file)
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/pci.h>
-#if defined(CONFIG_OF)
+#include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/of_platform.h>
-#endif
+#include <linux/platform_device.h>
+
 #include "mb862xxfb.h"
 #include "mb862xx_reg.h"
 
index ba94a0a..77fce12 100644 (file)
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/jiffies.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/sched/signal.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
-#include <linux/of_device.h>
 
 #include <video/omapfb_dss.h>
 #include <video/mipi_display.h>
index 0876962..e2e747c 100644 (file)
@@ -15,7 +15,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index f8283fc..b27f43b 100644 (file)
@@ -30,9 +30,9 @@
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/nvram.h>
+#include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
+#include <linux/platform_device.h>
 
 #include "macmodes.h"
 #include "platinumfb.h"
index 7f79db8..21e9fd8 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/fb.h>
 #include <linux/mm.h>
 #include <linux/uaccess.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 
 #include <asm/fbio.h>
 
index 490bd9a..17d61e1 100644 (file)
@@ -8,7 +8,8 @@
 #include <linux/kernel.h>
 #include <linux/fb.h>
 #include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 struct gfb_info {
        struct fb_info          *info;
index 2cab4b9..e64ec7d 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 
 #include <asm/io.h>
 
index 6ec358a..c4e01e8 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/fb.h>
 #include <linux/pci.h>
 #include <linux/init.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 
 #include <asm/io.h>
 
index fc3ac23..255eb57 100644 (file)
@@ -17,7 +17,8 @@
 #include <linux/init.h>
 #include <linux/fb.h>
 #include <linux/mm.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
 
 #include <asm/io.h>
 #include <asm/fbio.h>
index 2aa3a52..542badd 100644 (file)
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
+#include <linux/platform_device.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
-#include <linux/of_device.h>
-#include <linux/of_platform.h>
-#include <linux/of_address.h>
+#include <linux/of.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 
index c7715f8..3bdd5b5 100644 (file)
@@ -112,6 +112,7 @@ struct irq_info {
        unsigned int irq_epoch; /* If eoi_cpu valid: irq_epoch of event */
        u64 eoi_time;           /* Time in jiffies when to EOI. */
        raw_spinlock_t lock;
+       bool is_static;           /* Is event channel static */
 
        union {
                unsigned short virq;
@@ -815,15 +816,6 @@ static void xen_free_irq(unsigned irq)
        irq_free_desc(irq);
 }
 
-static void xen_evtchn_close(evtchn_port_t port)
-{
-       struct evtchn_close close;
-
-       close.port = port;
-       if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
-               BUG();
-}
-
 /* Not called for lateeoi events. */
 static void event_handler_exit(struct irq_info *info)
 {
@@ -982,7 +974,8 @@ static void __unbind_from_irq(unsigned int irq)
                unsigned int cpu = cpu_from_irq(irq);
                struct xenbus_device *dev;
 
-               xen_evtchn_close(evtchn);
+               if (!info->is_static)
+                       xen_evtchn_close(evtchn);
 
                switch (type_from_irq(irq)) {
                case IRQT_VIRQ:
@@ -1574,7 +1567,7 @@ int xen_set_irq_priority(unsigned irq, unsigned priority)
 }
 EXPORT_SYMBOL_GPL(xen_set_irq_priority);
 
-int evtchn_make_refcounted(evtchn_port_t evtchn)
+int evtchn_make_refcounted(evtchn_port_t evtchn, bool is_static)
 {
        int irq = get_evtchn_to_irq(evtchn);
        struct irq_info *info;
@@ -1590,6 +1583,7 @@ int evtchn_make_refcounted(evtchn_port_t evtchn)
        WARN_ON(info->refcnt != -1);
 
        info->refcnt = 1;
+       info->is_static = is_static;
 
        return 0;
 }
index c99415a..9139a73 100644 (file)
@@ -366,10 +366,10 @@ static int evtchn_resize_ring(struct per_user_data *u)
        return 0;
 }
 
-static int evtchn_bind_to_user(struct per_user_data *u, evtchn_port_t port)
+static int evtchn_bind_to_user(struct per_user_data *u, evtchn_port_t port,
+                              bool is_static)
 {
        struct user_evtchn *evtchn;
-       struct evtchn_close close;
        int rc = 0;
 
        /*
@@ -402,14 +402,14 @@ static int evtchn_bind_to_user(struct per_user_data *u, evtchn_port_t port)
        if (rc < 0)
                goto err;
 
-       rc = evtchn_make_refcounted(port);
+       rc = evtchn_make_refcounted(port, is_static);
        return rc;
 
 err:
        /* bind failed, should close the port now */
-       close.port = port;
-       if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
-               BUG();
+       if (!is_static)
+               xen_evtchn_close(port);
+
        del_evtchn(u, evtchn);
        return rc;
 }
@@ -456,7 +456,7 @@ static long evtchn_ioctl(struct file *file,
                if (rc != 0)
                        break;
 
-               rc = evtchn_bind_to_user(u, bind_virq.port);
+               rc = evtchn_bind_to_user(u, bind_virq.port, false);
                if (rc == 0)
                        rc = bind_virq.port;
                break;
@@ -482,7 +482,7 @@ static long evtchn_ioctl(struct file *file,
                if (rc != 0)
                        break;
 
-               rc = evtchn_bind_to_user(u, bind_interdomain.local_port);
+               rc = evtchn_bind_to_user(u, bind_interdomain.local_port, false);
                if (rc == 0)
                        rc = bind_interdomain.local_port;
                break;
@@ -507,7 +507,7 @@ static long evtchn_ioctl(struct file *file,
                if (rc != 0)
                        break;
 
-               rc = evtchn_bind_to_user(u, alloc_unbound.port);
+               rc = evtchn_bind_to_user(u, alloc_unbound.port, false);
                if (rc == 0)
                        rc = alloc_unbound.port;
                break;
@@ -536,6 +536,23 @@ static long evtchn_ioctl(struct file *file,
                break;
        }
 
+       case IOCTL_EVTCHN_BIND_STATIC: {
+               struct ioctl_evtchn_bind bind;
+               struct user_evtchn *evtchn;
+
+               rc = -EFAULT;
+               if (copy_from_user(&bind, uarg, sizeof(bind)))
+                       break;
+
+               rc = -EISCONN;
+               evtchn = find_evtchn(u, bind.port);
+               if (evtchn)
+                       break;
+
+               rc = evtchn_bind_to_user(u, bind.port, true);
+               break;
+       }
+
        case IOCTL_EVTCHN_NOTIFY: {
                struct ioctl_evtchn_notify notify;
                struct user_evtchn *evtchn;
index e1ec725..f13c3b7 100644 (file)
@@ -498,14 +498,21 @@ static LIST_HEAD(deferred_list);
 static void gnttab_handle_deferred(struct timer_list *);
 static DEFINE_TIMER(deferred_timer, gnttab_handle_deferred);
 
+static atomic64_t deferred_count;
+static atomic64_t leaked_count;
+static unsigned int free_per_iteration = 10;
+module_param(free_per_iteration, uint, 0600);
+
 static void gnttab_handle_deferred(struct timer_list *unused)
 {
-       unsigned int nr = 10;
+       unsigned int nr = READ_ONCE(free_per_iteration);
+       const bool ignore_limit = nr == 0;
        struct deferred_entry *first = NULL;
        unsigned long flags;
+       size_t freed = 0;
 
        spin_lock_irqsave(&gnttab_list_lock, flags);
-       while (nr--) {
+       while ((ignore_limit || nr--) && !list_empty(&deferred_list)) {
                struct deferred_entry *entry
                        = list_first_entry(&deferred_list,
                                           struct deferred_entry, list);
@@ -515,10 +522,14 @@ static void gnttab_handle_deferred(struct timer_list *unused)
                list_del(&entry->list);
                spin_unlock_irqrestore(&gnttab_list_lock, flags);
                if (_gnttab_end_foreign_access_ref(entry->ref)) {
+                       uint64_t ret = atomic64_dec_return(&deferred_count);
+
                        put_free_entry(entry->ref);
-                       pr_debug("freeing g.e. %#x (pfn %#lx)\n",
-                                entry->ref, page_to_pfn(entry->page));
+                       pr_debug("freeing g.e. %#x (pfn %#lx), %llu remaining\n",
+                                entry->ref, page_to_pfn(entry->page),
+                                (unsigned long long)ret);
                        put_page(entry->page);
+                       freed++;
                        kfree(entry);
                        entry = NULL;
                } else {
@@ -530,21 +541,22 @@ static void gnttab_handle_deferred(struct timer_list *unused)
                spin_lock_irqsave(&gnttab_list_lock, flags);
                if (entry)
                        list_add_tail(&entry->list, &deferred_list);
-               else if (list_empty(&deferred_list))
-                       break;
        }
-       if (!list_empty(&deferred_list) && !timer_pending(&deferred_timer)) {
+       if (list_empty(&deferred_list))
+               WARN_ON(atomic64_read(&deferred_count));
+       else if (!timer_pending(&deferred_timer)) {
                deferred_timer.expires = jiffies + HZ;
                add_timer(&deferred_timer);
        }
        spin_unlock_irqrestore(&gnttab_list_lock, flags);
+       pr_debug("Freed %zu references", freed);
 }
 
 static void gnttab_add_deferred(grant_ref_t ref, struct page *page)
 {
        struct deferred_entry *entry;
        gfp_t gfp = (in_atomic() || irqs_disabled()) ? GFP_ATOMIC : GFP_KERNEL;
-       const char *what = KERN_WARNING "leaking";
+       uint64_t leaked, deferred;
 
        entry = kmalloc(sizeof(*entry), gfp);
        if (!page) {
@@ -567,10 +579,16 @@ static void gnttab_add_deferred(grant_ref_t ref, struct page *page)
                        add_timer(&deferred_timer);
                }
                spin_unlock_irqrestore(&gnttab_list_lock, flags);
-               what = KERN_DEBUG "deferring";
+               deferred = atomic64_inc_return(&deferred_count);
+               leaked = atomic64_read(&leaked_count);
+               pr_debug("deferring g.e. %#x (pfn %#lx) (total deferred %llu, total leaked %llu)\n",
+                        ref, page ? page_to_pfn(page) : -1, deferred, leaked);
+       } else {
+               deferred = atomic64_read(&deferred_count);
+               leaked = atomic64_inc_return(&leaked_count);
+               pr_warn("leaking g.e. %#x (pfn %#lx) (total deferred %llu, total leaked %llu)\n",
+                       ref, page ? page_to_pfn(page) : -1, deferred, leaked);
        }
-       printk("%s g.e. %#x (pfn %#lx)\n",
-              what, ref, page ? page_to_pfn(page) : -1);
 }
 
 int gnttab_try_end_foreign_access(grant_ref_t ref)
index 58b732d..639bf62 100644 (file)
@@ -811,6 +811,9 @@ static int xenbus_probe_thread(void *unused)
 
 static int __init xenbus_probe_initcall(void)
 {
+       if (!xen_domain())
+               return -ENODEV;
+
        /*
         * Probe XenBus here in the XS_PV case, and also XS_HVM unless we
         * need to wait for the platform PCI device to come up or
index 0c51889..29281b7 100644 (file)
@@ -46,8 +46,8 @@ static inline struct p9_fid *v9fs_fid_clone(struct dentry *dentry)
  * NOTE: these are set after open so only reflect 9p client not
  * underlying file system on server.
  */
-static inline void v9fs_fid_add_modes(struct p9_fid *fid, int s_flags,
-       int s_cache, unsigned int f_flags)
+static inline void v9fs_fid_add_modes(struct p9_fid *fid, unsigned int s_flags,
+       unsigned int s_cache, unsigned int f_flags)
 {
        if (fid->qid.type != P9_QTFILE)
                return;
@@ -57,7 +57,7 @@ static inline void v9fs_fid_add_modes(struct p9_fid *fid, int s_flags,
           (s_flags & V9FS_DIRECT_IO) || (f_flags & O_DIRECT)) {
                fid->mode |= P9L_DIRECT; /* no read or write cache */
        } else if ((!(s_cache & CACHE_WRITEBACK)) ||
-                               (f_flags & O_DSYNC) | (s_flags & V9FS_SYNC)) {
+                               (f_flags & O_DSYNC) || (s_flags & V9FS_SYNC)) {
                fid->mode |= P9L_NOWRITECACHE;
        }
 }
index c7f774f..d525957 100644 (file)
@@ -545,8 +545,6 @@ void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses)
        p9_client_begin_disconnect(v9ses->clnt);
 }
 
-extern int v9fs_error_init(void);
-
 static struct kobject *v9fs_kobj;
 
 #ifdef CONFIG_9P_FSCACHE
index 06a2514..698c43d 100644 (file)
@@ -108,7 +108,7 @@ enum p9_cache_bits {
 
 struct v9fs_session_info {
        /* options */
-       unsigned char flags;
+       unsigned int flags;
        unsigned char nodev;
        unsigned short debug;
        unsigned int afid;
index 45b684b..4102759 100644 (file)
@@ -208,7 +208,7 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
        struct p9_fid *fid;
        __le32 version;
        loff_t i_size;
-       int retval = 0;
+       int retval = 0, put_err;
 
        fid = filp->private_data;
        p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d\n",
@@ -221,7 +221,8 @@ int v9fs_dir_release(struct inode *inode, struct file *filp)
                spin_lock(&inode->i_lock);
                hlist_del(&fid->ilist);
                spin_unlock(&inode->i_lock);
-               retval = p9_fid_put(fid);
+               put_err = p9_fid_put(fid);
+               retval = retval < 0 ? retval : put_err;
        }
 
        if ((filp->f_mode & FMODE_WRITE)) {
index 2996fb0..11cd8d2 100644 (file)
@@ -505,10 +505,7 @@ v9fs_file_mmap(struct file *filp, struct vm_area_struct *vma)
        p9_debug(P9_DEBUG_MMAP, "filp :%p\n", filp);
 
        if (!(v9ses->cache & CACHE_WRITEBACK)) {
-               p9_debug(P9_DEBUG_CACHE, "(no mmap mode)");
-               if (vma->vm_flags & VM_MAYSHARE)
-                       return -ENODEV;
-               invalidate_inode_pages2(filp->f_mapping);
+               p9_debug(P9_DEBUG_CACHE, "(read-only mmap mode)");
                return generic_file_readonly_mmap(filp, vma);
        }
 
index 36b466e..950cf61 100644 (file)
@@ -163,7 +163,6 @@ int v9fs_uflags2omode(int uflags, int extended)
 {
        int ret;
 
-       ret = 0;
        switch (uflags&3) {
        default:
        case O_RDONLY:
@@ -603,7 +602,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir,
 
        p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
 
-       err = 0;
        name = dentry->d_name.name;
        dfid = v9fs_parent_fid(dentry);
        if (IS_ERR(dfid)) {
@@ -815,8 +813,6 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
        if (!(flags & O_CREAT) || d_really_is_positive(dentry))
                return finish_no_open(file, res);
 
-       err = 0;
-
        v9ses = v9fs_inode2v9ses(dir);
        perm = unixmode2p9mode(v9ses, mode);
        p9_omode = v9fs_uflags2omode(flags, v9fs_proto_dotu(v9ses));
@@ -912,7 +908,6 @@ v9fs_vfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,
                return -EINVAL;
 
        p9_debug(P9_DEBUG_VFS, "\n");
-       retval = 0;
        old_inode = d_inode(old_dentry);
        new_inode = d_inode(new_dentry);
        v9ses = v9fs_inode2v9ses(old_inode);
@@ -1066,7 +1061,6 @@ static int v9fs_vfs_setattr(struct mnt_idmap *idmap,
        if (retval)
                return retval;
 
-       retval = -EPERM;
        v9ses = v9fs_dentry2v9ses(dentry);
        if (iattr->ia_valid & ATTR_FILE) {
                fid = iattr->ia_file->private_data;
index 5361cd2..1451087 100644 (file)
@@ -366,7 +366,6 @@ static int v9fs_vfs_mkdir_dotl(struct mnt_idmap *idmap,
        struct posix_acl *dacl = NULL, *pacl = NULL;
 
        p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry);
-       err = 0;
        v9ses = v9fs_inode2v9ses(dir);
 
        omode |= S_IFDIR;
index 3b3a6b1..54c12d9 100644 (file)
@@ -1,18 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
-config AUTOFS4_FS
-       tristate "Old Kconfig name for Kernel automounter support"
-       select AUTOFS_FS
-       help
-          This name exists for people to just automatically pick up the
-          new name of the autofs Kconfig option. All it does is select
-          the new option name.
-
-          It will go away in a release or two as people have
-          transitioned to just plain AUTOFS_FS.
-
 config AUTOFS_FS
        tristate "Kernel automounter support (supports v3, v4 and v5)"
-       default n
        help
           The automounter is a tool to automatically mount remote file systems
           on demand. This implementation is partially kernel-based to reduce
index 48ae509..030ab44 100644 (file)
@@ -499,12 +499,16 @@ static void fragment_free_space(struct btrfs_block_group *block_group)
  * used yet since their free space will be released as soon as the transaction
  * commits.
  */
-u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end)
+int add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end,
+                      u64 *total_added_ret)
 {
        struct btrfs_fs_info *info = block_group->fs_info;
-       u64 extent_start, extent_end, size, total_added = 0;
+       u64 extent_start, extent_end, size;
        int ret;
 
+       if (total_added_ret)
+               *total_added_ret = 0;
+
        while (start < end) {
                ret = find_first_extent_bit(&info->excluded_extents, start,
                                            &extent_start, &extent_end,
@@ -517,10 +521,12 @@ u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end
                        start = extent_end + 1;
                } else if (extent_start > start && extent_start < end) {
                        size = extent_start - start;
-                       total_added += size;
                        ret = btrfs_add_free_space_async_trimmed(block_group,
                                                                 start, size);
-                       BUG_ON(ret); /* -ENOMEM or logic error */
+                       if (ret)
+                               return ret;
+                       if (total_added_ret)
+                               *total_added_ret += size;
                        start = extent_end + 1;
                } else {
                        break;
@@ -529,13 +535,15 @@ u64 add_new_free_space(struct btrfs_block_group *block_group, u64 start, u64 end
 
        if (start < end) {
                size = end - start;
-               total_added += size;
                ret = btrfs_add_free_space_async_trimmed(block_group, start,
                                                         size);
-               BUG_ON(ret); /* -ENOMEM or logic error */
+               if (ret)
+                       return ret;
+               if (total_added_ret)
+                       *total_added_ret += size;
        }
 
-       return total_added;
+       return 0;
 }
 
 /*
@@ -779,8 +787,13 @@ next:
 
                if (key.type == BTRFS_EXTENT_ITEM_KEY ||
                    key.type == BTRFS_METADATA_ITEM_KEY) {
-                       total_found += add_new_free_space(block_group, last,
-                                                         key.objectid);
+                       u64 space_added;
+
+                       ret = add_new_free_space(block_group, last, key.objectid,
+                                                &space_added);
+                       if (ret)
+                               goto out;
+                       total_found += space_added;
                        if (key.type == BTRFS_METADATA_ITEM_KEY)
                                last = key.objectid +
                                        fs_info->nodesize;
@@ -795,11 +808,10 @@ next:
                }
                path->slots[0]++;
        }
-       ret = 0;
-
-       total_found += add_new_free_space(block_group, last,
-                               block_group->start + block_group->length);
 
+       ret = add_new_free_space(block_group, last,
+                                block_group->start + block_group->length,
+                                NULL);
 out:
        btrfs_free_path(path);
        return ret;
@@ -1640,13 +1652,14 @@ void btrfs_mark_bg_unused(struct btrfs_block_group *bg)
 {
        struct btrfs_fs_info *fs_info = bg->fs_info;
 
-       trace_btrfs_add_unused_block_group(bg);
        spin_lock(&fs_info->unused_bgs_lock);
        if (list_empty(&bg->bg_list)) {
                btrfs_get_block_group(bg);
+               trace_btrfs_add_unused_block_group(bg);
                list_add_tail(&bg->bg_list, &fs_info->unused_bgs);
-       } else {
+       } else if (!test_bit(BLOCK_GROUP_FLAG_NEW, &bg->runtime_flags)) {
                /* Pull out the block group from the reclaim_bgs list. */
+               trace_btrfs_add_unused_block_group(bg);
                list_move_tail(&bg->bg_list, &fs_info->unused_bgs);
        }
        spin_unlock(&fs_info->unused_bgs_lock);
@@ -2087,6 +2100,7 @@ static int exclude_super_stripes(struct btrfs_block_group *cache)
 
                /* Shouldn't have super stripes in sequential zones */
                if (zoned && nr) {
+                       kfree(logical);
                        btrfs_err(fs_info,
                        "zoned: block group %llu must not contain super block",
                                  cache->start);
@@ -2292,9 +2306,11 @@ static int read_one_block_group(struct btrfs_fs_info *info,
                btrfs_free_excluded_extents(cache);
        } else if (cache->used == 0) {
                cache->cached = BTRFS_CACHE_FINISHED;
-               add_new_free_space(cache, cache->start,
-                                  cache->start + cache->length);
+               ret = add_new_free_space(cache, cache->start,
+                                        cache->start + cache->length, NULL);
                btrfs_free_excluded_extents(cache);
+               if (ret)
+                       goto error;
        }
 
        ret = btrfs_add_block_group_cache(info, cache);
@@ -2668,6 +2684,7 @@ void btrfs_create_pending_block_groups(struct btrfs_trans_handle *trans)
 next:
                btrfs_delayed_refs_rsv_release(fs_info, 1);
                list_del_init(&block_group->bg_list);
+               clear_bit(BLOCK_GROUP_FLAG_NEW, &block_group->runtime_flags);
        }
        btrfs_trans_release_chunk_metadata(trans);
 }
@@ -2707,6 +2724,13 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
        if (!cache)
                return ERR_PTR(-ENOMEM);
 
+       /*
+        * Mark it as new before adding it to the rbtree of block groups or any
+        * list, so that no other task finds it and calls btrfs_mark_bg_unused()
+        * before the new flag is set.
+        */
+       set_bit(BLOCK_GROUP_FLAG_NEW, &cache->runtime_flags);
+
        cache->length = size;
        set_free_space_tree_thresholds(cache);
        cache->flags = type;
@@ -2730,9 +2754,12 @@ struct btrfs_block_group *btrfs_make_block_group(struct btrfs_trans_handle *tran
                return ERR_PTR(ret);
        }
 
-       add_new_free_space(cache, chunk_offset, chunk_offset + size);
-
+       ret = add_new_free_space(cache, chunk_offset, chunk_offset + size, NULL);
        btrfs_free_excluded_extents(cache);
+       if (ret) {
+               btrfs_put_block_group(cache);
+               return ERR_PTR(ret);
+       }
 
        /*
         * Ensure the corresponding space_info object is created and
index f204add..aba5dff 100644 (file)
@@ -70,6 +70,11 @@ enum btrfs_block_group_flags {
        BLOCK_GROUP_FLAG_NEEDS_FREE_SPACE,
        /* Indicate that the block group is placed on a sequential zone */
        BLOCK_GROUP_FLAG_SEQUENTIAL_ZONE,
+       /*
+        * Indicate that block group is in the list of new block groups of a
+        * transaction.
+        */
+       BLOCK_GROUP_FLAG_NEW,
 };
 
 enum btrfs_caching_type {
@@ -284,8 +289,8 @@ int btrfs_cache_block_group(struct btrfs_block_group *cache, bool wait);
 void btrfs_put_caching_control(struct btrfs_caching_control *ctl);
 struct btrfs_caching_control *btrfs_get_caching_control(
                struct btrfs_block_group *cache);
-u64 add_new_free_space(struct btrfs_block_group *block_group,
-                      u64 start, u64 end);
+int add_new_free_space(struct btrfs_block_group *block_group,
+                      u64 start, u64 end, u64 *total_added_ret);
 struct btrfs_trans_handle *btrfs_start_trans_remove_block_group(
                                struct btrfs_fs_info *fs_info,
                                const u64 chunk_offset);
index 6279d20..77684c5 100644 (file)
@@ -349,6 +349,11 @@ void btrfs_update_global_block_rsv(struct btrfs_fs_info *fs_info)
        }
        read_unlock(&fs_info->global_root_lock);
 
+       if (btrfs_fs_compat_ro(fs_info, BLOCK_GROUP_TREE)) {
+               num_bytes += btrfs_root_used(&fs_info->block_group_root->root_item);
+               min_items++;
+       }
+
        /*
         * But we also want to reserve enough space so we can do the fallback
         * global reserve for an unlink, which is an additional
index 7513388..9b9914e 100644 (file)
@@ -3438,11 +3438,16 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
         * For devices supporting discard turn on discard=async automatically,
         * unless it's already set or disabled. This could be turned off by
         * nodiscard for the same mount.
+        *
+        * The zoned mode piggy backs on the discard functionality for
+        * resetting a zone. There is no reason to delay the zone reset as it is
+        * fast enough. So, do not enable async discard for zoned mode.
         */
        if (!(btrfs_test_opt(fs_info, DISCARD_SYNC) ||
              btrfs_test_opt(fs_info, DISCARD_ASYNC) ||
              btrfs_test_opt(fs_info, NODISCARD)) &&
-           fs_info->fs_devices->discardable) {
+           fs_info->fs_devices->discardable &&
+           !btrfs_is_zoned(fs_info)) {
                btrfs_set_and_info(fs_info, DISCARD_ASYNC,
                                   "auto enabling async discard");
        }
index 045ddce..f169378 100644 (file)
@@ -1515,9 +1515,13 @@ static int load_free_space_bitmaps(struct btrfs_caching_control *caching_ctl,
                        if (prev_bit == 0 && bit == 1) {
                                extent_start = offset;
                        } else if (prev_bit == 1 && bit == 0) {
-                               total_found += add_new_free_space(block_group,
-                                                                 extent_start,
-                                                                 offset);
+                               u64 space_added;
+
+                               ret = add_new_free_space(block_group, extent_start,
+                                                        offset, &space_added);
+                               if (ret)
+                                       goto out;
+                               total_found += space_added;
                                if (total_found > CACHING_CTL_WAKE_UP) {
                                        total_found = 0;
                                        wake_up(&caching_ctl->wait);
@@ -1529,8 +1533,9 @@ static int load_free_space_bitmaps(struct btrfs_caching_control *caching_ctl,
                }
        }
        if (prev_bit == 1) {
-               total_found += add_new_free_space(block_group, extent_start,
-                                                 end);
+               ret = add_new_free_space(block_group, extent_start, end, NULL);
+               if (ret)
+                       goto out;
                extent_count++;
        }
 
@@ -1569,6 +1574,8 @@ static int load_free_space_extents(struct btrfs_caching_control *caching_ctl,
        end = block_group->start + block_group->length;
 
        while (1) {
+               u64 space_added;
+
                ret = btrfs_next_item(root, path);
                if (ret < 0)
                        goto out;
@@ -1583,8 +1590,11 @@ static int load_free_space_extents(struct btrfs_caching_control *caching_ctl,
                ASSERT(key.type == BTRFS_FREE_SPACE_EXTENT_KEY);
                ASSERT(key.objectid < end && key.objectid + key.offset <= end);
 
-               total_found += add_new_free_space(block_group, key.objectid,
-                                                 key.objectid + key.offset);
+               ret = add_new_free_space(block_group, key.objectid,
+                                        key.objectid + key.offset, &space_added);
+               if (ret)
+                       goto out;
+               total_found += space_added;
                if (total_found > CACHING_CTL_WAKE_UP) {
                        total_found = 0;
                        wake_up(&caching_ctl->wait);
index dbbb672..49cef61 100644 (file)
@@ -3482,15 +3482,21 @@ zeroit:
 void btrfs_add_delayed_iput(struct btrfs_inode *inode)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
+       unsigned long flags;
 
        if (atomic_add_unless(&inode->vfs_inode.i_count, -1, 1))
                return;
 
        atomic_inc(&fs_info->nr_delayed_iputs);
-       spin_lock(&fs_info->delayed_iput_lock);
+       /*
+        * Need to be irq safe here because we can be called from either an irq
+        * context (see bio.c and btrfs_put_ordered_extent()) or a non-irq
+        * context.
+        */
+       spin_lock_irqsave(&fs_info->delayed_iput_lock, flags);
        ASSERT(list_empty(&inode->delayed_iput));
        list_add_tail(&inode->delayed_iput, &fs_info->delayed_iputs);
-       spin_unlock(&fs_info->delayed_iput_lock);
+       spin_unlock_irqrestore(&fs_info->delayed_iput_lock, flags);
        if (!test_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags))
                wake_up_process(fs_info->cleaner_kthread);
 }
@@ -3499,37 +3505,46 @@ static void run_delayed_iput_locked(struct btrfs_fs_info *fs_info,
                                    struct btrfs_inode *inode)
 {
        list_del_init(&inode->delayed_iput);
-       spin_unlock(&fs_info->delayed_iput_lock);
+       spin_unlock_irq(&fs_info->delayed_iput_lock);
        iput(&inode->vfs_inode);
        if (atomic_dec_and_test(&fs_info->nr_delayed_iputs))
                wake_up(&fs_info->delayed_iputs_wait);
-       spin_lock(&fs_info->delayed_iput_lock);
+       spin_lock_irq(&fs_info->delayed_iput_lock);
 }
 
 static void btrfs_run_delayed_iput(struct btrfs_fs_info *fs_info,
                                   struct btrfs_inode *inode)
 {
        if (!list_empty(&inode->delayed_iput)) {
-               spin_lock(&fs_info->delayed_iput_lock);
+               spin_lock_irq(&fs_info->delayed_iput_lock);
                if (!list_empty(&inode->delayed_iput))
                        run_delayed_iput_locked(fs_info, inode);
-               spin_unlock(&fs_info->delayed_iput_lock);
+               spin_unlock_irq(&fs_info->delayed_iput_lock);
        }
 }
 
 void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info)
 {
-
-       spin_lock(&fs_info->delayed_iput_lock);
+       /*
+        * btrfs_put_ordered_extent() can run in irq context (see bio.c), which
+        * calls btrfs_add_delayed_iput() and that needs to lock
+        * fs_info->delayed_iput_lock. So we need to disable irqs here to
+        * prevent a deadlock.
+        */
+       spin_lock_irq(&fs_info->delayed_iput_lock);
        while (!list_empty(&fs_info->delayed_iputs)) {
                struct btrfs_inode *inode;
 
                inode = list_first_entry(&fs_info->delayed_iputs,
                                struct btrfs_inode, delayed_iput);
                run_delayed_iput_locked(fs_info, inode);
-               cond_resched_lock(&fs_info->delayed_iput_lock);
+               if (need_resched()) {
+                       spin_unlock_irq(&fs_info->delayed_iput_lock);
+                       cond_resched();
+                       spin_lock_irq(&fs_info->delayed_iput_lock);
+               }
        }
-       spin_unlock(&fs_info->delayed_iput_lock);
+       spin_unlock_irq(&fs_info->delayed_iput_lock);
 }
 
 /*
@@ -3659,11 +3674,14 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                found_key.type = BTRFS_INODE_ITEM_KEY;
                found_key.offset = 0;
                inode = btrfs_iget(fs_info->sb, last_objectid, root);
-               ret = PTR_ERR_OR_ZERO(inode);
-               if (ret && ret != -ENOENT)
-                       goto out;
+               if (IS_ERR(inode)) {
+                       ret = PTR_ERR(inode);
+                       inode = NULL;
+                       if (ret != -ENOENT)
+                               goto out;
+               }
 
-               if (ret == -ENOENT && root == fs_info->tree_root) {
+               if (!inode && root == fs_info->tree_root) {
                        struct btrfs_root *dead_root;
                        int is_dead_root = 0;
 
@@ -3724,17 +3742,17 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                 * deleted but wasn't. The inode number may have been reused,
                 * but either way, we can delete the orphan item.
                 */
-               if (ret == -ENOENT || inode->i_nlink) {
-                       if (!ret) {
+               if (!inode || inode->i_nlink) {
+                       if (inode) {
                                ret = btrfs_drop_verity_items(BTRFS_I(inode));
                                iput(inode);
+                               inode = NULL;
                                if (ret)
                                        goto out;
                        }
                        trans = btrfs_start_transaction(root, 1);
                        if (IS_ERR(trans)) {
                                ret = PTR_ERR(trans);
-                               iput(inode);
                                goto out;
                        }
                        btrfs_debug(fs_info, "auto deleting %Lu",
@@ -3742,10 +3760,8 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                        ret = btrfs_del_orphan_item(trans, root,
                                                    found_key.objectid);
                        btrfs_end_transaction(trans);
-                       if (ret) {
-                               iput(inode);
+                       if (ret)
                                goto out;
-                       }
                        continue;
                }
 
@@ -4847,9 +4863,6 @@ again:
                ret = -ENOMEM;
                goto out;
        }
-       ret = set_page_extent_mapped(page);
-       if (ret < 0)
-               goto out_unlock;
 
        if (!PageUptodate(page)) {
                ret = btrfs_read_folio(NULL, page_folio(page));
@@ -4864,6 +4877,17 @@ again:
                        goto out_unlock;
                }
        }
+
+       /*
+        * We unlock the page after the io is completed and then re-lock it
+        * above.  release_folio() could have come in between that and cleared
+        * PagePrivate(), but left the page in the mapping.  Set the page mapped
+        * here to make sure it's properly set for the subpage stuff.
+        */
+       ret = set_page_extent_mapped(page);
+       if (ret < 0)
+               goto out_unlock;
+
        wait_on_page_writeback(page);
 
        lock_extent(io_tree, block_start, block_end, &cached_state);
@@ -7849,8 +7873,11 @@ static void btrfs_dio_submit_io(const struct iomap_iter *iter, struct bio *bio,
 
                ret = btrfs_extract_ordered_extent(bbio, dio_data->ordered);
                if (ret) {
-                       bbio->bio.bi_status = errno_to_blk_status(ret);
-                       btrfs_dio_end_io(bbio);
+                       btrfs_finish_ordered_extent(dio_data->ordered, NULL,
+                                                   file_offset, dip->bytes,
+                                                   !ret);
+                       bio->bi_status = errno_to_blk_status(ret);
+                       iomap_dio_bio_end_io(bio);
                        return;
                }
        }
index da1f84a..2637d6b 100644 (file)
@@ -4445,4 +4445,5 @@ void btrfs_qgroup_destroy_extent_records(struct btrfs_transaction *trans)
                ulist_free(entry->old_roots);
                kfree(entry);
        }
+       *root = RB_ROOT;
 }
index f37b925..0249ea5 100644 (file)
@@ -71,7 +71,7 @@ static void rmw_rbio_work_locked(struct work_struct *work);
 static void index_rbio_pages(struct btrfs_raid_bio *rbio);
 static int alloc_rbio_pages(struct btrfs_raid_bio *rbio);
 
-static int finish_parity_scrub(struct btrfs_raid_bio *rbio, int need_check);
+static int finish_parity_scrub(struct btrfs_raid_bio *rbio);
 static void scrub_rbio_work_locked(struct work_struct *work);
 
 static void free_raid_bio_pointers(struct btrfs_raid_bio *rbio)
@@ -2404,7 +2404,7 @@ static int alloc_rbio_essential_pages(struct btrfs_raid_bio *rbio)
        return 0;
 }
 
-static int finish_parity_scrub(struct btrfs_raid_bio *rbio, int need_check)
+static int finish_parity_scrub(struct btrfs_raid_bio *rbio)
 {
        struct btrfs_io_context *bioc = rbio->bioc;
        const u32 sectorsize = bioc->fs_info->sectorsize;
@@ -2445,9 +2445,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio, int need_check)
         */
        clear_bit(RBIO_CACHE_READY_BIT, &rbio->flags);
 
-       if (!need_check)
-               goto writeback;
-
        p_sector.page = alloc_page(GFP_NOFS);
        if (!p_sector.page)
                return -ENOMEM;
@@ -2516,7 +2513,6 @@ static int finish_parity_scrub(struct btrfs_raid_bio *rbio, int need_check)
                q_sector.page = NULL;
        }
 
-writeback:
        /*
         * time to start writing.  Make bios for everything from the
         * higher layers (the bio_list in our rbio) and our p/q.  Ignore
@@ -2699,7 +2695,6 @@ static int scrub_assemble_read_bios(struct btrfs_raid_bio *rbio)
 
 static void scrub_rbio(struct btrfs_raid_bio *rbio)
 {
-       bool need_check = false;
        int sector_nr;
        int ret;
 
@@ -2722,7 +2717,7 @@ static void scrub_rbio(struct btrfs_raid_bio *rbio)
         * We have every sector properly prepared. Can finish the scrub
         * and writeback the good content.
         */
-       ret = finish_parity_scrub(rbio, need_check);
+       ret = finish_parity_scrub(rbio);
        wait_event(rbio->io_wait, atomic_read(&rbio->stripes_pending) == 0);
        for (sector_nr = 0; sector_nr < rbio->stripe_nsectors; sector_nr++) {
                int found_errors;
index cf30635..91b6c2f 100644 (file)
@@ -826,8 +826,13 @@ btrfs_attach_transaction_barrier(struct btrfs_root *root)
 
        trans = start_transaction(root, 0, TRANS_ATTACH,
                                  BTRFS_RESERVE_NO_FLUSH, true);
-       if (trans == ERR_PTR(-ENOENT))
-               btrfs_wait_for_commit(root->fs_info, 0);
+       if (trans == ERR_PTR(-ENOENT)) {
+               int ret;
+
+               ret = btrfs_wait_for_commit(root->fs_info, 0);
+               if (ret)
+                       return ERR_PTR(ret);
+       }
 
        return trans;
 }
@@ -931,6 +936,7 @@ int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid)
        }
 
        wait_for_commit(cur_trans, TRANS_STATE_COMPLETED);
+       ret = cur_trans->aborted;
        btrfs_put_transaction(cur_trans);
 out:
        return ret;
index 73f9ea7..2ecb76c 100644 (file)
@@ -4078,14 +4078,6 @@ static int alloc_profile_is_valid(u64 flags, int extended)
        return has_single_bit_set(flags);
 }
 
-static inline int balance_need_close(struct btrfs_fs_info *fs_info)
-{
-       /* cancel requested || normal exit path */
-       return atomic_read(&fs_info->balance_cancel_req) ||
-               (atomic_read(&fs_info->balance_pause_req) == 0 &&
-                atomic_read(&fs_info->balance_cancel_req) == 0);
-}
-
 /*
  * Validate target profile against allowed profiles and return true if it's OK.
  * Otherwise print the error message and return false.
@@ -4275,6 +4267,7 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
        u64 num_devices;
        unsigned seq;
        bool reducing_redundancy;
+       bool paused = false;
        int i;
 
        if (btrfs_fs_closing(fs_info) ||
@@ -4405,6 +4398,7 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
        if (ret == -ECANCELED && atomic_read(&fs_info->balance_pause_req)) {
                btrfs_info(fs_info, "balance: paused");
                btrfs_exclop_balance(fs_info, BTRFS_EXCLOP_BALANCE_PAUSED);
+               paused = true;
        }
        /*
         * Balance can be canceled by:
@@ -4433,8 +4427,8 @@ int btrfs_balance(struct btrfs_fs_info *fs_info,
                btrfs_update_ioctl_balance_args(fs_info, bargs);
        }
 
-       if ((ret && ret != -ECANCELED && ret != -ENOSPC) ||
-           balance_need_close(fs_info)) {
+       /* We didn't pause, we can clean everything up. */
+       if (!paused) {
                reset_balance_state(fs_info);
                btrfs_exclop_finish(fs_info);
        }
@@ -6404,7 +6398,8 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
            (op == BTRFS_MAP_READ || !dev_replace_is_ongoing ||
             !dev_replace->tgtdev)) {
                set_io_stripe(smap, map, stripe_index, stripe_offset, stripe_nr);
-               *mirror_num_ret = mirror_num;
+               if (mirror_num_ret)
+                       *mirror_num_ret = mirror_num;
                *bioc_ret = NULL;
                ret = 0;
                goto out;
index 85b8b33..72b90bc 100644 (file)
@@ -805,6 +805,9 @@ int btrfs_check_mountopts_zoned(struct btrfs_fs_info *info)
                return -EINVAL;
        }
 
+       btrfs_clear_and_info(info, DISCARD_ASYNC,
+                       "zoned: async discard ignored and disabled for zoned mode");
+
        return 0;
 }
 
index cce78d7..6d3584f 100644 (file)
@@ -216,7 +216,7 @@ static void metric_delayed_work(struct work_struct *work)
        struct ceph_mds_client *mdsc =
                container_of(m, struct ceph_mds_client, metric);
 
-       if (mdsc->stopping)
+       if (mdsc->stopping || disable_send_metrics)
                return;
 
        if (!m->session || !check_session_state(m->session)) {
index 9d6a3c6..566f68d 100644 (file)
@@ -889,8 +889,6 @@ static void erofs_kill_sb(struct super_block *sb)
 {
        struct erofs_sb_info *sbi;
 
-       WARN_ON(sb->s_magic != EROFS_SUPER_MAGIC);
-
        /* pseudo mount for anon inodes */
        if (sb->s_flags & SB_KERNMOUNT) {
                kill_anon_super(sb);
index b69d89a..de4f121 100644 (file)
@@ -1144,10 +1144,11 @@ static void z_erofs_do_decompressed_bvec(struct z_erofs_decompress_backend *be,
                                         struct z_erofs_bvec *bvec)
 {
        struct z_erofs_bvec_item *item;
+       unsigned int pgnr;
 
-       if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK)) {
-               unsigned int pgnr;
-
+       if (!((bvec->offset + be->pcl->pageofs_out) & ~PAGE_MASK) &&
+           (bvec->end == PAGE_SIZE ||
+            bvec->offset + bvec->end == be->pcl->length)) {
                pgnr = (bvec->offset + be->pcl->pageofs_out) >> PAGE_SHIFT;
                DBG_BUGON(pgnr >= be->nr_pages);
                if (!be->decompressed_pages[pgnr]) {
index 9f42f25..e918dec 100644 (file)
@@ -69,7 +69,7 @@ static int exfat_allocate_bitmap(struct super_block *sb,
        }
        sbi->map_sectors = ((need_map_size - 1) >>
                        (sb->s_blocksize_bits)) + 1;
-       sbi->vol_amap = kmalloc_array(sbi->map_sectors,
+       sbi->vol_amap = kvmalloc_array(sbi->map_sectors,
                                sizeof(struct buffer_head *), GFP_KERNEL);
        if (!sbi->vol_amap)
                return -ENOMEM;
@@ -84,7 +84,7 @@ static int exfat_allocate_bitmap(struct super_block *sb,
                        while (j < i)
                                brelse(sbi->vol_amap[j++]);
 
-                       kfree(sbi->vol_amap);
+                       kvfree(sbi->vol_amap);
                        sbi->vol_amap = NULL;
                        return -EIO;
                }
@@ -138,7 +138,7 @@ void exfat_free_bitmap(struct exfat_sb_info *sbi)
        for (i = 0; i < sbi->map_sectors; i++)
                __brelse(sbi->vol_amap[i]);
 
-       kfree(sbi->vol_amap);
+       kvfree(sbi->vol_amap);
 }
 
 int exfat_set_bitmap(struct inode *inode, unsigned int clu, bool sync)
index 9575741..598081d 100644 (file)
@@ -34,6 +34,7 @@ static int exfat_get_uniname_from_ext_entry(struct super_block *sb,
 {
        int i, err;
        struct exfat_entry_set_cache es;
+       unsigned int uni_len = 0, len;
 
        err = exfat_get_dentry_set(&es, sb, p_dir, entry, ES_ALL_ENTRIES);
        if (err)
@@ -52,7 +53,10 @@ static int exfat_get_uniname_from_ext_entry(struct super_block *sb,
                if (exfat_get_entry_type(ep) != TYPE_EXTEND)
                        break;
 
-               exfat_extract_uni_name(ep, uniname);
+               len = exfat_extract_uni_name(ep, uniname);
+               uni_len += len;
+               if (len != EXFAT_FILE_NAME_LEN || uni_len >= MAX_NAME_LENGTH)
+                       break;
                uniname += EXFAT_FILE_NAME_LEN;
        }
 
@@ -214,7 +218,10 @@ static void exfat_free_namebuf(struct exfat_dentry_namebuf *nb)
        exfat_init_namebuf(nb);
 }
 
-/* skip iterating emit_dots when dir is empty */
+/*
+ * Before calling dir_emit*(), sbi->s_lock should be released
+ * because page fault can occur in dir_emit*().
+ */
 #define ITER_POS_FILLED_DOTS    (2)
 static int exfat_iterate(struct file *file, struct dir_context *ctx)
 {
@@ -229,11 +236,10 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
        int err = 0, fake_offset = 0;
 
        exfat_init_namebuf(nb);
-       mutex_lock(&EXFAT_SB(sb)->s_lock);
 
        cpos = ctx->pos;
        if (!dir_emit_dots(file, ctx))
-               goto unlock;
+               goto out;
 
        if (ctx->pos == ITER_POS_FILLED_DOTS) {
                cpos = 0;
@@ -245,16 +251,18 @@ static int exfat_iterate(struct file *file, struct dir_context *ctx)
        /* name buffer should be allocated before use */
        err = exfat_alloc_namebuf(nb);
        if (err)
-               goto unlock;
+               goto out;
 get_new:
+       mutex_lock(&EXFAT_SB(sb)->s_lock);
+
        if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode))
                goto end_of_dir;
 
        err = exfat_readdir(inode, &cpos, &de);
        if (err) {
                /*
-                * At least we tried to read a sector.  Move cpos to next sector
-                * position (should be aligned).
+                * At least we tried to read a sector.
+                * Move cpos to next sector position (should be aligned).
                 */
                if (err == -EIO) {
                        cpos += 1 << (sb->s_blocksize_bits);
@@ -277,16 +285,10 @@ get_new:
                inum = iunique(sb, EXFAT_ROOT_INO);
        }
 
-       /*
-        * Before calling dir_emit(), sb_lock should be released.
-        * Because page fault can occur in dir_emit() when the size
-        * of buffer given from user is larger than one page size.
-        */
        mutex_unlock(&EXFAT_SB(sb)->s_lock);
        if (!dir_emit(ctx, nb->lfn, strlen(nb->lfn), inum,
                        (de.attr & ATTR_SUBDIR) ? DT_DIR : DT_REG))
-               goto out_unlocked;
-       mutex_lock(&EXFAT_SB(sb)->s_lock);
+               goto out;
        ctx->pos = cpos;
        goto get_new;
 
@@ -294,9 +296,8 @@ end_of_dir:
        if (!cpos && fake_offset)
                cpos = ITER_POS_FILLED_DOTS;
        ctx->pos = cpos;
-unlock:
        mutex_unlock(&EXFAT_SB(sb)->s_lock);
-out_unlocked:
+out:
        /*
         * To improve performance, free namebuf after unlock sb_lock.
         * If namebuf is not allocated, this function do nothing
@@ -1079,7 +1080,8 @@ rewind:
                        if (entry_type == TYPE_EXTEND) {
                                unsigned short entry_uniname[16], unichar;
 
-                               if (step != DIRENT_STEP_NAME) {
+                               if (step != DIRENT_STEP_NAME ||
+                                   name_len >= MAX_NAME_LENGTH) {
                                        step = DIRENT_STEP_FILE;
                                        continue;
                                }
index a2475b8..21b903f 100644 (file)
@@ -1006,14 +1006,11 @@ static void ext4_mb_choose_next_group_best_avail(struct ext4_allocation_context
         * fls() instead since we need to know the actual length while modifying
         * goal length.
         */
-       order = fls(ac->ac_g_ex.fe_len);
+       order = fls(ac->ac_g_ex.fe_len) - 1;
        min_order = order - sbi->s_mb_best_avail_max_trim_order;
        if (min_order < 0)
                min_order = 0;
 
-       if (1 << min_order < ac->ac_o_ex.fe_len)
-               min_order = fls(ac->ac_o_ex.fe_len) + 1;
-
        if (sbi->s_stripe > 0) {
                /*
                 * We are assuming that stripe size is always a multiple of
@@ -1021,9 +1018,16 @@ static void ext4_mb_choose_next_group_best_avail(struct ext4_allocation_context
                 */
                num_stripe_clusters = EXT4_NUM_B2C(sbi, sbi->s_stripe);
                if (1 << min_order < num_stripe_clusters)
-                       min_order = fls(num_stripe_clusters);
+                       /*
+                        * We consider 1 order less because later we round
+                        * up the goal len to num_stripe_clusters
+                        */
+                       min_order = fls(num_stripe_clusters) - 1;
        }
 
+       if (1 << min_order < ac->ac_o_ex.fe_len)
+               min_order = fls(ac->ac_o_ex.fe_len);
+
        for (i = order; i >= min_order; i--) {
                int frag_order;
                /*
@@ -4761,8 +4765,8 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
        int order, i;
        struct ext4_inode_info *ei = EXT4_I(ac->ac_inode);
        struct ext4_locality_group *lg;
-       struct ext4_prealloc_space *tmp_pa, *cpa = NULL;
-       ext4_lblk_t tmp_pa_start, tmp_pa_end;
+       struct ext4_prealloc_space *tmp_pa = NULL, *cpa = NULL;
+       loff_t tmp_pa_end;
        struct rb_node *iter;
        ext4_fsblk_t goal_block;
 
@@ -4770,47 +4774,151 @@ ext4_mb_use_preallocated(struct ext4_allocation_context *ac)
        if (!(ac->ac_flags & EXT4_MB_HINT_DATA))
                return false;
 
-       /* first, try per-file preallocation */
+       /*
+        * first, try per-file preallocation by searching the inode pa rbtree.
+        *
+        * Here, we can't do a direct traversal of the tree because
+        * ext4_mb_discard_group_preallocation() can paralelly mark the pa
+        * deleted and that can cause direct traversal to skip some entries.
+        */
        read_lock(&ei->i_prealloc_lock);
+
+       if (RB_EMPTY_ROOT(&ei->i_prealloc_node)) {
+               goto try_group_pa;
+       }
+
+       /*
+        * Step 1: Find a pa with logical start immediately adjacent to the
+        * original logical start. This could be on the left or right.
+        *
+        * (tmp_pa->pa_lstart never changes so we can skip locking for it).
+        */
        for (iter = ei->i_prealloc_node.rb_node; iter;
             iter = ext4_mb_pa_rb_next_iter(ac->ac_o_ex.fe_logical,
-                                           tmp_pa_start, iter)) {
+                                           tmp_pa->pa_lstart, iter)) {
                tmp_pa = rb_entry(iter, struct ext4_prealloc_space,
                                  pa_node.inode_node);
+       }
 
-               /* all fields in this condition don't change,
-                * so we can skip locking for them */
-               tmp_pa_start = tmp_pa->pa_lstart;
-               tmp_pa_end = tmp_pa->pa_lstart + EXT4_C2B(sbi, tmp_pa->pa_len);
-
-               /* original request start doesn't lie in this PA */
-               if (ac->ac_o_ex.fe_logical < tmp_pa_start ||
-                   ac->ac_o_ex.fe_logical >= tmp_pa_end)
-                       continue;
+       /*
+        * Step 2: The adjacent pa might be to the right of logical start, find
+        * the left adjacent pa. After this step we'd have a valid tmp_pa whose
+        * logical start is towards the left of original request's logical start
+        */
+       if (tmp_pa->pa_lstart > ac->ac_o_ex.fe_logical) {
+               struct rb_node *tmp;
+               tmp = rb_prev(&tmp_pa->pa_node.inode_node);
 
-               /* non-extent files can't have physical blocks past 2^32 */
-               if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&
-                   (tmp_pa->pa_pstart + EXT4_C2B(sbi, tmp_pa->pa_len) >
-                    EXT4_MAX_BLOCK_FILE_PHYS)) {
+               if (tmp) {
+                       tmp_pa = rb_entry(tmp, struct ext4_prealloc_space,
+                                           pa_node.inode_node);
+               } else {
                        /*
-                        * Since PAs don't overlap, we won't find any
-                        * other PA to satisfy this.
+                        * If there is no adjacent pa to the left then finding
+                        * an overlapping pa is not possible hence stop searching
+                        * inode pa tree
                         */
-                       break;
+                       goto try_group_pa;
                }
+       }
+
+       BUG_ON(!(tmp_pa && tmp_pa->pa_lstart <= ac->ac_o_ex.fe_logical));
 
-               /* found preallocated blocks, use them */
+       /*
+        * Step 3: If the left adjacent pa is deleted, keep moving left to find
+        * the first non deleted adjacent pa. After this step we should have a
+        * valid tmp_pa which is guaranteed to be non deleted.
+        */
+       for (iter = &tmp_pa->pa_node.inode_node;; iter = rb_prev(iter)) {
+               if (!iter) {
+                       /*
+                        * no non deleted left adjacent pa, so stop searching
+                        * inode pa tree
+                        */
+                       goto try_group_pa;
+               }
+               tmp_pa = rb_entry(iter, struct ext4_prealloc_space,
+                                 pa_node.inode_node);
                spin_lock(&tmp_pa->pa_lock);
-               if (tmp_pa->pa_deleted == 0 && tmp_pa->pa_free &&
-                   likely(ext4_mb_pa_goal_check(ac, tmp_pa))) {
-                       atomic_inc(&tmp_pa->pa_count);
-                       ext4_mb_use_inode_pa(ac, tmp_pa);
+               if (tmp_pa->pa_deleted == 0) {
+                       /*
+                        * We will keep holding the pa_lock from
+                        * this point on because we don't want group discard
+                        * to delete this pa underneath us. Since group
+                        * discard is anyways an ENOSPC operation it
+                        * should be okay for it to wait a few more cycles.
+                        */
+                       break;
+               } else {
                        spin_unlock(&tmp_pa->pa_lock);
-                       read_unlock(&ei->i_prealloc_lock);
-                       return true;
                }
+       }
+
+       BUG_ON(!(tmp_pa && tmp_pa->pa_lstart <= ac->ac_o_ex.fe_logical));
+       BUG_ON(tmp_pa->pa_deleted == 1);
+
+       /*
+        * Step 4: We now have the non deleted left adjacent pa. Only this
+        * pa can possibly satisfy the request hence check if it overlaps
+        * original logical start and stop searching if it doesn't.
+        */
+       tmp_pa_end = (loff_t)tmp_pa->pa_lstart + EXT4_C2B(sbi, tmp_pa->pa_len);
+
+       if (ac->ac_o_ex.fe_logical >= tmp_pa_end) {
                spin_unlock(&tmp_pa->pa_lock);
+               goto try_group_pa;
+       }
+
+       /* non-extent files can't have physical blocks past 2^32 */
+       if (!(ext4_test_inode_flag(ac->ac_inode, EXT4_INODE_EXTENTS)) &&
+           (tmp_pa->pa_pstart + EXT4_C2B(sbi, tmp_pa->pa_len) >
+            EXT4_MAX_BLOCK_FILE_PHYS)) {
+               /*
+                * Since PAs don't overlap, we won't find any other PA to
+                * satisfy this.
+                */
+               spin_unlock(&tmp_pa->pa_lock);
+               goto try_group_pa;
+       }
+
+       if (tmp_pa->pa_free && likely(ext4_mb_pa_goal_check(ac, tmp_pa))) {
+               atomic_inc(&tmp_pa->pa_count);
+               ext4_mb_use_inode_pa(ac, tmp_pa);
+               spin_unlock(&tmp_pa->pa_lock);
+               read_unlock(&ei->i_prealloc_lock);
+               return true;
+       } else {
+               /*
+                * We found a valid overlapping pa but couldn't use it because
+                * it had no free blocks. This should ideally never happen
+                * because:
+                *
+                * 1. When a new inode pa is added to rbtree it must have
+                *    pa_free > 0 since otherwise we won't actually need
+                *    preallocation.
+                *
+                * 2. An inode pa that is in the rbtree can only have it's
+                *    pa_free become zero when another thread calls:
+                *      ext4_mb_new_blocks
+                *       ext4_mb_use_preallocated
+                *        ext4_mb_use_inode_pa
+                *
+                * 3. Further, after the above calls make pa_free == 0, we will
+                *    immediately remove it from the rbtree in:
+                *      ext4_mb_new_blocks
+                *       ext4_mb_release_context
+                *        ext4_mb_put_pa
+                *
+                * 4. Since the pa_free becoming 0 and pa_free getting removed
+                * from tree both happen in ext4_mb_new_blocks, which is always
+                * called with i_data_sem held for data allocations, we can be
+                * sure that another process will never see a pa in rbtree with
+                * pa_free == 0.
+                */
+               WARN_ON_ONCE(tmp_pa->pa_free == 0);
        }
+       spin_unlock(&tmp_pa->pa_lock);
+try_group_pa:
        read_unlock(&ei->i_prealloc_lock);
 
        /* can we use group allocation? */
index 321e3a8..05151d6 100644 (file)
@@ -1782,6 +1782,20 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,
                memmove(here, (void *)here + size,
                        (void *)last - (void *)here + sizeof(__u32));
                memset(last, 0, size);
+
+               /*
+                * Update i_inline_off - moved ibody region might contain
+                * system.data attribute.  Handling a failure here won't
+                * cause other complications for setting an xattr.
+                */
+               if (!is_block && ext4_has_inline_data(inode)) {
+                       ret = ext4_find_inline_data_nolock(inode);
+                       if (ret) {
+                               ext4_warning_inode(inode,
+                                       "unable to update i_inline_off");
+                               goto out;
+                       }
+               }
        } else if (s->not_found) {
                /* Insert new name. */
                size_t size = EXT4_XATTR_LEN(name_len);
index 7893ea1..35c62b5 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -1042,10 +1042,8 @@ unsigned long __fdget_pos(unsigned int fd)
        struct file *file = (struct file *)(v & ~3);
 
        if (file && (file->f_mode & FMODE_ATOMIC_POS)) {
-               if (file_count(file) > 1) {
-                       v |= FDPUT_POS_UNLOCK;
-                       mutex_lock(&file->f_pos_lock);
-               }
+               v |= FDPUT_POS_UNLOCK;
+               mutex_lock(&file->f_pos_lock);
        }
        return v;
 }
index 35bc174..f67bef9 100644 (file)
@@ -258,7 +258,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
                        spin_unlock(&fi->lock);
                }
                kfree(forget);
-               if (ret == -ENOMEM)
+               if (ret == -ENOMEM || ret == -EINTR)
                        goto out;
                if (ret || fuse_invalid_attr(&outarg.attr) ||
                    fuse_stale_inode(inode, outarg.generation, &outarg.attr))
@@ -395,8 +395,6 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
                goto out_put_forget;
 
        err = -EIO;
-       if (!outarg->nodeid)
-               goto out_put_forget;
        if (fuse_invalid_attr(&outarg->attr))
                goto out_put_forget;
 
index d66070a..f19d748 100644 (file)
@@ -1134,7 +1134,10 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
                process_init_limits(fc, arg);
 
                if (arg->minor >= 6) {
-                       u64 flags = arg->flags | (u64) arg->flags2 << 32;
+                       u64 flags = arg->flags;
+
+                       if (flags & FUSE_INIT_EXT)
+                               flags |= (u64) arg->flags2 << 32;
 
                        ra_pages = arg->max_readahead / PAGE_SIZE;
                        if (flags & FUSE_ASYNC_READ)
@@ -1254,7 +1257,8 @@ void fuse_send_init(struct fuse_mount *fm)
                FUSE_ABORT_ERROR | FUSE_MAX_PAGES | FUSE_CACHE_SYMLINKS |
                FUSE_NO_OPENDIR_SUPPORT | FUSE_EXPLICIT_INVAL_DATA |
                FUSE_HANDLE_KILLPRIV_V2 | FUSE_SETXATTR_EXT | FUSE_INIT_EXT |
-               FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP;
+               FUSE_SECURITY_CTX | FUSE_CREATE_SUPP_GROUP |
+               FUSE_HAS_EXPIRE_ONLY;
 #ifdef CONFIG_FUSE_DAX
        if (fm->fc->dax)
                flags |= FUSE_MAP_ALIGNMENT;
index 8e01bfd..726640f 100644 (file)
@@ -9,14 +9,23 @@
 #include <linux/compat.h>
 #include <linux/fileattr.h>
 
-static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args)
+static ssize_t fuse_send_ioctl(struct fuse_mount *fm, struct fuse_args *args,
+                              struct fuse_ioctl_out *outarg)
 {
-       ssize_t ret = fuse_simple_request(fm, args);
+       ssize_t ret;
+
+       args->out_args[0].size = sizeof(*outarg);
+       args->out_args[0].value = outarg;
+
+       ret = fuse_simple_request(fm, args);
 
        /* Translate ENOSYS, which shouldn't be returned from fs */
        if (ret == -ENOSYS)
                ret = -ENOTTY;
 
+       if (ret >= 0 && outarg->result == -ENOSYS)
+               outarg->result = -ENOTTY;
+
        return ret;
 }
 
@@ -264,13 +273,11 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
        }
 
        ap.args.out_numargs = 2;
-       ap.args.out_args[0].size = sizeof(outarg);
-       ap.args.out_args[0].value = &outarg;
        ap.args.out_args[1].size = out_size;
        ap.args.out_pages = true;
        ap.args.out_argvar = true;
 
-       transferred = fuse_send_ioctl(fm, &ap.args);
+       transferred = fuse_send_ioctl(fm, &ap.args, &outarg);
        err = transferred;
        if (transferred < 0)
                goto out;
@@ -399,12 +406,10 @@ static int fuse_priv_ioctl(struct inode *inode, struct fuse_file *ff,
        args.in_args[1].size = inarg.in_size;
        args.in_args[1].value = ptr;
        args.out_numargs = 2;
-       args.out_args[0].size = sizeof(outarg);
-       args.out_args[0].value = &outarg;
        args.out_args[1].size = inarg.out_size;
        args.out_args[1].value = ptr;
 
-       err = fuse_send_ioctl(fm, &args);
+       err = fuse_send_ioctl(fm, &args, &outarg);
        if (!err) {
                if (outarg.result < 0)
                        err = outarg.result;
index adb92cd..aa8967c 100644 (file)
@@ -872,10 +872,10 @@ iomap_file_buffered_write(struct kiocb *iocb, struct iov_iter *i,
        while ((ret = iomap_iter(&iter, ops)) > 0)
                iter.processed = iomap_write_iter(&iter, i);
 
-       if (unlikely(ret < 0))
+       if (unlikely(iter.pos == iocb->ki_pos))
                return ret;
        ret = iter.pos - iocb->ki_pos;
-       iocb->ki_pos += ret;
+       iocb->ki_pos = iter.pos;
        return ret;
 }
 EXPORT_SYMBOL_GPL(iomap_file_buffered_write);
index 51bd38d..9ec9101 100644 (file)
@@ -27,7 +27,7 @@
  *
  * Called with j_list_lock held.
  */
-static inline void __buffer_unlink_first(struct journal_head *jh)
+static inline void __buffer_unlink(struct journal_head *jh)
 {
        transaction_t *transaction = jh->b_cp_transaction;
 
@@ -41,45 +41,6 @@ static inline void __buffer_unlink_first(struct journal_head *jh)
 }
 
 /*
- * Unlink a buffer from a transaction checkpoint(io) list.
- *
- * Called with j_list_lock held.
- */
-static inline void __buffer_unlink(struct journal_head *jh)
-{
-       transaction_t *transaction = jh->b_cp_transaction;
-
-       __buffer_unlink_first(jh);
-       if (transaction->t_checkpoint_io_list == jh) {
-               transaction->t_checkpoint_io_list = jh->b_cpnext;
-               if (transaction->t_checkpoint_io_list == jh)
-                       transaction->t_checkpoint_io_list = NULL;
-       }
-}
-
-/*
- * Move a buffer from the checkpoint list to the checkpoint io list
- *
- * Called with j_list_lock held
- */
-static inline void __buffer_relink_io(struct journal_head *jh)
-{
-       transaction_t *transaction = jh->b_cp_transaction;
-
-       __buffer_unlink_first(jh);
-
-       if (!transaction->t_checkpoint_io_list) {
-               jh->b_cpnext = jh->b_cpprev = jh;
-       } else {
-               jh->b_cpnext = transaction->t_checkpoint_io_list;
-               jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev;
-               jh->b_cpprev->b_cpnext = jh;
-               jh->b_cpnext->b_cpprev = jh;
-       }
-       transaction->t_checkpoint_io_list = jh;
-}
-
-/*
  * Check a checkpoint buffer could be release or not.
  *
  * Requires j_list_lock
@@ -183,6 +144,7 @@ __flush_batch(journal_t *journal, int *batch_count)
                struct buffer_head *bh = journal->j_chkpt_bhs[i];
                BUFFER_TRACE(bh, "brelse");
                __brelse(bh);
+               journal->j_chkpt_bhs[i] = NULL;
        }
        *batch_count = 0;
 }
@@ -242,15 +204,6 @@ restart:
                jh = transaction->t_checkpoint_list;
                bh = jh2bh(jh);
 
-               if (buffer_locked(bh)) {
-                       get_bh(bh);
-                       spin_unlock(&journal->j_list_lock);
-                       wait_on_buffer(bh);
-                       /* the journal_head may have gone by now */
-                       BUFFER_TRACE(bh, "brelse");
-                       __brelse(bh);
-                       goto retry;
-               }
                if (jh->b_transaction != NULL) {
                        transaction_t *t = jh->b_transaction;
                        tid_t tid = t->t_tid;
@@ -285,30 +238,50 @@ restart:
                        spin_lock(&journal->j_list_lock);
                        goto restart;
                }
-               if (!buffer_dirty(bh)) {
+               if (!trylock_buffer(bh)) {
+                       /*
+                        * The buffer is locked, it may be writing back, or
+                        * flushing out in the last couple of cycles, or
+                        * re-adding into a new transaction, need to check
+                        * it again until it's unlocked.
+                        */
+                       get_bh(bh);
+                       spin_unlock(&journal->j_list_lock);
+                       wait_on_buffer(bh);
+                       /* the journal_head may have gone by now */
+                       BUFFER_TRACE(bh, "brelse");
+                       __brelse(bh);
+                       goto retry;
+               } else if (!buffer_dirty(bh)) {
+                       unlock_buffer(bh);
                        BUFFER_TRACE(bh, "remove from checkpoint");
-                       if (__jbd2_journal_remove_checkpoint(jh))
-                               /* The transaction was released; we're done */
+                       /*
+                        * If the transaction was released or the checkpoint
+                        * list was empty, we're done.
+                        */
+                       if (__jbd2_journal_remove_checkpoint(jh) ||
+                           !transaction->t_checkpoint_list)
                                goto out;
-                       continue;
+               } else {
+                       unlock_buffer(bh);
+                       /*
+                        * We are about to write the buffer, it could be
+                        * raced by some other transaction shrink or buffer
+                        * re-log logic once we release the j_list_lock,
+                        * leave it on the checkpoint list and check status
+                        * again to make sure it's clean.
+                        */
+                       BUFFER_TRACE(bh, "queue");
+                       get_bh(bh);
+                       J_ASSERT_BH(bh, !buffer_jwrite(bh));
+                       journal->j_chkpt_bhs[batch_count++] = bh;
+                       transaction->t_chp_stats.cs_written++;
+                       transaction->t_checkpoint_list = jh->b_cpnext;
                }
-               /*
-                * Important: we are about to write the buffer, and
-                * possibly block, while still holding the journal
-                * lock.  We cannot afford to let the transaction
-                * logic start messing around with this buffer before
-                * we write it to disk, as that would break
-                * recoverability.
-                */
-               BUFFER_TRACE(bh, "queue");
-               get_bh(bh);
-               J_ASSERT_BH(bh, !buffer_jwrite(bh));
-               journal->j_chkpt_bhs[batch_count++] = bh;
-               __buffer_relink_io(jh);
-               transaction->t_chp_stats.cs_written++;
+
                if ((batch_count == JBD2_NR_BATCH) ||
-                   need_resched() ||
-                   spin_needbreak(&journal->j_list_lock))
+                   need_resched() || spin_needbreak(&journal->j_list_lock) ||
+                   jh2bh(transaction->t_checkpoint_list) == journal->j_chkpt_bhs[0])
                        goto unlock_and_flush;
        }
 
@@ -322,38 +295,6 @@ restart:
                        goto restart;
        }
 
-       /*
-        * Now we issued all of the transaction's buffers, let's deal
-        * with the buffers that are out for I/O.
-        */
-restart2:
-       /* Did somebody clean up the transaction in the meanwhile? */
-       if (journal->j_checkpoint_transactions != transaction ||
-           transaction->t_tid != this_tid)
-               goto out;
-
-       while (transaction->t_checkpoint_io_list) {
-               jh = transaction->t_checkpoint_io_list;
-               bh = jh2bh(jh);
-               if (buffer_locked(bh)) {
-                       get_bh(bh);
-                       spin_unlock(&journal->j_list_lock);
-                       wait_on_buffer(bh);
-                       /* the journal_head may have gone by now */
-                       BUFFER_TRACE(bh, "brelse");
-                       __brelse(bh);
-                       spin_lock(&journal->j_list_lock);
-                       goto restart2;
-               }
-
-               /*
-                * Now in whatever state the buffer currently is, we
-                * know that it has been written out and so we can
-                * drop it from the list
-                */
-               if (__jbd2_journal_remove_checkpoint(jh))
-                       break;
-       }
 out:
        spin_unlock(&journal->j_list_lock);
        result = jbd2_cleanup_journal_tail(journal);
@@ -409,49 +350,9 @@ int jbd2_cleanup_journal_tail(journal_t *journal)
 /* Checkpoint list management */
 
 /*
- * journal_clean_one_cp_list
- *
- * Find all the written-back checkpoint buffers in the given list and
- * release them. If 'destroy' is set, clean all buffers unconditionally.
- *
- * Called with j_list_lock held.
- * Returns 1 if we freed the transaction, 0 otherwise.
- */
-static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy)
-{
-       struct journal_head *last_jh;
-       struct journal_head *next_jh = jh;
-
-       if (!jh)
-               return 0;
-
-       last_jh = jh->b_cpprev;
-       do {
-               jh = next_jh;
-               next_jh = jh->b_cpnext;
-
-               if (!destroy && __cp_buffer_busy(jh))
-                       return 0;
-
-               if (__jbd2_journal_remove_checkpoint(jh))
-                       return 1;
-               /*
-                * This function only frees up some memory
-                * if possible so we dont have an obligation
-                * to finish processing. Bail out if preemption
-                * requested:
-                */
-               if (need_resched())
-                       return 0;
-       } while (jh != last_jh);
-
-       return 0;
-}
-
-/*
  * journal_shrink_one_cp_list
  *
- * Find 'nr_to_scan' written-back checkpoint buffers in the given list
+ * Find all the written-back checkpoint buffers in the given list
  * and try to release them. If the whole transaction is released, set
  * the 'released' parameter. Return the number of released checkpointed
  * buffers.
@@ -459,15 +360,15 @@ static int journal_clean_one_cp_list(struct journal_head *jh, bool destroy)
  * Called with j_list_lock held.
  */
 static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
-                                               unsigned long *nr_to_scan,
-                                               bool *released)
+                                               bool destroy, bool *released)
 {
        struct journal_head *last_jh;
        struct journal_head *next_jh = jh;
        unsigned long nr_freed = 0;
        int ret;
 
-       if (!jh || *nr_to_scan == 0)
+       *released = false;
+       if (!jh)
                return 0;
 
        last_jh = jh->b_cpprev;
@@ -475,12 +376,15 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
                jh = next_jh;
                next_jh = jh->b_cpnext;
 
-               (*nr_to_scan)--;
-               if (__cp_buffer_busy(jh))
-                       continue;
+               if (destroy) {
+                       ret = __jbd2_journal_remove_checkpoint(jh);
+               } else {
+                       ret = jbd2_journal_try_remove_checkpoint(jh);
+                       if (ret < 0)
+                               continue;
+               }
 
                nr_freed++;
-               ret = __jbd2_journal_remove_checkpoint(jh);
                if (ret) {
                        *released = true;
                        break;
@@ -488,7 +392,7 @@ static unsigned long journal_shrink_one_cp_list(struct journal_head *jh,
 
                if (need_resched())
                        break;
-       } while (jh != last_jh && *nr_to_scan);
+       } while (jh != last_jh);
 
        return nr_freed;
 }
@@ -506,11 +410,11 @@ unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal,
                                                  unsigned long *nr_to_scan)
 {
        transaction_t *transaction, *last_transaction, *next_transaction;
-       bool released;
+       bool __maybe_unused released;
        tid_t first_tid = 0, last_tid = 0, next_tid = 0;
        tid_t tid = 0;
        unsigned long nr_freed = 0;
-       unsigned long nr_scanned = *nr_to_scan;
+       unsigned long freed;
 
 again:
        spin_lock(&journal->j_list_lock);
@@ -539,19 +443,11 @@ again:
                transaction = next_transaction;
                next_transaction = transaction->t_cpnext;
                tid = transaction->t_tid;
-               released = false;
-
-               nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_list,
-                                                      nr_to_scan, &released);
-               if (*nr_to_scan == 0)
-                       break;
-               if (need_resched() || spin_needbreak(&journal->j_list_lock))
-                       break;
-               if (released)
-                       continue;
 
-               nr_freed += journal_shrink_one_cp_list(transaction->t_checkpoint_io_list,
-                                                      nr_to_scan, &released);
+               freed = journal_shrink_one_cp_list(transaction->t_checkpoint_list,
+                                                  false, &released);
+               nr_freed += freed;
+               (*nr_to_scan) -= min(*nr_to_scan, freed);
                if (*nr_to_scan == 0)
                        break;
                if (need_resched() || spin_needbreak(&journal->j_list_lock))
@@ -572,9 +468,8 @@ again:
        if (*nr_to_scan && next_tid)
                goto again;
 out:
-       nr_scanned -= *nr_to_scan;
        trace_jbd2_shrink_checkpoint_list(journal, first_tid, tid, last_tid,
-                                         nr_freed, nr_scanned, next_tid);
+                                         nr_freed, next_tid);
 
        return nr_freed;
 }
@@ -590,7 +485,7 @@ out:
 void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
 {
        transaction_t *transaction, *last_transaction, *next_transaction;
-       int ret;
+       bool released;
 
        transaction = journal->j_checkpoint_transactions;
        if (!transaction)
@@ -601,8 +496,8 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
        do {
                transaction = next_transaction;
                next_transaction = transaction->t_cpnext;
-               ret = journal_clean_one_cp_list(transaction->t_checkpoint_list,
-                                               destroy);
+               journal_shrink_one_cp_list(transaction->t_checkpoint_list,
+                                          destroy, &released);
                /*
                 * This function only frees up some memory if possible so we
                 * dont have an obligation to finish processing. Bail out if
@@ -610,23 +505,12 @@ void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy)
                 */
                if (need_resched())
                        return;
-               if (ret)
-                       continue;
-               /*
-                * It is essential that we are as careful as in the case of
-                * t_checkpoint_list with removing the buffer from the list as
-                * we can possibly see not yet submitted buffers on io_list
-                */
-               ret = journal_clean_one_cp_list(transaction->
-                               t_checkpoint_io_list, destroy);
-               if (need_resched())
-                       return;
                /*
                 * Stop scanning if we couldn't free the transaction. This
                 * avoids pointless scanning of transactions which still
                 * weren't checkpointed.
                 */
-               if (!ret)
+               if (!released)
                        return;
        } while (transaction != last_transaction);
 }
@@ -705,7 +589,7 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
        jbd2_journal_put_journal_head(jh);
 
        /* Is this transaction empty? */
-       if (transaction->t_checkpoint_list || transaction->t_checkpoint_io_list)
+       if (transaction->t_checkpoint_list)
                return 0;
 
        /*
@@ -737,6 +621,34 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh)
 }
 
 /*
+ * Check the checkpoint buffer and try to remove it from the checkpoint
+ * list if it's clean. Returns -EBUSY if it is not clean, returns 1 if
+ * it frees the transaction, 0 otherwise.
+ *
+ * This function is called with j_list_lock held.
+ */
+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh)
+{
+       struct buffer_head *bh = jh2bh(jh);
+
+       if (!trylock_buffer(bh))
+               return -EBUSY;
+       if (buffer_dirty(bh)) {
+               unlock_buffer(bh);
+               return -EBUSY;
+       }
+       unlock_buffer(bh);
+
+       /*
+        * Buffer is clean and the IO has finished (we held the buffer
+        * lock) so the checkpoint is done. We can safely remove the
+        * buffer from this transaction.
+        */
+       JBUFFER_TRACE(jh, "remove from checkpoint list");
+       return __jbd2_journal_remove_checkpoint(jh);
+}
+
+/*
  * journal_insert_checkpoint: put a committed buffer onto a checkpoint
  * list so that we know when it is safe to clean the transaction out of
  * the log.
@@ -797,7 +709,6 @@ void __jbd2_journal_drop_transaction(journal_t *journal, transaction_t *transact
        J_ASSERT(transaction->t_forget == NULL);
        J_ASSERT(transaction->t_shadow_list == NULL);
        J_ASSERT(transaction->t_checkpoint_list == NULL);
-       J_ASSERT(transaction->t_checkpoint_io_list == NULL);
        J_ASSERT(atomic_read(&transaction->t_updates) == 0);
        J_ASSERT(journal->j_committing_transaction != transaction);
        J_ASSERT(journal->j_running_transaction != transaction);
index b33155d..1073259 100644 (file)
@@ -1141,8 +1141,7 @@ restart_loop:
        spin_lock(&journal->j_list_lock);
        commit_transaction->t_state = T_FINISHED;
        /* Check if the transaction can be dropped now that we are finished */
-       if (commit_transaction->t_checkpoint_list == NULL &&
-           commit_transaction->t_checkpoint_io_list == NULL) {
+       if (commit_transaction->t_checkpoint_list == NULL) {
                __jbd2_journal_drop_transaction(journal, commit_transaction);
                jbd2_journal_free_transaction(commit_transaction);
        }
index 1861124..4d1fda1 100644 (file)
@@ -1784,8 +1784,7 @@ int jbd2_journal_forget(handle_t *handle, struct buffer_head *bh)
                 * Otherwise, if the buffer has been written to disk,
                 * it is safe to remove the checkpoint and drop it.
                 */
-               if (!buffer_dirty(bh)) {
-                       __jbd2_journal_remove_checkpoint(jh);
+               if (jbd2_journal_try_remove_checkpoint(jh) >= 0) {
                        spin_unlock(&journal->j_list_lock);
                        goto drop;
                }
@@ -2100,35 +2099,6 @@ void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh)
        __brelse(bh);
 }
 
-/*
- * Called from jbd2_journal_try_to_free_buffers().
- *
- * Called under jh->b_state_lock
- */
-static void
-__journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh)
-{
-       struct journal_head *jh;
-
-       jh = bh2jh(bh);
-
-       if (buffer_locked(bh) || buffer_dirty(bh))
-               goto out;
-
-       if (jh->b_next_transaction != NULL || jh->b_transaction != NULL)
-               goto out;
-
-       spin_lock(&journal->j_list_lock);
-       if (jh->b_cp_transaction != NULL) {
-               /* written-back checkpointed metadata buffer */
-               JBUFFER_TRACE(jh, "remove from checkpoint list");
-               __jbd2_journal_remove_checkpoint(jh);
-       }
-       spin_unlock(&journal->j_list_lock);
-out:
-       return;
-}
-
 /**
  * jbd2_journal_try_to_free_buffers() - try to free page buffers.
  * @journal: journal for operation
@@ -2186,7 +2156,13 @@ bool jbd2_journal_try_to_free_buffers(journal_t *journal, struct folio *folio)
                        continue;
 
                spin_lock(&jh->b_state_lock);
-               __journal_try_to_free_buffer(journal, bh);
+               if (!jh->b_transaction && !jh->b_next_transaction) {
+                       spin_lock(&journal->j_list_lock);
+                       /* Remove written-back checkpointed metadata buffer */
+                       if (jh->b_cp_transaction != NULL)
+                               jbd2_journal_try_remove_checkpoint(jh);
+                       spin_unlock(&journal->j_list_lock);
+               }
                spin_unlock(&jh->b_state_lock);
                jbd2_journal_put_journal_head(jh);
                if (buffer_jbd(bh))
index 6e61fa3..3aefbad 100644 (file)
@@ -6341,8 +6341,6 @@ static __be32 nfsd4_validate_stateid(struct nfs4_client *cl, stateid_t *stateid)
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid) ||
                CLOSE_STATEID(stateid))
                return status;
-       if (!same_clid(&stateid->si_opaque.so_clid, &cl->cl_clientid))
-               return status;
        spin_lock(&cl->cl_lock);
        s = find_stateid_locked(cl, stateid);
        if (!s)
index 8a2321d..2c9074a 100644 (file)
@@ -956,10 +956,13 @@ nfsd_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
        last_page = page + (offset + sd->len - 1) / PAGE_SIZE;
        for (page += offset / PAGE_SIZE; page <= last_page; page++) {
                /*
-                * Skip page replacement when extending the contents
-                * of the current page.
+                * Skip page replacement when extending the contents of the
+                * current page.  But note that we may get two zero_pages in a
+                * row from shmem.
                 */
-               if (page == *(rqstp->rq_next_page - 1))
+               if (page == *(rqstp->rq_next_page - 1) &&
+                   offset_in_page(rqstp->rq_res.page_base +
+                                  rqstp->rq_res.page_len))
                        continue;
                if (unlikely(!svc_rqst_replace_page(rqstp, page)))
                        return -EIO;
index 52ccd34..a026dbd 100644 (file)
@@ -272,7 +272,7 @@ int unregister_nls(struct nls_table * nls)
        return -EINVAL;
 }
 
-static struct nls_table *find_nls(char *charset)
+static struct nls_table *find_nls(const char *charset)
 {
        struct nls_table *nls;
        spin_lock(&nls_lock);
@@ -288,7 +288,7 @@ static struct nls_table *find_nls(char *charset)
        return nls;
 }
 
-struct nls_table *load_nls(char *charset)
+struct nls_table *load_nls(const char *charset)
 {
        return try_then_request_module(find_nls(charset), "nls_%s", charset);
 }
index 5b069f1..cc89774 100644 (file)
@@ -1460,7 +1460,7 @@ int ovl_fill_super(struct super_block *sb, struct fs_context *fc)
                ovl_trusted_xattr_handlers;
        sb->s_fs_info = ofs;
        sb->s_flags |= SB_POSIXACL;
-       sb->s_iflags |= SB_I_SKIP_SYNC;
+       sb->s_iflags |= SB_I_SKIP_SYNC | SB_I_IMA_UNVERIFIABLE_SIGNATURE;
 
        err = -ENOMEM;
        root_dentry = ovl_get_root(sb, ctx->upper.dentry, oe);
index cb80a77..1fb213f 100644 (file)
@@ -132,7 +132,7 @@ ssize_t read_from_oldmem(struct iov_iter *iter, size_t count,
                         u64 *ppos, bool encrypted)
 {
        unsigned long pfn, offset;
-       size_t nr_bytes;
+       ssize_t nr_bytes;
        ssize_t read = 0, tmp;
        int idx;
 
index d7274ee..15c8cc4 100644 (file)
@@ -159,6 +159,6 @@ extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
 /* when changing internal version - update following two lines at same time */
-#define SMB3_PRODUCT_BUILD 43
-#define CIFS_VERSION   "2.43"
+#define SMB3_PRODUCT_BUILD 44
+#define CIFS_VERSION   "2.44"
 #endif                         /* _CIFSFS_H */
index e5eec6d..657dee4 100644 (file)
@@ -1062,6 +1062,7 @@ struct cifs_ses {
        unsigned long chans_need_reconnect;
        /* ========= end: protected by chan_lock ======== */
        struct cifs_ses *dfs_root_ses;
+       struct nls_table *local_nls;
 };
 
 static inline bool
index 9dee267..25503f1 100644 (file)
@@ -129,7 +129,7 @@ again:
        }
        spin_unlock(&server->srv_lock);
 
-       nls_codepage = load_nls_default();
+       nls_codepage = ses->local_nls;
 
        /*
         * need to prevent multiple threads trying to simultaneously
@@ -200,7 +200,6 @@ out:
                rc = -EAGAIN;
        }
 
-       unload_nls(nls_codepage);
        return rc;
 }
 
index 9280e25..238538d 100644 (file)
@@ -1842,6 +1842,10 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
                            CIFS_MAX_PASSWORD_LEN))
                        return 0;
        }
+
+       if (strcmp(ctx->local_nls->charset, ses->local_nls->charset))
+               return 0;
+
        return 1;
 }
 
@@ -2286,6 +2290,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
 
        ses->sectype = ctx->sectype;
        ses->sign = ctx->sign;
+       ses->local_nls = load_nls(ctx->local_nls->charset);
 
        /* add server as first channel */
        spin_lock(&ses->chan_lock);
index fff092b..f716000 100644 (file)
@@ -433,16 +433,21 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                         * Dump encryption keys. This is an old ioctl that only
                         * handles AES-128-{CCM,GCM}.
                         */
-                       if (pSMBFile == NULL)
-                               break;
                        if (!capable(CAP_SYS_ADMIN)) {
                                rc = -EACCES;
                                break;
                        }
 
-                       tcon = tlink_tcon(pSMBFile->tlink);
+                       cifs_sb = CIFS_SB(inode->i_sb);
+                       tlink = cifs_sb_tlink(cifs_sb);
+                       if (IS_ERR(tlink)) {
+                               rc = PTR_ERR(tlink);
+                               break;
+                       }
+                       tcon = tlink_tcon(tlink);
                        if (!smb3_encryption_required(tcon)) {
                                rc = -EOPNOTSUPP;
+                               cifs_put_tlink(tlink);
                                break;
                        }
                        pkey_inf.cipher_type =
@@ -459,6 +464,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                                rc = -EFAULT;
                        else
                                rc = 0;
+                       cifs_put_tlink(tlink);
                        break;
                case CIFS_DUMP_FULL_KEY:
                        /*
@@ -470,8 +476,16 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                                rc = -EACCES;
                                break;
                        }
-                       tcon = tlink_tcon(pSMBFile->tlink);
+                       cifs_sb = CIFS_SB(inode->i_sb);
+                       tlink = cifs_sb_tlink(cifs_sb);
+                       if (IS_ERR(tlink)) {
+                               rc = PTR_ERR(tlink);
+                               break;
+                       }
+
+                       tcon = tlink_tcon(tlink);
                        rc = cifs_dump_full_key(tcon, (void __user *)arg);
+                       cifs_put_tlink(tlink);
                        break;
                case CIFS_IOC_NOTIFY:
                        if (!S_ISDIR(inode->i_mode)) {
index 70dbfe6..d7e85d9 100644 (file)
@@ -95,6 +95,7 @@ sesInfoFree(struct cifs_ses *buf_to_free)
                return;
        }
 
+       unload_nls(buf_to_free->local_nls);
        atomic_dec(&sesInfoAllocCount);
        kfree(buf_to_free->serverOS);
        kfree(buf_to_free->serverDomain);
index 335c078..c57ca20 100644 (file)
@@ -1013,6 +1013,7 @@ setup_ntlm_smb3_neg_ret:
 }
 
 
+/* See MS-NLMP 2.2.1.3 */
 int build_ntlmssp_auth_blob(unsigned char **pbuffer,
                                        u16 *buflen,
                                   struct cifs_ses *ses,
@@ -1047,7 +1048,8 @@ int build_ntlmssp_auth_blob(unsigned char **pbuffer,
 
        flags = ses->ntlmssp->server_flags | NTLMSSP_REQUEST_TARGET |
                NTLMSSP_NEGOTIATE_TARGET_INFO | NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED;
-
+       /* we only send version information in ntlmssp negotiate, so do not set this flag */
+       flags = flags & ~NTLMSSP_NEGOTIATE_VERSION;
        tmp = *pbuffer + sizeof(AUTHENTICATE_MESSAGE);
        sec_blob->NegotiateFlags = cpu_to_le32(flags);
 
index e04766f..a457f07 100644 (file)
@@ -242,7 +242,7 @@ again:
        }
        spin_unlock(&server->srv_lock);
 
-       nls_codepage = load_nls_default();
+       nls_codepage = ses->local_nls;
 
        /*
         * need to prevent multiple threads trying to simultaneously
@@ -324,7 +324,6 @@ out:
                rc = -EAGAIN;
        }
 failed:
-       unload_nls(nls_codepage);
        return rc;
 }
 
index fb8b2d5..b7521e4 100644 (file)
@@ -352,7 +352,8 @@ enum KSMBD_TREE_CONN_STATUS {
 #define KSMBD_SHARE_FLAG_STREAMS               BIT(11)
 #define KSMBD_SHARE_FLAG_FOLLOW_SYMLINKS       BIT(12)
 #define KSMBD_SHARE_FLAG_ACL_XATTR             BIT(13)
-#define KSMBD_SHARE_FLAG_UPDATE                BIT(14)
+#define KSMBD_SHARE_FLAG_UPDATE                        BIT(14)
+#define KSMBD_SHARE_FLAG_CROSSMNT              BIT(15)
 
 /*
  * Tree connect request flags.
index ced7a9e..9df121b 100644 (file)
@@ -286,6 +286,7 @@ static void handle_ksmbd_work(struct work_struct *wk)
 static int queue_ksmbd_work(struct ksmbd_conn *conn)
 {
        struct ksmbd_work *work;
+       int err;
 
        work = ksmbd_alloc_work_struct();
        if (!work) {
@@ -297,7 +298,11 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
        work->request_buf = conn->request_buf;
        conn->request_buf = NULL;
 
-       ksmbd_init_smb_server(work);
+       err = ksmbd_init_smb_server(work);
+       if (err) {
+               ksmbd_free_work_struct(work);
+               return 0;
+       }
 
        ksmbd_conn_enqueue_request(work);
        atomic_inc(&conn->r_count);
index cf88221..9849d74 100644 (file)
@@ -87,9 +87,9 @@ struct channel *lookup_chann_list(struct ksmbd_session *sess, struct ksmbd_conn
  */
 int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
 {
-       struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+       struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
        unsigned int cmd = le16_to_cpu(req_hdr->Command);
-       int tree_id;
+       unsigned int tree_id;
 
        if (cmd == SMB2_TREE_CONNECT_HE ||
            cmd ==  SMB2_CANCEL_HE ||
@@ -114,7 +114,7 @@ int smb2_get_ksmbd_tcon(struct ksmbd_work *work)
                        pr_err("The first operation in the compound does not have tcon\n");
                        return -EINVAL;
                }
-               if (work->tcon->id != tree_id) {
+               if (tree_id != UINT_MAX && work->tcon->id != tree_id) {
                        pr_err("tree id(%u) is different with id(%u) in first operation\n",
                                        tree_id, work->tcon->id);
                        return -EINVAL;
@@ -559,9 +559,9 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
  */
 int smb2_check_user_session(struct ksmbd_work *work)
 {
-       struct smb2_hdr *req_hdr = smb2_get_msg(work->request_buf);
+       struct smb2_hdr *req_hdr = ksmbd_req_buf_next(work);
        struct ksmbd_conn *conn = work->conn;
-       unsigned int cmd = conn->ops->get_cmd_val(work);
+       unsigned int cmd = le16_to_cpu(req_hdr->Command);
        unsigned long long sess_id;
 
        /*
@@ -587,7 +587,7 @@ int smb2_check_user_session(struct ksmbd_work *work)
                        pr_err("The first operation in the compound does not have sess\n");
                        return -EINVAL;
                }
-               if (work->sess->id != sess_id) {
+               if (sess_id != ULLONG_MAX && work->sess->id != sess_id) {
                        pr_err("session id(%llu) is different with the first operation(%lld)\n",
                                        sess_id, work->sess->id);
                        return -EINVAL;
@@ -2467,8 +2467,9 @@ static void smb2_update_xattrs(struct ksmbd_tree_connect *tcon,
        }
 }
 
-static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
-                     int open_flags, umode_t posix_mode, bool is_dir)
+static int smb2_creat(struct ksmbd_work *work, struct path *parent_path,
+                     struct path *path, char *name, int open_flags,
+                     umode_t posix_mode, bool is_dir)
 {
        struct ksmbd_tree_connect *tcon = work->tcon;
        struct ksmbd_share_config *share = tcon->share_conf;
@@ -2495,7 +2496,7 @@ static int smb2_creat(struct ksmbd_work *work, struct path *path, char *name,
                        return rc;
        }
 
-       rc = ksmbd_vfs_kern_path_locked(work, name, 0, path, 0);
+       rc = ksmbd_vfs_kern_path_locked(work, name, 0, parent_path, path, 0);
        if (rc) {
                pr_err("cannot get linux path (%s), err = %d\n",
                       name, rc);
@@ -2565,7 +2566,7 @@ int smb2_open(struct ksmbd_work *work)
        struct ksmbd_tree_connect *tcon = work->tcon;
        struct smb2_create_req *req;
        struct smb2_create_rsp *rsp;
-       struct path path;
+       struct path path, parent_path;
        struct ksmbd_share_config *share = tcon->share_conf;
        struct ksmbd_file *fp = NULL;
        struct file *filp = NULL;
@@ -2786,7 +2787,8 @@ int smb2_open(struct ksmbd_work *work)
                goto err_out1;
        }
 
-       rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS, &path, 1);
+       rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS,
+                                       &parent_path, &path, 1);
        if (!rc) {
                file_present = true;
 
@@ -2906,7 +2908,8 @@ int smb2_open(struct ksmbd_work *work)
 
        /*create file if not present */
        if (!file_present) {
-               rc = smb2_creat(work, &path, name, open_flags, posix_mode,
+               rc = smb2_creat(work, &parent_path, &path, name, open_flags,
+                               posix_mode,
                                req->CreateOptions & FILE_DIRECTORY_FILE_LE);
                if (rc) {
                        if (rc == -ENOENT) {
@@ -3321,8 +3324,9 @@ int smb2_open(struct ksmbd_work *work)
 
 err_out:
        if (file_present || created) {
-               inode_unlock(d_inode(path.dentry->d_parent));
-               dput(path.dentry);
+               inode_unlock(d_inode(parent_path.dentry));
+               path_put(&path);
+               path_put(&parent_path);
        }
        ksmbd_revert_fsids(work);
 err_out1:
@@ -5545,7 +5549,7 @@ static int smb2_create_link(struct ksmbd_work *work,
                            struct nls_table *local_nls)
 {
        char *link_name = NULL, *target_name = NULL, *pathname = NULL;
-       struct path path;
+       struct path path, parent_path;
        bool file_present = false;
        int rc;
 
@@ -5575,7 +5579,7 @@ static int smb2_create_link(struct ksmbd_work *work,
 
        ksmbd_debug(SMB, "target name is %s\n", target_name);
        rc = ksmbd_vfs_kern_path_locked(work, link_name, LOOKUP_NO_SYMLINKS,
-                                       &path, 0);
+                                       &parent_path, &path, 0);
        if (rc) {
                if (rc != -ENOENT)
                        goto out;
@@ -5605,8 +5609,9 @@ static int smb2_create_link(struct ksmbd_work *work,
                rc = -EINVAL;
 out:
        if (file_present) {
-               inode_unlock(d_inode(path.dentry->d_parent));
+               inode_unlock(d_inode(parent_path.dentry));
                path_put(&path);
+               path_put(&parent_path);
        }
        if (!IS_ERR(link_name))
                kfree(link_name);
@@ -6209,6 +6214,11 @@ int smb2_read(struct ksmbd_work *work)
        unsigned int max_read_size = conn->vals->max_read_size;
 
        WORK_BUFFERS(work, req, rsp);
+       if (work->next_smb2_rcv_hdr_off) {
+               work->send_no_response = 1;
+               err = -EOPNOTSUPP;
+               goto out;
+       }
 
        if (test_share_config_flag(work->tcon->share_conf,
                                   KSMBD_SHARE_FLAG_PIPE)) {
@@ -8609,7 +8619,8 @@ int smb3_decrypt_req(struct ksmbd_work *work)
        struct smb2_transform_hdr *tr_hdr = smb2_get_msg(buf);
        int rc = 0;
 
-       if (buf_data_size < sizeof(struct smb2_hdr)) {
+       if (pdu_length < sizeof(struct smb2_transform_hdr) ||
+           buf_data_size < sizeof(struct smb2_hdr)) {
                pr_err("Transform message is too small (%u)\n",
                       pdu_length);
                return -ECONNABORTED;
index ef20f63..c2b75d8 100644 (file)
@@ -388,26 +388,29 @@ static struct smb_version_cmds smb1_server_cmds[1] = {
        [SMB_COM_NEGOTIATE_EX]  = { .proc = smb1_negotiate, },
 };
 
-static void init_smb1_server(struct ksmbd_conn *conn)
+static int init_smb1_server(struct ksmbd_conn *conn)
 {
        conn->ops = &smb1_server_ops;
        conn->cmds = smb1_server_cmds;
        conn->max_cmds = ARRAY_SIZE(smb1_server_cmds);
+       return 0;
 }
 
-void ksmbd_init_smb_server(struct ksmbd_work *work)
+int ksmbd_init_smb_server(struct ksmbd_work *work)
 {
        struct ksmbd_conn *conn = work->conn;
        __le32 proto;
 
-       if (conn->need_neg == false)
-               return;
-
        proto = *(__le32 *)((struct smb_hdr *)work->request_buf)->Protocol;
+       if (conn->need_neg == false) {
+               if (proto == SMB1_PROTO_NUMBER)
+                       return -EINVAL;
+               return 0;
+       }
+
        if (proto == SMB1_PROTO_NUMBER)
-               init_smb1_server(conn);
-       else
-               init_smb3_11_server(conn);
+               return init_smb1_server(conn);
+       return init_smb3_11_server(conn);
 }
 
 int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work, int info_level,
index aeca0f4..f109251 100644 (file)
@@ -427,7 +427,7 @@ bool ksmbd_smb_request(struct ksmbd_conn *conn);
 
 int ksmbd_lookup_dialect_by_id(__le16 *cli_dialects, __le16 dialects_count);
 
-void ksmbd_init_smb_server(struct ksmbd_work *work);
+int ksmbd_init_smb_server(struct ksmbd_work *work);
 
 struct ksmbd_kstat;
 int ksmbd_populate_dot_dotdot_entries(struct ksmbd_work *work,
index e359144..3d5d652 100644 (file)
@@ -63,13 +63,13 @@ int ksmbd_vfs_lock_parent(struct dentry *parent, struct dentry *child)
 
 static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
                                        char *pathname, unsigned int flags,
+                                       struct path *parent_path,
                                        struct path *path)
 {
        struct qstr last;
        struct filename *filename;
        struct path *root_share_path = &share_conf->vfs_path;
        int err, type;
-       struct path parent_path;
        struct dentry *d;
 
        if (pathname[0] == '\0') {
@@ -84,7 +84,7 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
                return PTR_ERR(filename);
 
        err = vfs_path_parent_lookup(filename, flags,
-                                    &parent_path, &last, &type,
+                                    parent_path, &last, &type,
                                     root_share_path);
        if (err) {
                putname(filename);
@@ -92,13 +92,13 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
        }
 
        if (unlikely(type != LAST_NORM)) {
-               path_put(&parent_path);
+               path_put(parent_path);
                putname(filename);
                return -ENOENT;
        }
 
-       inode_lock_nested(parent_path.dentry->d_inode, I_MUTEX_PARENT);
-       d = lookup_one_qstr_excl(&last, parent_path.dentry, 0);
+       inode_lock_nested(parent_path->dentry->d_inode, I_MUTEX_PARENT);
+       d = lookup_one_qstr_excl(&last, parent_path->dentry, 0);
        if (IS_ERR(d))
                goto err_out;
 
@@ -108,15 +108,22 @@ static int ksmbd_vfs_path_lookup_locked(struct ksmbd_share_config *share_conf,
        }
 
        path->dentry = d;
-       path->mnt = share_conf->vfs_path.mnt;
-       path_put(&parent_path);
-       putname(filename);
+       path->mnt = mntget(parent_path->mnt);
 
+       if (test_share_config_flag(share_conf, KSMBD_SHARE_FLAG_CROSSMNT)) {
+               err = follow_down(path, 0);
+               if (err < 0) {
+                       path_put(path);
+                       goto err_out;
+               }
+       }
+
+       putname(filename);
        return 0;
 
 err_out:
-       inode_unlock(parent_path.dentry->d_inode);
-       path_put(&parent_path);
+       inode_unlock(d_inode(parent_path->dentry));
+       path_put(parent_path);
        putname(filename);
        return -ENOENT;
 }
@@ -412,7 +419,8 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
 {
        char *stream_buf = NULL, *wbuf;
        struct mnt_idmap *idmap = file_mnt_idmap(fp->filp);
-       size_t size, v_len;
+       size_t size;
+       ssize_t v_len;
        int err = 0;
 
        ksmbd_debug(VFS, "write stream data pos : %llu, count : %zd\n",
@@ -429,9 +437,9 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
                                       fp->stream.name,
                                       fp->stream.size,
                                       &stream_buf);
-       if ((int)v_len < 0) {
+       if (v_len < 0) {
                pr_err("not found stream in xattr : %zd\n", v_len);
-               err = (int)v_len;
+               err = v_len;
                goto out;
        }
 
@@ -1194,14 +1202,14 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name,
  * Return:     0 on success, otherwise error
  */
 int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
-                              unsigned int flags, struct path *path,
-                              bool caseless)
+                              unsigned int flags, struct path *parent_path,
+                              struct path *path, bool caseless)
 {
        struct ksmbd_share_config *share_conf = work->tcon->share_conf;
        int err;
-       struct path parent_path;
 
-       err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, path);
+       err = ksmbd_vfs_path_lookup_locked(share_conf, name, flags, parent_path,
+                                          path);
        if (!err)
                return 0;
 
@@ -1216,10 +1224,10 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
                path_len = strlen(filepath);
                remain_len = path_len;
 
-               parent_path = share_conf->vfs_path;
-               path_get(&parent_path);
+               *parent_path = share_conf->vfs_path;
+               path_get(parent_path);
 
-               while (d_can_lookup(parent_path.dentry)) {
+               while (d_can_lookup(parent_path->dentry)) {
                        char *filename = filepath + path_len - remain_len;
                        char *next = strchrnul(filename, '/');
                        size_t filename_len = next - filename;
@@ -1228,7 +1236,7 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
                        if (filename_len == 0)
                                break;
 
-                       err = ksmbd_vfs_lookup_in_dir(&parent_path, filename,
+                       err = ksmbd_vfs_lookup_in_dir(parent_path, filename,
                                                      filename_len,
                                                      work->conn->um);
                        if (err)
@@ -1245,8 +1253,8 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
                                goto out2;
                        else if (is_last)
                                goto out1;
-                       path_put(&parent_path);
-                       parent_path = *path;
+                       path_put(parent_path);
+                       *parent_path = *path;
 
                        next[0] = '/';
                        remain_len -= filename_len + 1;
@@ -1254,16 +1262,17 @@ int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
 
                err = -EINVAL;
 out2:
-               path_put(&parent_path);
+               path_put(parent_path);
 out1:
                kfree(filepath);
        }
 
        if (!err) {
-               err = ksmbd_vfs_lock_parent(parent_path.dentry, path->dentry);
-               if (err)
-                       dput(path->dentry);
-               path_put(&parent_path);
+               err = ksmbd_vfs_lock_parent(parent_path->dentry, path->dentry);
+               if (err) {
+                       path_put(path);
+                       path_put(parent_path);
+               }
        }
        return err;
 }
index 8003931..72f9fb4 100644 (file)
@@ -115,8 +115,8 @@ int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
 int ksmbd_vfs_remove_xattr(struct mnt_idmap *idmap,
                           const struct path *path, char *attr_name);
 int ksmbd_vfs_kern_path_locked(struct ksmbd_work *work, char *name,
-                              unsigned int flags, struct path *path,
-                              bool caseless);
+                              unsigned int flags, struct path *parent_path,
+                              struct path *path, bool caseless);
 struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
                                          const char *name,
                                          unsigned int flags,
index 004eb1c..3e2a31e 100644 (file)
@@ -876,6 +876,8 @@ ssize_t splice_to_socket(struct pipe_inode_info *pipe, struct file *out,
                        msg.msg_flags |= MSG_MORE;
                if (remain && pipe_occupancy(pipe->head, tail) > 0)
                        msg.msg_flags |= MSG_MORE;
+               if (out->f_flags & O_NONBLOCK)
+                       msg.msg_flags |= MSG_DONTWAIT;
 
                iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, bvec, bc,
                              len - remain);
index 25e2841..f9015f8 100644 (file)
@@ -591,7 +591,7 @@ struct xfs_attr_shortform {
                uint8_t valuelen;       /* actual length of value (no NULL) */
                uint8_t flags;  /* flags bits (see xfs_attr_leaf.h) */
                uint8_t nameval[];      /* name & value bytes concatenated */
-       } list[1];                      /* variable sized array */
+       } list[];                       /* variable sized array */
 };
 
 typedef struct xfs_attr_leaf_map {     /* RLE map of free bytes */
@@ -620,19 +620,29 @@ typedef struct xfs_attr_leaf_entry {      /* sorted on key, not name */
 typedef struct xfs_attr_leaf_name_local {
        __be16  valuelen;               /* number of bytes in value */
        __u8    namelen;                /* length of name bytes */
-       __u8    nameval[1];             /* name/value bytes */
+       /*
+        * In Linux 6.5 this flex array was converted from nameval[1] to
+        * nameval[].  Be very careful here about extra padding at the end;
+        * see xfs_attr_leaf_entsize_local() for details.
+        */
+       __u8    nameval[];              /* name/value bytes */
 } xfs_attr_leaf_name_local_t;
 
 typedef struct xfs_attr_leaf_name_remote {
        __be32  valueblk;               /* block number of value bytes */
        __be32  valuelen;               /* number of bytes in value */
        __u8    namelen;                /* length of name bytes */
-       __u8    name[1];                /* name bytes */
+       /*
+        * In Linux 6.5 this flex array was converted from name[1] to name[].
+        * Be very careful here about extra padding at the end; see
+        * xfs_attr_leaf_entsize_remote() for details.
+        */
+       __u8    name[];                 /* name bytes */
 } xfs_attr_leaf_name_remote_t;
 
 typedef struct xfs_attr_leafblock {
        xfs_attr_leaf_hdr_t     hdr;    /* constant-structure header block */
-       xfs_attr_leaf_entry_t   entries[1];     /* sorted on key, not name */
+       xfs_attr_leaf_entry_t   entries[];      /* sorted on key, not name */
        /*
         * The rest of the block contains the following structures after the
         * leaf entries, growing from the bottom up. The variables are never
@@ -664,7 +674,7 @@ struct xfs_attr3_leaf_hdr {
 
 struct xfs_attr3_leafblock {
        struct xfs_attr3_leaf_hdr       hdr;
-       struct xfs_attr_leaf_entry      entries[1];
+       struct xfs_attr_leaf_entry      entries[];
 
        /*
         * The rest of the block contains the following structures after the
@@ -747,14 +757,61 @@ xfs_attr3_leaf_name_local(xfs_attr_leafblock_t *leafp, int idx)
  */
 static inline int xfs_attr_leaf_entsize_remote(int nlen)
 {
-       return round_up(sizeof(struct xfs_attr_leaf_name_remote) - 1 +
-                       nlen, XFS_ATTR_LEAF_NAME_ALIGN);
+       /*
+        * Prior to Linux 6.5, struct xfs_attr_leaf_name_remote ended with
+        * name[1], which was used as a flexarray.  The layout of this struct
+        * is 9 bytes of fixed-length fields followed by a __u8 flex array at
+        * offset 9.
+        *
+        * On most architectures, struct xfs_attr_leaf_name_remote had two
+        * bytes of implicit padding at the end of the struct to make the
+        * struct length 12.  After converting name[1] to name[], there are
+        * three implicit padding bytes and the struct size remains 12.
+        * However, there are compiler configurations that do not add implicit
+        * padding at all (m68k) and have been broken for years.
+        *
+        * This entsize computation historically added (the xattr name length)
+        * to (the padded struct length - 1) and rounded that sum up to the
+        * nearest multiple of 4 (NAME_ALIGN).  IOWs, round_up(11 + nlen, 4).
+        * This is encoded in the ondisk format, so we cannot change this.
+        *
+        * Compute the entsize from offsetof of the flexarray and manually
+        * adding bytes for the implicit padding.
+        */
+       const size_t remotesize =
+                       offsetof(struct xfs_attr_leaf_name_remote, name) + 2;
+
+       return round_up(remotesize + nlen, XFS_ATTR_LEAF_NAME_ALIGN);
 }
 
 static inline int xfs_attr_leaf_entsize_local(int nlen, int vlen)
 {
-       return round_up(sizeof(struct xfs_attr_leaf_name_local) - 1 +
-                       nlen + vlen, XFS_ATTR_LEAF_NAME_ALIGN);
+       /*
+        * Prior to Linux 6.5, struct xfs_attr_leaf_name_local ended with
+        * nameval[1], which was used as a flexarray.  The layout of this
+        * struct is 3 bytes of fixed-length fields followed by a __u8 flex
+        * array at offset 3.
+        *
+        * struct xfs_attr_leaf_name_local had zero bytes of implicit padding
+        * at the end of the struct to make the struct length 4.  On most
+        * architectures, after converting nameval[1] to nameval[], there is
+        * one implicit padding byte and the struct size remains 4.  However,
+        * there are compiler configurations that do not add implicit padding
+        * at all (m68k) and would break.
+        *
+        * This entsize computation historically added (the xattr name and
+        * value length) to (the padded struct length - 1) and rounded that sum
+        * up to the nearest multiple of 4 (NAME_ALIGN).  IOWs, the formula is
+        * round_up(3 + nlen + vlen, 4).  This is encoded in the ondisk format,
+        * so we cannot change this.
+        *
+        * Compute the entsize from offsetof of the flexarray and manually
+        * adding bytes for the implicit padding.
+        */
+       const size_t localsize =
+                       offsetof(struct xfs_attr_leaf_name_local, nameval);
+
+       return round_up(localsize + nlen + vlen, XFS_ATTR_LEAF_NAME_ALIGN);
 }
 
 static inline int xfs_attr_leaf_entsize_local_max(int bsize)
index 9c60ebb..2cbf9ea 100644 (file)
@@ -592,12 +592,12 @@ typedef struct xfs_attrlist_cursor {
 struct xfs_attrlist {
        __s32   al_count;       /* number of entries in attrlist */
        __s32   al_more;        /* T/F: more attrs (do call again) */
-       __s32   al_offset[1];   /* byte offsets of attrs [var-sized] */
+       __s32   al_offset[];    /* byte offsets of attrs [var-sized] */
 };
 
 struct xfs_attrlist_ent {      /* data from attr_list() */
        __u32   a_valuelen;     /* number bytes in value of attr */
-       char    a_name[1];      /* attr name (NULL terminated) */
+       char    a_name[];       /* attr name (NULL terminated) */
 };
 
 typedef struct xfs_fsop_attrlist_handlereq {
index 9737b5a..c4cc99b 100644 (file)
@@ -56,7 +56,7 @@ xfs_check_ondisk_structs(void)
 
        /* dir/attr trees */
        XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leaf_hdr,        80);
-       XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leafblock,       88);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_leafblock,       80);
        XFS_CHECK_STRUCT_SIZE(struct xfs_attr3_rmt_hdr,         56);
        XFS_CHECK_STRUCT_SIZE(struct xfs_da3_blkinfo,           56);
        XFS_CHECK_STRUCT_SIZE(struct xfs_da3_intnode,           64);
@@ -88,7 +88,8 @@ xfs_check_ondisk_structs(void)
        XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, valuelen, 4);
        XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, namelen,  8);
        XFS_CHECK_OFFSET(xfs_attr_leaf_name_remote_t, name,     9);
-       XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t,             40);
+       XFS_CHECK_STRUCT_SIZE(xfs_attr_leafblock_t,             32);
+       XFS_CHECK_STRUCT_SIZE(struct xfs_attr_shortform,        4);
        XFS_CHECK_OFFSET(struct xfs_attr_shortform, hdr.totsize, 0);
        XFS_CHECK_OFFSET(struct xfs_attr_shortform, hdr.count,   2);
        XFS_CHECK_OFFSET(struct xfs_attr_shortform, list[0].namelen,    4);
index 20c93f0..95a1d21 100644 (file)
@@ -38,7 +38,7 @@ static inline long find_zero(unsigned long mask)
        return (mask >> 8) ? byte : byte + 1;
 }
 
-static inline bool has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
+static inline unsigned long has_zero(unsigned long val, unsigned long *data, const struct word_at_a_time *c)
 {
        unsigned long rhs = val | c->low_bits;
        *data = rhs;
index 4863b0f..375737f 100644 (file)
@@ -368,11 +368,6 @@ static inline void drm_fb_helper_deferred_io(struct fb_info *info,
 {
 }
 
-static inline int drm_fb_helper_defio_init(struct drm_fb_helper *fb_helper)
-{
-       return -ENODEV;
-}
-
 static inline void drm_fb_helper_set_suspend(struct drm_fb_helper *fb_helper,
                                             bool suspend)
 {
index 402b545..5b27f94 100644 (file)
@@ -431,7 +431,7 @@ int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
 
 int vgic_v4_load(struct kvm_vcpu *vcpu);
 void vgic_v4_commit(struct kvm_vcpu *vcpu);
-int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db);
+int vgic_v4_put(struct kvm_vcpu *vcpu);
 
 /* CPU HP callbacks */
 void kvm_vgic_cpu_up(void);
index b96e004..495ca19 100644 (file)
@@ -397,8 +397,6 @@ struct blk_mq_hw_ctx {
         */
        struct blk_mq_tags      *sched_tags;
 
-       /** @queued: Number of queued requests. */
-       unsigned long           queued;
        /** @run: Number of dispatched requests. */
        unsigned long           run;
 
index 0d2e2a3..f10fb87 100644 (file)
@@ -175,8 +175,8 @@ static inline unsigned int cpumask_first_zero(const struct cpumask *srcp)
 
 /**
  * cpumask_first_and - return the first cpu from *srcp1 & *srcp2
- * @src1p: the first input
- * @src2p: the second input
+ * @srcp1: the first input
+ * @srcp2: the second input
  *
  * Returns >= nr_cpu_ids if no cpus set in both.  See also cpumask_next_and().
  */
@@ -1197,6 +1197,10 @@ cpumap_print_bitmask_to_buf(char *buf, const struct cpumask *mask,
 /**
  * cpumap_print_list_to_buf  - copies the cpumask into the buffer as
  *     comma-separated list of cpus
+ * @buf: the buffer to copy into
+ * @mask: the cpumask to copy
+ * @off: in the string from which we are copying, we copy to @buf
+ * @count: the maximum number of bytes to print
  *
  * Everything is same with the above cpumap_print_bitmask_to_buf()
  * except the print format.
index ce156c7..aad9cf8 100644 (file)
@@ -684,7 +684,6 @@ void __init
 ftrace_set_early_filter(struct ftrace_ops *ops, char *buf, int enable);
 
 /* defined in arch */
-extern int ftrace_ip_converted(unsigned long ip);
 extern int ftrace_dyn_arch_init(void);
 extern void ftrace_replace_code(int enable);
 extern int ftrace_update_ftrace_func(ftrace_func_t func);
@@ -859,9 +858,6 @@ static inline int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_a
 }
 #endif
 
-/* May be defined in arch */
-extern int ftrace_arch_read_dyn_info(char *buf, int size);
-
 extern int skip_trace(unsigned long ip);
 extern void ftrace_module_init(struct module *mod);
 extern void ftrace_module_enable(struct module *mod);
index d860499..44c298a 100644 (file)
@@ -614,12 +614,6 @@ struct transaction_s
        struct journal_head     *t_checkpoint_list;
 
        /*
-        * Doubly-linked circular list of all buffers submitted for IO while
-        * checkpointing. [j_list_lock]
-        */
-       struct journal_head     *t_checkpoint_io_list;
-
-       /*
         * Doubly-linked circular list of metadata buffers being
         * shadowed by log IO.  The IO buffers on the iobuf list and
         * the shadow buffers on this list match each other one for
@@ -1449,6 +1443,7 @@ extern void jbd2_journal_commit_transaction(journal_t *);
 void __jbd2_journal_clean_checkpoint_list(journal_t *journal, bool destroy);
 unsigned long jbd2_journal_shrink_checkpoint_list(journal_t *journal, unsigned long *nr_to_scan);
 int __jbd2_journal_remove_checkpoint(struct journal_head *);
+int jbd2_journal_try_remove_checkpoint(struct journal_head *jh);
 void jbd2_journal_destroy_checkpoint(journal_t *journal);
 void __jbd2_journal_insert_checkpoint(struct journal_head *, transaction_t *);
 
index 2dd73e4..406ab9e 100644 (file)
@@ -641,8 +641,14 @@ static inline void vma_numab_state_free(struct vm_area_struct *vma) {}
  */
 static inline bool vma_start_read(struct vm_area_struct *vma)
 {
-       /* Check before locking. A race might cause false locked result. */
-       if (vma->vm_lock_seq == READ_ONCE(vma->vm_mm->mm_lock_seq))
+       /*
+        * Check before locking. A race might cause false locked result.
+        * We can use READ_ONCE() for the mm_lock_seq here, and don't need
+        * ACQUIRE semantics, because this is just a lockless check whose result
+        * we don't rely on for anything - the mm_lock_seq read against which we
+        * need ordering is below.
+        */
+       if (READ_ONCE(vma->vm_lock_seq) == READ_ONCE(vma->vm_mm->mm_lock_seq))
                return false;
 
        if (unlikely(down_read_trylock(&vma->vm_lock->lock) == 0))
@@ -653,8 +659,13 @@ static inline bool vma_start_read(struct vm_area_struct *vma)
         * False unlocked result is impossible because we modify and check
         * vma->vm_lock_seq under vma->vm_lock protection and mm->mm_lock_seq
         * modification invalidates all existing locks.
+        *
+        * We must use ACQUIRE semantics for the mm_lock_seq so that if we are
+        * racing with vma_end_write_all(), we only start reading from the VMA
+        * after it has been unlocked.
+        * This pairs with RELEASE semantics in vma_end_write_all().
         */
-       if (unlikely(vma->vm_lock_seq == READ_ONCE(vma->vm_mm->mm_lock_seq))) {
+       if (unlikely(vma->vm_lock_seq == smp_load_acquire(&vma->vm_mm->mm_lock_seq))) {
                up_read(&vma->vm_lock->lock);
                return false;
        }
@@ -676,7 +687,7 @@ static bool __is_vma_write_locked(struct vm_area_struct *vma, int *mm_lock_seq)
         * current task is holding mmap_write_lock, both vma->vm_lock_seq and
         * mm->mm_lock_seq can't be concurrently modified.
         */
-       *mm_lock_seq = READ_ONCE(vma->vm_mm->mm_lock_seq);
+       *mm_lock_seq = vma->vm_mm->mm_lock_seq;
        return (vma->vm_lock_seq == *mm_lock_seq);
 }
 
@@ -688,7 +699,13 @@ static inline void vma_start_write(struct vm_area_struct *vma)
                return;
 
        down_write(&vma->vm_lock->lock);
-       vma->vm_lock_seq = mm_lock_seq;
+       /*
+        * We should use WRITE_ONCE() here because we can have concurrent reads
+        * from the early lockless pessimistic check in vma_start_read().
+        * We don't really care about the correctness of that early check, but
+        * we should use WRITE_ONCE() for cleanliness and to keep KCSAN happy.
+        */
+       WRITE_ONCE(vma->vm_lock_seq, mm_lock_seq);
        up_write(&vma->vm_lock->lock);
 }
 
@@ -702,7 +719,7 @@ static inline bool vma_try_start_write(struct vm_area_struct *vma)
        if (!down_write_trylock(&vma->vm_lock->lock))
                return false;
 
-       vma->vm_lock_seq = mm_lock_seq;
+       WRITE_ONCE(vma->vm_lock_seq, mm_lock_seq);
        up_write(&vma->vm_lock->lock);
        return true;
 }
index de10fc7..5e74ce4 100644 (file)
@@ -514,6 +514,20 @@ struct vm_area_struct {
        };
 
 #ifdef CONFIG_PER_VMA_LOCK
+       /*
+        * Can only be written (using WRITE_ONCE()) while holding both:
+        *  - mmap_lock (in write mode)
+        *  - vm_lock->lock (in write mode)
+        * Can be read reliably while holding one of:
+        *  - mmap_lock (in read or write mode)
+        *  - vm_lock->lock (in read or write mode)
+        * Can be read unreliably (using READ_ONCE()) for pessimistic bailout
+        * while holding nothing (except RCU to keep the VMA struct allocated).
+        *
+        * This sequence counter is explicitly allowed to overflow; sequence
+        * counter reuse can only lead to occasional unnecessary use of the
+        * slowpath.
+        */
        int vm_lock_seq;
        struct vma_lock *vm_lock;
 
@@ -679,6 +693,20 @@ struct mm_struct {
                                          * by mmlist_lock
                                          */
 #ifdef CONFIG_PER_VMA_LOCK
+               /*
+                * This field has lock-like semantics, meaning it is sometimes
+                * accessed with ACQUIRE/RELEASE semantics.
+                * Roughly speaking, incrementing the sequence number is
+                * equivalent to releasing locks on VMAs; reading the sequence
+                * number can be part of taking a read lock on a VMA.
+                *
+                * Can be modified under write mmap_lock using RELEASE
+                * semantics.
+                * Can be read with no other protection when holding write
+                * mmap_lock.
+                * Can be read with ACQUIRE semantics if not holding write
+                * mmap_lock.
+                */
                int mm_lock_seq;
 #endif
 
index aab8f1b..e05e167 100644 (file)
@@ -76,8 +76,14 @@ static inline void mmap_assert_write_locked(struct mm_struct *mm)
 static inline void vma_end_write_all(struct mm_struct *mm)
 {
        mmap_assert_write_locked(mm);
-       /* No races during update due to exclusive mmap_lock being held */
-       WRITE_ONCE(mm->mm_lock_seq, mm->mm_lock_seq + 1);
+       /*
+        * Nobody can concurrently modify mm->mm_lock_seq due to exclusive
+        * mmap_lock being held.
+        * We need RELEASE semantics here to ensure that preceding stores into
+        * the VMA take effect before we unlock it with this store.
+        * Pairs with ACQUIRE semantics in vma_start_read().
+        */
+       smp_store_release(&mm->mm_lock_seq, mm->mm_lock_seq + 1);
 }
 #else
 static inline void vma_end_write_all(struct mm_struct *mm) {}
index 499e486..e0bf836 100644 (file)
@@ -47,7 +47,7 @@ enum utf16_endian {
 /* nls_base.c */
 extern int __register_nls(struct nls_table *, struct module *);
 extern int unregister_nls(struct nls_table *);
-extern struct nls_table *load_nls(char *);
+extern struct nls_table *load_nls(const char *charset);
 extern void unload_nls(struct nls_table *);
 extern struct nls_table *load_nls_default(void);
 #define register_nls(nls) __register_nls((nls), THIS_MODULE)
index dd42d16..d9642c6 100644 (file)
@@ -10,8 +10,6 @@ extern int dev_pm_set_wake_irq(struct device *dev, int irq);
 extern int dev_pm_set_dedicated_wake_irq(struct device *dev, int irq);
 extern int dev_pm_set_dedicated_wake_irq_reverse(struct device *dev, int irq);
 extern void dev_pm_clear_wake_irq(struct device *dev);
-extern void dev_pm_enable_wake_irq(struct device *dev);
-extern void dev_pm_disable_wake_irq(struct device *dev);
 
 #else  /* !CONFIG_PM */
 
@@ -34,13 +32,5 @@ static inline void dev_pm_clear_wake_irq(struct device *dev)
 {
 }
 
-static inline void dev_pm_enable_wake_irq(struct device *dev)
-{
-}
-
-static inline void dev_pm_disable_wake_irq(struct device *dev)
-{
-}
-
 #endif /* CONFIG_PM */
 #endif /* _LINUX_PM_WAKEIRQ_H */
index 0b85761..fc6c151 100644 (file)
@@ -15,4 +15,6 @@ struct corgi_lcd_platform_data {
        void (*kick_battery)(void);
 };
 
+void corgi_lcd_limit_intensity(int limit);
+
 #endif /* __LINUX_SPI_CORGI_LCD_H */
index b4c08ac..91a37c9 100644 (file)
@@ -513,7 +513,7 @@ static inline void fastopen_queue_tune(struct sock *sk, int backlog)
        struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue;
        int somaxconn = READ_ONCE(sock_net(sk)->core.sysctl_somaxconn);
 
-       queue->fastopenq.max_qlen = min_t(unsigned int, backlog, somaxconn);
+       WRITE_ONCE(queue->fastopenq.max_qlen, min_t(unsigned int, backlog, somaxconn));
 }
 
 static inline void tcp_move_syn(struct tcp_sock *tp,
index 8783709..dee66ad 100644 (file)
@@ -301,14 +301,14 @@ int thermal_acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp);
 #ifdef CONFIG_THERMAL
 struct thermal_zone_device *thermal_zone_device_register(const char *, int, int,
                void *, struct thermal_zone_device_ops *,
-               struct thermal_zone_params *, int, int);
+               const struct thermal_zone_params *, int, int);
 
 void thermal_zone_device_unregister(struct thermal_zone_device *);
 
 struct thermal_zone_device *
 thermal_zone_device_register_with_trips(const char *, struct thermal_trip *, int, int,
                                        void *, struct thermal_zone_device_ops *,
-                                       struct thermal_zone_params *, int, int);
+                                       const struct thermal_zone_params *, int, int);
 
 void *thermal_zone_device_priv(struct thermal_zone_device *tzd);
 const char *thermal_zone_device_type(struct thermal_zone_device *tzd);
@@ -348,7 +348,7 @@ void thermal_zone_device_critical(struct thermal_zone_device *tz);
 static inline struct thermal_zone_device *thermal_zone_device_register(
        const char *type, int trips, int mask, void *devdata,
        struct thermal_zone_device_ops *ops,
-       struct thermal_zone_params *tzp,
+       const struct thermal_zone_params *tzp,
        int passive_delay, int polling_delay)
 { return ERR_PTR(-ENODEV); }
 static inline void thermal_zone_device_unregister(
index 9654567..e01d52c 100644 (file)
@@ -593,9 +593,7 @@ struct hci_dev {
        const char              *fw_info;
        struct dentry           *debugfs;
 
-#ifdef CONFIG_DEV_COREDUMP
        struct hci_devcoredump  dump;
-#endif
 
        struct device           dev;
 
@@ -822,6 +820,7 @@ struct hci_conn_params {
 
        struct hci_conn *conn;
        bool explicit_connect;
+       /* Accessed without hdev->lock: */
        hci_conn_flags_t flags;
        u8  privacy_mode;
 };
@@ -1573,7 +1572,11 @@ struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
                                            bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type);
 void hci_conn_params_clear_disabled(struct hci_dev *hdev);
+void hci_conn_params_free(struct hci_conn_params *param);
 
+void hci_pend_le_list_del_init(struct hci_conn_params *param);
+void hci_pend_le_list_add(struct hci_conn_params *param,
+                         struct list_head *list);
 struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
                                                  bdaddr_t *addr,
                                                  u8 addr_type);
index b57bec6..30ac427 100644 (file)
@@ -277,7 +277,7 @@ struct bond_vlan_tag {
        unsigned short  vlan_id;
 };
 
-/**
+/*
  * Returns NULL if the net_device does not belong to any of the bond's slaves
  *
  * Caller must hold bond lock for read
index e000579..f79ce13 100644 (file)
@@ -170,7 +170,8 @@ wpan_phy_cca_cmp(const struct wpan_phy_cca *a, const struct wpan_phy_cca *b)
 }
 
 /**
- * @WPAN_PHY_FLAG_TRANSMIT_POWER: Indicates that transceiver will support
+ * enum wpan_phy_flags - WPAN PHY state flags
+ * @WPAN_PHY_FLAG_TXPOWER: Indicates that transceiver will support
  *     transmit power setting.
  * @WPAN_PHY_FLAG_CCA_ED_LEVEL: Indicates that transceiver will support cca ed
  *     level setting.
index 5fed2f1..aa80f74 100644 (file)
@@ -145,8 +145,8 @@ struct codel_vars {
  * @maxpacket: largest packet we've seen so far
  * @drop_count:        temp count of dropped packets in dequeue()
  * @drop_len:  bytes of dropped packets in dequeue()
- * ecn_mark:   number of packets we ECN marked instead of dropping
- * ce_mark:    number of packets CE marked because sojourn time was above ce_threshold
+ * @ecn_mark:  number of packets we ECN marked instead of dropping
+ * @ce_mark:   number of packets CE marked because sojourn time was above ce_threshold
  */
 struct codel_stats {
        u32             maxpacket;
index 9a3c51a..0cdb4b1 100644 (file)
@@ -221,7 +221,7 @@ struct devlink_dpipe_field {
 /**
  * struct devlink_dpipe_header - dpipe header object
  * @name: header name
- * @id: index, global/local detrmined by global bit
+ * @id: index, global/local determined by global bit
  * @fields: fields
  * @fields_count: number of fields
  * @global: indicates if header is shared like most protocol header
@@ -241,7 +241,7 @@ struct devlink_dpipe_header {
  * @header_index: header index (packets can have several headers of same
  *               type like in case of tunnels)
  * @header: header
- * @fieled_id: field index
+ * @field_id: field index
  */
 struct devlink_dpipe_match {
        enum devlink_dpipe_match_type type;
@@ -256,7 +256,7 @@ struct devlink_dpipe_match {
  * @header_index: header index (packets can have several headers of same
  *               type like in case of tunnels)
  * @header: header
- * @fieled_id: field index
+ * @field_id: field index
  */
 struct devlink_dpipe_action {
        enum devlink_dpipe_action_type type;
@@ -292,7 +292,7 @@ struct devlink_dpipe_value {
  * struct devlink_dpipe_entry - table entry object
  * @index: index of the entry in the table
  * @match_values: match values
- * @matche_values_count: count of matches tuples
+ * @match_values_count: count of matches tuples
  * @action_values: actions values
  * @action_values_count: count of actions values
  * @counter: value of counter
@@ -342,7 +342,9 @@ struct devlink_dpipe_table_ops;
  */
 struct devlink_dpipe_table {
        void *priv;
+       /* private: */
        struct list_head list;
+       /* public: */
        const char *name;
        bool counters_enabled;
        bool counter_control_extern;
@@ -355,13 +357,13 @@ struct devlink_dpipe_table {
 
 /**
  * struct devlink_dpipe_table_ops - dpipe_table ops
- * @actions_dump - dumps all tables actions
- * @matches_dump - dumps all tables matches
- * @entries_dump - dumps all active entries in the table
- * @counters_set_update - when changing the counter status hardware sync
+ * @actions_dump: dumps all tables actions
+ * @matches_dump: dumps all tables matches
+ * @entries_dump: dumps all active entries in the table
+ * @counters_set_update when changing the counter status hardware sync
  *                       maybe needed to allocate/free counter related
  *                       resources
- * @size_get - get size
+ * @size_get: get size
  */
 struct devlink_dpipe_table_ops {
        int (*actions_dump)(void *priv, struct sk_buff *skb);
@@ -374,8 +376,8 @@ struct devlink_dpipe_table_ops {
 
 /**
  * struct devlink_dpipe_headers - dpipe headers
- * @headers - header array can be shared (global bit) or driver specific
- * @headers_count - count of headers
+ * @headers: header array can be shared (global bit) or driver specific
+ * @headers_count: count of headers
  */
 struct devlink_dpipe_headers {
        struct devlink_dpipe_header **headers;
@@ -387,7 +389,7 @@ struct devlink_dpipe_headers {
  * @size_min: minimum size which can be set
  * @size_max: maximum size which can be set
  * @size_granularity: size granularity
- * @size_unit: resource's basic unit
+ * @unit: resource's basic unit
  */
 struct devlink_resource_size_params {
        u64 size_min;
@@ -457,6 +459,7 @@ struct devlink_flash_notify {
 
 /**
  * struct devlink_param - devlink configuration parameter data
+ * @id: devlink parameter id number
  * @name: name of the parameter
  * @generic: indicates if the parameter is generic or driver specific
  * @type: parameter type
@@ -632,6 +635,7 @@ enum devlink_param_generic_id {
  * struct devlink_flash_update_params - Flash Update parameters
  * @fw: pointer to the firmware data to update from
  * @component: the flash component to update
+ * @overwrite_mask: which types of flash update are supported (may be %0)
  *
  * With the exception of fw, drivers must opt-in to parameters by
  * setting the appropriate bit in the supported_flash_update_params field in
index 75efa6f..88644b3 100644 (file)
@@ -452,6 +452,49 @@ static inline void gro_normal_one(struct napi_struct *napi, struct sk_buff *skb,
                gro_normal_list(napi);
 }
 
+/* This function is the alternative of 'inet_iif' and 'inet_sdif'
+ * functions in case we can not rely on fields of IPCB.
+ *
+ * The caller must verify skb_valid_dst(skb) is false and skb->dev is initialized.
+ * The caller must hold the RCU read lock.
+ */
+static inline void inet_get_iif_sdif(const struct sk_buff *skb, int *iif, int *sdif)
+{
+       *iif = inet_iif(skb) ?: skb->dev->ifindex;
+       *sdif = 0;
+
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+       if (netif_is_l3_slave(skb->dev)) {
+               struct net_device *master = netdev_master_upper_dev_get_rcu(skb->dev);
+
+               *sdif = *iif;
+               *iif = master ? master->ifindex : 0;
+       }
+#endif
+}
+
+/* This function is the alternative of 'inet6_iif' and 'inet6_sdif'
+ * functions in case we can not rely on fields of IP6CB.
+ *
+ * The caller must verify skb_valid_dst(skb) is false and skb->dev is initialized.
+ * The caller must hold the RCU read lock.
+ */
+static inline void inet6_get_iif_sdif(const struct sk_buff *skb, int *iif, int *sdif)
+{
+       /* using skb->dev->ifindex because skb_dst(skb) is not initialized */
+       *iif = skb->dev->ifindex;
+       *sdif = 0;
+
+#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
+       if (netif_is_l3_slave(skb->dev)) {
+               struct net_device *master = netdev_master_upper_dev_get_rcu(skb->dev);
+
+               *sdif = *iif;
+               *iif = master ? master->ifindex : 0;
+       }
+#endif
+}
+
 extern struct list_head offload_base;
 
 #endif /* _NET_IPV6_GRO_H */
index 325ad89..1539606 100644 (file)
@@ -29,7 +29,7 @@ struct fqdir {
 };
 
 /**
- * fragment queue flags
+ * enum: fragment queue flags
  *
  * @INET_FRAG_FIRST_IN: first fragment has arrived
  * @INET_FRAG_LAST_IN: final fragment has arrived
index caa20a9..0bb32bf 100644 (file)
@@ -107,11 +107,12 @@ static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
 
 static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb)
 {
-       if (!sk->sk_mark &&
-           READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept))
+       u32 mark = READ_ONCE(sk->sk_mark);
+
+       if (!mark && READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_fwmark_accept))
                return skb->mark;
 
-       return sk->sk_mark;
+       return mark;
 }
 
 static inline int inet_request_bound_dev_if(const struct sock *sk,
index 50d4358..3325211 100644 (file)
@@ -93,7 +93,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
 {
        ipcm_init(ipcm);
 
-       ipcm->sockc.mark = inet->sk.sk_mark;
+       ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark);
        ipcm->sockc.tsflags = inet->sk.sk_tsflags;
        ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
        ipcm->addr = inet->inet_saddr;
index 7332296..2acc4c8 100644 (file)
@@ -752,12 +752,8 @@ static inline u32 ipv6_addr_hash(const struct in6_addr *a)
 /* more secured version of ipv6_addr_hash() */
 static inline u32 __ipv6_addr_jhash(const struct in6_addr *a, const u32 initval)
 {
-       u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1];
-
-       return jhash_3words(v,
-                           (__force u32)a->s6_addr32[2],
-                           (__force u32)a->s6_addr32[3],
-                           initval);
+       return jhash2((__force const u32 *)a->s6_addr32,
+                     ARRAY_SIZE(a->s6_addr32), initval);
 }
 
 static inline bool ipv6_addr_loopback(const struct in6_addr *a)
index 2c1ea34..374411b 100644 (file)
@@ -111,7 +111,7 @@ void llc_conn_resend_i_pdu_as_cmd(struct sock *sk, u8 nr, u8 first_p_bit);
 void llc_conn_resend_i_pdu_as_rsp(struct sock *sk, u8 nr, u8 first_f_bit);
 int llc_conn_remove_acked_pdus(struct sock *conn, u8 nr, u16 *how_many_unacked);
 struct sock *llc_lookup_established(struct llc_sap *sap, struct llc_addr *daddr,
-                                   struct llc_addr *laddr);
+                                   struct llc_addr *laddr, const struct net *net);
 void llc_sap_add_socket(struct llc_sap *sap, struct sock *sk);
 void llc_sap_remove_socket(struct llc_sap *sap, struct sock *sk);
 
index 49aa79c..7e73f8e 100644 (file)
@@ -269,7 +269,7 @@ static inline void llc_pdu_decode_sa(struct sk_buff *skb, u8 *sa)
 /**
  *     llc_pdu_decode_da - extracts dest address of input frame
  *     @skb: input skb that destination address must be extracted from it
- *     @sa: pointer to destination address (6 byte array).
+ *     @da: pointer to destination address (6 byte array).
  *
  *     This function extracts destination address(MAC) of input frame.
  */
@@ -321,7 +321,7 @@ static inline void llc_pdu_init_as_ui_cmd(struct sk_buff *skb)
 
 /**
  *     llc_pdu_init_as_test_cmd - sets PDU as TEST
- *     @skb - Address of the skb to build
+ *     @skb: Address of the skb to build
  *
  *     Sets a PDU as TEST
  */
@@ -369,6 +369,8 @@ struct llc_xid_info {
 /**
  *     llc_pdu_init_as_xid_cmd - sets bytes 3, 4 & 5 of LLC header as XID
  *     @skb: input skb that header must be set into it.
+ *     @svcs_supported: The class of the LLC (I or II)
+ *     @rx_window: The size of the receive window of the LLC
  *
  *     This function sets third,fourth,fifth and sixth bytes of LLC header as
  *     a XID PDU.
index 350b1ad..16a7510 100644 (file)
 
 /**
  * struct nsh_md1_ctx - Keeps track of NSH context data
- * @nshc<1-4>: NSH Contexts.
+ * @context: NSH Contexts.
  */
 struct nsh_md1_ctx {
        __be32 context[4];
index 3fe2361..01cbc66 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * struct pie_params - contains pie parameters
  * @target:            target delay in pschedtime
- * @tudpate:           interval at which drop probability is calculated
+ * @tupdate:           interval at which drop probability is calculated
  * @limit:             total number of packets that can be in the queue
  * @alpha:             parameter to control drop probability
  * @beta:              parameter to control drop probability
index 5a5c726..8c2a8e7 100644 (file)
@@ -168,7 +168,7 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi
                                                   __be16 dport, __be16 sport,
                                                   __u8 proto, __u8 tos, int oif)
 {
-       flowi4_init_output(fl4, oif, sk ? sk->sk_mark : 0, tos,
+       flowi4_init_output(fl4, oif, sk ? READ_ONCE(sk->sk_mark) : 0, tos,
                           RT_SCOPE_UNIVERSE, proto,
                           sk ? inet_sk_flowi_flags(sk) : 0,
                           daddr, saddr, dport, sport, sock_net_uid(net, sk));
@@ -301,7 +301,7 @@ static inline void ip_route_connect_init(struct flowi4 *fl4, __be32 dst,
        if (inet_sk(sk)->transparent)
                flow_flags |= FLOWI_FLAG_ANYSRC;
 
-       flowi4_init_output(fl4, oif, sk->sk_mark, ip_sock_rt_tos(sk),
+       flowi4_init_output(fl4, oif, READ_ONCE(sk->sk_mark), ip_sock_rt_tos(sk),
                           ip_sock_rt_scope(sk), protocol, flow_flags, dst,
                           src, dport, sport, sk->sk_uid);
 }
index 040f07b..b228376 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Copyright (c) 2017 Redpine Signals Inc.
  *
  * Permission to use, copy, modify, and/or distribute this software for any
index 226bce6..0ca972e 100644 (file)
@@ -1509,25 +1509,38 @@ void tcp_leave_memory_pressure(struct sock *sk);
 static inline int keepalive_intvl_when(const struct tcp_sock *tp)
 {
        struct net *net = sock_net((struct sock *)tp);
+       int val;
 
-       return tp->keepalive_intvl ? :
-               READ_ONCE(net->ipv4.sysctl_tcp_keepalive_intvl);
+       /* Paired with WRITE_ONCE() in tcp_sock_set_keepintvl()
+        * and do_tcp_setsockopt().
+        */
+       val = READ_ONCE(tp->keepalive_intvl);
+
+       return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_intvl);
 }
 
 static inline int keepalive_time_when(const struct tcp_sock *tp)
 {
        struct net *net = sock_net((struct sock *)tp);
+       int val;
 
-       return tp->keepalive_time ? :
-               READ_ONCE(net->ipv4.sysctl_tcp_keepalive_time);
+       /* Paired with WRITE_ONCE() in tcp_sock_set_keepidle_locked() */
+       val = READ_ONCE(tp->keepalive_time);
+
+       return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_time);
 }
 
 static inline int keepalive_probes(const struct tcp_sock *tp)
 {
        struct net *net = sock_net((struct sock *)tp);
+       int val;
 
-       return tp->keepalive_probes ? :
-               READ_ONCE(net->ipv4.sysctl_tcp_keepalive_probes);
+       /* Paired with WRITE_ONCE() in tcp_sock_set_keepcnt()
+        * and do_tcp_setsockopt().
+        */
+       val = READ_ONCE(tp->keepalive_probes);
+
+       return val ? : READ_ONCE(net->ipv4.sysctl_tcp_keepalive_probes);
 }
 
 static inline u32 keepalive_time_elapsed(const struct tcp_sock *tp)
@@ -2048,7 +2061,11 @@ void __tcp_v4_send_check(struct sk_buff *skb, __be32 saddr, __be32 daddr);
 static inline u32 tcp_notsent_lowat(const struct tcp_sock *tp)
 {
        struct net *net = sock_net((struct sock *)tp);
-       return tp->notsent_lowat ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat);
+       u32 val;
+
+       val = READ_ONCE(tp->notsent_lowat);
+
+       return val ?: READ_ONCE(net->ipv4.sysctl_tcp_notsent_lowat);
 }
 
 bool tcp_stream_memory_free(const struct sock *sk, int wake);
index 0be91ca..6a9f8a5 100644 (file)
@@ -386,10 +386,15 @@ static inline netdev_features_t vxlan_features_check(struct sk_buff *skb,
        return features;
 }
 
-/* IP header + UDP + VXLAN + Ethernet header */
-#define VXLAN_HEADROOM (20 + 8 + 8 + 14)
-/* IPv6 header + UDP + VXLAN + Ethernet header */
-#define VXLAN6_HEADROOM (40 + 8 + 8 + 14)
+static inline int vxlan_headroom(u32 flags)
+{
+       /* VXLAN:     IP4/6 header + UDP + VXLAN + Ethernet header */
+       /* VXLAN-GPE: IP4/6 header + UDP + VXLAN */
+       return (flags & VXLAN_F_IPV6 ? sizeof(struct ipv6hdr) :
+                                      sizeof(struct iphdr)) +
+              sizeof(struct udphdr) + sizeof(struct vxlanhdr) +
+              (flags & VXLAN_F_GPE ? 0 : ETH_HLEN);
+}
 
 static inline struct vxlanhdr *vxlan_hdr(struct sk_buff *skb)
 {
@@ -551,12 +556,12 @@ static inline void vxlan_flag_attr_error(int attrtype,
 }
 
 static inline bool vxlan_fdb_nh_path_select(struct nexthop *nh,
-                                           int hash,
+                                           u32 hash,
                                            struct vxlan_rdst *rdst)
 {
        struct fib_nh_common *nhc;
 
-       nhc = nexthop_path_fdb_result(nh, hash);
+       nhc = nexthop_path_fdb_result(nh, hash >> 1);
        if (unlikely(!nhc))
                return false;
 
index fc30014..a5ef849 100644 (file)
@@ -175,6 +175,9 @@ struct tegra_mc_icc_ops {
        int (*get_bw)(struct icc_node *node, u32 *avg, u32 *peak);
 };
 
+struct icc_node *tegra_mc_icc_xlate(struct of_phandle_args *spec, void *data);
+extern const struct tegra_mc_icc_ops tegra_mc_icc_ops;
+
 struct tegra_mc_ops {
        /*
         * @probe: Callback to set up SoC-specific bits of the memory controller. This is called
index 8f5ee38..5646ae1 100644 (file)
@@ -462,11 +462,9 @@ TRACE_EVENT(jbd2_shrink_scan_exit,
 TRACE_EVENT(jbd2_shrink_checkpoint_list,
 
        TP_PROTO(journal_t *journal, tid_t first_tid, tid_t tid, tid_t last_tid,
-                unsigned long nr_freed, unsigned long nr_scanned,
-                tid_t next_tid),
+                unsigned long nr_freed, tid_t next_tid),
 
-       TP_ARGS(journal, first_tid, tid, last_tid, nr_freed,
-               nr_scanned, next_tid),
+       TP_ARGS(journal, first_tid, tid, last_tid, nr_freed, next_tid),
 
        TP_STRUCT__entry(
                __field(dev_t, dev)
@@ -474,7 +472,6 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list,
                __field(tid_t, tid)
                __field(tid_t, last_tid)
                __field(unsigned long, nr_freed)
-               __field(unsigned long, nr_scanned)
                __field(tid_t, next_tid)
        ),
 
@@ -484,15 +481,14 @@ TRACE_EVENT(jbd2_shrink_checkpoint_list,
                __entry->tid            = tid;
                __entry->last_tid       = last_tid;
                __entry->nr_freed       = nr_freed;
-               __entry->nr_scanned     = nr_scanned;
                __entry->next_tid       = next_tid;
        ),
 
        TP_printk("dev %d,%d shrink transaction %u-%u(%u) freed %lu "
-                 "scanned %lu next transaction %u",
+                 "next transaction %u",
                  MAJOR(__entry->dev), MINOR(__entry->dev),
                  __entry->first_tid, __entry->tid, __entry->last_tid,
-                 __entry->nr_freed, __entry->nr_scanned, __entry->next_tid)
+                 __entry->nr_freed, __entry->next_tid)
 );
 
 #endif /* _TRACE_JBD2_H */
index b80fcc9..f85743e 100644 (file)
@@ -51,13 +51,13 @@ enum blk_zone_type {
  *
  * The Zone Condition state machine in the ZBC/ZAC standards maps the above
  * deinitions as:
- *   - ZC1: Empty         | BLK_ZONE_EMPTY
+ *   - ZC1: Empty         | BLK_ZONE_COND_EMPTY
  *   - ZC2: Implicit Open | BLK_ZONE_COND_IMP_OPEN
  *   - ZC3: Explicit Open | BLK_ZONE_COND_EXP_OPEN
- *   - ZC4: Closed        | BLK_ZONE_CLOSED
- *   - ZC5: Full          | BLK_ZONE_FULL
- *   - ZC6: Read Only     | BLK_ZONE_READONLY
- *   - ZC7: Offline       | BLK_ZONE_OFFLINE
+ *   - ZC4: Closed        | BLK_ZONE_COND_CLOSED
+ *   - ZC5: Full          | BLK_ZONE_COND_FULL
+ *   - ZC6: Read Only     | BLK_ZONE_COND_READONLY
+ *   - ZC7: Offline       | BLK_ZONE_COND_OFFLINE
  *
  * Conditions 0x5 to 0xC are reserved by the current ZBC/ZAC spec and should
  * be considered invalid.
index 1b9d0df..b3fcab1 100644 (file)
  *  - add extension header
  *  - add FUSE_EXT_GROUPS
  *  - add FUSE_CREATE_SUPP_GROUP
+ *  - add FUSE_HAS_EXPIRE_ONLY
  */
 
 #ifndef _LINUX_FUSE_H
@@ -369,6 +370,7 @@ struct fuse_file_lock {
  * FUSE_HAS_INODE_DAX:  use per inode DAX
  * FUSE_CREATE_SUPP_GROUP: add supplementary group info to create, mkdir,
  *                     symlink and mknod (single group that matches parent)
+ * FUSE_HAS_EXPIRE_ONLY: kernel supports expiry-only entry invalidation
  */
 #define FUSE_ASYNC_READ                (1 << 0)
 #define FUSE_POSIX_LOCKS       (1 << 1)
@@ -406,6 +408,7 @@ struct fuse_file_lock {
 #define FUSE_SECURITY_CTX      (1ULL << 32)
 #define FUSE_HAS_INODE_DAX     (1ULL << 33)
 #define FUSE_CREATE_SUPP_GROUP (1ULL << 34)
+#define FUSE_HAS_EXPIRE_ONLY   (1ULL << 35)
 
 /**
  * CUSE INIT request/reply flags
index 9efc423..4d0ad22 100644 (file)
@@ -18,7 +18,11 @@ struct sockaddr_ll {
        unsigned short  sll_hatype;
        unsigned char   sll_pkttype;
        unsigned char   sll_halen;
-       unsigned char   sll_addr[8];
+       union {
+               unsigned char   sll_addr[8];
+               /* Actual length is in sll_halen. */
+               __DECLARE_FLEX_ARRAY(unsigned char, sll_addr_flex);
+       };
 };
 
 /* Packet types */
index 7865f5a..4f3932b 100644 (file)
@@ -710,9 +710,11 @@ enum {
        TCA_FLOWER_KEY_CFM_OPT_UNSPEC,
        TCA_FLOWER_KEY_CFM_MD_LEVEL,
        TCA_FLOWER_KEY_CFM_OPCODE,
-       TCA_FLOWER_KEY_CFM_OPT_MAX,
+       __TCA_FLOWER_KEY_CFM_OPT_MAX,
 };
 
+#define TCA_FLOWER_KEY_CFM_OPT_MAX (__TCA_FLOWER_KEY_CFM_OPT_MAX - 1)
+
 #define TCA_FLOWER_MASK_FLAGS_RANGE    (1 << 0) /* Range-based match */
 
 /* Match-all classifier */
index 7fbf732..aef2b75 100644 (file)
@@ -101,4 +101,13 @@ struct ioctl_evtchn_restrict_domid {
        domid_t domid;
 };
 
+/*
+ * Bind statically allocated @port.
+ */
+#define IOCTL_EVTCHN_BIND_STATIC                       \
+       _IOC(_IOC_NONE, 'E', 7, sizeof(struct ioctl_evtchn_bind))
+struct ioctl_evtchn_bind {
+       unsigned int port;
+};
+
 #endif /* __LINUX_PUBLIC_EVTCHN_H__ */
index ac1281c..95970a2 100644 (file)
@@ -69,7 +69,7 @@ int xen_set_irq_priority(unsigned irq, unsigned priority);
 /*
  * Allow extra references to event channels exposed to userspace by evtchn
  */
-int evtchn_make_refcounted(evtchn_port_t evtchn);
+int evtchn_make_refcounted(evtchn_port_t evtchn, bool is_static);
 int evtchn_get(evtchn_port_t evtchn);
 void evtchn_put(evtchn_port_t evtchn);
 
@@ -141,4 +141,13 @@ void xen_init_IRQ(void);
 
 irqreturn_t xen_debug_interrupt(int irq, void *dev_id);
 
+static inline void xen_evtchn_close(evtchn_port_t port)
+{
+       struct evtchn_close close;
+
+       close.port = port;
+       if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
+               BUG();
+}
+
 #endif /* _XEN_EVENTS_H */
index 7505de2..f4591b9 100644 (file)
@@ -1948,6 +1948,14 @@ fail:
                ret = io_issue_sqe(req, issue_flags);
                if (ret != -EAGAIN)
                        break;
+
+               /*
+                * If REQ_F_NOWAIT is set, then don't wait or retry with
+                * poll. -EAGAIN is final for that case.
+                */
+               if (req->flags & REQ_F_NOWAIT)
+                       break;
+
                /*
                 * We can get EAGAIN for iopolled IO even though we're
                 * forcing a sync submission from here, since we can't
@@ -2485,11 +2493,20 @@ int io_run_task_work_sig(struct io_ring_ctx *ctx)
        return 0;
 }
 
+static bool current_pending_io(void)
+{
+       struct io_uring_task *tctx = current->io_uring;
+
+       if (!tctx)
+               return false;
+       return percpu_counter_read_positive(&tctx->inflight);
+}
+
 /* when returns >0, the caller should retry */
 static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
                                          struct io_wait_queue *iowq)
 {
-       int token, ret;
+       int io_wait, ret;
 
        if (unlikely(READ_ONCE(ctx->check_cq)))
                return 1;
@@ -2503,17 +2520,19 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
                return 0;
 
        /*
-        * Use io_schedule_prepare/finish, so cpufreq can take into account
-        * that the task is waiting for IO - turns out to be important for low
-        * QD IO.
+        * Mark us as being in io_wait if we have pending requests, so cpufreq
+        * can take into account that the task is waiting for IO - turns out
+        * to be important for low QD IO.
         */
-       token = io_schedule_prepare();
+       io_wait = current->in_iowait;
+       if (current_pending_io())
+               current->in_iowait = 1;
        ret = 0;
        if (iowq->timeout == KTIME_MAX)
                schedule();
        else if (!schedule_hrtimeout(&iowq->timeout, HRTIMER_MODE_ABS))
                ret = -ETIME;
-       io_schedule_finish(token);
+       current->in_iowait = io_wait;
        return ret;
 }
 
@@ -3429,8 +3448,6 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp,
                        unsigned long addr, unsigned long len,
                        unsigned long pgoff, unsigned long flags)
 {
-       const unsigned long mmap_end = arch_get_mmap_end(addr, len, flags);
-       struct vm_unmapped_area_info info;
        void *ptr;
 
        /*
@@ -3445,32 +3462,26 @@ static unsigned long io_uring_mmu_get_unmapped_area(struct file *filp,
        if (IS_ERR(ptr))
                return -ENOMEM;
 
-       info.flags = VM_UNMAPPED_AREA_TOPDOWN;
-       info.length = len;
-       info.low_limit = max(PAGE_SIZE, mmap_min_addr);
-       info.high_limit = arch_get_mmap_base(addr, current->mm->mmap_base);
+       /*
+        * Some architectures have strong cache aliasing requirements.
+        * For such architectures we need a coherent mapping which aliases
+        * kernel memory *and* userspace memory. To achieve that:
+        * - use a NULL file pointer to reference physical memory, and
+        * - use the kernel virtual address of the shared io_uring context
+        *   (instead of the userspace-provided address, which has to be 0UL
+        *   anyway).
+        * For architectures without such aliasing requirements, the
+        * architecture will return any suitable mapping because addr is 0.
+        */
+       filp = NULL;
+       flags |= MAP_SHARED;
+       pgoff = 0;      /* has been translated to ptr above */
 #ifdef SHM_COLOUR
-       info.align_mask = PAGE_MASK & (SHM_COLOUR - 1UL);
+       addr = (uintptr_t) ptr;
 #else
-       info.align_mask = PAGE_MASK & (SHMLBA - 1UL);
+       addr = 0UL;
 #endif
-       info.align_offset = (unsigned long) ptr;
-
-       /*
-        * A failed mmap() very likely causes application failure,
-        * so fall back to the bottom-up function here. This scenario
-        * can happen with large stack limits and large mmap()
-        * allocations.
-        */
-       addr = vm_unmapped_area(&info);
-       if (offset_in_page(addr)) {
-               info.flags = 0;
-               info.low_limit = TASK_UNMAPPED_BASE;
-               info.high_limit = mmap_end;
-               addr = vm_unmapped_area(&info);
-       }
-
-       return addr;
+       return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
 }
 
 #else /* !CONFIG_MMU */
@@ -3870,7 +3881,7 @@ static __cold int io_uring_create(unsigned entries, struct io_uring_params *p,
                ctx->syscall_iopoll = 1;
 
        ctx->compat = in_compat_syscall();
-       if (!capable(CAP_IPC_LOCK))
+       if (!ns_capable_noaudit(&init_user_ns, CAP_IPC_LOCK))
                ctx->user = get_uid(current_user());
 
        /*
index 6ae02be..286ab3d 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/sched.h>
 #include <linux/workqueue.h>
 #include <linux/kthread.h>
+#include <linux/completion.h>
 #include <trace/events/xdp.h>
 #include <linux/btf_ids.h>
 
@@ -73,6 +74,7 @@ struct bpf_cpu_map_entry {
        struct rcu_head rcu;
 
        struct work_struct kthread_stop_wq;
+       struct completion kthread_running;
 };
 
 struct bpf_cpu_map {
@@ -129,11 +131,17 @@ static void __cpu_map_ring_cleanup(struct ptr_ring *ring)
         * invoked cpu_map_kthread_stop(). Catch any broken behaviour
         * gracefully and warn once.
         */
-       struct xdp_frame *xdpf;
+       void *ptr;
 
-       while ((xdpf = ptr_ring_consume(ring)))
-               if (WARN_ON_ONCE(xdpf))
-                       xdp_return_frame(xdpf);
+       while ((ptr = ptr_ring_consume(ring))) {
+               WARN_ON_ONCE(1);
+               if (unlikely(__ptr_test_bit(0, &ptr))) {
+                       __ptr_clear_bit(0, &ptr);
+                       kfree_skb(ptr);
+                       continue;
+               }
+               xdp_return_frame(ptr);
+       }
 }
 
 static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu)
@@ -153,7 +161,6 @@ static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu)
 static void cpu_map_kthread_stop(struct work_struct *work)
 {
        struct bpf_cpu_map_entry *rcpu;
-       int err;
 
        rcpu = container_of(work, struct bpf_cpu_map_entry, kthread_stop_wq);
 
@@ -163,14 +170,7 @@ static void cpu_map_kthread_stop(struct work_struct *work)
        rcu_barrier();
 
        /* kthread_stop will wake_up_process and wait for it to complete */
-       err = kthread_stop(rcpu->kthread);
-       if (err) {
-               /* kthread_stop may be called before cpu_map_kthread_run
-                * is executed, so we need to release the memory related
-                * to rcpu.
-                */
-               put_cpu_map_entry(rcpu);
-       }
+       kthread_stop(rcpu->kthread);
 }
 
 static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu,
@@ -298,11 +298,11 @@ static int cpu_map_bpf_prog_run(struct bpf_cpu_map_entry *rcpu, void **frames,
        return nframes;
 }
 
-
 static int cpu_map_kthread_run(void *data)
 {
        struct bpf_cpu_map_entry *rcpu = data;
 
+       complete(&rcpu->kthread_running);
        set_current_state(TASK_INTERRUPTIBLE);
 
        /* When kthread gives stop order, then rcpu have been disconnected
@@ -467,6 +467,7 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value,
                goto free_ptr_ring;
 
        /* Setup kthread */
+       init_completion(&rcpu->kthread_running);
        rcpu->kthread = kthread_create_on_node(cpu_map_kthread_run, rcpu, numa,
                                               "cpumap/%d/map:%d", cpu,
                                               map->id);
@@ -480,6 +481,12 @@ __cpu_map_entry_alloc(struct bpf_map *map, struct bpf_cpumap_val *value,
        kthread_bind(rcpu->kthread, cpu);
        wake_up_process(rcpu->kthread);
 
+       /* Make sure kthread has been running, so kthread_stop() will not
+        * stop the kthread prematurely and all pending frames or skbs
+        * will be handled by the kthread before kthread_stop() returns.
+        */
+       wait_for_completion(&rcpu->kthread_running);
+
        return rcpu;
 
 free_prog:
index 930b555..02a021c 100644 (file)
@@ -5573,16 +5573,17 @@ static int update_stack_depth(struct bpf_verifier_env *env,
  * Since recursion is prevented by check_cfg() this algorithm
  * only needs a local stack of MAX_CALL_FRAMES to remember callsites
  */
-static int check_max_stack_depth(struct bpf_verifier_env *env)
+static int check_max_stack_depth_subprog(struct bpf_verifier_env *env, int idx)
 {
-       int depth = 0, frame = 0, idx = 0, i = 0, subprog_end;
        struct bpf_subprog_info *subprog = env->subprog_info;
        struct bpf_insn *insn = env->prog->insnsi;
+       int depth = 0, frame = 0, i, subprog_end;
        bool tail_call_reachable = false;
        int ret_insn[MAX_CALL_FRAMES];
        int ret_prog[MAX_CALL_FRAMES];
        int j;
 
+       i = subprog[idx].start;
 process_func:
        /* protect against potential stack overflow that might happen when
         * bpf2bpf calls get combined with tailcalls. Limit the caller's stack
@@ -5621,7 +5622,7 @@ process_func:
 continue_func:
        subprog_end = subprog[idx + 1].start;
        for (; i < subprog_end; i++) {
-               int next_insn;
+               int next_insn, sidx;
 
                if (!bpf_pseudo_call(insn + i) && !bpf_pseudo_func(insn + i))
                        continue;
@@ -5631,14 +5632,14 @@ continue_func:
 
                /* find the callee */
                next_insn = i + insn[i].imm + 1;
-               idx = find_subprog(env, next_insn);
-               if (idx < 0) {
+               sidx = find_subprog(env, next_insn);
+               if (sidx < 0) {
                        WARN_ONCE(1, "verifier bug. No program starts at insn %d\n",
                                  next_insn);
                        return -EFAULT;
                }
-               if (subprog[idx].is_async_cb) {
-                       if (subprog[idx].has_tail_call) {
+               if (subprog[sidx].is_async_cb) {
+                       if (subprog[sidx].has_tail_call) {
                                verbose(env, "verifier bug. subprog has tail_call and async cb\n");
                                return -EFAULT;
                        }
@@ -5647,6 +5648,7 @@ continue_func:
                                continue;
                }
                i = next_insn;
+               idx = sidx;
 
                if (subprog[idx].has_tail_call)
                        tail_call_reachable = true;
@@ -5682,6 +5684,22 @@ continue_func:
        goto continue_func;
 }
 
+static int check_max_stack_depth(struct bpf_verifier_env *env)
+{
+       struct bpf_subprog_info *si = env->subprog_info;
+       int ret;
+
+       for (int i = 0; i < env->subprog_cnt; i++) {
+               if (!i || si[i].is_async_cb) {
+                       ret = check_max_stack_depth_subprog(env, i);
+                       if (ret < 0)
+                               return ret;
+               }
+               continue;
+       }
+       return 0;
+}
+
 #ifndef CONFIG_BPF_JIT_ALWAYS_ON
 static int get_callee_stack_depth(struct bpf_verifier_env *env,
                                  const struct bpf_insn *insn, int idx)
index 1fc6095..ca385b6 100644 (file)
@@ -1545,6 +1545,17 @@ static int check_ftrace_location(struct kprobe *p)
        return 0;
 }
 
+static bool is_cfi_preamble_symbol(unsigned long addr)
+{
+       char symbuf[KSYM_NAME_LEN];
+
+       if (lookup_symbol_name(addr, symbuf))
+               return false;
+
+       return str_has_prefix("__cfi_", symbuf) ||
+               str_has_prefix("__pfx_", symbuf);
+}
+
 static int check_kprobe_address_safe(struct kprobe *p,
                                     struct module **probed_mod)
 {
@@ -1563,7 +1574,8 @@ static int check_kprobe_address_safe(struct kprobe *p,
            within_kprobe_blacklist((unsigned long) p->addr) ||
            jump_label_text_reserved(p->addr, p->addr) ||
            static_call_text_reserved(p->addr, p->addr) ||
-           find_bug((unsigned long)p->addr)) {
+           find_bug((unsigned long)p->addr) ||
+           is_cfi_preamble_symbol((unsigned long)p->addr)) {
                ret = -EINVAL;
                goto out;
        }
index 728f434..21db0df 100644 (file)
@@ -333,21 +333,43 @@ static __always_inline int __waiter_prio(struct task_struct *task)
        return prio;
 }
 
+/*
+ * Update the waiter->tree copy of the sort keys.
+ */
 static __always_inline void
 waiter_update_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
 {
-       waiter->prio = __waiter_prio(task);
-       waiter->deadline = task->dl.deadline;
+       lockdep_assert_held(&waiter->lock->wait_lock);
+       lockdep_assert(RB_EMPTY_NODE(&waiter->tree.entry));
+
+       waiter->tree.prio = __waiter_prio(task);
+       waiter->tree.deadline = task->dl.deadline;
+}
+
+/*
+ * Update the waiter->pi_tree copy of the sort keys (from the tree copy).
+ */
+static __always_inline void
+waiter_clone_prio(struct rt_mutex_waiter *waiter, struct task_struct *task)
+{
+       lockdep_assert_held(&waiter->lock->wait_lock);
+       lockdep_assert_held(&task->pi_lock);
+       lockdep_assert(RB_EMPTY_NODE(&waiter->pi_tree.entry));
+
+       waiter->pi_tree.prio = waiter->tree.prio;
+       waiter->pi_tree.deadline = waiter->tree.deadline;
 }
 
 /*
- * Only use with rt_mutex_waiter_{less,equal}()
+ * Only use with rt_waiter_node_{less,equal}()
  */
+#define task_to_waiter_node(p) \
+       &(struct rt_waiter_node){ .prio = __waiter_prio(p), .deadline = (p)->dl.deadline }
 #define task_to_waiter(p)      \
-       &(struct rt_mutex_waiter){ .prio = __waiter_prio(p), .deadline = (p)->dl.deadline }
+       &(struct rt_mutex_waiter){ .tree = *task_to_waiter_node(p) }
 
-static __always_inline int rt_mutex_waiter_less(struct rt_mutex_waiter *left,
-                                               struct rt_mutex_waiter *right)
+static __always_inline int rt_waiter_node_less(struct rt_waiter_node *left,
+                                              struct rt_waiter_node *right)
 {
        if (left->prio < right->prio)
                return 1;
@@ -364,8 +386,8 @@ static __always_inline int rt_mutex_waiter_less(struct rt_mutex_waiter *left,
        return 0;
 }
 
-static __always_inline int rt_mutex_waiter_equal(struct rt_mutex_waiter *left,
-                                                struct rt_mutex_waiter *right)
+static __always_inline int rt_waiter_node_equal(struct rt_waiter_node *left,
+                                                struct rt_waiter_node *right)
 {
        if (left->prio != right->prio)
                return 0;
@@ -385,7 +407,7 @@ static __always_inline int rt_mutex_waiter_equal(struct rt_mutex_waiter *left,
 static inline bool rt_mutex_steal(struct rt_mutex_waiter *waiter,
                                  struct rt_mutex_waiter *top_waiter)
 {
-       if (rt_mutex_waiter_less(waiter, top_waiter))
+       if (rt_waiter_node_less(&waiter->tree, &top_waiter->tree))
                return true;
 
 #ifdef RT_MUTEX_BUILD_SPINLOCKS
@@ -393,30 +415,30 @@ static inline bool rt_mutex_steal(struct rt_mutex_waiter *waiter,
         * Note that RT tasks are excluded from same priority (lateral)
         * steals to prevent the introduction of an unbounded latency.
         */
-       if (rt_prio(waiter->prio) || dl_prio(waiter->prio))
+       if (rt_prio(waiter->tree.prio) || dl_prio(waiter->tree.prio))
                return false;
 
-       return rt_mutex_waiter_equal(waiter, top_waiter);
+       return rt_waiter_node_equal(&waiter->tree, &top_waiter->tree);
 #else
        return false;
 #endif
 }
 
 #define __node_2_waiter(node) \
-       rb_entry((node), struct rt_mutex_waiter, tree_entry)
+       rb_entry((node), struct rt_mutex_waiter, tree.entry)
 
 static __always_inline bool __waiter_less(struct rb_node *a, const struct rb_node *b)
 {
        struct rt_mutex_waiter *aw = __node_2_waiter(a);
        struct rt_mutex_waiter *bw = __node_2_waiter(b);
 
-       if (rt_mutex_waiter_less(aw, bw))
+       if (rt_waiter_node_less(&aw->tree, &bw->tree))
                return 1;
 
        if (!build_ww_mutex())
                return 0;
 
-       if (rt_mutex_waiter_less(bw, aw))
+       if (rt_waiter_node_less(&bw->tree, &aw->tree))
                return 0;
 
        /* NOTE: relies on waiter->ww_ctx being set before insertion */
@@ -434,48 +456,58 @@ static __always_inline bool __waiter_less(struct rb_node *a, const struct rb_nod
 static __always_inline void
 rt_mutex_enqueue(struct rt_mutex_base *lock, struct rt_mutex_waiter *waiter)
 {
-       rb_add_cached(&waiter->tree_entry, &lock->waiters, __waiter_less);
+       lockdep_assert_held(&lock->wait_lock);
+
+       rb_add_cached(&waiter->tree.entry, &lock->waiters, __waiter_less);
 }
 
 static __always_inline void
 rt_mutex_dequeue(struct rt_mutex_base *lock, struct rt_mutex_waiter *waiter)
 {
-       if (RB_EMPTY_NODE(&waiter->tree_entry))
+       lockdep_assert_held(&lock->wait_lock);
+
+       if (RB_EMPTY_NODE(&waiter->tree.entry))
                return;
 
-       rb_erase_cached(&waiter->tree_entry, &lock->waiters);
-       RB_CLEAR_NODE(&waiter->tree_entry);
+       rb_erase_cached(&waiter->tree.entry, &lock->waiters);
+       RB_CLEAR_NODE(&waiter->tree.entry);
 }
 
-#define __node_2_pi_waiter(node) \
-       rb_entry((node), struct rt_mutex_waiter, pi_tree_entry)
+#define __node_2_rt_node(node) \
+       rb_entry((node), struct rt_waiter_node, entry)
 
-static __always_inline bool
-__pi_waiter_less(struct rb_node *a, const struct rb_node *b)
+static __always_inline bool __pi_waiter_less(struct rb_node *a, const struct rb_node *b)
 {
-       return rt_mutex_waiter_less(__node_2_pi_waiter(a), __node_2_pi_waiter(b));
+       return rt_waiter_node_less(__node_2_rt_node(a), __node_2_rt_node(b));
 }
 
 static __always_inline void
 rt_mutex_enqueue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter)
 {
-       rb_add_cached(&waiter->pi_tree_entry, &task->pi_waiters, __pi_waiter_less);
+       lockdep_assert_held(&task->pi_lock);
+
+       rb_add_cached(&waiter->pi_tree.entry, &task->pi_waiters, __pi_waiter_less);
 }
 
 static __always_inline void
 rt_mutex_dequeue_pi(struct task_struct *task, struct rt_mutex_waiter *waiter)
 {
-       if (RB_EMPTY_NODE(&waiter->pi_tree_entry))
+       lockdep_assert_held(&task->pi_lock);
+
+       if (RB_EMPTY_NODE(&waiter->pi_tree.entry))
                return;
 
-       rb_erase_cached(&waiter->pi_tree_entry, &task->pi_waiters);
-       RB_CLEAR_NODE(&waiter->pi_tree_entry);
+       rb_erase_cached(&waiter->pi_tree.entry, &task->pi_waiters);
+       RB_CLEAR_NODE(&waiter->pi_tree.entry);
 }
 
-static __always_inline void rt_mutex_adjust_prio(struct task_struct *p)
+static __always_inline void rt_mutex_adjust_prio(struct rt_mutex_base *lock,
+                                                struct task_struct *p)
 {
        struct task_struct *pi_task = NULL;
 
+       lockdep_assert_held(&lock->wait_lock);
+       lockdep_assert(rt_mutex_owner(lock) == p);
        lockdep_assert_held(&p->pi_lock);
 
        if (task_has_pi_waiters(p))
@@ -571,9 +603,14 @@ static __always_inline struct rt_mutex_base *task_blocked_on_lock(struct task_st
  * Chain walk basics and protection scope
  *
  * [R] refcount on task
- * [P] task->pi_lock held
+ * [Pn] task->pi_lock held
  * [L] rtmutex->wait_lock held
  *
+ * Normal locking order:
+ *
+ *   rtmutex->wait_lock
+ *     task->pi_lock
+ *
  * Step        Description                             Protected by
  *     function arguments:
  *     @task                                   [R]
@@ -588,27 +625,32 @@ static __always_inline struct rt_mutex_base *task_blocked_on_lock(struct task_st
  *     again:
  *       loop_sanity_check();
  *     retry:
- * [1]   lock(task->pi_lock);                  [R] acquire [P]
- * [2]   waiter = task->pi_blocked_on;         [P]
- * [3]   check_exit_conditions_1();            [P]
- * [4]   lock = waiter->lock;                  [P]
- * [5]   if (!try_lock(lock->wait_lock)) {     [P] try to acquire [L]
- *         unlock(task->pi_lock);              release [P]
+ * [1]   lock(task->pi_lock);                  [R] acquire [P1]
+ * [2]   waiter = task->pi_blocked_on;         [P1]
+ * [3]   check_exit_conditions_1();            [P1]
+ * [4]   lock = waiter->lock;                  [P1]
+ * [5]   if (!try_lock(lock->wait_lock)) {     [P1] try to acquire [L]
+ *         unlock(task->pi_lock);              release [P1]
  *         goto retry;
  *       }
- * [6]   check_exit_conditions_2();            [P] + [L]
- * [7]   requeue_lock_waiter(lock, waiter);    [P] + [L]
- * [8]   unlock(task->pi_lock);                release [P]
+ * [6]   check_exit_conditions_2();            [P1] + [L]
+ * [7]   requeue_lock_waiter(lock, waiter);    [P1] + [L]
+ * [8]   unlock(task->pi_lock);                release [P1]
  *       put_task_struct(task);                release [R]
  * [9]   check_exit_conditions_3();            [L]
  * [10]          task = owner(lock);                   [L]
  *       get_task_struct(task);                [L] acquire [R]
- *       lock(task->pi_lock);                  [L] acquire [P]
- * [11]          requeue_pi_waiter(tsk, waiters(lock));[P] + [L]
- * [12]          check_exit_conditions_4();            [P] + [L]
- * [13]          unlock(task->pi_lock);                release [P]
+ *       lock(task->pi_lock);                  [L] acquire [P2]
+ * [11]          requeue_pi_waiter(tsk, waiters(lock));[P2] + [L]
+ * [12]          check_exit_conditions_4();            [P2] + [L]
+ * [13]          unlock(task->pi_lock);                release [P2]
  *       unlock(lock->wait_lock);              release [L]
  *       goto again;
+ *
+ * Where P1 is the blocking task and P2 is the lock owner; going up one step
+ * the owner becomes the next blocked task etc..
+ *
+*
  */
 static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task,
                                              enum rtmutex_chainwalk chwalk,
@@ -756,7 +798,7 @@ static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task,
         * enabled we continue, but stop the requeueing in the chain
         * walk.
         */
-       if (rt_mutex_waiter_equal(waiter, task_to_waiter(task))) {
+       if (rt_waiter_node_equal(&waiter->tree, task_to_waiter_node(task))) {
                if (!detect_deadlock)
                        goto out_unlock_pi;
                else
@@ -764,13 +806,18 @@ static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task,
        }
 
        /*
-        * [4] Get the next lock
+        * [4] Get the next lock; per holding task->pi_lock we can't unblock
+        * and guarantee @lock's existence.
         */
        lock = waiter->lock;
        /*
         * [5] We need to trylock here as we are holding task->pi_lock,
         * which is the reverse lock order versus the other rtmutex
         * operations.
+        *
+        * Per the above, holding task->pi_lock guarantees lock exists, so
+        * inverting this lock order is infeasible from a life-time
+        * perspective.
         */
        if (!raw_spin_trylock(&lock->wait_lock)) {
                raw_spin_unlock_irq(&task->pi_lock);
@@ -874,17 +921,18 @@ static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task,
         * or
         *
         *   DL CBS enforcement advancing the effective deadline.
-        *
-        * Even though pi_waiters also uses these fields, and that tree is only
-        * updated in [11], we can do this here, since we hold [L], which
-        * serializes all pi_waiters access and rb_erase() does not care about
-        * the values of the node being removed.
         */
        waiter_update_prio(waiter, task);
 
        rt_mutex_enqueue(lock, waiter);
 
-       /* [8] Release the task */
+       /*
+        * [8] Release the (blocking) task in preparation for
+        * taking the owner task in [10].
+        *
+        * Since we hold lock->waiter_lock, task cannot unblock, even if we
+        * release task->pi_lock.
+        */
        raw_spin_unlock(&task->pi_lock);
        put_task_struct(task);
 
@@ -908,7 +956,12 @@ static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task,
                return 0;
        }
 
-       /* [10] Grab the next task, i.e. the owner of @lock */
+       /*
+        * [10] Grab the next task, i.e. the owner of @lock
+        *
+        * Per holding lock->wait_lock and checking for !owner above, there
+        * must be an owner and it cannot go away.
+        */
        task = get_task_struct(rt_mutex_owner(lock));
        raw_spin_lock(&task->pi_lock);
 
@@ -921,8 +974,9 @@ static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task,
                 * and adjust the priority of the owner.
                 */
                rt_mutex_dequeue_pi(task, prerequeue_top_waiter);
+               waiter_clone_prio(waiter, task);
                rt_mutex_enqueue_pi(task, waiter);
-               rt_mutex_adjust_prio(task);
+               rt_mutex_adjust_prio(lock, task);
 
        } else if (prerequeue_top_waiter == waiter) {
                /*
@@ -937,8 +991,9 @@ static int __sched rt_mutex_adjust_prio_chain(struct task_struct *task,
                 */
                rt_mutex_dequeue_pi(task, waiter);
                waiter = rt_mutex_top_waiter(lock);
+               waiter_clone_prio(waiter, task);
                rt_mutex_enqueue_pi(task, waiter);
-               rt_mutex_adjust_prio(task);
+               rt_mutex_adjust_prio(lock, task);
        } else {
                /*
                 * Nothing changed. No need to do any priority
@@ -1154,6 +1209,7 @@ static int __sched task_blocks_on_rt_mutex(struct rt_mutex_base *lock,
        waiter->task = task;
        waiter->lock = lock;
        waiter_update_prio(waiter, task);
+       waiter_clone_prio(waiter, task);
 
        /* Get the top priority waiter on the lock */
        if (rt_mutex_has_waiters(lock))
@@ -1187,7 +1243,7 @@ static int __sched task_blocks_on_rt_mutex(struct rt_mutex_base *lock,
                rt_mutex_dequeue_pi(owner, top_waiter);
                rt_mutex_enqueue_pi(owner, waiter);
 
-               rt_mutex_adjust_prio(owner);
+               rt_mutex_adjust_prio(lock, owner);
                if (owner->pi_blocked_on)
                        chain_walk = 1;
        } else if (rt_mutex_cond_detect_deadlock(waiter, chwalk)) {
@@ -1234,6 +1290,8 @@ static void __sched mark_wakeup_next_waiter(struct rt_wake_q_head *wqh,
 {
        struct rt_mutex_waiter *waiter;
 
+       lockdep_assert_held(&lock->wait_lock);
+
        raw_spin_lock(&current->pi_lock);
 
        waiter = rt_mutex_top_waiter(lock);
@@ -1246,7 +1304,7 @@ static void __sched mark_wakeup_next_waiter(struct rt_wake_q_head *wqh,
         * task unblocks.
         */
        rt_mutex_dequeue_pi(current, waiter);
-       rt_mutex_adjust_prio(current);
+       rt_mutex_adjust_prio(lock, current);
 
        /*
         * As we are waking up the top waiter, and the waiter stays
@@ -1482,7 +1540,7 @@ static void __sched remove_waiter(struct rt_mutex_base *lock,
        if (rt_mutex_has_waiters(lock))
                rt_mutex_enqueue_pi(owner, rt_mutex_top_waiter(lock));
 
-       rt_mutex_adjust_prio(owner);
+       rt_mutex_adjust_prio(lock, owner);
 
        /* Store the lock on which owner is blocked or NULL */
        next_lock = task_blocked_on_lock(owner);
index cb9fdff..a6974d0 100644 (file)
@@ -459,7 +459,7 @@ void __sched rt_mutex_adjust_pi(struct task_struct *task)
        raw_spin_lock_irqsave(&task->pi_lock, flags);
 
        waiter = task->pi_blocked_on;
-       if (!waiter || rt_mutex_waiter_equal(waiter, task_to_waiter(task))) {
+       if (!waiter || rt_waiter_node_equal(&waiter->tree, task_to_waiter_node(task))) {
                raw_spin_unlock_irqrestore(&task->pi_lock, flags);
                return;
        }
index c47e836..1162e07 100644 (file)
 #include <linux/rtmutex.h>
 #include <linux/sched/wake_q.h>
 
+
+/*
+ * This is a helper for the struct rt_mutex_waiter below. A waiter goes in two
+ * separate trees and they need their own copy of the sort keys because of
+ * different locking requirements.
+ *
+ * @entry:             rbtree node to enqueue into the waiters tree
+ * @prio:              Priority of the waiter
+ * @deadline:          Deadline of the waiter if applicable
+ *
+ * See rt_waiter_node_less() and waiter_*_prio().
+ */
+struct rt_waiter_node {
+       struct rb_node  entry;
+       int             prio;
+       u64             deadline;
+};
+
 /*
  * This is the control structure for tasks blocked on a rt_mutex,
  * which is allocated on the kernel stack on of the blocked task.
  *
- * @tree_entry:                pi node to enqueue into the mutex waiters tree
- * @pi_tree_entry:     pi node to enqueue into the mutex owner waiters tree
+ * @tree:              node to enqueue into the mutex waiters tree
+ * @pi_tree:           node to enqueue into the mutex owner waiters tree
  * @task:              task reference to the blocked task
  * @lock:              Pointer to the rt_mutex on which the waiter blocks
  * @wake_state:                Wakeup state to use (TASK_NORMAL or TASK_RTLOCK_WAIT)
- * @prio:              Priority of the waiter
- * @deadline:          Deadline of the waiter if applicable
  * @ww_ctx:            WW context pointer
+ *
+ * @tree is ordered by @lock->wait_lock
+ * @pi_tree is ordered by rt_mutex_owner(@lock)->pi_lock
  */
 struct rt_mutex_waiter {
-       struct rb_node          tree_entry;
-       struct rb_node          pi_tree_entry;
+       struct rt_waiter_node   tree;
+       struct rt_waiter_node   pi_tree;
        struct task_struct      *task;
        struct rt_mutex_base    *lock;
        unsigned int            wake_state;
-       int                     prio;
-       u64                     deadline;
        struct ww_acquire_ctx   *ww_ctx;
 };
 
@@ -105,7 +122,7 @@ static inline bool rt_mutex_waiter_is_top_waiter(struct rt_mutex_base *lock,
 {
        struct rb_node *leftmost = rb_first_cached(&lock->waiters);
 
-       return rb_entry(leftmost, struct rt_mutex_waiter, tree_entry) == waiter;
+       return rb_entry(leftmost, struct rt_mutex_waiter, tree.entry) == waiter;
 }
 
 static inline struct rt_mutex_waiter *rt_mutex_top_waiter(struct rt_mutex_base *lock)
@@ -113,8 +130,10 @@ static inline struct rt_mutex_waiter *rt_mutex_top_waiter(struct rt_mutex_base *
        struct rb_node *leftmost = rb_first_cached(&lock->waiters);
        struct rt_mutex_waiter *w = NULL;
 
+       lockdep_assert_held(&lock->wait_lock);
+
        if (leftmost) {
-               w = rb_entry(leftmost, struct rt_mutex_waiter, tree_entry);
+               w = rb_entry(leftmost, struct rt_mutex_waiter, tree.entry);
                BUG_ON(w->lock != lock);
        }
        return w;
@@ -127,8 +146,10 @@ static inline int task_has_pi_waiters(struct task_struct *p)
 
 static inline struct rt_mutex_waiter *task_top_pi_waiter(struct task_struct *p)
 {
+       lockdep_assert_held(&p->pi_lock);
+
        return rb_entry(p->pi_waiters.rb_leftmost, struct rt_mutex_waiter,
-                       pi_tree_entry);
+                       pi_tree.entry);
 }
 
 #define RT_MUTEX_HAS_WAITERS   1UL
@@ -190,8 +211,8 @@ static inline void debug_rt_mutex_free_waiter(struct rt_mutex_waiter *waiter)
 static inline void rt_mutex_init_waiter(struct rt_mutex_waiter *waiter)
 {
        debug_rt_mutex_init_waiter(waiter);
-       RB_CLEAR_NODE(&waiter->pi_tree_entry);
-       RB_CLEAR_NODE(&waiter->tree_entry);
+       RB_CLEAR_NODE(&waiter->pi_tree.entry);
+       RB_CLEAR_NODE(&waiter->tree.entry);
        waiter->wake_state = TASK_NORMAL;
        waiter->task = NULL;
 }
index 56f1392..3ad2cc4 100644 (file)
@@ -96,25 +96,25 @@ __ww_waiter_first(struct rt_mutex *lock)
        struct rb_node *n = rb_first(&lock->rtmutex.waiters.rb_root);
        if (!n)
                return NULL;
-       return rb_entry(n, struct rt_mutex_waiter, tree_entry);
+       return rb_entry(n, struct rt_mutex_waiter, tree.entry);
 }
 
 static inline struct rt_mutex_waiter *
 __ww_waiter_next(struct rt_mutex *lock, struct rt_mutex_waiter *w)
 {
-       struct rb_node *n = rb_next(&w->tree_entry);
+       struct rb_node *n = rb_next(&w->tree.entry);
        if (!n)
                return NULL;
-       return rb_entry(n, struct rt_mutex_waiter, tree_entry);
+       return rb_entry(n, struct rt_mutex_waiter, tree.entry);
 }
 
 static inline struct rt_mutex_waiter *
 __ww_waiter_prev(struct rt_mutex *lock, struct rt_mutex_waiter *w)
 {
-       struct rb_node *n = rb_prev(&w->tree_entry);
+       struct rb_node *n = rb_prev(&w->tree.entry);
        if (!n)
                return NULL;
-       return rb_entry(n, struct rt_mutex_waiter, tree_entry);
+       return rb_entry(n, struct rt_mutex_waiter, tree.entry);
 }
 
 static inline struct rt_mutex_waiter *
@@ -123,7 +123,7 @@ __ww_waiter_last(struct rt_mutex *lock)
        struct rb_node *n = rb_last(&lock->rtmutex.waiters.rb_root);
        if (!n)
                return NULL;
-       return rb_entry(n, struct rt_mutex_waiter, tree_entry);
+       return rb_entry(n, struct rt_mutex_waiter, tree.entry);
 }
 
 static inline void
index b5370fe..128e9bb 100644 (file)
@@ -562,6 +562,10 @@ bool unhandled_signal(struct task_struct *tsk, int sig)
        if (handler != SIG_IGN && handler != SIG_DFL)
                return false;
 
+       /* If dying, we handle all new signals by ignoring them */
+       if (fatal_signal_pending(tsk))
+               return false;
+
        /* if ptraced, let the tracer determine */
        return !tsk->ptrace;
 }
index 5f2dcab..bd1a42b 100644 (file)
@@ -661,8 +661,7 @@ static DEFINE_PER_CPU(int, bpf_trace_nest_level);
 BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
           u64, flags, void *, data, u64, size)
 {
-       struct bpf_trace_sample_data *sds = this_cpu_ptr(&bpf_trace_sds);
-       int nest_level = this_cpu_inc_return(bpf_trace_nest_level);
+       struct bpf_trace_sample_data *sds;
        struct perf_raw_record raw = {
                .frag = {
                        .size = size,
@@ -670,7 +669,11 @@ BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
                },
        };
        struct perf_sample_data *sd;
-       int err;
+       int nest_level, err;
+
+       preempt_disable();
+       sds = this_cpu_ptr(&bpf_trace_sds);
+       nest_level = this_cpu_inc_return(bpf_trace_nest_level);
 
        if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(sds->sds))) {
                err = -EBUSY;
@@ -688,9 +691,9 @@ BPF_CALL_5(bpf_perf_event_output, struct pt_regs *, regs, struct bpf_map *, map,
        perf_sample_save_raw_data(sd, &raw);
 
        err = __bpf_perf_event_output(regs, map, flags, sd);
-
 out:
        this_cpu_dec(bpf_trace_nest_level);
+       preempt_enable();
        return err;
 }
 
@@ -715,7 +718,6 @@ static DEFINE_PER_CPU(struct bpf_trace_sample_data, bpf_misc_sds);
 u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
                     void *ctx, u64 ctx_size, bpf_ctx_copy_t ctx_copy)
 {
-       int nest_level = this_cpu_inc_return(bpf_event_output_nest_level);
        struct perf_raw_frag frag = {
                .copy           = ctx_copy,
                .size           = ctx_size,
@@ -732,8 +734,12 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
        };
        struct perf_sample_data *sd;
        struct pt_regs *regs;
+       int nest_level;
        u64 ret;
 
+       preempt_disable();
+       nest_level = this_cpu_inc_return(bpf_event_output_nest_level);
+
        if (WARN_ON_ONCE(nest_level > ARRAY_SIZE(bpf_misc_sds.sds))) {
                ret = -EBUSY;
                goto out;
@@ -748,6 +754,7 @@ u64 bpf_event_output(struct bpf_map *map, u64 flags, void *meta, u64 meta_size,
        ret = __bpf_perf_event_output(regs, map, flags, sd);
 out:
        this_cpu_dec(bpf_event_output_nest_level);
+       preempt_enable();
        return ret;
 }
 
index 14d8001..52dea5d 100644 (file)
@@ -523,6 +523,8 @@ struct ring_buffer_per_cpu {
        rb_time_t                       before_stamp;
        u64                             event_stamp[MAX_NEST];
        u64                             read_stamp;
+       /* pages removed since last reset */
+       unsigned long                   pages_removed;
        /* ring buffer pages to update, > 0 to add, < 0 to remove */
        long                            nr_pages_to_update;
        struct list_head                new_pages; /* new pages to add */
@@ -536,6 +538,7 @@ struct trace_buffer {
        unsigned                        flags;
        int                             cpus;
        atomic_t                        record_disabled;
+       atomic_t                        resizing;
        cpumask_var_t                   cpumask;
 
        struct lock_class_key           *reader_lock_key;
@@ -558,6 +561,7 @@ struct ring_buffer_iter {
        struct buffer_page              *head_page;
        struct buffer_page              *cache_reader_page;
        unsigned long                   cache_read;
+       unsigned long                   cache_pages_removed;
        u64                             read_stamp;
        u64                             page_stamp;
        struct ring_buffer_event        *event;
@@ -946,6 +950,7 @@ static void rb_wake_up_waiters(struct irq_work *work)
 /**
  * ring_buffer_wake_waiters - wake up any waiters on this ring buffer
  * @buffer: The ring buffer to wake waiters on
+ * @cpu: The CPU buffer to wake waiters on
  *
  * In the case of a file that represents a ring buffer is closing,
  * it is prudent to wake up any waiters that are on this.
@@ -1956,6 +1961,8 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages)
                to_remove = rb_list_head(to_remove)->next;
                head_bit |= (unsigned long)to_remove & RB_PAGE_HEAD;
        }
+       /* Read iterators need to reset themselves when some pages removed */
+       cpu_buffer->pages_removed += nr_removed;
 
        next_page = rb_list_head(to_remove)->next;
 
@@ -1977,12 +1984,6 @@ rb_remove_pages(struct ring_buffer_per_cpu *cpu_buffer, unsigned long nr_pages)
                cpu_buffer->head_page = list_entry(next_page,
                                                struct buffer_page, list);
 
-       /*
-        * change read pointer to make sure any read iterators reset
-        * themselves
-        */
-       cpu_buffer->read = 0;
-
        /* pages are removed, resume tracing and then free the pages */
        atomic_dec(&cpu_buffer->record_disabled);
        raw_spin_unlock_irq(&cpu_buffer->reader_lock);
@@ -2167,7 +2168,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
 
        /* prevent another thread from changing buffer sizes */
        mutex_lock(&buffer->mutex);
-
+       atomic_inc(&buffer->resizing);
 
        if (cpu_id == RING_BUFFER_ALL_CPUS) {
                /*
@@ -2322,6 +2323,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
                atomic_dec(&buffer->record_disabled);
        }
 
+       atomic_dec(&buffer->resizing);
        mutex_unlock(&buffer->mutex);
        return 0;
 
@@ -2342,6 +2344,7 @@ int ring_buffer_resize(struct trace_buffer *buffer, unsigned long size,
                }
        }
  out_err_unlock:
+       atomic_dec(&buffer->resizing);
        mutex_unlock(&buffer->mutex);
        return err;
 }
@@ -3373,7 +3376,6 @@ void ring_buffer_nest_end(struct trace_buffer *buffer)
 /**
  * ring_buffer_unlock_commit - commit a reserved
  * @buffer: The buffer to commit to
- * @event: The event pointer to commit.
  *
  * This commits the data to the ring buffer, and releases any locks held.
  *
@@ -4392,6 +4394,7 @@ static void rb_iter_reset(struct ring_buffer_iter *iter)
 
        iter->cache_reader_page = iter->head_page;
        iter->cache_read = cpu_buffer->read;
+       iter->cache_pages_removed = cpu_buffer->pages_removed;
 
        if (iter->head) {
                iter->read_stamp = cpu_buffer->read_stamp;
@@ -4846,12 +4849,13 @@ rb_iter_peek(struct ring_buffer_iter *iter, u64 *ts)
        buffer = cpu_buffer->buffer;
 
        /*
-        * Check if someone performed a consuming read to
-        * the buffer. A consuming read invalidates the iterator
-        * and we need to reset the iterator in this case.
+        * Check if someone performed a consuming read to the buffer
+        * or removed some pages from the buffer. In these cases,
+        * iterator was invalidated and we need to reset it.
         */
        if (unlikely(iter->cache_read != cpu_buffer->read ||
-                    iter->cache_reader_page != cpu_buffer->reader_page))
+                    iter->cache_reader_page != cpu_buffer->reader_page ||
+                    iter->cache_pages_removed != cpu_buffer->pages_removed))
                rb_iter_reset(iter);
 
  again:
@@ -5295,6 +5299,7 @@ rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
        cpu_buffer->last_overrun = 0;
 
        rb_head_page_activate(cpu_buffer);
+       cpu_buffer->pages_removed = 0;
 }
 
 /* Must have disabled the cpu buffer then done a synchronize_rcu */
@@ -5353,7 +5358,6 @@ EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu);
 /**
  * ring_buffer_reset_online_cpus - reset a ring buffer per CPU buffer
  * @buffer: The ring buffer to reset a per cpu buffer of
- * @cpu: The CPU buffer to be reset
  */
 void ring_buffer_reset_online_cpus(struct trace_buffer *buffer)
 {
@@ -5541,6 +5545,15 @@ int ring_buffer_swap_cpu(struct trace_buffer *buffer_a,
        if (local_read(&cpu_buffer_b->committing))
                goto out_dec;
 
+       /*
+        * When resize is in progress, we cannot swap it because
+        * it will mess the state of the cpu buffer.
+        */
+       if (atomic_read(&buffer_a->resizing))
+               goto out_dec;
+       if (atomic_read(&buffer_b->resizing))
+               goto out_dec;
+
        buffer_a->buffers[cpu] = cpu_buffer_b;
        buffer_b->buffers[cpu] = cpu_buffer_a;
 
index be847d4..b887007 100644 (file)
@@ -1928,9 +1928,10 @@ update_max_tr_single(struct trace_array *tr, struct task_struct *tsk, int cpu)
                 * place on this CPU. We fail to record, but we reset
                 * the max trace buffer (no one writes directly to it)
                 * and flag that it failed.
+                * Another reason is resize is in progress.
                 */
                trace_array_printk_buf(tr->max_buffer.buffer, _THIS_IP_,
-                       "Failed to swap buffers due to commit in progress\n");
+                       "Failed to swap buffers due to commit or resize in progress\n");
        }
 
        WARN_ON_ONCE(ret && ret != -EAGAIN && ret != -EBUSY);
index 5d6ae4e..578f1f7 100644 (file)
@@ -611,7 +611,6 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
 {
        struct trace_event_call *call = file->event_call;
        struct trace_array *tr = file->tr;
-       unsigned long file_flags = file->flags;
        int ret = 0;
        int disable;
 
@@ -635,6 +634,8 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
                                break;
                        disable = file->flags & EVENT_FILE_FL_SOFT_DISABLED;
                        clear_bit(EVENT_FILE_FL_SOFT_MODE_BIT, &file->flags);
+                       /* Disable use of trace_buffered_event */
+                       trace_buffered_event_disable();
                } else
                        disable = !(file->flags & EVENT_FILE_FL_SOFT_MODE);
 
@@ -673,6 +674,8 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
                        if (atomic_inc_return(&file->sm_ref) > 1)
                                break;
                        set_bit(EVENT_FILE_FL_SOFT_MODE_BIT, &file->flags);
+                       /* Enable use of trace_buffered_event */
+                       trace_buffered_event_enable();
                }
 
                if (!(file->flags & EVENT_FILE_FL_ENABLED)) {
@@ -712,15 +715,6 @@ static int __ftrace_event_enable_disable(struct trace_event_file *file,
                break;
        }
 
-       /* Enable or disable use of trace_buffered_event */
-       if ((file_flags & EVENT_FILE_FL_SOFT_DISABLED) !=
-           (file->flags & EVENT_FILE_FL_SOFT_DISABLED)) {
-               if (file->flags & EVENT_FILE_FL_SOFT_DISABLED)
-                       trace_buffered_event_enable();
-               else
-                       trace_buffered_event_disable();
-       }
-
        return ret;
 }
 
index c8c6138..d06938a 100644 (file)
@@ -6668,7 +6668,8 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
                goto out_unreg;
 
        if (has_hist_vars(hist_data) || hist_data->n_var_refs) {
-               if (save_hist_vars(hist_data))
+               ret = save_hist_vars(hist_data);
+               if (ret)
                        goto out_unreg;
        }
 
index d6a70af..dd398af 100644 (file)
@@ -1230,6 +1230,7 @@ EXPORT_SYMBOL_GPL(__synth_event_gen_cmd_start);
  * synth_event_gen_cmd_array_start - Start synthetic event command from an array
  * @cmd: A pointer to the dynevent_cmd struct representing the new event
  * @name: The name of the synthetic event
+ * @mod: The module creating the event, NULL if not created from a module
  * @fields: An array of type/name field descriptions
  * @n_fields: The number of field descriptions contained in the fields array
  *
index e535959..46439e3 100644 (file)
@@ -31,7 +31,9 @@ void trigger_data_free(struct event_trigger_data *data)
 /**
  * event_triggers_call - Call triggers associated with a trace event
  * @file: The trace_event_file associated with the event
+ * @buffer: The ring buffer that the event is being written to
  * @rec: The trace entry for the event, NULL for unconditional invocation
+ * @event: The event meta data in the ring buffer
  *
  * For each trigger associated with an event, invoke the trigger
  * function registered with the associated trigger command.  If rec is
index b2b726b..c68a727 100644 (file)
@@ -386,12 +386,12 @@ static const struct btf_type *find_btf_func_proto(const char *funcname)
 
        /* Get BTF_KIND_FUNC type */
        t = btf_type_by_id(btf, id);
-       if (!btf_type_is_func(t))
+       if (!t || !btf_type_is_func(t))
                return ERR_PTR(-ENOENT);
 
        /* The type of BTF_KIND_FUNC is BTF_KIND_FUNC_PROTO */
        t = btf_type_by_id(btf, t->type);
-       if (!btf_type_is_func_proto(t))
+       if (!t || !btf_type_is_func_proto(t))
                return ERR_PTR(-ENOENT);
 
        return t;
@@ -443,7 +443,7 @@ static int parse_btf_arg(const char *varname, struct fetch_insn *code,
        if (!ctx->params) {
                params = find_btf_func_param(ctx->funcname, &ctx->nr_params,
                                             ctx->flags & TPARG_FL_TPOINT);
-               if (IS_ERR(params)) {
+               if (IS_ERR_OR_NULL(params)) {
                        trace_probe_log_err(ctx->offset, NO_BTF_ENTRY);
                        return PTR_ERR(params);
                }
@@ -1273,7 +1273,7 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],
 
        params = find_btf_func_param(ctx->funcname, &nr_params,
                                     ctx->flags & TPARG_FL_TPOINT);
-       if (IS_ERR(params)) {
+       if (IS_ERR_OR_NULL(params)) {
                if (args_idx != -1) {
                        /* $arg* requires BTF info */
                        trace_probe_log_err(0, NOSUP_BTFARG);
index e5e2992..bac06ee 100644 (file)
@@ -131,6 +131,7 @@ EXPORT_SYMBOL_GPL(trace_seq_bitmask);
  * trace_seq_vprintf - sequence printing of trace information
  * @s: trace sequence descriptor
  * @fmt: printf format string
+ * @args: Arguments for the format string
  *
  * The tracer may use either sequence operations or its own
  * copy to user routines. To simplify formatting of a trace
index 2c765ee..99c37ee 100644 (file)
@@ -272,10 +272,6 @@ extern u64 tracing_map_read_sum(struct tracing_map_elt *elt, unsigned int i);
 extern u64 tracing_map_read_var(struct tracing_map_elt *elt, unsigned int i);
 extern u64 tracing_map_read_var_once(struct tracing_map_elt *elt, unsigned int i);
 
-extern void tracing_map_set_field_descr(struct tracing_map *map,
-                                       unsigned int i,
-                                       unsigned int key_offset,
-                                       tracing_map_cmp_fn_t cmp_fn);
 extern int
 tracing_map_sort_entries(struct tracing_map *map,
                         struct tracing_map_sort_key *sort_keys,
index 42d307a..1ffae65 100644 (file)
@@ -82,7 +82,13 @@ obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
 obj-$(CONFIG_TEST_DYNAMIC_DEBUG) += test_dynamic_debug.o
 obj-$(CONFIG_TEST_PRINTF) += test_printf.o
 obj-$(CONFIG_TEST_SCANF) += test_scanf.o
+
 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
+ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_KASAN),yy)
+# FIXME: Clang breaks test_bitmap_const_eval when KASAN and GCOV are enabled
+GCOV_PROFILE_test_bitmap.o := n
+endif
+
 obj-$(CONFIG_TEST_UUID) += test_uuid.o
 obj-$(CONFIG_TEST_XARRAY) += test_xarray.o
 obj-$(CONFIG_TEST_MAPLE_TREE) += test_maple_tree.o
index de356f1..a7fd02b 100644 (file)
@@ -45,6 +45,7 @@ EXPORT_SYMBOL(cpumask_next_wrap);
  * alloc_cpumask_var_node - allocate a struct cpumask on a given node
  * @mask: pointer to cpumask_var_t where the cpumask is returned
  * @flags: GFP_ flags
+ * @node: memory node from which to allocate or %NUMA_NO_NODE
  *
  * Only defined when CONFIG_CPUMASK_OFFSTACK=y, otherwise is
  * a nop returning a constant 1 (in <linux/cpumask.h>)
@@ -157,7 +158,9 @@ EXPORT_SYMBOL(cpumask_local_spread);
 static DEFINE_PER_CPU(int, distribute_cpu_mask_prev);
 
 /**
- * cpumask_any_and_distribute - Return an arbitrary cpu within srcp1 & srcp2.
+ * cpumask_any_and_distribute - Return an arbitrary cpu within src1p & src2p.
+ * @src1p: first &cpumask for intersection
+ * @src2p: second &cpumask for intersection
  *
  * Iterated calls using the same srcp1 and srcp2 will be distributed within
  * their intersection.
index 0c883d6..6c644f9 100644 (file)
@@ -895,7 +895,7 @@ struct gen_pool *of_gen_pool_get(struct device_node *np,
 
                of_property_read_string(np_pool, "label", &name);
                if (!name)
-                       name = np_pool->name;
+                       name = of_node_full_name(np_pool);
        }
        if (pdev)
                pool = gen_pool_get(&pdev->dev, name);
index eff4e42..d0a5081 100644 (file)
@@ -550,7 +550,7 @@ EXPORT_SYMBOL_GPL(sbitmap_queue_min_shallow_depth);
 
 static void __sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr)
 {
-       int i, wake_index;
+       int i, wake_index, woken;
 
        if (!atomic_read(&sbq->ws_active))
                return;
@@ -567,13 +567,12 @@ static void __sbitmap_queue_wake_up(struct sbitmap_queue *sbq, int nr)
                 */
                wake_index = sbq_index_inc(wake_index);
 
-               /*
-                * It is sufficient to wake up at least one waiter to
-                * guarantee forward progress.
-                */
-               if (waitqueue_active(&ws->wait) &&
-                   wake_up_nr(&ws->wait, nr))
-                       break;
+               if (waitqueue_active(&ws->wait)) {
+                       woken = wake_up_nr(&ws->wait, nr);
+                       if (woken == nr)
+                               break;
+                       nr -= woken;
+               }
        }
 
        if (wake_index != atomic_read(&sbq->wake_index))
index 187f5b2..f2ea9f3 100644 (file)
@@ -1161,6 +1161,10 @@ static void __init test_bitmap_print_buf(void)
        }
 }
 
+/*
+ * FIXME: Clang breaks compile-time evaluations when KASAN and GCOV are enabled.
+ * To workaround it, GCOV is force-disabled in Makefile for this configuration.
+ */
 static void __init test_bitmap_const_eval(void)
 {
        DECLARE_BITMAP(bitmap, BITS_PER_LONG);
@@ -1186,11 +1190,7 @@ static void __init test_bitmap_const_eval(void)
         * the compiler is fixed.
         */
        bitmap_clear(bitmap, 0, BITS_PER_LONG);
-#if defined(__s390__) && defined(__clang__)
-       if (!const_test_bit(7, bitmap))
-#else
        if (!test_bit(7, bitmap))
-#endif
                bitmap_set(bitmap, 5, 2);
 
        /* Equals to `unsigned long bitopvar = BIT(20)` */
index c112101..bb07721 100644 (file)
@@ -320,25 +320,25 @@ static void damon_test_update_monitoring_result(struct kunit *test)
 
 static void damon_test_set_attrs(struct kunit *test)
 {
-       struct damon_ctx ctx;
+       struct damon_ctx *c = damon_new_ctx();
        struct damon_attrs valid_attrs = {
                .min_nr_regions = 10, .max_nr_regions = 1000,
                .sample_interval = 5000, .aggr_interval = 100000,};
        struct damon_attrs invalid_attrs;
 
-       KUNIT_EXPECT_EQ(test, damon_set_attrs(&ctx, &valid_attrs), 0);
+       KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &valid_attrs), 0);
 
        invalid_attrs = valid_attrs;
        invalid_attrs.min_nr_regions = 1;
-       KUNIT_EXPECT_EQ(test, damon_set_attrs(&ctx, &invalid_attrs), -EINVAL);
+       KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
 
        invalid_attrs = valid_attrs;
        invalid_attrs.max_nr_regions = 9;
-       KUNIT_EXPECT_EQ(test, damon_set_attrs(&ctx, &invalid_attrs), -EINVAL);
+       KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
 
        invalid_attrs = valid_attrs;
        invalid_attrs.aggr_interval = 4999;
-       KUNIT_EXPECT_EQ(test, damon_set_attrs(&ctx, &invalid_attrs), -EINVAL);
+       KUNIT_EXPECT_EQ(test, damon_set_attrs(c, &invalid_attrs), -EINVAL);
 }
 
 static struct kunit_case damon_test_cases[] = {
index e245191..ece5d48 100644 (file)
@@ -2487,7 +2487,7 @@ int unpoison_memory(unsigned long pfn)
                goto unlock_mutex;
        }
 
-       if (!folio_test_hwpoison(folio)) {
+       if (!PageHWPoison(p)) {
                unpoison_pr_info("Unpoison: Page was already unpoisoned %#lx\n",
                                 pfn, &unpoison_rs);
                goto unlock_mutex;
index 01f39e8..603b2f4 100644 (file)
@@ -5393,27 +5393,28 @@ retry:
        if (!vma_is_anonymous(vma) && !vma_is_tcp(vma))
                goto inval;
 
-       /* find_mergeable_anon_vma uses adjacent vmas which are not locked */
-       if (!vma->anon_vma && !vma_is_tcp(vma))
-               goto inval;
-
        if (!vma_start_read(vma))
                goto inval;
 
        /*
+        * find_mergeable_anon_vma uses adjacent vmas which are not locked.
+        * This check must happen after vma_start_read(); otherwise, a
+        * concurrent mremap() with MREMAP_DONTUNMAP could dissociate the VMA
+        * from its anon_vma.
+        */
+       if (unlikely(!vma->anon_vma && !vma_is_tcp(vma)))
+               goto inval_end_read;
+
+       /*
         * Due to the possibility of userfault handler dropping mmap_lock, avoid
         * it for now and fall back to page fault handling under mmap_lock.
         */
-       if (userfaultfd_armed(vma)) {
-               vma_end_read(vma);
-               goto inval;
-       }
+       if (userfaultfd_armed(vma))
+               goto inval_end_read;
 
        /* Check since vm_start/vm_end might change before we lock the VMA */
-       if (unlikely(address < vma->vm_start || address >= vma->vm_end)) {
-               vma_end_read(vma);
-               goto inval;
-       }
+       if (unlikely(address < vma->vm_start || address >= vma->vm_end))
+               goto inval_end_read;
 
        /* Check if the VMA got isolated after we found it */
        if (vma->detached) {
@@ -5425,6 +5426,9 @@ retry:
 
        rcu_read_unlock();
        return vma;
+
+inval_end_read:
+       vma_end_read(vma);
 inval:
        rcu_read_unlock();
        count_vm_vma_lock_event(VMA_LOCK_ABORT);
index edc2519..c53f8be 100644 (file)
@@ -384,8 +384,10 @@ void mpol_rebind_mm(struct mm_struct *mm, nodemask_t *new)
        VMA_ITERATOR(vmi, mm, 0);
 
        mmap_write_lock(mm);
-       for_each_vma(vmi, vma)
+       for_each_vma(vmi, vma) {
+               vma_start_write(vma);
                mpol_rebind_policy(vma->vm_policy, new);
+       }
        mmap_write_unlock(mm);
 }
 
@@ -768,6 +770,8 @@ static int vma_replace_policy(struct vm_area_struct *vma,
        struct mempolicy *old;
        struct mempolicy *new;
 
+       vma_assert_write_locked(vma);
+
        pr_debug("vma %lx-%lx/%lx vm_ops %p vm_file %p set_policy %p\n",
                 vma->vm_start, vma->vm_end, vma->vm_pgoff,
                 vma->vm_ops, vma->vm_file,
@@ -1313,6 +1317,14 @@ static long do_mbind(unsigned long start, unsigned long len,
        if (err)
                goto mpol_out;
 
+       /*
+        * Lock the VMAs before scanning for pages to migrate, to ensure we don't
+        * miss a concurrently inserted page.
+        */
+       vma_iter_init(&vmi, mm, start);
+       for_each_vma_range(vmi, vma, end)
+               vma_start_write(vma);
+
        ret = queue_pages_range(mm, start, end, nmask,
                          flags | MPOL_MF_INVERT, &pagelist);
 
@@ -1538,6 +1550,7 @@ SYSCALL_DEFINE4(set_mempolicy_home_node, unsigned long, start, unsigned long, le
                        break;
                }
 
+               vma_start_write(vma);
                new->home_node = home_node;
                err = mbind_range(&vmi, vma, &prev, start, end, new);
                mpol_put(new);
index 3eda23c..3937479 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -615,6 +615,7 @@ static inline int dup_anon_vma(struct vm_area_struct *dst,
         * anon pages imported.
         */
        if (src->anon_vma && !dst->anon_vma) {
+               vma_start_write(dst);
                dst->anon_vma = src->anon_vma;
                return anon_vma_clone(dst, src);
        }
index 6443710..2022333 100644 (file)
@@ -48,8 +48,11 @@ static int walk_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
        if (walk->no_vma) {
                /*
                 * pte_offset_map() might apply user-specific validation.
+                * Indeed, on x86_64 the pmd entries set up by init_espfix_ap()
+                * fit its pmd_bad() check (_PAGE_NX set and _PAGE_RW clear),
+                * and CONFIG_EFI_PGT_DUMP efi_mm goes so far as to walk them.
                 */
-               if (walk->mm == &init_mm)
+               if (walk->mm == &init_mm || addr >= TASK_SIZE)
                        pte = pte_offset_kernel(pmd, addr);
                else
                        pte = pte_offset_map(pmd, addr);
index 2f2e0e6..f5af4b9 100644 (file)
@@ -2796,7 +2796,8 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
                if (*ppos >= i_size_read(inode))
                        break;
 
-               error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio, SGP_READ);
+               error = shmem_get_folio(inode, *ppos / PAGE_SIZE, &folio,
+                                       SGP_READ);
                if (error) {
                        if (error == -EINVAL)
                                error = 0;
@@ -2805,7 +2806,9 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
                if (folio) {
                        folio_unlock(folio);
 
-                       if (folio_test_hwpoison(folio)) {
+                       if (folio_test_hwpoison(folio) ||
+                           (folio_test_large(folio) &&
+                            folio_test_has_hwpoisoned(folio))) {
                                error = -EIO;
                                break;
                        }
@@ -2841,7 +2844,7 @@ static ssize_t shmem_file_splice_read(struct file *in, loff_t *ppos,
                        folio_put(folio);
                        folio = NULL;
                } else {
-                       n = splice_zeropage_into_pipe(pipe, *ppos, len);
+                       n = splice_zeropage_into_pipe(pipe, *ppos, part);
                }
 
                if (!n)
index a334026..86bbc71 100644 (file)
@@ -904,7 +904,7 @@ EXPORT_SYMBOL(do_trace_9p_fid_put);
 
 static int p9_client_version(struct p9_client *c)
 {
-       int err = 0;
+       int err;
        struct p9_req_t *req;
        char *version = NULL;
        int msize;
@@ -975,7 +975,6 @@ struct p9_client *p9_client_create(const char *dev_name, char *options)
        struct p9_client *clnt;
        char *client_id;
 
-       err = 0;
        clnt = kmalloc(sizeof(*clnt), GFP_KERNEL);
        if (!clnt)
                return ERR_PTR(-ENOMEM);
@@ -1094,7 +1093,7 @@ struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
                                const char *uname, kuid_t n_uname,
                                const char *aname)
 {
-       int err = 0;
+       int err;
        struct p9_req_t *req;
        struct p9_fid *fid;
        struct p9_qid qid;
@@ -1147,7 +1146,6 @@ struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname,
        struct p9_req_t *req;
        u16 nwqids, count;
 
-       err = 0;
        wqids = NULL;
        clnt = oldfid->clnt;
        if (clone) {
@@ -1224,7 +1222,6 @@ int p9_client_open(struct p9_fid *fid, int mode)
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P, ">>> %s fid %d mode %d\n",
                 p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode);
-       err = 0;
 
        if (fid->mode != -1)
                return -EINVAL;
@@ -1262,7 +1259,7 @@ EXPORT_SYMBOL(p9_client_open);
 int p9_client_create_dotl(struct p9_fid *ofid, const char *name, u32 flags,
                          u32 mode, kgid_t gid, struct p9_qid *qid)
 {
-       int err = 0;
+       int err;
        struct p9_client *clnt;
        struct p9_req_t *req;
        int iounit;
@@ -1314,7 +1311,6 @@ int p9_client_fcreate(struct p9_fid *fid, const char *name, u32 perm, int mode,
 
        p9_debug(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
                 fid->fid, name, perm, mode);
-       err = 0;
        clnt = fid->clnt;
 
        if (fid->mode != -1)
@@ -1350,7 +1346,7 @@ EXPORT_SYMBOL(p9_client_fcreate);
 int p9_client_symlink(struct p9_fid *dfid, const char *name,
                      const char *symtgt, kgid_t gid, struct p9_qid *qid)
 {
-       int err = 0;
+       int err;
        struct p9_client *clnt;
        struct p9_req_t *req;
 
@@ -1402,13 +1398,12 @@ EXPORT_SYMBOL(p9_client_link);
 
 int p9_client_fsync(struct p9_fid *fid, int datasync)
 {
-       int err;
+       int err = 0;
        struct p9_client *clnt;
        struct p9_req_t *req;
 
        p9_debug(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n",
                 fid->fid, datasync);
-       err = 0;
        clnt = fid->clnt;
 
        req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync);
@@ -1428,7 +1423,7 @@ EXPORT_SYMBOL(p9_client_fsync);
 
 int p9_client_clunk(struct p9_fid *fid)
 {
-       int err;
+       int err = 0;
        struct p9_client *clnt;
        struct p9_req_t *req;
        int retries = 0;
@@ -1436,7 +1431,6 @@ int p9_client_clunk(struct p9_fid *fid)
 again:
        p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n",
                 fid->fid, retries);
-       err = 0;
        clnt = fid->clnt;
 
        req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid);
@@ -1465,12 +1459,11 @@ EXPORT_SYMBOL(p9_client_clunk);
 
 int p9_client_remove(struct p9_fid *fid)
 {
-       int err;
+       int err = 0;
        struct p9_client *clnt;
        struct p9_req_t *req;
 
        p9_debug(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid);
-       err = 0;
        clnt = fid->clnt;
 
        req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid);
@@ -1680,7 +1673,6 @@ struct p9_wstat *p9_client_stat(struct p9_fid *fid)
        if (!ret)
                return ERR_PTR(-ENOMEM);
 
-       err = 0;
        clnt = fid->clnt;
 
        req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
@@ -1733,7 +1725,6 @@ struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid,
        if (!ret)
                return ERR_PTR(-ENOMEM);
 
-       err = 0;
        clnt = fid->clnt;
 
        req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask);
@@ -1812,11 +1803,10 @@ static int p9_client_statsize(struct p9_wstat *wst, int proto_version)
 
 int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
 {
-       int err;
+       int err = 0;
        struct p9_req_t *req;
        struct p9_client *clnt;
 
-       err = 0;
        clnt = fid->clnt;
        wst->size = p9_client_statsize(wst, clnt->proto_version);
        p9_debug(P9_DEBUG_9P, ">>> TWSTAT fid %d\n",
@@ -1851,11 +1841,10 @@ EXPORT_SYMBOL(p9_client_wstat);
 
 int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr)
 {
-       int err;
+       int err = 0;
        struct p9_req_t *req;
        struct p9_client *clnt;
 
-       err = 0;
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid);
        p9_debug(P9_DEBUG_9P, "    valid=%x mode=%x uid=%d gid=%d size=%lld\n",
@@ -1887,7 +1876,6 @@ int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb)
        struct p9_req_t *req;
        struct p9_client *clnt;
 
-       err = 0;
        clnt = fid->clnt;
 
        p9_debug(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid);
@@ -1921,11 +1909,10 @@ EXPORT_SYMBOL(p9_client_statfs);
 int p9_client_rename(struct p9_fid *fid,
                     struct p9_fid *newdirfid, const char *name)
 {
-       int err;
+       int err = 0;
        struct p9_req_t *req;
        struct p9_client *clnt;
 
-       err = 0;
        clnt = fid->clnt;
 
        p9_debug(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n",
@@ -1949,11 +1936,10 @@ EXPORT_SYMBOL(p9_client_rename);
 int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name,
                       struct p9_fid *newdirfid, const char *new_name)
 {
-       int err;
+       int err = 0;
        struct p9_req_t *req;
        struct p9_client *clnt;
 
-       err = 0;
        clnt = olddirfid->clnt;
 
        p9_debug(P9_DEBUG_9P,
@@ -1986,7 +1972,6 @@ struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid,
        struct p9_client *clnt;
        struct p9_fid *attr_fid;
 
-       err = 0;
        clnt = file_fid->clnt;
        attr_fid = p9_fid_create(clnt);
        if (!attr_fid) {
@@ -2027,14 +2012,13 @@ EXPORT_SYMBOL_GPL(p9_client_xattrwalk);
 int p9_client_xattrcreate(struct p9_fid *fid, const char *name,
                          u64 attr_size, int flags)
 {
-       int err;
+       int err = 0;
        struct p9_req_t *req;
        struct p9_client *clnt;
 
        p9_debug(P9_DEBUG_9P,
                 ">>> TXATTRCREATE fid %d name  %s size %llu flag %d\n",
                 fid->fid, name, attr_size, flags);
-       err = 0;
        clnt = fid->clnt;
        req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd",
                            fid->fid, name, attr_size, flags);
@@ -2063,7 +2047,6 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
        p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
                 fid->fid, offset, count);
 
-       err = 0;
        clnt = fid->clnt;
 
        rsize = fid->iounit;
@@ -2122,7 +2105,6 @@ int p9_client_mknod_dotl(struct p9_fid *fid, const char *name, int mode,
        struct p9_client *clnt;
        struct p9_req_t *req;
 
-       err = 0;
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P,
                 ">>> TMKNOD fid %d name %s mode %d major %d minor %d\n",
@@ -2153,7 +2135,6 @@ int p9_client_mkdir_dotl(struct p9_fid *fid, const char *name, int mode,
        struct p9_client *clnt;
        struct p9_req_t *req;
 
-       err = 0;
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n",
                 fid->fid, name, mode, from_kgid(&init_user_ns, gid));
@@ -2182,7 +2163,6 @@ int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status)
        struct p9_client *clnt;
        struct p9_req_t *req;
 
-       err = 0;
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P,
                 ">>> TLOCK fid %d type %i flags %d start %lld length %lld proc_id %d client_id %s\n",
@@ -2214,7 +2194,6 @@ int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock)
        struct p9_client *clnt;
        struct p9_req_t *req;
 
-       err = 0;
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P,
                 ">>> TGETLOCK fid %d, type %i start %lld length %lld proc_id %d client_id %s\n",
@@ -2251,7 +2230,6 @@ int p9_client_readlink(struct p9_fid *fid, char **target)
        struct p9_client *clnt;
        struct p9_req_t *req;
 
-       err = 0;
        clnt = fid->clnt;
        p9_debug(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid);
 
index 3c27ffb..e305071 100644 (file)
@@ -384,7 +384,7 @@ static void handle_rerror(struct p9_req_t *req, int in_hdr_len,
        void *to = req->rc.sdata + in_hdr_len;
 
        // Fits entirely into the static data?  Nothing to do.
-       if (req->rc.size < in_hdr_len)
+       if (req->rc.size < in_hdr_len || !pages)
                return;
 
        // Really long error message?  Tough, truncate the reply.  Might get
@@ -428,7 +428,7 @@ p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req,
        struct page **in_pages = NULL, **out_pages = NULL;
        struct virtio_chan *chan = client->trans;
        struct scatterlist *sgs[4];
-       size_t offs;
+       size_t offs = 0;
        int need_drop = 0;
        int kicked = 0;
 
@@ -501,8 +501,8 @@ req_retry_pinned:
 
        if (in_pages) {
                sgs[out_sgs + in_sgs++] = chan->sg + out + in;
-               in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM,
-                                    in_pages, in_nr_pages, offs, inlen);
+               pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM,
+                              in_pages, in_nr_pages, offs, inlen);
        }
 
        BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs));
index 056f951..7622256 100644 (file)
@@ -118,7 +118,7 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
         */
        params->explicit_connect = false;
 
-       list_del_init(&params->action);
+       hci_pend_le_list_del_init(params);
 
        switch (params->auto_connect) {
        case HCI_AUTO_CONN_EXPLICIT:
@@ -127,10 +127,10 @@ static void hci_connect_le_scan_cleanup(struct hci_conn *conn, u8 status)
                return;
        case HCI_AUTO_CONN_DIRECT:
        case HCI_AUTO_CONN_ALWAYS:
-               list_add(&params->action, &hdev->pend_le_conns);
+               hci_pend_le_list_add(params, &hdev->pend_le_conns);
                break;
        case HCI_AUTO_CONN_REPORT:
-               list_add(&params->action, &hdev->pend_le_reports);
+               hci_pend_le_list_add(params, &hdev->pend_le_reports);
                break;
        default:
                break;
@@ -1426,8 +1426,8 @@ static int hci_explicit_conn_params_set(struct hci_dev *hdev,
        if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
            params->auto_connect == HCI_AUTO_CONN_REPORT ||
            params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
-               list_del_init(&params->action);
-               list_add(&params->action, &hdev->pend_le_conns);
+               hci_pend_le_list_del_init(params);
+               hci_pend_le_list_add(params, &hdev->pend_le_conns);
        }
 
        params->explicit_connect = true;
@@ -1684,7 +1684,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst,
        if (!link) {
                hci_conn_drop(acl);
                hci_conn_drop(sco);
-               return NULL;
+               return ERR_PTR(-ENOLINK);
        }
 
        sco->setting = setting;
@@ -2254,7 +2254,7 @@ struct hci_conn *hci_connect_cis(struct hci_dev *hdev, bdaddr_t *dst,
        if (!link) {
                hci_conn_drop(le);
                hci_conn_drop(cis);
-               return NULL;
+               return ERR_PTR(-ENOLINK);
        }
 
        /* If LE is already connected and CIS handle is already set proceed to
index 48917c6..1ec8398 100644 (file)
@@ -1972,6 +1972,7 @@ static int hci_remove_adv_monitor(struct hci_dev *hdev,
                                  struct adv_monitor *monitor)
 {
        int status = 0;
+       int handle;
 
        switch (hci_get_adv_monitor_offload_ext(hdev)) {
        case HCI_ADV_MONITOR_EXT_NONE: /* also goes here when powered off */
@@ -1980,9 +1981,10 @@ static int hci_remove_adv_monitor(struct hci_dev *hdev,
                goto free_monitor;
 
        case HCI_ADV_MONITOR_EXT_MSFT:
+               handle = monitor->handle;
                status = msft_remove_monitor(hdev, monitor);
                bt_dev_dbg(hdev, "%s remove monitor %d msft status %d",
-                          hdev->name, monitor->handle, status);
+                          hdev->name, handle, status);
                break;
        }
 
@@ -2249,22 +2251,46 @@ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev,
        return NULL;
 }
 
-/* This function requires the caller holds hdev->lock */
+/* This function requires the caller holds hdev->lock or rcu_read_lock */
 struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list,
                                                  bdaddr_t *addr, u8 addr_type)
 {
        struct hci_conn_params *param;
 
-       list_for_each_entry(param, list, action) {
+       rcu_read_lock();
+
+       list_for_each_entry_rcu(param, list, action) {
                if (bacmp(&param->addr, addr) == 0 &&
-                   param->addr_type == addr_type)
+                   param->addr_type == addr_type) {
+                       rcu_read_unlock();
                        return param;
+               }
        }
 
+       rcu_read_unlock();
+
        return NULL;
 }
 
 /* This function requires the caller holds hdev->lock */
+void hci_pend_le_list_del_init(struct hci_conn_params *param)
+{
+       if (list_empty(&param->action))
+               return;
+
+       list_del_rcu(&param->action);
+       synchronize_rcu();
+       INIT_LIST_HEAD(&param->action);
+}
+
+/* This function requires the caller holds hdev->lock */
+void hci_pend_le_list_add(struct hci_conn_params *param,
+                         struct list_head *list)
+{
+       list_add_rcu(&param->action, list);
+}
+
+/* This function requires the caller holds hdev->lock */
 struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
                                            bdaddr_t *addr, u8 addr_type)
 {
@@ -2297,14 +2323,15 @@ struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev,
        return params;
 }
 
-static void hci_conn_params_free(struct hci_conn_params *params)
+void hci_conn_params_free(struct hci_conn_params *params)
 {
+       hci_pend_le_list_del_init(params);
+
        if (params->conn) {
                hci_conn_drop(params->conn);
                hci_conn_put(params->conn);
        }
 
-       list_del(&params->action);
        list_del(&params->list);
        kfree(params);
 }
@@ -2342,8 +2369,7 @@ void hci_conn_params_clear_disabled(struct hci_dev *hdev)
                        continue;
                }
 
-               list_del(&params->list);
-               kfree(params);
+               hci_conn_params_free(params);
        }
 
        BT_DBG("All LE disabled connection parameters were removed");
index 95816a9..31ca320 100644 (file)
@@ -1564,7 +1564,7 @@ static u8 hci_cc_le_set_privacy_mode(struct hci_dev *hdev, void *data,
 
        params = hci_conn_params_lookup(hdev, &cp->bdaddr, cp->bdaddr_type);
        if (params)
-               params->privacy_mode = cp->mode;
+               WRITE_ONCE(params->privacy_mode, cp->mode);
 
        hci_dev_unlock(hdev);
 
@@ -2784,6 +2784,9 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
                        hci_enable_advertising(hdev);
                }
 
+               /* Inform sockets conn is gone before we delete it */
+               hci_disconn_cfm(conn, HCI_ERROR_UNSPECIFIED);
+
                goto done;
        }
 
@@ -2804,8 +2807,8 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
 
                case HCI_AUTO_CONN_DIRECT:
                case HCI_AUTO_CONN_ALWAYS:
-                       list_del_init(&params->action);
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_del_init(params);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                        break;
 
                default:
@@ -3423,8 +3426,8 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data,
 
                case HCI_AUTO_CONN_DIRECT:
                case HCI_AUTO_CONN_ALWAYS:
-                       list_del_init(&params->action);
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_del_init(params);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                        hci_update_passive_scan(hdev);
                        break;
 
@@ -5962,7 +5965,7 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
        params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
                                           conn->dst_type);
        if (params) {
-               list_del_init(&params->action);
+               hci_pend_le_list_del_init(params);
                if (params->conn) {
                        hci_conn_drop(params->conn);
                        hci_conn_put(params->conn);
index 8561616..4d1e32b 100644 (file)
@@ -2160,15 +2160,23 @@ static int hci_le_del_accept_list_sync(struct hci_dev *hdev,
        return 0;
 }
 
+struct conn_params {
+       bdaddr_t addr;
+       u8 addr_type;
+       hci_conn_flags_t flags;
+       u8 privacy_mode;
+};
+
 /* Adds connection to resolve list if needed.
  * Setting params to NULL programs local hdev->irk
  */
 static int hci_le_add_resolve_list_sync(struct hci_dev *hdev,
-                                       struct hci_conn_params *params)
+                                       struct conn_params *params)
 {
        struct hci_cp_le_add_to_resolv_list cp;
        struct smp_irk *irk;
        struct bdaddr_list_with_irk *entry;
+       struct hci_conn_params *p;
 
        if (!use_ll_privacy(hdev))
                return 0;
@@ -2203,6 +2211,16 @@ static int hci_le_add_resolve_list_sync(struct hci_dev *hdev,
        /* Default privacy mode is always Network */
        params->privacy_mode = HCI_NETWORK_PRIVACY;
 
+       rcu_read_lock();
+       p = hci_pend_le_action_lookup(&hdev->pend_le_conns,
+                                     &params->addr, params->addr_type);
+       if (!p)
+               p = hci_pend_le_action_lookup(&hdev->pend_le_reports,
+                                             &params->addr, params->addr_type);
+       if (p)
+               WRITE_ONCE(p->privacy_mode, HCI_NETWORK_PRIVACY);
+       rcu_read_unlock();
+
 done:
        if (hci_dev_test_flag(hdev, HCI_PRIVACY))
                memcpy(cp.local_irk, hdev->irk, 16);
@@ -2215,7 +2233,7 @@ done:
 
 /* Set Device Privacy Mode. */
 static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev,
-                                       struct hci_conn_params *params)
+                                       struct conn_params *params)
 {
        struct hci_cp_le_set_privacy_mode cp;
        struct smp_irk *irk;
@@ -2240,6 +2258,8 @@ static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev,
        bacpy(&cp.bdaddr, &irk->bdaddr);
        cp.mode = HCI_DEVICE_PRIVACY;
 
+       /* Note: params->privacy_mode is not updated since it is a copy */
+
        return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_PRIVACY_MODE,
                                     sizeof(cp), &cp, HCI_CMD_TIMEOUT);
 }
@@ -2249,7 +2269,7 @@ static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev,
  * properly set the privacy mode.
  */
 static int hci_le_add_accept_list_sync(struct hci_dev *hdev,
-                                      struct hci_conn_params *params,
+                                      struct conn_params *params,
                                       u8 *num_entries)
 {
        struct hci_cp_le_add_to_accept_list cp;
@@ -2447,6 +2467,52 @@ struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
        return __hci_cmd_sync_sk(hdev, opcode, 0, NULL, 0, HCI_CMD_TIMEOUT, sk);
 }
 
+static struct conn_params *conn_params_copy(struct list_head *list, size_t *n)
+{
+       struct hci_conn_params *params;
+       struct conn_params *p;
+       size_t i;
+
+       rcu_read_lock();
+
+       i = 0;
+       list_for_each_entry_rcu(params, list, action)
+               ++i;
+       *n = i;
+
+       rcu_read_unlock();
+
+       p = kvcalloc(*n, sizeof(struct conn_params), GFP_KERNEL);
+       if (!p)
+               return NULL;
+
+       rcu_read_lock();
+
+       i = 0;
+       list_for_each_entry_rcu(params, list, action) {
+               /* Racing adds are handled in next scan update */
+               if (i >= *n)
+                       break;
+
+               /* No hdev->lock, but: addr, addr_type are immutable.
+                * privacy_mode is only written by us or in
+                * hci_cc_le_set_privacy_mode that we wait for.
+                * We should be idempotent so MGMT updating flags
+                * while we are processing is OK.
+                */
+               bacpy(&p[i].addr, &params->addr);
+               p[i].addr_type = params->addr_type;
+               p[i].flags = READ_ONCE(params->flags);
+               p[i].privacy_mode = READ_ONCE(params->privacy_mode);
+               ++i;
+       }
+
+       rcu_read_unlock();
+
+       *n = i;
+       return p;
+}
+
 /* Device must not be scanning when updating the accept list.
  *
  * Update is done using the following sequence:
@@ -2466,11 +2532,12 @@ struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
  */
 static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
 {
-       struct hci_conn_params *params;
+       struct conn_params *params;
        struct bdaddr_list *b, *t;
        u8 num_entries = 0;
        bool pend_conn, pend_report;
        u8 filter_policy;
+       size_t i, n;
        int err;
 
        /* Pause advertising if resolving list can be used as controllers
@@ -2504,6 +2571,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
                if (hci_conn_hash_lookup_le(hdev, &b->bdaddr, b->bdaddr_type))
                        continue;
 
+               /* Pointers not dereferenced, no locks needed */
                pend_conn = hci_pend_le_action_lookup(&hdev->pend_le_conns,
                                                      &b->bdaddr,
                                                      b->bdaddr_type);
@@ -2532,23 +2600,50 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev)
         * available accept list entries in the controller, then
         * just abort and return filer policy value to not use the
         * accept list.
+        *
+        * The list and params may be mutated while we wait for events,
+        * so make a copy and iterate it.
         */
-       list_for_each_entry(params, &hdev->pend_le_conns, action) {
-               err = hci_le_add_accept_list_sync(hdev, params, &num_entries);
-               if (err)
+
+       params = conn_params_copy(&hdev->pend_le_conns, &n);
+       if (!params) {
+               err = -ENOMEM;
+               goto done;
+       }
+
+       for (i = 0; i < n; ++i) {
+               err = hci_le_add_accept_list_sync(hdev, &params[i],
+                                                 &num_entries);
+               if (err) {
+                       kvfree(params);
                        goto done;
+               }
        }
 
+       kvfree(params);
+
        /* After adding all new pending connections, walk through
         * the list of pending reports and also add these to the
         * accept list if there is still space. Abort if space runs out.
         */
-       list_for_each_entry(params, &hdev->pend_le_reports, action) {
-               err = hci_le_add_accept_list_sync(hdev, params, &num_entries);
-               if (err)
+
+       params = conn_params_copy(&hdev->pend_le_reports, &n);
+       if (!params) {
+               err = -ENOMEM;
+               goto done;
+       }
+
+       for (i = 0; i < n; ++i) {
+               err = hci_le_add_accept_list_sync(hdev, &params[i],
+                                                 &num_entries);
+               if (err) {
+                       kvfree(params);
                        goto done;
+               }
        }
 
+       kvfree(params);
+
        /* Use the allowlist unless the following conditions are all true:
         * - We are not currently suspending
         * - There are 1 or more ADV monitors registered and it's not offloaded
@@ -4837,12 +4932,12 @@ static void hci_pend_le_actions_clear(struct hci_dev *hdev)
        struct hci_conn_params *p;
 
        list_for_each_entry(p, &hdev->le_conn_params, list) {
+               hci_pend_le_list_del_init(p);
                if (p->conn) {
                        hci_conn_drop(p->conn);
                        hci_conn_put(p->conn);
                        p->conn = NULL;
                }
-               list_del_init(&p->action);
        }
 
        BT_DBG("All LE pending actions cleared");
index 0e6cc57..505d622 100644 (file)
@@ -123,8 +123,11 @@ static struct iso_conn *iso_conn_add(struct hci_conn *hcon)
 {
        struct iso_conn *conn = hcon->iso_data;
 
-       if (conn)
+       if (conn) {
+               if (!conn->hcon)
+                       conn->hcon = hcon;
                return conn;
+       }
 
        conn = kzalloc(sizeof(*conn), GFP_KERNEL);
        if (!conn)
@@ -300,14 +303,13 @@ static int iso_connect_bis(struct sock *sk)
                goto unlock;
        }
 
-       hci_dev_unlock(hdev);
-       hci_dev_put(hdev);
+       lock_sock(sk);
 
        err = iso_chan_add(conn, sk, NULL);
-       if (err)
-               return err;
-
-       lock_sock(sk);
+       if (err) {
+               release_sock(sk);
+               goto unlock;
+       }
 
        /* Update source addr of the socket */
        bacpy(&iso_pi(sk)->src, &hcon->src);
@@ -321,7 +323,6 @@ static int iso_connect_bis(struct sock *sk)
        }
 
        release_sock(sk);
-       return err;
 
 unlock:
        hci_dev_unlock(hdev);
@@ -389,14 +390,13 @@ static int iso_connect_cis(struct sock *sk)
                goto unlock;
        }
 
-       hci_dev_unlock(hdev);
-       hci_dev_put(hdev);
+       lock_sock(sk);
 
        err = iso_chan_add(conn, sk, NULL);
-       if (err)
-               return err;
-
-       lock_sock(sk);
+       if (err) {
+               release_sock(sk);
+               goto unlock;
+       }
 
        /* Update source addr of the socket */
        bacpy(&iso_pi(sk)->src, &hcon->src);
@@ -413,7 +413,6 @@ static int iso_connect_cis(struct sock *sk)
        }
 
        release_sock(sk);
-       return err;
 
 unlock:
        hci_dev_unlock(hdev);
@@ -1072,8 +1071,8 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
                            size_t len)
 {
        struct sock *sk = sock->sk;
-       struct iso_conn *conn = iso_pi(sk)->conn;
        struct sk_buff *skb, **frag;
+       size_t mtu;
        int err;
 
        BT_DBG("sock %p, sk %p", sock, sk);
@@ -1085,11 +1084,18 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
        if (msg->msg_flags & MSG_OOB)
                return -EOPNOTSUPP;
 
-       if (sk->sk_state != BT_CONNECTED)
+       lock_sock(sk);
+
+       if (sk->sk_state != BT_CONNECTED) {
+               release_sock(sk);
                return -ENOTCONN;
+       }
+
+       mtu = iso_pi(sk)->conn->hcon->hdev->iso_mtu;
+
+       release_sock(sk);
 
-       skb = bt_skb_sendmsg(sk, msg, len, conn->hcon->hdev->iso_mtu,
-                            HCI_ISO_DATA_HDR_SIZE, 0);
+       skb = bt_skb_sendmsg(sk, msg, len, mtu, HCI_ISO_DATA_HDR_SIZE, 0);
        if (IS_ERR(skb))
                return PTR_ERR(skb);
 
@@ -1102,8 +1108,7 @@ static int iso_sock_sendmsg(struct socket *sock, struct msghdr *msg,
        while (len) {
                struct sk_buff *tmp;
 
-               tmp = bt_skb_sendmsg(sk, msg, len, conn->hcon->hdev->iso_mtu,
-                                    0, 0);
+               tmp = bt_skb_sendmsg(sk, msg, len, mtu, 0, 0);
                if (IS_ERR(tmp)) {
                        kfree_skb(skb);
                        return PTR_ERR(tmp);
@@ -1158,15 +1163,19 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
        BT_DBG("sk %p", sk);
 
        if (test_and_clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+               lock_sock(sk);
                switch (sk->sk_state) {
                case BT_CONNECT2:
-                       lock_sock(sk);
                        iso_conn_defer_accept(pi->conn->hcon);
                        sk->sk_state = BT_CONFIG;
                        release_sock(sk);
                        return 0;
                case BT_CONNECT:
+                       release_sock(sk);
                        return iso_connect_cis(sk);
+               default:
+                       release_sock(sk);
+                       break;
                }
        }
 
index f7b2d09..d449803 100644 (file)
@@ -1297,15 +1297,15 @@ static void restart_le_actions(struct hci_dev *hdev)
                /* Needed for AUTO_OFF case where might not "really"
                 * have been powered off.
                 */
-               list_del_init(&p->action);
+               hci_pend_le_list_del_init(p);
 
                switch (p->auto_connect) {
                case HCI_AUTO_CONN_DIRECT:
                case HCI_AUTO_CONN_ALWAYS:
-                       list_add(&p->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_add(p, &hdev->pend_le_conns);
                        break;
                case HCI_AUTO_CONN_REPORT:
-                       list_add(&p->action, &hdev->pend_le_reports);
+                       hci_pend_le_list_add(p, &hdev->pend_le_reports);
                        break;
                default:
                        break;
@@ -5169,7 +5169,7 @@ static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
                goto unlock;
        }
 
-       params->flags = current_flags;
+       WRITE_ONCE(params->flags, current_flags);
        status = MGMT_STATUS_SUCCESS;
 
        /* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
@@ -7285,7 +7285,7 @@ static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err)
 
        bt_dev_dbg(hdev, "err %d", err);
 
-       memcpy(&rp.addr, &cp->addr.bdaddr, sizeof(rp.addr));
+       memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
 
        status = mgmt_status(err);
        if (status == MGMT_STATUS_SUCCESS) {
@@ -7580,7 +7580,7 @@ static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
        if (params->auto_connect == auto_connect)
                return 0;
 
-       list_del_init(&params->action);
+       hci_pend_le_list_del_init(params);
 
        switch (auto_connect) {
        case HCI_AUTO_CONN_DISABLED:
@@ -7589,18 +7589,18 @@ static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
                 * connect to device, keep connecting.
                 */
                if (params->explicit_connect)
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                break;
        case HCI_AUTO_CONN_REPORT:
                if (params->explicit_connect)
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                else
-                       list_add(&params->action, &hdev->pend_le_reports);
+                       hci_pend_le_list_add(params, &hdev->pend_le_reports);
                break;
        case HCI_AUTO_CONN_DIRECT:
        case HCI_AUTO_CONN_ALWAYS:
                if (!is_connected(hdev, addr, addr_type))
-                       list_add(&params->action, &hdev->pend_le_conns);
+                       hci_pend_le_list_add(params, &hdev->pend_le_conns);
                break;
        }
 
@@ -7823,9 +7823,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                        goto unlock;
                }
 
-               list_del(&params->action);
-               list_del(&params->list);
-               kfree(params);
+               hci_conn_params_free(params);
 
                device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
        } else {
@@ -7856,9 +7854,7 @@ static int remove_device(struct sock *sk, struct hci_dev *hdev,
                                p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
                                continue;
                        }
-                       list_del(&p->action);
-                       list_del(&p->list);
-                       kfree(p);
+                       hci_conn_params_free(p);
                }
 
                bt_dev_dbg(hdev, "All LE connection parameters were removed");
index cd1a27a..7762604 100644 (file)
@@ -126,8 +126,11 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon)
        struct hci_dev *hdev = hcon->hdev;
        struct sco_conn *conn = hcon->sco_data;
 
-       if (conn)
+       if (conn) {
+               if (!conn->hcon)
+                       conn->hcon = hcon;
                return conn;
+       }
 
        conn = kzalloc(sizeof(struct sco_conn), GFP_KERNEL);
        if (!conn)
@@ -268,21 +271,21 @@ static int sco_connect(struct sock *sk)
                goto unlock;
        }
 
-       hci_dev_unlock(hdev);
-       hci_dev_put(hdev);
-
        conn = sco_conn_add(hcon);
        if (!conn) {
                hci_conn_drop(hcon);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto unlock;
        }
 
-       err = sco_chan_add(conn, sk, NULL);
-       if (err)
-               return err;
-
        lock_sock(sk);
 
+       err = sco_chan_add(conn, sk, NULL);
+       if (err) {
+               release_sock(sk);
+               goto unlock;
+       }
+
        /* Update source addr of the socket */
        bacpy(&sco_pi(sk)->src, &hcon->src);
 
@@ -296,8 +299,6 @@ static int sco_connect(struct sock *sk)
 
        release_sock(sk);
 
-       return err;
-
 unlock:
        hci_dev_unlock(hdev);
        hci_dev_put(hdev);
index 9ba3568..9168114 100644 (file)
@@ -1526,6 +1526,12 @@ static int bcm_release(struct socket *sock)
 
        lock_sock(sk);
 
+#if IS_ENABLED(CONFIG_PROC_FS)
+       /* remove procfs entry */
+       if (net->can.bcmproc_dir && bo->bcm_proc_read)
+               remove_proc_entry(bo->procname, net->can.bcmproc_dir);
+#endif /* CONFIG_PROC_FS */
+
        list_for_each_entry_safe(op, next, &bo->tx_ops, list)
                bcm_remove_op(op);
 
@@ -1561,12 +1567,6 @@ static int bcm_release(struct socket *sock)
        list_for_each_entry_safe(op, next, &bo->rx_ops, list)
                bcm_remove_op(op);
 
-#if IS_ENABLED(CONFIG_PROC_FS)
-       /* remove procfs entry */
-       if (net->can.bcmproc_dir && bo->bcm_proc_read)
-               remove_proc_entry(bo->procname, net->can.bcmproc_dir);
-#endif /* CONFIG_PROC_FS */
-
        /* remove device reference */
        if (bo->bound) {
                bo->bound   = 0;
index 15c79b0..e10f593 100644 (file)
@@ -84,6 +84,7 @@ struct raw_sock {
        struct sock sk;
        int bound;
        int ifindex;
+       struct net_device *dev;
        struct list_head notifier;
        int loopback;
        int recv_own_msgs;
@@ -277,7 +278,7 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,
        if (!net_eq(dev_net(dev), sock_net(sk)))
                return;
 
-       if (ro->ifindex != dev->ifindex)
+       if (ro->dev != dev)
                return;
 
        switch (msg) {
@@ -292,6 +293,7 @@ static void raw_notify(struct raw_sock *ro, unsigned long msg,
 
                ro->ifindex = 0;
                ro->bound = 0;
+               ro->dev = NULL;
                ro->count = 0;
                release_sock(sk);
 
@@ -337,6 +339,7 @@ static int raw_init(struct sock *sk)
 
        ro->bound            = 0;
        ro->ifindex          = 0;
+       ro->dev              = NULL;
 
        /* set default filter to single entry dfilter */
        ro->dfilter.can_id   = 0;
@@ -383,21 +386,15 @@ static int raw_release(struct socket *sock)
        list_del(&ro->notifier);
        spin_unlock(&raw_notifier_lock);
 
+       rtnl_lock();
        lock_sock(sk);
 
        /* remove current filters & unregister */
        if (ro->bound) {
-               if (ro->ifindex) {
-                       struct net_device *dev;
-
-                       dev = dev_get_by_index(sock_net(sk), ro->ifindex);
-                       if (dev) {
-                               raw_disable_allfilters(dev_net(dev), dev, sk);
-                               dev_put(dev);
-                       }
-               } else {
+               if (ro->dev)
+                       raw_disable_allfilters(dev_net(ro->dev), ro->dev, sk);
+               else
                        raw_disable_allfilters(sock_net(sk), NULL, sk);
-               }
        }
 
        if (ro->count > 1)
@@ -405,6 +402,7 @@ static int raw_release(struct socket *sock)
 
        ro->ifindex = 0;
        ro->bound = 0;
+       ro->dev = NULL;
        ro->count = 0;
        free_percpu(ro->uniq);
 
@@ -412,6 +410,8 @@ static int raw_release(struct socket *sock)
        sock->sk = NULL;
 
        release_sock(sk);
+       rtnl_unlock();
+
        sock_put(sk);
 
        return 0;
@@ -422,6 +422,7 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        struct sockaddr_can *addr = (struct sockaddr_can *)uaddr;
        struct sock *sk = sock->sk;
        struct raw_sock *ro = raw_sk(sk);
+       struct net_device *dev = NULL;
        int ifindex;
        int err = 0;
        int notify_enetdown = 0;
@@ -431,14 +432,13 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        if (addr->can_family != AF_CAN)
                return -EINVAL;
 
+       rtnl_lock();
        lock_sock(sk);
 
        if (ro->bound && addr->can_ifindex == ro->ifindex)
                goto out;
 
        if (addr->can_ifindex) {
-               struct net_device *dev;
-
                dev = dev_get_by_index(sock_net(sk), addr->can_ifindex);
                if (!dev) {
                        err = -ENODEV;
@@ -467,26 +467,20 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        if (!err) {
                if (ro->bound) {
                        /* unregister old filters */
-                       if (ro->ifindex) {
-                               struct net_device *dev;
-
-                               dev = dev_get_by_index(sock_net(sk),
-                                                      ro->ifindex);
-                               if (dev) {
-                                       raw_disable_allfilters(dev_net(dev),
-                                                              dev, sk);
-                                       dev_put(dev);
-                               }
-                       } else {
+                       if (ro->dev)
+                               raw_disable_allfilters(dev_net(ro->dev),
+                                                      ro->dev, sk);
+                       else
                                raw_disable_allfilters(sock_net(sk), NULL, sk);
-                       }
                }
                ro->ifindex = ifindex;
                ro->bound = 1;
+               ro->dev = dev;
        }
 
  out:
        release_sock(sk);
+       rtnl_unlock();
 
        if (notify_enetdown) {
                sk->sk_err = ENETDOWN;
@@ -553,9 +547,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                rtnl_lock();
                lock_sock(sk);
 
-               if (ro->bound && ro->ifindex) {
-                       dev = dev_get_by_index(sock_net(sk), ro->ifindex);
-                       if (!dev) {
+               dev = ro->dev;
+               if (ro->bound && dev) {
+                       if (dev->reg_state != NETREG_REGISTERED) {
                                if (count > 1)
                                        kfree(filter);
                                err = -ENODEV;
@@ -596,7 +590,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                ro->count  = count;
 
  out_fil:
-               dev_put(dev);
                release_sock(sk);
                rtnl_unlock();
 
@@ -614,9 +607,9 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                rtnl_lock();
                lock_sock(sk);
 
-               if (ro->bound && ro->ifindex) {
-                       dev = dev_get_by_index(sock_net(sk), ro->ifindex);
-                       if (!dev) {
+               dev = ro->dev;
+               if (ro->bound && dev) {
+                       if (dev->reg_state != NETREG_REGISTERED) {
                                err = -ENODEV;
                                goto out_err;
                        }
@@ -640,7 +633,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname,
                ro->err_mask = err_mask;
 
  out_err:
-               dev_put(dev);
                release_sock(sk);
                rtnl_unlock();
 
@@ -873,7 +865,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
 
        skb->dev = dev;
        skb->priority = sk->sk_priority;
-       skb->mark = sk->sk_mark;
+       skb->mark = READ_ONCE(sk->sk_mark);
        skb->tstamp = sockc.transmit_time;
 
        skb_setup_tx_timestamp(skb, sockc.tsflags);
index cd7b0bf..5eb4898 100644 (file)
@@ -1123,6 +1123,7 @@ bool ceph_addr_is_blank(const struct ceph_entity_addr *addr)
                return true;
        }
 }
+EXPORT_SYMBOL(ceph_addr_is_blank);
 
 int ceph_addr_port(const struct ceph_entity_addr *addr)
 {
index d417253..cca7594 100644 (file)
@@ -496,8 +496,11 @@ bpf_sk_storage_diag_alloc(const struct nlattr *nla_stgs)
                return ERR_PTR(-EPERM);
 
        nla_for_each_nested(nla, nla_stgs, rem) {
-               if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD)
+               if (nla_type(nla) == SK_DIAG_BPF_STORAGE_REQ_MAP_FD) {
+                       if (nla_len(nla) != sizeof(u32))
+                               return ERR_PTR(-EINVAL);
                        nr_maps++;
+               }
        }
 
        diag = kzalloc(struct_size(diag, maps, nr_maps), GFP_KERNEL);
index 3ad4e03..aef25aa 100644 (file)
@@ -5140,13 +5140,17 @@ static int rtnl_bridge_setlink(struct sk_buff *skb, struct nlmsghdr *nlh,
        br_spec = nlmsg_find_attr(nlh, sizeof(struct ifinfomsg), IFLA_AF_SPEC);
        if (br_spec) {
                nla_for_each_nested(attr, br_spec, rem) {
-                       if (nla_type(attr) == IFLA_BRIDGE_FLAGS) {
+                       if (nla_type(attr) == IFLA_BRIDGE_FLAGS && !have_flags) {
                                if (nla_len(attr) < sizeof(flags))
                                        return -EINVAL;
 
                                have_flags = true;
                                flags = nla_get_u16(attr);
-                               break;
+                       }
+
+                       if (nla_type(attr) == IFLA_BRIDGE_MODE) {
+                               if (nla_len(attr) < sizeof(u16))
+                                       return -EINVAL;
                        }
                }
        }
index 9370fd5..6d4f28e 100644 (file)
@@ -429,6 +429,7 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen,
 {
        struct __kernel_sock_timeval tv;
        int err = sock_copy_user_timeval(&tv, optval, optlen, old_timeval);
+       long val;
 
        if (err)
                return err;
@@ -439,7 +440,7 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen,
        if (tv.tv_sec < 0) {
                static int warned __read_mostly;
 
-               *timeo_p = 0;
+               WRITE_ONCE(*timeo_p, 0);
                if (warned < 10 && net_ratelimit()) {
                        warned++;
                        pr_info("%s: `%s' (pid %d) tries to set negative timeout\n",
@@ -447,11 +448,12 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen,
                }
                return 0;
        }
-       *timeo_p = MAX_SCHEDULE_TIMEOUT;
-       if (tv.tv_sec == 0 && tv.tv_usec == 0)
-               return 0;
-       if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1))
-               *timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec, USEC_PER_SEC / HZ);
+       val = MAX_SCHEDULE_TIMEOUT;
+       if ((tv.tv_sec || tv.tv_usec) &&
+           (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1)))
+               val = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec,
+                                                   USEC_PER_SEC / HZ);
+       WRITE_ONCE(*timeo_p, val);
        return 0;
 }
 
@@ -804,7 +806,7 @@ EXPORT_SYMBOL(sock_no_linger);
 void sock_set_priority(struct sock *sk, u32 priority)
 {
        lock_sock(sk);
-       sk->sk_priority = priority;
+       WRITE_ONCE(sk->sk_priority, priority);
        release_sock(sk);
 }
 EXPORT_SYMBOL(sock_set_priority);
@@ -813,9 +815,9 @@ void sock_set_sndtimeo(struct sock *sk, s64 secs)
 {
        lock_sock(sk);
        if (secs && secs < MAX_SCHEDULE_TIMEOUT / HZ - 1)
-               sk->sk_sndtimeo = secs * HZ;
+               WRITE_ONCE(sk->sk_sndtimeo, secs * HZ);
        else
-               sk->sk_sndtimeo = MAX_SCHEDULE_TIMEOUT;
+               WRITE_ONCE(sk->sk_sndtimeo, MAX_SCHEDULE_TIMEOUT);
        release_sock(sk);
 }
 EXPORT_SYMBOL(sock_set_sndtimeo);
@@ -988,7 +990,7 @@ EXPORT_SYMBOL(sock_set_rcvbuf);
 static void __sock_set_mark(struct sock *sk, u32 val)
 {
        if (val != sk->sk_mark) {
-               sk->sk_mark = val;
+               WRITE_ONCE(sk->sk_mark, val);
                sk_dst_reset(sk);
        }
 }
@@ -1007,7 +1009,7 @@ static void sock_release_reserved_memory(struct sock *sk, int bytes)
        bytes = round_down(bytes, PAGE_SIZE);
 
        WARN_ON(bytes > sk->sk_reserved_mem);
-       sk->sk_reserved_mem -= bytes;
+       WRITE_ONCE(sk->sk_reserved_mem, sk->sk_reserved_mem - bytes);
        sk_mem_reclaim(sk);
 }
 
@@ -1044,7 +1046,8 @@ static int sock_reserve_memory(struct sock *sk, int bytes)
        }
        sk->sk_forward_alloc += pages << PAGE_SHIFT;
 
-       sk->sk_reserved_mem += pages << PAGE_SHIFT;
+       WRITE_ONCE(sk->sk_reserved_mem,
+                  sk->sk_reserved_mem + (pages << PAGE_SHIFT));
 
        return 0;
 }
@@ -1213,7 +1216,7 @@ set_sndbuf:
                if ((val >= 0 && val <= 6) ||
                    sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) ||
                    sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
-                       sk->sk_priority = val;
+                       WRITE_ONCE(sk->sk_priority, val);
                else
                        ret = -EPERM;
                break;
@@ -1438,7 +1441,8 @@ set_sndbuf:
                        cmpxchg(&sk->sk_pacing_status,
                                SK_PACING_NONE,
                                SK_PACING_NEEDED);
-               sk->sk_max_pacing_rate = ulval;
+               /* Pairs with READ_ONCE() from sk_getsockopt() */
+               WRITE_ONCE(sk->sk_max_pacing_rate, ulval);
                sk->sk_pacing_rate = min(sk->sk_pacing_rate, ulval);
                break;
                }
@@ -1533,7 +1537,9 @@ set_sndbuf:
                }
                if ((u8)val == SOCK_TXREHASH_DEFAULT)
                        val = READ_ONCE(sock_net(sk)->core.sysctl_txrehash);
-               /* Paired with READ_ONCE() in tcp_rtx_synack() */
+               /* Paired with READ_ONCE() in tcp_rtx_synack()
+                * and sk_getsockopt().
+                */
                WRITE_ONCE(sk->sk_txrehash, (u8)val);
                break;
 
@@ -1633,11 +1639,11 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case SO_SNDBUF:
-               v.val = sk->sk_sndbuf;
+               v.val = READ_ONCE(sk->sk_sndbuf);
                break;
 
        case SO_RCVBUF:
-               v.val = sk->sk_rcvbuf;
+               v.val = READ_ONCE(sk->sk_rcvbuf);
                break;
 
        case SO_REUSEADDR:
@@ -1679,7 +1685,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case SO_PRIORITY:
-               v.val = sk->sk_priority;
+               v.val = READ_ONCE(sk->sk_priority);
                break;
 
        case SO_LINGER:
@@ -1717,16 +1723,18 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
 
        case SO_RCVTIMEO_OLD:
        case SO_RCVTIMEO_NEW:
-               lv = sock_get_timeout(sk->sk_rcvtimeo, &v, SO_RCVTIMEO_OLD == optname);
+               lv = sock_get_timeout(READ_ONCE(sk->sk_rcvtimeo), &v,
+                                     SO_RCVTIMEO_OLD == optname);
                break;
 
        case SO_SNDTIMEO_OLD:
        case SO_SNDTIMEO_NEW:
-               lv = sock_get_timeout(sk->sk_sndtimeo, &v, SO_SNDTIMEO_OLD == optname);
+               lv = sock_get_timeout(READ_ONCE(sk->sk_sndtimeo), &v,
+                                     SO_SNDTIMEO_OLD == optname);
                break;
 
        case SO_RCVLOWAT:
-               v.val = sk->sk_rcvlowat;
+               v.val = READ_ONCE(sk->sk_rcvlowat);
                break;
 
        case SO_SNDLOWAT:
@@ -1843,7 +1851,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                                                         optval, optlen, len);
 
        case SO_MARK:
-               v.val = sk->sk_mark;
+               v.val = READ_ONCE(sk->sk_mark);
                break;
 
        case SO_RCVMARK:
@@ -1862,7 +1870,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                if (!sock->ops->set_peek_off)
                        return -EOPNOTSUPP;
 
-               v.val = sk->sk_peek_off;
+               v.val = READ_ONCE(sk->sk_peek_off);
                break;
        case SO_NOFCS:
                v.val = sock_flag(sk, SOCK_NOFCS);
@@ -1892,7 +1900,7 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
 
 #ifdef CONFIG_NET_RX_BUSY_POLL
        case SO_BUSY_POLL:
-               v.val = sk->sk_ll_usec;
+               v.val = READ_ONCE(sk->sk_ll_usec);
                break;
        case SO_PREFER_BUSY_POLL:
                v.val = READ_ONCE(sk->sk_prefer_busy_poll);
@@ -1900,12 +1908,14 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
 #endif
 
        case SO_MAX_PACING_RATE:
+               /* The READ_ONCE() pair with the WRITE_ONCE() in sk_setsockopt() */
                if (sizeof(v.ulval) != sizeof(v.val) && len >= sizeof(v.ulval)) {
                        lv = sizeof(v.ulval);
-                       v.ulval = sk->sk_max_pacing_rate;
+                       v.ulval = READ_ONCE(sk->sk_max_pacing_rate);
                } else {
                        /* 32bit version */
-                       v.val = min_t(unsigned long, sk->sk_max_pacing_rate, ~0U);
+                       v.val = min_t(unsigned long, ~0U,
+                                     READ_ONCE(sk->sk_max_pacing_rate));
                }
                break;
 
@@ -1973,11 +1983,12 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
                break;
 
        case SO_RESERVE_MEM:
-               v.val = sk->sk_reserved_mem;
+               v.val = READ_ONCE(sk->sk_reserved_mem);
                break;
 
        case SO_TXREHASH:
-               v.val = sk->sk_txrehash;
+               /* Paired with WRITE_ONCE() in sk_setsockopt() */
+               v.val = READ_ONCE(sk->sk_txrehash);
                break;
 
        default:
@@ -3168,7 +3179,7 @@ EXPORT_SYMBOL(__sk_mem_reclaim);
 
 int sk_set_peek_off(struct sock *sk, int val)
 {
-       sk->sk_peek_off = val;
+       WRITE_ONCE(sk->sk_peek_off, val);
        return 0;
 }
 EXPORT_SYMBOL_GPL(sk_set_peek_off);
index 19538d6..08ab108 100644 (file)
@@ -115,7 +115,6 @@ static void sock_map_sk_acquire(struct sock *sk)
        __acquires(&sk->sk_lock.slock)
 {
        lock_sock(sk);
-       preempt_disable();
        rcu_read_lock();
 }
 
@@ -123,7 +122,6 @@ static void sock_map_sk_release(struct sock *sk)
        __releases(&sk->sk_lock.slock)
 {
        rcu_read_unlock();
-       preempt_enable();
        release_sock(sk);
 }
 
index c0c4381..2e6b8c8 100644 (file)
@@ -980,7 +980,7 @@ static int dcbnl_bcn_setcfg(struct net_device *netdev, struct nlmsghdr *nlh,
                return -EOPNOTSUPP;
 
        ret = nla_parse_nested_deprecated(data, DCB_BCN_ATTR_MAX,
-                                         tb[DCB_ATTR_BCN], dcbnl_pfc_up_nest,
+                                         tb[DCB_ATTR_BCN], dcbnl_bcn_nest,
                                          NULL);
        if (ret)
                return ret;
index 7249ef2..d29d116 100644 (file)
@@ -238,8 +238,8 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req
                opt = ireq->ipv6_opt;
                if (!opt)
                        opt = rcu_dereference(np->opt);
-               err = ip6_xmit(sk, skb, &fl6, sk->sk_mark, opt, np->tclass,
-                              sk->sk_priority);
+               err = ip6_xmit(sk, skb, &fl6, READ_ONCE(sk->sk_mark), opt,
+                              np->tclass, sk->sk_priority);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
index 0ce8fd3..2f6195d 100644 (file)
@@ -1727,8 +1727,15 @@ int dsa_port_phylink_create(struct dsa_port *dp)
            ds->ops->phylink_mac_an_restart)
                dp->pl_config.legacy_pre_march2020 = true;
 
-       if (ds->ops->phylink_get_caps)
+       if (ds->ops->phylink_get_caps) {
                ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config);
+       } else {
+               /* For legacy drivers */
+               __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+                         dp->pl_config.supported_interfaces);
+               __set_bit(PHY_INTERFACE_MODE_GMII,
+                         dp->pl_config.supported_interfaces);
+       }
 
        pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn),
                            mode, &dsa_port_phylink_mac_ops);
index ba06ed4..2be2d49 100644 (file)
@@ -1132,7 +1132,7 @@ static int esp_init_authenc(struct xfrm_state *x,
        err = crypto_aead_setkey(aead, key, keylen);
 
 free_key:
-       kfree(key);
+       kfree_sensitive(key);
 
 error:
        return err;
index 0cc19cf..aeebe88 100644 (file)
@@ -1019,7 +1019,7 @@ static void reqsk_timer_handler(struct timer_list *t)
 
        icsk = inet_csk(sk_listener);
        net = sock_net(sk_listener);
-       max_syn_ack_retries = icsk->icsk_syn_retries ? :
+       max_syn_ack_retries = READ_ONCE(icsk->icsk_syn_retries) ? :
                READ_ONCE(net->ipv4.sysctl_tcp_synack_retries);
        /* Normally all the openreqs are young and become mature
         * (i.e. converted to established socket) for first timeout.
index b812eb3..f742692 100644 (file)
@@ -150,7 +150,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
        }
 #endif
 
-       if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark))
+       if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, READ_ONCE(sk->sk_mark)))
                goto errout;
 
        if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) ||
@@ -799,7 +799,7 @@ int inet_diag_bc_sk(const struct nlattr *bc, struct sock *sk)
        entry.ifindex = sk->sk_bound_dev_if;
        entry.userlocks = sk_fullsock(sk) ? sk->sk_userlocks : 0;
        if (sk_fullsock(sk))
-               entry.mark = sk->sk_mark;
+               entry.mark = READ_ONCE(sk->sk_mark);
        else if (sk->sk_state == TCP_NEW_SYN_RECV)
                entry.mark = inet_rsk(inet_reqsk(sk))->ir_mark;
        else if (sk->sk_state == TCP_TIME_WAIT)
index e7391bf..0819d60 100644 (file)
@@ -650,20 +650,8 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
        spin_lock(lock);
        if (osk) {
                WARN_ON_ONCE(sk->sk_hash != osk->sk_hash);
-               ret = sk_hashed(osk);
-               if (ret) {
-                       /* Before deleting the node, we insert a new one to make
-                        * sure that the look-up-sk process would not miss either
-                        * of them and that at least one node would exist in ehash
-                        * table all the time. Otherwise there's a tiny chance
-                        * that lookup process could find nothing in ehash table.
-                        */
-                       __sk_nulls_add_node_tail_rcu(sk, list);
-                       sk_nulls_del_node_init_rcu(osk);
-               }
-               goto unlock;
-       }
-       if (found_dup_sk) {
+               ret = sk_nulls_del_node_init_rcu(osk);
+       } else if (found_dup_sk) {
                *found_dup_sk = inet_ehash_lookup_by_sk(sk, list);
                if (*found_dup_sk)
                        ret = false;
@@ -672,7 +660,6 @@ bool inet_ehash_insert(struct sock *sk, struct sock *osk, bool *found_dup_sk)
        if (ret)
                __sk_nulls_add_node_rcu(sk, list);
 
-unlock:
        spin_unlock(lock);
 
        return ret;
index 4005241..2c1b245 100644 (file)
@@ -88,10 +88,10 @@ void inet_twsk_put(struct inet_timewait_sock *tw)
 }
 EXPORT_SYMBOL_GPL(inet_twsk_put);
 
-static void inet_twsk_add_node_tail_rcu(struct inet_timewait_sock *tw,
-                                       struct hlist_nulls_head *list)
+static void inet_twsk_add_node_rcu(struct inet_timewait_sock *tw,
+                                  struct hlist_nulls_head *list)
 {
-       hlist_nulls_add_tail_rcu(&tw->tw_node, list);
+       hlist_nulls_add_head_rcu(&tw->tw_node, list);
 }
 
 static void inet_twsk_add_bind_node(struct inet_timewait_sock *tw,
@@ -144,7 +144,7 @@ void inet_twsk_hashdance(struct inet_timewait_sock *tw, struct sock *sk,
 
        spin_lock(lock);
 
-       inet_twsk_add_node_tail_rcu(tw, &ehead->chain);
+       inet_twsk_add_node_rcu(tw, &ehead->chain);
 
        /* Step 3: Remove SK from hash chain */
        if (__sk_nulls_del_node_init_rcu(sk))
index 81a1cce..22a26d1 100644 (file)
@@ -548,7 +548,8 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
                goto err_free_skb;
 
        if (skb->len > dev->mtu + dev->hard_header_len) {
-               pskb_trim(skb, dev->mtu + dev->hard_header_len);
+               if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+                       goto err_free_skb;
                truncate = true;
        }
 
@@ -689,7 +690,8 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
                goto free_skb;
 
        if (skb->len > dev->mtu + dev->hard_header_len) {
-               pskb_trim(skb, dev->mtu + dev->hard_header_len);
+               if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+                       goto free_skb;
                truncate = true;
        }
 
index 6e70839..6ba1a0f 100644 (file)
@@ -184,9 +184,9 @@ int ip_build_and_send_pkt(struct sk_buff *skb, const struct sock *sk,
                ip_options_build(skb, &opt->opt, daddr, rt);
        }
 
-       skb->priority = sk->sk_priority;
+       skb->priority = READ_ONCE(sk->sk_priority);
        if (!skb->mark)
-               skb->mark = sk->sk_mark;
+               skb->mark = READ_ONCE(sk->sk_mark);
 
        /* Send it out. */
        return ip_local_out(net, skb->sk, skb);
@@ -528,8 +528,8 @@ packet_routed:
                             skb_shinfo(skb)->gso_segs ?: 1);
 
        /* TODO : should we use skb->sk here instead of sk ? */
-       skb->priority = sk->sk_priority;
-       skb->mark = sk->sk_mark;
+       skb->priority = READ_ONCE(sk->sk_priority);
+       skb->mark = READ_ONCE(sk->sk_mark);
 
        res = ip_local_out(net, sk, skb);
        rcu_read_unlock();
@@ -1158,10 +1158,15 @@ alloc_new_skb:
                        }
 
                        copy = datalen - transhdrlen - fraggap - pagedlen;
+                       /* [!] NOTE: copy will be negative if pagedlen>0
+                        * because then the equation reduces to -fraggap.
+                        */
                        if (copy > 0 && getfrag(from, data + transhdrlen, offset, copy, fraggap, skb) < 0) {
                                err = -EFAULT;
                                kfree_skb(skb);
                                goto error;
+                       } else if (flags & MSG_SPLICE_PAGES) {
+                               copy = 0;
                        }
 
                        offset += copy;
@@ -1209,6 +1214,10 @@ alloc_new_skb:
                } else if (flags & MSG_SPLICE_PAGES) {
                        struct msghdr *msg = from;
 
+                       err = -EIO;
+                       if (WARN_ON_ONCE(copy > msg->msg_iter.count))
+                               goto error;
+
                        err = skb_splice_from_iter(skb, &msg->msg_iter, copy,
                                                   sk->sk_allocation);
                        if (err < 0)
index 8e97d8d..d41bce8 100644 (file)
@@ -592,7 +592,7 @@ void __ip_sock_set_tos(struct sock *sk, int val)
        }
        if (inet_sk(sk)->tos != val) {
                inet_sk(sk)->tos = val;
-               sk->sk_priority = rt_tos2priority(val);
+               WRITE_ONCE(sk->sk_priority, rt_tos2priority(val));
                sk_dst_reset(sk);
        }
 }
index 7782ff5..cb381f5 100644 (file)
@@ -348,7 +348,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
                goto error;
        skb_reserve(skb, hlen);
 
-       skb->priority = sk->sk_priority;
+       skb->priority = READ_ONCE(sk->sk_priority);
        skb->mark = sockc->mark;
        skb->tstamp = sockc->transmit_time;
        skb_dst_set(skb, &rt->dst);
index 98d7e6b..92fede3 100644 (file)
@@ -518,7 +518,7 @@ static void __build_flow_key(const struct net *net, struct flowi4 *fl4,
                const struct inet_sock *inet = inet_sk(sk);
 
                oif = sk->sk_bound_dev_if;
-               mark = sk->sk_mark;
+               mark = READ_ONCE(sk->sk_mark);
                tos = ip_sock_rt_tos(sk);
                scope = ip_sock_rt_scope(sk);
                prot = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol;
@@ -552,7 +552,7 @@ static void build_sk_flow_key(struct flowi4 *fl4, const struct sock *sk)
        inet_opt = rcu_dereference(inet->inet_opt);
        if (inet_opt && inet_opt->opt.srr)
                daddr = inet_opt->opt.faddr;
-       flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark,
+       flowi4_init_output(fl4, sk->sk_bound_dev_if, READ_ONCE(sk->sk_mark),
                           ip_sock_rt_tos(sk) & IPTOS_RT_MASK,
                           ip_sock_rt_scope(sk),
                           inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol,
index e03e087..8ed52e1 100644 (file)
@@ -3291,7 +3291,7 @@ int tcp_sock_set_syncnt(struct sock *sk, int val)
                return -EINVAL;
 
        lock_sock(sk);
-       inet_csk(sk)->icsk_syn_retries = val;
+       WRITE_ONCE(inet_csk(sk)->icsk_syn_retries, val);
        release_sock(sk);
        return 0;
 }
@@ -3300,7 +3300,7 @@ EXPORT_SYMBOL(tcp_sock_set_syncnt);
 void tcp_sock_set_user_timeout(struct sock *sk, u32 val)
 {
        lock_sock(sk);
-       inet_csk(sk)->icsk_user_timeout = val;
+       WRITE_ONCE(inet_csk(sk)->icsk_user_timeout, val);
        release_sock(sk);
 }
 EXPORT_SYMBOL(tcp_sock_set_user_timeout);
@@ -3312,7 +3312,8 @@ int tcp_sock_set_keepidle_locked(struct sock *sk, int val)
        if (val < 1 || val > MAX_TCP_KEEPIDLE)
                return -EINVAL;
 
-       tp->keepalive_time = val * HZ;
+       /* Paired with WRITE_ONCE() in keepalive_time_when() */
+       WRITE_ONCE(tp->keepalive_time, val * HZ);
        if (sock_flag(sk, SOCK_KEEPOPEN) &&
            !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) {
                u32 elapsed = keepalive_time_elapsed(tp);
@@ -3344,7 +3345,7 @@ int tcp_sock_set_keepintvl(struct sock *sk, int val)
                return -EINVAL;
 
        lock_sock(sk);
-       tcp_sk(sk)->keepalive_intvl = val * HZ;
+       WRITE_ONCE(tcp_sk(sk)->keepalive_intvl, val * HZ);
        release_sock(sk);
        return 0;
 }
@@ -3356,7 +3357,8 @@ int tcp_sock_set_keepcnt(struct sock *sk, int val)
                return -EINVAL;
 
        lock_sock(sk);
-       tcp_sk(sk)->keepalive_probes = val;
+       /* Paired with READ_ONCE() in keepalive_probes() */
+       WRITE_ONCE(tcp_sk(sk)->keepalive_probes, val);
        release_sock(sk);
        return 0;
 }
@@ -3558,19 +3560,19 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                if (val < 1 || val > MAX_TCP_KEEPINTVL)
                        err = -EINVAL;
                else
-                       tp->keepalive_intvl = val * HZ;
+                       WRITE_ONCE(tp->keepalive_intvl, val * HZ);
                break;
        case TCP_KEEPCNT:
                if (val < 1 || val > MAX_TCP_KEEPCNT)
                        err = -EINVAL;
                else
-                       tp->keepalive_probes = val;
+                       WRITE_ONCE(tp->keepalive_probes, val);
                break;
        case TCP_SYNCNT:
                if (val < 1 || val > MAX_TCP_SYNCNT)
                        err = -EINVAL;
                else
-                       icsk->icsk_syn_retries = val;
+                       WRITE_ONCE(icsk->icsk_syn_retries, val);
                break;
 
        case TCP_SAVE_SYN:
@@ -3583,18 +3585,18 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
 
        case TCP_LINGER2:
                if (val < 0)
-                       tp->linger2 = -1;
+                       WRITE_ONCE(tp->linger2, -1);
                else if (val > TCP_FIN_TIMEOUT_MAX / HZ)
-                       tp->linger2 = TCP_FIN_TIMEOUT_MAX;
+                       WRITE_ONCE(tp->linger2, TCP_FIN_TIMEOUT_MAX);
                else
-                       tp->linger2 = val * HZ;
+                       WRITE_ONCE(tp->linger2, val * HZ);
                break;
 
        case TCP_DEFER_ACCEPT:
                /* Translate value in seconds to number of retransmits */
-               icsk->icsk_accept_queue.rskq_defer_accept =
-                       secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
-                                       TCP_RTO_MAX / HZ);
+               WRITE_ONCE(icsk->icsk_accept_queue.rskq_defer_accept,
+                          secs_to_retrans(val, TCP_TIMEOUT_INIT / HZ,
+                                          TCP_RTO_MAX / HZ));
                break;
 
        case TCP_WINDOW_CLAMP:
@@ -3618,7 +3620,7 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                if (val < 0)
                        err = -EINVAL;
                else
-                       icsk->icsk_user_timeout = val;
+                       WRITE_ONCE(icsk->icsk_user_timeout, val);
                break;
 
        case TCP_FASTOPEN:
@@ -3656,13 +3658,13 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
                if (!tp->repair)
                        err = -EPERM;
                else
-                       tp->tsoffset = val - tcp_time_stamp_raw();
+                       WRITE_ONCE(tp->tsoffset, val - tcp_time_stamp_raw());
                break;
        case TCP_REPAIR_WINDOW:
                err = tcp_repair_set_window(tp, optval, optlen);
                break;
        case TCP_NOTSENT_LOWAT:
-               tp->notsent_lowat = val;
+               WRITE_ONCE(tp->notsent_lowat, val);
                sk->sk_write_space(sk);
                break;
        case TCP_INQ:
@@ -3674,7 +3676,7 @@ int do_tcp_setsockopt(struct sock *sk, int level, int optname,
        case TCP_TX_DELAY:
                if (val)
                        tcp_enable_tx_delay();
-               tp->tcp_tx_delay = val;
+               WRITE_ONCE(tp->tcp_tx_delay, val);
                break;
        default:
                err = -ENOPROTOOPT;
@@ -3991,17 +3993,18 @@ int do_tcp_getsockopt(struct sock *sk, int level,
                val = keepalive_probes(tp);
                break;
        case TCP_SYNCNT:
-               val = icsk->icsk_syn_retries ? :
+               val = READ_ONCE(icsk->icsk_syn_retries) ? :
                        READ_ONCE(net->ipv4.sysctl_tcp_syn_retries);
                break;
        case TCP_LINGER2:
-               val = tp->linger2;
+               val = READ_ONCE(tp->linger2);
                if (val >= 0)
                        val = (val ? : READ_ONCE(net->ipv4.sysctl_tcp_fin_timeout)) / HZ;
                break;
        case TCP_DEFER_ACCEPT:
-               val = retrans_to_secs(icsk->icsk_accept_queue.rskq_defer_accept,
-                                     TCP_TIMEOUT_INIT / HZ, TCP_RTO_MAX / HZ);
+               val = READ_ONCE(icsk->icsk_accept_queue.rskq_defer_accept);
+               val = retrans_to_secs(val, TCP_TIMEOUT_INIT / HZ,
+                                     TCP_RTO_MAX / HZ);
                break;
        case TCP_WINDOW_CLAMP:
                val = tp->window_clamp;
@@ -4138,11 +4141,11 @@ int do_tcp_getsockopt(struct sock *sk, int level,
                break;
 
        case TCP_USER_TIMEOUT:
-               val = icsk->icsk_user_timeout;
+               val = READ_ONCE(icsk->icsk_user_timeout);
                break;
 
        case TCP_FASTOPEN:
-               val = icsk->icsk_accept_queue.fastopenq.max_qlen;
+               val = READ_ONCE(icsk->icsk_accept_queue.fastopenq.max_qlen);
                break;
 
        case TCP_FASTOPEN_CONNECT:
@@ -4154,14 +4157,14 @@ int do_tcp_getsockopt(struct sock *sk, int level,
                break;
 
        case TCP_TX_DELAY:
-               val = tp->tcp_tx_delay;
+               val = READ_ONCE(tp->tcp_tx_delay);
                break;
 
        case TCP_TIMESTAMP:
-               val = tcp_time_stamp_raw() + tp->tsoffset;
+               val = tcp_time_stamp_raw() + READ_ONCE(tp->tsoffset);
                break;
        case TCP_NOTSENT_LOWAT:
-               val = tp->notsent_lowat;
+               val = READ_ONCE(tp->notsent_lowat);
                break;
        case TCP_INQ:
                val = tp->recvmsg_inq;
index 45cc7f1..85e4953 100644 (file)
@@ -296,6 +296,7 @@ static struct sock *tcp_fastopen_create_child(struct sock *sk,
 static bool tcp_fastopen_queue_check(struct sock *sk)
 {
        struct fastopen_queue *fastopenq;
+       int max_qlen;
 
        /* Make sure the listener has enabled fastopen, and we don't
         * exceed the max # of pending TFO requests allowed before trying
@@ -308,10 +309,11 @@ static bool tcp_fastopen_queue_check(struct sock *sk)
         * temporarily vs a server not supporting Fast Open at all.
         */
        fastopenq = &inet_csk(sk)->icsk_accept_queue.fastopenq;
-       if (fastopenq->max_qlen == 0)
+       max_qlen = READ_ONCE(fastopenq->max_qlen);
+       if (max_qlen == 0)
                return false;
 
-       if (fastopenq->qlen >= fastopenq->max_qlen) {
+       if (fastopenq->qlen >= max_qlen) {
                struct request_sock *req1;
                spin_lock(&fastopenq->lock);
                req1 = fastopenq->rskq_rst_head;
index fd365de..a59cc4b 100644 (file)
@@ -307,8 +307,9 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                                                  inet->inet_daddr,
                                                  inet->inet_sport,
                                                  usin->sin_port));
-               tp->tsoffset = secure_tcp_ts_off(net, inet->inet_saddr,
-                                                inet->inet_daddr);
+               WRITE_ONCE(tp->tsoffset,
+                          secure_tcp_ts_off(net, inet->inet_saddr,
+                                            inet->inet_daddr));
        }
 
        inet->inet_id = get_random_u16();
@@ -930,9 +931,9 @@ static void tcp_v4_send_ack(const struct sock *sk,
        ctl_sk = this_cpu_read(ipv4_tcp_sk);
        sock_net_set(ctl_sk, net);
        ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
-                          inet_twsk(sk)->tw_mark : sk->sk_mark;
+                          inet_twsk(sk)->tw_mark : READ_ONCE(sk->sk_mark);
        ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ?
-                          inet_twsk(sk)->tw_priority : sk->sk_priority;
+                          inet_twsk(sk)->tw_priority : READ_ONCE(sk->sk_priority);
        transmit_time = tcp_transmit_time(sk);
        ip_send_unicast_reply(ctl_sk,
                              skb, &TCP_SKB_CB(skb)->header.h4.opt,
@@ -988,11 +989,12 @@ static void tcp_v4_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
                        tcp_rsk(req)->rcv_nxt,
                        req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
                        tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
-                       req->ts_recent,
+                       READ_ONCE(req->ts_recent),
                        0,
                        tcp_md5_do_lookup(sk, l3index, addr, AF_INET),
                        inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0,
-                       ip_hdr(skb)->tos, tcp_rsk(req)->txhash);
+                       ip_hdr(skb)->tos,
+                       READ_ONCE(tcp_rsk(req)->txhash));
 }
 
 /*
index 82f4575..99ac5ef 100644 (file)
@@ -40,7 +40,7 @@ struct tcp_fastopen_metrics {
 
 struct tcp_metrics_block {
        struct tcp_metrics_block __rcu  *tcpm_next;
-       possible_net_t                  tcpm_net;
+       struct net                      *tcpm_net;
        struct inetpeer_addr            tcpm_saddr;
        struct inetpeer_addr            tcpm_daddr;
        unsigned long                   tcpm_stamp;
@@ -51,34 +51,38 @@ struct tcp_metrics_block {
        struct rcu_head                 rcu_head;
 };
 
-static inline struct net *tm_net(struct tcp_metrics_block *tm)
+static inline struct net *tm_net(const struct tcp_metrics_block *tm)
 {
-       return read_pnet(&tm->tcpm_net);
+       /* Paired with the WRITE_ONCE() in tcpm_new() */
+       return READ_ONCE(tm->tcpm_net);
 }
 
 static bool tcp_metric_locked(struct tcp_metrics_block *tm,
                              enum tcp_metric_index idx)
 {
-       return tm->tcpm_lock & (1 << idx);
+       /* Paired with WRITE_ONCE() in tcpm_suck_dst() */
+       return READ_ONCE(tm->tcpm_lock) & (1 << idx);
 }
 
-static u32 tcp_metric_get(struct tcp_metrics_block *tm,
+static u32 tcp_metric_get(const struct tcp_metrics_block *tm,
                          enum tcp_metric_index idx)
 {
-       return tm->tcpm_vals[idx];
+       /* Paired with WRITE_ONCE() in tcp_metric_set() */
+       return READ_ONCE(tm->tcpm_vals[idx]);
 }
 
 static void tcp_metric_set(struct tcp_metrics_block *tm,
                           enum tcp_metric_index idx,
                           u32 val)
 {
-       tm->tcpm_vals[idx] = val;
+       /* Paired with READ_ONCE() in tcp_metric_get() */
+       WRITE_ONCE(tm->tcpm_vals[idx], val);
 }
 
 static bool addr_same(const struct inetpeer_addr *a,
                      const struct inetpeer_addr *b)
 {
-       return inetpeer_addr_cmp(a, b) == 0;
+       return (a->family == b->family) && !inetpeer_addr_cmp(a, b);
 }
 
 struct tcpm_hash_bucket {
@@ -89,6 +93,7 @@ static struct tcpm_hash_bucket        *tcp_metrics_hash __read_mostly;
 static unsigned int            tcp_metrics_hash_log __read_mostly;
 
 static DEFINE_SPINLOCK(tcp_metrics_lock);
+static DEFINE_SEQLOCK(fastopen_seqlock);
 
 static void tcpm_suck_dst(struct tcp_metrics_block *tm,
                          const struct dst_entry *dst,
@@ -97,7 +102,7 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm,
        u32 msval;
        u32 val;
 
-       tm->tcpm_stamp = jiffies;
+       WRITE_ONCE(tm->tcpm_stamp, jiffies);
 
        val = 0;
        if (dst_metric_locked(dst, RTAX_RTT))
@@ -110,30 +115,42 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm,
                val |= 1 << TCP_METRIC_CWND;
        if (dst_metric_locked(dst, RTAX_REORDERING))
                val |= 1 << TCP_METRIC_REORDERING;
-       tm->tcpm_lock = val;
+       /* Paired with READ_ONCE() in tcp_metric_locked() */
+       WRITE_ONCE(tm->tcpm_lock, val);
 
        msval = dst_metric_raw(dst, RTAX_RTT);
-       tm->tcpm_vals[TCP_METRIC_RTT] = msval * USEC_PER_MSEC;
+       tcp_metric_set(tm, TCP_METRIC_RTT, msval * USEC_PER_MSEC);
 
        msval = dst_metric_raw(dst, RTAX_RTTVAR);
-       tm->tcpm_vals[TCP_METRIC_RTTVAR] = msval * USEC_PER_MSEC;
-       tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH);
-       tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND);
-       tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING);
+       tcp_metric_set(tm, TCP_METRIC_RTTVAR, msval * USEC_PER_MSEC);
+       tcp_metric_set(tm, TCP_METRIC_SSTHRESH,
+                      dst_metric_raw(dst, RTAX_SSTHRESH));
+       tcp_metric_set(tm, TCP_METRIC_CWND,
+                      dst_metric_raw(dst, RTAX_CWND));
+       tcp_metric_set(tm, TCP_METRIC_REORDERING,
+                      dst_metric_raw(dst, RTAX_REORDERING));
        if (fastopen_clear) {
+               write_seqlock(&fastopen_seqlock);
                tm->tcpm_fastopen.mss = 0;
                tm->tcpm_fastopen.syn_loss = 0;
                tm->tcpm_fastopen.try_exp = 0;
                tm->tcpm_fastopen.cookie.exp = false;
                tm->tcpm_fastopen.cookie.len = 0;
+               write_sequnlock(&fastopen_seqlock);
        }
 }
 
 #define TCP_METRICS_TIMEOUT            (60 * 60 * HZ)
 
-static void tcpm_check_stamp(struct tcp_metrics_block *tm, struct dst_entry *dst)
+static void tcpm_check_stamp(struct tcp_metrics_block *tm,
+                            const struct dst_entry *dst)
 {
-       if (tm && unlikely(time_after(jiffies, tm->tcpm_stamp + TCP_METRICS_TIMEOUT)))
+       unsigned long limit;
+
+       if (!tm)
+               return;
+       limit = READ_ONCE(tm->tcpm_stamp) + TCP_METRICS_TIMEOUT;
+       if (unlikely(time_after(jiffies, limit)))
                tcpm_suck_dst(tm, dst, false);
 }
 
@@ -174,20 +191,23 @@ static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
                oldest = deref_locked(tcp_metrics_hash[hash].chain);
                for (tm = deref_locked(oldest->tcpm_next); tm;
                     tm = deref_locked(tm->tcpm_next)) {
-                       if (time_before(tm->tcpm_stamp, oldest->tcpm_stamp))
+                       if (time_before(READ_ONCE(tm->tcpm_stamp),
+                                       READ_ONCE(oldest->tcpm_stamp)))
                                oldest = tm;
                }
                tm = oldest;
        } else {
-               tm = kmalloc(sizeof(*tm), GFP_ATOMIC);
+               tm = kzalloc(sizeof(*tm), GFP_ATOMIC);
                if (!tm)
                        goto out_unlock;
        }
-       write_pnet(&tm->tcpm_net, net);
+       /* Paired with the READ_ONCE() in tm_net() */
+       WRITE_ONCE(tm->tcpm_net, net);
+
        tm->tcpm_saddr = *saddr;
        tm->tcpm_daddr = *daddr;
 
-       tcpm_suck_dst(tm, dst, true);
+       tcpm_suck_dst(tm, dst, reclaim);
 
        if (likely(!reclaim)) {
                tm->tcpm_next = tcp_metrics_hash[hash].chain;
@@ -434,7 +454,7 @@ void tcp_update_metrics(struct sock *sk)
                                               tp->reordering);
                }
        }
-       tm->tcpm_stamp = jiffies;
+       WRITE_ONCE(tm->tcpm_stamp, jiffies);
 out_unlock:
        rcu_read_unlock();
 }
@@ -539,8 +559,6 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst)
        return ret;
 }
 
-static DEFINE_SEQLOCK(fastopen_seqlock);
-
 void tcp_fastopen_cache_get(struct sock *sk, u16 *mss,
                            struct tcp_fastopen_cookie *cookie)
 {
@@ -647,7 +665,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
        }
 
        if (nla_put_msecs(msg, TCP_METRICS_ATTR_AGE,
-                         jiffies - tm->tcpm_stamp,
+                         jiffies - READ_ONCE(tm->tcpm_stamp),
                          TCP_METRICS_ATTR_PAD) < 0)
                goto nla_put_failure;
 
@@ -658,7 +676,7 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
                if (!nest)
                        goto nla_put_failure;
                for (i = 0; i < TCP_METRIC_MAX_KERNEL + 1; i++) {
-                       u32 val = tm->tcpm_vals[i];
+                       u32 val = tcp_metric_get(tm, i);
 
                        if (!val)
                                continue;
index 04fc328..c8f2aa0 100644 (file)
@@ -528,7 +528,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
        newicsk->icsk_ack.lrcvtime = tcp_jiffies32;
 
        newtp->lsndtime = tcp_jiffies32;
-       newsk->sk_txhash = treq->txhash;
+       newsk->sk_txhash = READ_ONCE(treq->txhash);
        newtp->total_retrans = req->num_retrans;
 
        tcp_init_xmit_timers(newsk);
@@ -555,7 +555,7 @@ struct sock *tcp_create_openreq_child(const struct sock *sk,
        newtp->max_window = newtp->snd_wnd;
 
        if (newtp->rx_opt.tstamp_ok) {
-               newtp->rx_opt.ts_recent = req->ts_recent;
+               newtp->rx_opt.ts_recent = READ_ONCE(req->ts_recent);
                newtp->rx_opt.ts_recent_stamp = ktime_get_seconds();
                newtp->tcp_header_len = sizeof(struct tcphdr) + TCPOLEN_TSTAMP_ALIGNED;
        } else {
@@ -619,7 +619,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
                tcp_parse_options(sock_net(sk), skb, &tmp_opt, 0, NULL);
 
                if (tmp_opt.saw_tstamp) {
-                       tmp_opt.ts_recent = req->ts_recent;
+                       tmp_opt.ts_recent = READ_ONCE(req->ts_recent);
                        if (tmp_opt.rcv_tsecr)
                                tmp_opt.rcv_tsecr -= tcp_rsk(req)->ts_off;
                        /* We do not store true stamp, but it is not required,
@@ -758,8 +758,11 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb,
 
        /* In sequence, PAWS is OK. */
 
+       /* TODO: We probably should defer ts_recent change once
+        * we take ownership of @req.
+        */
        if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_nxt))
-               req->ts_recent = tmp_opt.rcv_tsval;
+               WRITE_ONCE(req->ts_recent, tmp_opt.rcv_tsval);
 
        if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) {
                /* Truncate SYN, it is out of window starting
index 2cb39b6..51d8638 100644 (file)
@@ -878,7 +878,7 @@ static unsigned int tcp_synack_options(const struct sock *sk,
        if (likely(ireq->tstamp_ok)) {
                opts->options |= OPTION_TS;
                opts->tsval = tcp_skb_timestamp(skb) + tcp_rsk(req)->ts_off;
-               opts->tsecr = req->ts_recent;
+               opts->tsecr = READ_ONCE(req->ts_recent);
                remaining -= TCPOLEN_TSTAMP_ALIGNED;
        }
        if (likely(ireq->sack_ok)) {
@@ -3660,7 +3660,7 @@ struct sk_buff *tcp_make_synack(const struct sock *sk, struct dst_entry *dst,
        rcu_read_lock();
        md5 = tcp_rsk(req)->af_specific->req_md5_lookup(sk, req_to_sk(req));
 #endif
-       skb_set_hash(skb, tcp_rsk(req)->txhash, PKT_HASH_TYPE_L4);
+       skb_set_hash(skb, READ_ONCE(tcp_rsk(req)->txhash), PKT_HASH_TYPE_L4);
        /* bpf program will be interested in the tcp_flags */
        TCP_SKB_CB(skb)->tcp_flags = TCPHDR_SYN | TCPHDR_ACK;
        tcp_header_size = tcp_synack_options(sk, req, mss, skb, &opts, md5,
@@ -4210,7 +4210,7 @@ int tcp_rtx_synack(const struct sock *sk, struct request_sock *req)
 
        /* Paired with WRITE_ONCE() in sock_setsockopt() */
        if (READ_ONCE(sk->sk_txrehash) == SOCK_TXREHASH_ENABLED)
-               tcp_rsk(req)->txhash = net_tx_rndhash();
+               WRITE_ONCE(tcp_rsk(req)->txhash, net_tx_rndhash());
        res = af_ops->send_synack(sk, NULL, &fl, req, NULL, TCP_SYNACK_NORMAL,
                                  NULL);
        if (!res) {
index 42a96b3..abfa860 100644 (file)
 #include <net/sock_reuseport.h>
 #include <net/addrconf.h>
 #include <net/udp_tunnel.h>
+#include <net/gro.h>
 #if IS_ENABLED(CONFIG_IPV6)
 #include <net/ipv6_stubs.h>
 #endif
@@ -555,10 +556,13 @@ struct sock *udp4_lib_lookup_skb(const struct sk_buff *skb,
 {
        const struct iphdr *iph = ip_hdr(skb);
        struct net *net = dev_net(skb->dev);
+       int iif, sdif;
+
+       inet_get_iif_sdif(skb, &iif, &sdif);
 
        return __udp4_lib_lookup(net, iph->saddr, sport,
-                                iph->daddr, dport, inet_iif(skb),
-                                inet_sdif(skb), net->ipv4.udp_table, NULL);
+                                iph->daddr, dport, iif,
+                                sdif, net->ipv4.udp_table, NULL);
 }
 
 /* Must be called under rcu_read_lock().
index 75aa4de..0f46b3c 100644 (file)
@@ -274,13 +274,20 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,
        __sum16 check;
        __be16 newlen;
 
-       if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST)
-               return __udp_gso_segment_list(gso_skb, features, is_ipv6);
-
        mss = skb_shinfo(gso_skb)->gso_size;
        if (gso_skb->len <= sizeof(*uh) + mss)
                return ERR_PTR(-EINVAL);
 
+       if (skb_gso_ok(gso_skb, features | NETIF_F_GSO_ROBUST)) {
+               /* Packet is from an untrusted source, reset gso_segs. */
+               skb_shinfo(gso_skb)->gso_segs = DIV_ROUND_UP(gso_skb->len - sizeof(*uh),
+                                                            mss);
+               return NULL;
+       }
+
+       if (skb_shinfo(gso_skb)->gso_type & SKB_GSO_FRAGLIST)
+               return __udp_gso_segment_list(gso_skb, features, is_ipv6);
+
        skb_pull(gso_skb, sizeof(*uh));
 
        /* clear destructor to avoid skb_segment assigning it to tail */
@@ -388,8 +395,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
        if (!pskb_may_pull(skb, sizeof(struct udphdr)))
                goto out;
 
-       if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
-           !skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
+       if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
                return __udp_gso_segment(skb, features, false);
 
        mss = skb_shinfo(skb)->gso_size;
@@ -603,10 +609,13 @@ static struct sock *udp4_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
 {
        const struct iphdr *iph = skb_gro_network_header(skb);
        struct net *net = dev_net(skb->dev);
+       int iif, sdif;
+
+       inet_get_iif_sdif(skb, &iif, &sdif);
 
        return __udp4_lib_lookup(net, iph->saddr, sport,
-                                iph->daddr, dport, inet_iif(skb),
-                                inet_sdif(skb), net->ipv4.udp_table, NULL);
+                                iph->daddr, dport, iif,
+                                sdif, net->ipv4.udp_table, NULL);
 }
 
 INDIRECT_CALLABLE_SCOPE
index e5213e5..94cec20 100644 (file)
@@ -2561,12 +2561,18 @@ static void manage_tempaddrs(struct inet6_dev *idev,
                        ipv6_ifa_notify(0, ift);
        }
 
-       if ((create || list_empty(&idev->tempaddr_list)) &&
-           idev->cnf.use_tempaddr > 0) {
+       /* Also create a temporary address if it's enabled but no temporary
+        * address currently exists.
+        * However, we get called with valid_lft == 0, prefered_lft == 0, create == false
+        * as part of cleanup (ie. deleting the mngtmpaddr).
+        * We don't want that to result in creating a new temporary ip address.
+        */
+       if (list_empty(&idev->tempaddr_list) && (valid_lft || prefered_lft))
+               create = true;
+
+       if (create && idev->cnf.use_tempaddr > 0) {
                /* When a new public address is created as described
                 * in [ADDRCONF], also create a new temporary address.
-                * Also create a temporary address if it's enabled but
-                * no temporary address currently exists.
                 */
                read_unlock_bh(&idev->lock);
                ipv6_create_tempaddr(ifp, false);
index da80974..070d87a 100644 (file)
@@ -955,7 +955,8 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
                goto tx_err;
 
        if (skb->len > dev->mtu + dev->hard_header_len) {
-               pskb_trim(skb, dev->mtu + dev->hard_header_len);
+               if (pskb_trim(skb, dev->mtu + dev->hard_header_len))
+                       goto tx_err;
                truncate = true;
        }
 
index cc3d5ad..67a3b8f 100644 (file)
@@ -1073,7 +1073,7 @@ static int ip6mr_cache_report(const struct mr_table *mrt, struct sk_buff *pkt,
                   And all this only to mangle msg->im6_msgtype and
                   to set msg->im6_mbz to "mbz" :-)
                 */
-               skb_push(skb, -skb_network_offset(pkt));
+               __skb_pull(skb, skb_network_offset(pkt));
 
                skb_push(skb, sizeof(*msg));
                skb_reset_transport_header(skb);
index f804c11..c2c2918 100644 (file)
@@ -120,7 +120,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
 
        ipcm6_init_sk(&ipc6, np);
        ipc6.sockc.tsflags = sk->sk_tsflags;
-       ipc6.sockc.mark = sk->sk_mark;
+       ipc6.sockc.mark = READ_ONCE(sk->sk_mark);
 
        fl6.flowi6_oif = oif;
 
index ac1cef0..49381f3 100644 (file)
@@ -614,7 +614,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
        skb_reserve(skb, hlen);
 
        skb->protocol = htons(ETH_P_IPV6);
-       skb->priority = sk->sk_priority;
+       skb->priority = READ_ONCE(sk->sk_priority);
        skb->mark = sockc->mark;
        skb->tstamp = sockc->transmit_time;
 
@@ -774,12 +774,12 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
         */
        memset(&fl6, 0, sizeof(fl6));
 
-       fl6.flowi6_mark = sk->sk_mark;
+       fl6.flowi6_mark = READ_ONCE(sk->sk_mark);
        fl6.flowi6_uid = sk->sk_uid;
 
        ipcm6_init(&ipc6);
        ipc6.sockc.tsflags = sk->sk_tsflags;
-       ipc6.sockc.mark = sk->sk_mark;
+       ipc6.sockc.mark = fl6.flowi6_mark;
 
        if (sin6) {
                if (addr_len < SIN6_LEN_RFC2133)
index 64e873f..56a5558 100644 (file)
@@ -2951,7 +2951,8 @@ void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, __be32 mtu)
        if (!oif && skb->dev)
                oif = l3mdev_master_ifindex(skb->dev);
 
-       ip6_update_pmtu(skb, sock_net(sk), mtu, oif, sk->sk_mark, sk->sk_uid);
+       ip6_update_pmtu(skb, sock_net(sk), mtu, oif, READ_ONCE(sk->sk_mark),
+                       sk->sk_uid);
 
        dst = __sk_dst_get(sk);
        if (!dst || !dst->obsolete ||
@@ -3172,8 +3173,8 @@ void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif)
 
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
-       ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark,
-                    sk->sk_uid);
+       ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if,
+                    READ_ONCE(sk->sk_mark), sk->sk_uid);
 }
 EXPORT_SYMBOL_GPL(ip6_sk_redirect);
 
index 40dd92a..6e86721 100644 (file)
@@ -564,8 +564,8 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
                opt = ireq->ipv6_opt;
                if (!opt)
                        opt = rcu_dereference(np->opt);
-               err = ip6_xmit(sk, skb, fl6, skb->mark ? : sk->sk_mark, opt,
-                              tclass, sk->sk_priority);
+               err = ip6_xmit(sk, skb, fl6, skb->mark ? : READ_ONCE(sk->sk_mark),
+                              opt, tclass, sk->sk_priority);
                rcu_read_unlock();
                err = net_xmit_eval(err);
        }
@@ -939,7 +939,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
                if (sk->sk_state == TCP_TIME_WAIT)
                        mark = inet_twsk(sk)->tw_mark;
                else
-                       mark = sk->sk_mark;
+                       mark = READ_ONCE(sk->sk_mark);
                skb_set_delivery_time(buff, tcp_transmit_time(sk), true);
        }
        if (txhash) {
@@ -1126,10 +1126,11 @@ static void tcp_v6_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
                        tcp_rsk(req)->rcv_nxt,
                        req->rsk_rcv_wnd >> inet_rsk(req)->rcv_wscale,
                        tcp_time_stamp_raw() + tcp_rsk(req)->ts_off,
-                       req->ts_recent, sk->sk_bound_dev_if,
+                       READ_ONCE(req->ts_recent), sk->sk_bound_dev_if,
                        tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr, l3index),
-                       ipv6_get_dsfield(ipv6_hdr(skb)), 0, sk->sk_priority,
-                       tcp_rsk(req)->txhash);
+                       ipv6_get_dsfield(ipv6_hdr(skb)), 0,
+                       READ_ONCE(sk->sk_priority),
+                       READ_ONCE(tcp_rsk(req)->txhash));
 }
 
 
index b7c972a..f787e6b 100644 (file)
@@ -51,6 +51,7 @@
 #include <net/inet6_hashtables.h>
 #include <net/busy_poll.h>
 #include <net/sock_reuseport.h>
+#include <net/gro.h>
 
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
@@ -300,10 +301,13 @@ struct sock *udp6_lib_lookup_skb(const struct sk_buff *skb,
 {
        const struct ipv6hdr *iph = ipv6_hdr(skb);
        struct net *net = dev_net(skb->dev);
+       int iif, sdif;
+
+       inet6_get_iif_sdif(skb, &iif, &sdif);
 
        return __udp6_lib_lookup(net, &iph->saddr, sport,
-                                &iph->daddr, dport, inet6_iif(skb),
-                                inet6_sdif(skb), net->ipv4.udp_table, NULL);
+                                &iph->daddr, dport, iif,
+                                sdif, net->ipv4.udp_table, NULL);
 }
 
 /* Must be called under rcu_read_lock().
@@ -624,7 +628,7 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        if (type == NDISC_REDIRECT) {
                if (tunnel) {
                        ip6_redirect(skb, sock_net(sk), inet6_iif(skb),
-                                    sk->sk_mark, sk->sk_uid);
+                                    READ_ONCE(sk->sk_mark), sk->sk_uid);
                } else {
                        ip6_sk_redirect(skb, sk);
                }
@@ -1356,7 +1360,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        ipcm6_init(&ipc6);
        ipc6.gso_size = READ_ONCE(up->gso_size);
        ipc6.sockc.tsflags = sk->sk_tsflags;
-       ipc6.sockc.mark = sk->sk_mark;
+       ipc6.sockc.mark = READ_ONCE(sk->sk_mark);
 
        /* destination address check */
        if (sin6) {
index ad3b872..6b95ba2 100644 (file)
@@ -43,8 +43,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
                if (!pskb_may_pull(skb, sizeof(struct udphdr)))
                        goto out;
 
-               if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4 &&
-                   !skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
+               if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP_L4)
                        return __udp_gso_segment(skb, features, true);
 
                mss = skb_shinfo(skb)->gso_size;
@@ -119,10 +118,13 @@ static struct sock *udp6_gro_lookup_skb(struct sk_buff *skb, __be16 sport,
 {
        const struct ipv6hdr *iph = skb_gro_network_header(skb);
        struct net *net = dev_net(skb->dev);
+       int iif, sdif;
+
+       inet6_get_iif_sdif(skb, &iif, &sdif);
 
        return __udp6_lib_lookup(net, &iph->saddr, sport,
-                                &iph->daddr, dport, inet6_iif(skb),
-                                inet6_sdif(skb), net->ipv4.udp_table, NULL);
+                                &iph->daddr, dport, iif,
+                                sdif, net->ipv4.udp_table, NULL);
 }
 
 INDIRECT_CALLABLE_SCOPE
index b1623f9..ff78217 100644 (file)
@@ -519,7 +519,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
        /* Get and verify the address */
        memset(&fl6, 0, sizeof(fl6));
 
-       fl6.flowi6_mark = sk->sk_mark;
+       fl6.flowi6_mark = READ_ONCE(sk->sk_mark);
        fl6.flowi6_uid = sk->sk_uid;
 
        ipcm6_init(&ipc6);
index 57c35c9..9b06c38 100644 (file)
@@ -402,7 +402,7 @@ static int llc_ui_bind(struct socket *sock, struct sockaddr *uaddr, int addrlen)
                memcpy(laddr.mac, addr->sllc_mac, IFHWADDRLEN);
                laddr.lsap = addr->sllc_sap;
                rc = -EADDRINUSE; /* mac + sap clash. */
-               ask = llc_lookup_established(sap, &daddr, &laddr);
+               ask = llc_lookup_established(sap, &daddr, &laddr, &init_net);
                if (ask) {
                        sock_put(ask);
                        goto out_put;
index 912aa9b..d037009 100644 (file)
@@ -453,11 +453,13 @@ static int llc_exec_conn_trans_actions(struct sock *sk,
 static inline bool llc_estab_match(const struct llc_sap *sap,
                                   const struct llc_addr *daddr,
                                   const struct llc_addr *laddr,
-                                  const struct sock *sk)
+                                  const struct sock *sk,
+                                  const struct net *net)
 {
        struct llc_sock *llc = llc_sk(sk);
 
-       return llc->laddr.lsap == laddr->lsap &&
+       return net_eq(sock_net(sk), net) &&
+               llc->laddr.lsap == laddr->lsap &&
                llc->daddr.lsap == daddr->lsap &&
                ether_addr_equal(llc->laddr.mac, laddr->mac) &&
                ether_addr_equal(llc->daddr.mac, daddr->mac);
@@ -468,6 +470,7 @@ static inline bool llc_estab_match(const struct llc_sap *sap,
  *     @sap: SAP
  *     @daddr: address of remote LLC (MAC + SAP)
  *     @laddr: address of local LLC (MAC + SAP)
+ *     @net: netns to look up a socket in
  *
  *     Search connection list of the SAP and finds connection using the remote
  *     mac, remote sap, local mac, and local sap. Returns pointer for
@@ -476,7 +479,8 @@ static inline bool llc_estab_match(const struct llc_sap *sap,
  */
 static struct sock *__llc_lookup_established(struct llc_sap *sap,
                                             struct llc_addr *daddr,
-                                            struct llc_addr *laddr)
+                                            struct llc_addr *laddr,
+                                            const struct net *net)
 {
        struct sock *rc;
        struct hlist_nulls_node *node;
@@ -486,12 +490,12 @@ static struct sock *__llc_lookup_established(struct llc_sap *sap,
        rcu_read_lock();
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
-               if (llc_estab_match(sap, daddr, laddr, rc)) {
+               if (llc_estab_match(sap, daddr, laddr, rc, net)) {
                        /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
-                                    !llc_estab_match(sap, daddr, laddr, rc))) {
+                                    !llc_estab_match(sap, daddr, laddr, rc, net))) {
                                sock_put(rc);
                                continue;
                        }
@@ -513,29 +517,33 @@ found:
 
 struct sock *llc_lookup_established(struct llc_sap *sap,
                                    struct llc_addr *daddr,
-                                   struct llc_addr *laddr)
+                                   struct llc_addr *laddr,
+                                   const struct net *net)
 {
        struct sock *sk;
 
        local_bh_disable();
-       sk = __llc_lookup_established(sap, daddr, laddr);
+       sk = __llc_lookup_established(sap, daddr, laddr, net);
        local_bh_enable();
        return sk;
 }
 
 static inline bool llc_listener_match(const struct llc_sap *sap,
                                      const struct llc_addr *laddr,
-                                     const struct sock *sk)
+                                     const struct sock *sk,
+                                     const struct net *net)
 {
        struct llc_sock *llc = llc_sk(sk);
 
-       return sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN &&
+       return net_eq(sock_net(sk), net) &&
+               sk->sk_type == SOCK_STREAM && sk->sk_state == TCP_LISTEN &&
                llc->laddr.lsap == laddr->lsap &&
                ether_addr_equal(llc->laddr.mac, laddr->mac);
 }
 
 static struct sock *__llc_lookup_listener(struct llc_sap *sap,
-                                         struct llc_addr *laddr)
+                                         struct llc_addr *laddr,
+                                         const struct net *net)
 {
        struct sock *rc;
        struct hlist_nulls_node *node;
@@ -545,12 +553,12 @@ static struct sock *__llc_lookup_listener(struct llc_sap *sap,
        rcu_read_lock();
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
-               if (llc_listener_match(sap, laddr, rc)) {
+               if (llc_listener_match(sap, laddr, rc, net)) {
                        /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
-                                    !llc_listener_match(sap, laddr, rc))) {
+                                    !llc_listener_match(sap, laddr, rc, net))) {
                                sock_put(rc);
                                continue;
                        }
@@ -574,6 +582,7 @@ found:
  *     llc_lookup_listener - Finds listener for local MAC + SAP
  *     @sap: SAP
  *     @laddr: address of local LLC (MAC + SAP)
+ *     @net: netns to look up a socket in
  *
  *     Search connection list of the SAP and finds connection listening on
  *     local mac, and local sap. Returns pointer for parent socket found,
@@ -581,24 +590,26 @@ found:
  *     Caller has to make sure local_bh is disabled.
  */
 static struct sock *llc_lookup_listener(struct llc_sap *sap,
-                                       struct llc_addr *laddr)
+                                       struct llc_addr *laddr,
+                                       const struct net *net)
 {
+       struct sock *rc = __llc_lookup_listener(sap, laddr, net);
        static struct llc_addr null_addr;
-       struct sock *rc = __llc_lookup_listener(sap, laddr);
 
        if (!rc)
-               rc = __llc_lookup_listener(sap, &null_addr);
+               rc = __llc_lookup_listener(sap, &null_addr, net);
 
        return rc;
 }
 
 static struct sock *__llc_lookup(struct llc_sap *sap,
                                 struct llc_addr *daddr,
-                                struct llc_addr *laddr)
+                                struct llc_addr *laddr,
+                                const struct net *net)
 {
-       struct sock *sk = __llc_lookup_established(sap, daddr, laddr);
+       struct sock *sk = __llc_lookup_established(sap, daddr, laddr, net);
 
-       return sk ? : llc_lookup_listener(sap, laddr);
+       return sk ? : llc_lookup_listener(sap, laddr, net);
 }
 
 /**
@@ -776,7 +787,7 @@ void llc_conn_handler(struct llc_sap *sap, struct sk_buff *skb)
        llc_pdu_decode_da(skb, daddr.mac);
        llc_pdu_decode_dsap(skb, &daddr.lsap);
 
-       sk = __llc_lookup(sap, &saddr, &daddr);
+       sk = __llc_lookup(sap, &saddr, &daddr, dev_net(skb->dev));
        if (!sk)
                goto drop;
 
index dde9bf0..58a5f41 100644 (file)
@@ -92,7 +92,7 @@ int llc_establish_connection(struct sock *sk, const u8 *lmac, u8 *dmac, u8 dsap)
        daddr.lsap = dsap;
        memcpy(daddr.mac, dmac, sizeof(daddr.mac));
        memcpy(laddr.mac, lmac, sizeof(laddr.mac));
-       existing = llc_lookup_established(llc->sap, &daddr, &laddr);
+       existing = llc_lookup_established(llc->sap, &daddr, &laddr, sock_net(sk));
        if (existing) {
                if (existing->sk_state == TCP_ESTABLISHED) {
                        sk = existing;
index c309b72..7cac441 100644 (file)
@@ -163,9 +163,6 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev,
        void (*sta_handler)(struct sk_buff *skb);
        void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb);
 
-       if (!net_eq(dev_net(dev), &init_net))
-               goto drop;
-
        /*
         * When the interface is in promisc. mode, drop all the crap that it
         * receives, do not try to analyse it.
index 6805ce4..116c0e4 100644 (file)
@@ -294,25 +294,29 @@ static void llc_sap_rcv(struct llc_sap *sap, struct sk_buff *skb,
 
 static inline bool llc_dgram_match(const struct llc_sap *sap,
                                   const struct llc_addr *laddr,
-                                  const struct sock *sk)
+                                  const struct sock *sk,
+                                  const struct net *net)
 {
      struct llc_sock *llc = llc_sk(sk);
 
      return sk->sk_type == SOCK_DGRAM &&
-         llc->laddr.lsap == laddr->lsap &&
-         ether_addr_equal(llc->laddr.mac, laddr->mac);
+            net_eq(sock_net(sk), net) &&
+            llc->laddr.lsap == laddr->lsap &&
+            ether_addr_equal(llc->laddr.mac, laddr->mac);
 }
 
 /**
  *     llc_lookup_dgram - Finds dgram socket for the local sap/mac
  *     @sap: SAP
  *     @laddr: address of local LLC (MAC + SAP)
+ *     @net: netns to look up a socket in
  *
  *     Search socket list of the SAP and finds connection using the local
  *     mac, and local sap. Returns pointer for socket found, %NULL otherwise.
  */
 static struct sock *llc_lookup_dgram(struct llc_sap *sap,
-                                    const struct llc_addr *laddr)
+                                    const struct llc_addr *laddr,
+                                    const struct net *net)
 {
        struct sock *rc;
        struct hlist_nulls_node *node;
@@ -322,12 +326,12 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap,
        rcu_read_lock_bh();
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
-               if (llc_dgram_match(sap, laddr, rc)) {
+               if (llc_dgram_match(sap, laddr, rc, net)) {
                        /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!refcount_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
-                                    !llc_dgram_match(sap, laddr, rc))) {
+                                    !llc_dgram_match(sap, laddr, rc, net))) {
                                sock_put(rc);
                                continue;
                        }
@@ -429,7 +433,7 @@ void llc_sap_handler(struct llc_sap *sap, struct sk_buff *skb)
                llc_sap_mcast(sap, &laddr, skb);
                kfree_skb(skb);
        } else {
-               struct sock *sk = llc_lookup_dgram(sap, &laddr);
+               struct sock *sk = llc_lookup_dgram(sap, &laddr, dev_net(skb->dev));
                if (sk) {
                        llc_sap_rcv(sap, skb, sk);
                        sock_put(sk);
index 3613489..3317d1c 100644 (file)
@@ -3723,10 +3723,9 @@ static int mptcp_listen(struct socket *sock, int backlog)
        if (!err) {
                sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1);
                mptcp_copy_inaddrs(sk, ssock->sk);
+               mptcp_event_pm_listener(ssock->sk, MPTCP_EVENT_LISTENER_CREATED);
        }
 
-       mptcp_event_pm_listener(ssock->sk, MPTCP_EVENT_LISTENER_CREATED);
-
 unlock:
        release_sock(sk);
        return err;
index 63f7a09..a3f1fe8 100644 (file)
@@ -103,7 +103,7 @@ static void mptcp_sol_socket_sync_intval(struct mptcp_sock *msk, int optname, in
                        break;
                case SO_MARK:
                        if (READ_ONCE(ssk->sk_mark) != sk->sk_mark) {
-                               ssk->sk_mark = sk->sk_mark;
+                               WRITE_ONCE(ssk->sk_mark, sk->sk_mark);
                                sk_dst_reset(ssk);
                        }
                        break;
index 237f739..d3c6ecd 100644 (file)
@@ -3685,8 +3685,6 @@ int nft_chain_validate(const struct nft_ctx *ctx, const struct nft_chain *chain)
                        if (err < 0)
                                return err;
                }
-
-               cond_resched();
        }
 
        return 0;
@@ -3710,6 +3708,8 @@ static int nft_table_validate(struct net *net, const struct nft_table *table)
                err = nft_chain_validate(&ctx, chain);
                if (err < 0)
                        return err;
+
+               cond_resched();
        }
 
        return 0;
@@ -3811,8 +3811,6 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
                        NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN]);
                        return PTR_ERR(chain);
                }
-               if (nft_chain_is_bound(chain))
-                       return -EOPNOTSUPP;
 
        } else if (nla[NFTA_RULE_CHAIN_ID]) {
                chain = nft_chain_lookup_byid(net, table, nla[NFTA_RULE_CHAIN_ID],
@@ -3825,6 +3823,9 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
                return -EINVAL;
        }
 
+       if (nft_chain_is_bound(chain))
+               return -EOPNOTSUPP;
+
        if (nla[NFTA_RULE_HANDLE]) {
                handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_HANDLE]));
                rule = __nft_rule_lookup(chain, handle);
@@ -4087,6 +4088,8 @@ static int nf_tables_delrule(struct sk_buff *skb, const struct nfnl_info *info,
                list_for_each_entry(chain, &table->chains, list) {
                        if (!nft_is_active_next(net, chain))
                                continue;
+                       if (nft_chain_is_bound(chain))
+                               continue;
 
                        ctx.chain = chain;
                        err = nft_delrule_by_chain(&ctx);
@@ -10517,6 +10520,9 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
 
        if (!tb[NFTA_VERDICT_CODE])
                return -EINVAL;
+
+       /* zero padding hole for memcmp */
+       memset(data, 0, sizeof(*data));
        data->verdict.code = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE]));
 
        switch (data->verdict.code) {
@@ -10799,6 +10805,9 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
        ctx.family = table->family;
        ctx.table = table;
        list_for_each_entry(chain, &table->chains, list) {
+               if (nft_chain_is_bound(chain))
+                       continue;
+
                ctx.chain = chain;
                list_for_each_entry_safe(rule, nr, &chain->rules, list) {
                        list_del(&rule->list);
index 407d719..fccb3cf 100644 (file)
@@ -125,15 +125,27 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
        return nft_data_hold(&priv->data, nft_dreg_to_type(priv->dreg));
 }
 
+static void nft_immediate_chain_deactivate(const struct nft_ctx *ctx,
+                                          struct nft_chain *chain,
+                                          enum nft_trans_phase phase)
+{
+       struct nft_ctx chain_ctx;
+       struct nft_rule *rule;
+
+       chain_ctx = *ctx;
+       chain_ctx.chain = chain;
+
+       list_for_each_entry(rule, &chain->rules, list)
+               nft_rule_expr_deactivate(&chain_ctx, rule, phase);
+}
+
 static void nft_immediate_deactivate(const struct nft_ctx *ctx,
                                     const struct nft_expr *expr,
                                     enum nft_trans_phase phase)
 {
        const struct nft_immediate_expr *priv = nft_expr_priv(expr);
        const struct nft_data *data = &priv->data;
-       struct nft_ctx chain_ctx;
        struct nft_chain *chain;
-       struct nft_rule *rule;
 
        if (priv->dreg == NFT_REG_VERDICT) {
                switch (data->verdict.code) {
@@ -143,20 +155,17 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
                        if (!nft_chain_binding(chain))
                                break;
 
-                       chain_ctx = *ctx;
-                       chain_ctx.chain = chain;
-
-                       list_for_each_entry(rule, &chain->rules, list)
-                               nft_rule_expr_deactivate(&chain_ctx, rule, phase);
-
                        switch (phase) {
                        case NFT_TRANS_PREPARE_ERROR:
                                nf_tables_unbind_chain(ctx, chain);
-                               fallthrough;
+                               nft_deactivate_next(ctx->net, chain);
+                               break;
                        case NFT_TRANS_PREPARE:
+                               nft_immediate_chain_deactivate(ctx, chain, phase);
                                nft_deactivate_next(ctx->net, chain);
                                break;
                        default:
+                               nft_immediate_chain_deactivate(ctx, chain, phase);
                                nft_chain_del(chain);
                                chain->bound = false;
                                nft_use_dec(&chain->table->use);
index db526cb..49915a2 100644 (file)
@@ -1929,7 +1929,11 @@ static void nft_pipapo_remove(const struct net *net, const struct nft_set *set,
                int i, start, rules_fx;
 
                match_start = data;
-               match_end = (const u8 *)nft_set_ext_key_end(&e->ext)->data;
+
+               if (nft_set_ext_exists(&e->ext, NFT_SET_EXT_KEY_END))
+                       match_end = (const u8 *)nft_set_ext_key_end(&e->ext)->data;
+               else
+                       match_end = data;
 
                start = first_rule;
                rules_fx = rules_f0;
index 5c05c9b..8d73fff 100644 (file)
@@ -217,29 +217,37 @@ static void *nft_rbtree_get(const struct net *net, const struct nft_set *set,
 
 static int nft_rbtree_gc_elem(const struct nft_set *__set,
                              struct nft_rbtree *priv,
-                             struct nft_rbtree_elem *rbe)
+                             struct nft_rbtree_elem *rbe,
+                             u8 genmask)
 {
        struct nft_set *set = (struct nft_set *)__set;
        struct rb_node *prev = rb_prev(&rbe->node);
-       struct nft_rbtree_elem *rbe_prev = NULL;
+       struct nft_rbtree_elem *rbe_prev;
        struct nft_set_gc_batch *gcb;
 
        gcb = nft_set_gc_batch_check(set, NULL, GFP_ATOMIC);
        if (!gcb)
                return -ENOMEM;
 
-       /* search for expired end interval coming before this element. */
+       /* search for end interval coming before this element.
+        * end intervals don't carry a timeout extension, they
+        * are coupled with the interval start element.
+        */
        while (prev) {
                rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
-               if (nft_rbtree_interval_end(rbe_prev))
+               if (nft_rbtree_interval_end(rbe_prev) &&
+                   nft_set_elem_active(&rbe_prev->ext, genmask))
                        break;
 
                prev = rb_prev(prev);
        }
 
-       if (rbe_prev) {
+       if (prev) {
+               rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node);
+
                rb_erase(&rbe_prev->node, &priv->root);
                atomic_dec(&set->nelems);
+               nft_set_gc_batch_add(gcb, rbe_prev);
        }
 
        rb_erase(&rbe->node, &priv->root);
@@ -321,7 +329,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set,
 
                /* perform garbage collection to avoid bogus overlap reports. */
                if (nft_set_elem_expired(&rbe->ext)) {
-                       err = nft_rbtree_gc_elem(set, priv, rbe);
+                       err = nft_rbtree_gc_elem(set, priv, rbe, genmask);
                        if (err < 0)
                                return err;
 
index 84def74..9ed85be 100644 (file)
@@ -107,7 +107,7 @@ static void nft_socket_eval(const struct nft_expr *expr,
                break;
        case NFT_SOCKET_MARK:
                if (sk_fullsock(sk)) {
-                       *dest = sk->sk_mark;
+                       *dest = READ_ONCE(sk->sk_mark);
                } else {
                        regs->verdict.code = NFT_BREAK;
                        return;
index 7013f55..76e01f2 100644 (file)
@@ -77,7 +77,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
 
                if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
                    transparent && sk_fullsock(sk))
-                       pskb->mark = sk->sk_mark;
+                       pskb->mark = READ_ONCE(sk->sk_mark);
 
                if (sk != skb->sk)
                        sock_gen_put(sk);
@@ -138,7 +138,7 @@ socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
 
                if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
                    transparent && sk_fullsock(sk))
-                       pskb->mark = sk->sk_mark;
+                       pskb->mark = READ_ONCE(sk->sk_mark);
 
                if (sk != skb->sk)
                        sock_gen_put(sk);
index 85ff90a..a4631cb 100644 (file)
@@ -2050,8 +2050,8 @@ retry:
 
        skb->protocol = proto;
        skb->dev = dev;
-       skb->priority = sk->sk_priority;
-       skb->mark = sk->sk_mark;
+       skb->priority = READ_ONCE(sk->sk_priority);
+       skb->mark = READ_ONCE(sk->sk_mark);
        skb->tstamp = sockc.transmit_time;
 
        skb_setup_tx_timestamp(skb, sockc.tsflags);
@@ -2585,8 +2585,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
 
        skb->protocol = proto;
        skb->dev = dev;
-       skb->priority = po->sk.sk_priority;
-       skb->mark = po->sk.sk_mark;
+       skb->priority = READ_ONCE(po->sk.sk_priority);
+       skb->mark = READ_ONCE(po->sk.sk_mark);
        skb->tstamp = sockc->transmit_time;
        skb_setup_tx_timestamp(skb, sockc->tsflags);
        skb_zcopy_set_nouarg(skb, ph.raw);
@@ -2988,7 +2988,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                goto out_unlock;
 
        sockcm_init(&sockc, sk);
-       sockc.mark = sk->sk_mark;
+       sockc.mark = READ_ONCE(sk->sk_mark);
        if (msg->msg_controllen) {
                err = sock_cmsg_send(sk, msg, &sockc);
                if (unlikely(err))
@@ -3061,7 +3061,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
 
        skb->protocol = proto;
        skb->dev = dev;
-       skb->priority = sk->sk_priority;
+       skb->priority = READ_ONCE(sk->sk_priority);
        skb->mark = sockc.mark;
        skb->tstamp = sockc.transmit_time;
 
@@ -3601,7 +3601,7 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr,
        if (dev) {
                sll->sll_hatype = dev->type;
                sll->sll_halen = dev->addr_len;
-               memcpy(sll->sll_addr, dev->dev_addr, dev->addr_len);
+               memcpy(sll->sll_addr_flex, dev->dev_addr, dev->addr_len);
        } else {
                sll->sll_hatype = 0;    /* Bad: we have no ARPHRD_UNSPEC */
                sll->sll_halen = 0;
index 466c26d..382c7a7 100644 (file)
@@ -406,56 +406,6 @@ static int cls_bpf_prog_from_efd(struct nlattr **tb, struct cls_bpf_prog *prog,
        return 0;
 }
 
-static int cls_bpf_set_parms(struct net *net, struct tcf_proto *tp,
-                            struct cls_bpf_prog *prog, unsigned long base,
-                            struct nlattr **tb, struct nlattr *est, u32 flags,
-                            struct netlink_ext_ack *extack)
-{
-       bool is_bpf, is_ebpf, have_exts = false;
-       u32 gen_flags = 0;
-       int ret;
-
-       is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS];
-       is_ebpf = tb[TCA_BPF_FD];
-       if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf))
-               return -EINVAL;
-
-       ret = tcf_exts_validate(net, tp, tb, est, &prog->exts, flags,
-                               extack);
-       if (ret < 0)
-               return ret;
-
-       if (tb[TCA_BPF_FLAGS]) {
-               u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);
-
-               if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT)
-                       return -EINVAL;
-
-               have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
-       }
-       if (tb[TCA_BPF_FLAGS_GEN]) {
-               gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
-               if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
-                   !tc_flags_valid(gen_flags))
-                       return -EINVAL;
-       }
-
-       prog->exts_integrated = have_exts;
-       prog->gen_flags = gen_flags;
-
-       ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
-                      cls_bpf_prog_from_efd(tb, prog, gen_flags, tp);
-       if (ret < 0)
-               return ret;
-
-       if (tb[TCA_BPF_CLASSID]) {
-               prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
-               tcf_bind_filter(tp, &prog->res, base);
-       }
-
-       return 0;
-}
-
 static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
                          struct tcf_proto *tp, unsigned long base,
                          u32 handle, struct nlattr **tca,
@@ -463,9 +413,12 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
                          struct netlink_ext_ack *extack)
 {
        struct cls_bpf_head *head = rtnl_dereference(tp->root);
+       bool is_bpf, is_ebpf, have_exts = false;
        struct cls_bpf_prog *oldprog = *arg;
        struct nlattr *tb[TCA_BPF_MAX + 1];
+       bool bound_to_filter = false;
        struct cls_bpf_prog *prog;
+       u32 gen_flags = 0;
        int ret;
 
        if (tca[TCA_OPTIONS] == NULL)
@@ -504,11 +457,51 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
                goto errout;
        prog->handle = handle;
 
-       ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], flags,
-                               extack);
+       is_bpf = tb[TCA_BPF_OPS_LEN] && tb[TCA_BPF_OPS];
+       is_ebpf = tb[TCA_BPF_FD];
+       if ((!is_bpf && !is_ebpf) || (is_bpf && is_ebpf)) {
+               ret = -EINVAL;
+               goto errout_idr;
+       }
+
+       ret = tcf_exts_validate(net, tp, tb, tca[TCA_RATE], &prog->exts,
+                               flags, extack);
+       if (ret < 0)
+               goto errout_idr;
+
+       if (tb[TCA_BPF_FLAGS]) {
+               u32 bpf_flags = nla_get_u32(tb[TCA_BPF_FLAGS]);
+
+               if (bpf_flags & ~TCA_BPF_FLAG_ACT_DIRECT) {
+                       ret = -EINVAL;
+                       goto errout_idr;
+               }
+
+               have_exts = bpf_flags & TCA_BPF_FLAG_ACT_DIRECT;
+       }
+       if (tb[TCA_BPF_FLAGS_GEN]) {
+               gen_flags = nla_get_u32(tb[TCA_BPF_FLAGS_GEN]);
+               if (gen_flags & ~CLS_BPF_SUPPORTED_GEN_FLAGS ||
+                   !tc_flags_valid(gen_flags)) {
+                       ret = -EINVAL;
+                       goto errout_idr;
+               }
+       }
+
+       prog->exts_integrated = have_exts;
+       prog->gen_flags = gen_flags;
+
+       ret = is_bpf ? cls_bpf_prog_from_ops(tb, prog) :
+               cls_bpf_prog_from_efd(tb, prog, gen_flags, tp);
        if (ret < 0)
                goto errout_idr;
 
+       if (tb[TCA_BPF_CLASSID]) {
+               prog->res.classid = nla_get_u32(tb[TCA_BPF_CLASSID]);
+               tcf_bind_filter(tp, &prog->res, base);
+               bound_to_filter = true;
+       }
+
        ret = cls_bpf_offload(tp, prog, oldprog, extack);
        if (ret)
                goto errout_parms;
@@ -530,6 +523,8 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb,
        return 0;
 
 errout_parms:
+       if (bound_to_filter)
+               tcf_unbind_filter(tp, &prog->res);
        cls_bpf_free_parms(prog);
 errout_idr:
        if (!oldprog)
index f2b0bc4..9f0711d 100644 (file)
@@ -776,7 +776,8 @@ mpls_stack_entry_policy[TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX + 1] = {
        [TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL]    = { .type = NLA_U32 },
 };
 
-static const struct nla_policy cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX] = {
+static const struct nla_policy
+cfm_opt_policy[TCA_FLOWER_KEY_CFM_OPT_MAX + 1] = {
        [TCA_FLOWER_KEY_CFM_MD_LEVEL]   = NLA_POLICY_MAX(NLA_U8,
                                                FLOW_DIS_CFM_MDL_MAX),
        [TCA_FLOWER_KEY_CFM_OPCODE]     = { .type = NLA_U8 },
@@ -1709,7 +1710,7 @@ static int fl_set_key_cfm(struct nlattr **tb,
                          struct fl_flow_key *mask,
                          struct netlink_ext_ack *extack)
 {
-       struct nlattr *nla_cfm_opt[TCA_FLOWER_KEY_CFM_OPT_MAX];
+       struct nlattr *nla_cfm_opt[TCA_FLOWER_KEY_CFM_OPT_MAX + 1];
        int err;
 
        if (!tb[TCA_FLOWER_KEY_CFM])
@@ -2173,53 +2174,6 @@ static bool fl_needs_tc_skb_ext(const struct fl_flow_key *mask)
        return mask->meta.l2_miss;
 }
 
-static int fl_set_parms(struct net *net, struct tcf_proto *tp,
-                       struct cls_fl_filter *f, struct fl_flow_mask *mask,
-                       unsigned long base, struct nlattr **tb,
-                       struct nlattr *est,
-                       struct fl_flow_tmplt *tmplt,
-                       u32 flags, u32 fl_flags,
-                       struct netlink_ext_ack *extack)
-{
-       int err;
-
-       err = tcf_exts_validate_ex(net, tp, tb, est, &f->exts, flags,
-                                  fl_flags, extack);
-       if (err < 0)
-               return err;
-
-       if (tb[TCA_FLOWER_CLASSID]) {
-               f->res.classid = nla_get_u32(tb[TCA_FLOWER_CLASSID]);
-               if (flags & TCA_ACT_FLAGS_NO_RTNL)
-                       rtnl_lock();
-               tcf_bind_filter(tp, &f->res, base);
-               if (flags & TCA_ACT_FLAGS_NO_RTNL)
-                       rtnl_unlock();
-       }
-
-       err = fl_set_key(net, tb, &f->key, &mask->key, extack);
-       if (err)
-               return err;
-
-       fl_mask_update_range(mask);
-       fl_set_masked_key(&f->mkey, &f->key, mask);
-
-       if (!fl_mask_fits_tmplt(tmplt, mask)) {
-               NL_SET_ERR_MSG_MOD(extack, "Mask does not fit the template");
-               return -EINVAL;
-       }
-
-       /* Enable tc skb extension if filter matches on data extracted from
-        * this extension.
-        */
-       if (fl_needs_tc_skb_ext(&mask->key)) {
-               f->needs_tc_skb_ext = 1;
-               tc_skb_ext_tc_enable();
-       }
-
-       return 0;
-}
-
 static int fl_ht_insert_unique(struct cls_fl_filter *fnew,
                               struct cls_fl_filter *fold,
                               bool *in_ht)
@@ -2251,6 +2205,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        struct cls_fl_head *head = fl_head_dereference(tp);
        bool rtnl_held = !(flags & TCA_ACT_FLAGS_NO_RTNL);
        struct cls_fl_filter *fold = *arg;
+       bool bound_to_filter = false;
        struct cls_fl_filter *fnew;
        struct fl_flow_mask *mask;
        struct nlattr **tb;
@@ -2335,15 +2290,46 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        if (err < 0)
                goto errout_idr;
 
-       err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE],
-                          tp->chain->tmplt_priv, flags, fnew->flags,
-                          extack);
-       if (err)
+       err = tcf_exts_validate_ex(net, tp, tb, tca[TCA_RATE],
+                                  &fnew->exts, flags, fnew->flags,
+                                  extack);
+       if (err < 0)
                goto errout_idr;
 
+       if (tb[TCA_FLOWER_CLASSID]) {
+               fnew->res.classid = nla_get_u32(tb[TCA_FLOWER_CLASSID]);
+               if (flags & TCA_ACT_FLAGS_NO_RTNL)
+                       rtnl_lock();
+               tcf_bind_filter(tp, &fnew->res, base);
+               if (flags & TCA_ACT_FLAGS_NO_RTNL)
+                       rtnl_unlock();
+               bound_to_filter = true;
+       }
+
+       err = fl_set_key(net, tb, &fnew->key, &mask->key, extack);
+       if (err)
+               goto unbind_filter;
+
+       fl_mask_update_range(mask);
+       fl_set_masked_key(&fnew->mkey, &fnew->key, mask);
+
+       if (!fl_mask_fits_tmplt(tp->chain->tmplt_priv, mask)) {
+               NL_SET_ERR_MSG_MOD(extack, "Mask does not fit the template");
+               err = -EINVAL;
+               goto unbind_filter;
+       }
+
+       /* Enable tc skb extension if filter matches on data extracted from
+        * this extension.
+        */
+       if (fl_needs_tc_skb_ext(&mask->key)) {
+               fnew->needs_tc_skb_ext = 1;
+               tc_skb_ext_tc_enable();
+       }
+
        err = fl_check_assign_mask(head, fnew, fold, mask);
        if (err)
-               goto errout_idr;
+               goto unbind_filter;
 
        err = fl_ht_insert_unique(fnew, fold, &in_ht);
        if (err)
@@ -2434,6 +2420,16 @@ errout_hw:
                                       fnew->mask->filter_ht_params);
 errout_mask:
        fl_mask_put(head, fnew->mask);
+
+unbind_filter:
+       if (bound_to_filter) {
+               if (flags & TCA_ACT_FLAGS_NO_RTNL)
+                       rtnl_lock();
+               tcf_unbind_filter(tp, &fnew->res);
+               if (flags & TCA_ACT_FLAGS_NO_RTNL)
+                       rtnl_unlock();
+       }
+
 errout_idr:
        if (!fold)
                idr_remove(&head->handle_idr, fnew->handle);
index 8641f80..c49d6af 100644 (file)
@@ -267,7 +267,6 @@ static int fw_change(struct net *net, struct sk_buff *in_skb,
                        return -ENOBUFS;
 
                fnew->id = f->id;
-               fnew->res = f->res;
                fnew->ifindex = f->ifindex;
                fnew->tp = f->tp;
 
index fa3bbd1..c4ed11d 100644 (file)
@@ -159,26 +159,6 @@ static const struct nla_policy mall_policy[TCA_MATCHALL_MAX + 1] = {
        [TCA_MATCHALL_FLAGS]            = { .type = NLA_U32 },
 };
 
-static int mall_set_parms(struct net *net, struct tcf_proto *tp,
-                         struct cls_mall_head *head,
-                         unsigned long base, struct nlattr **tb,
-                         struct nlattr *est, u32 flags, u32 fl_flags,
-                         struct netlink_ext_ack *extack)
-{
-       int err;
-
-       err = tcf_exts_validate_ex(net, tp, tb, est, &head->exts, flags,
-                                  fl_flags, extack);
-       if (err < 0)
-               return err;
-
-       if (tb[TCA_MATCHALL_CLASSID]) {
-               head->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
-               tcf_bind_filter(tp, &head->res, base);
-       }
-       return 0;
-}
-
 static int mall_change(struct net *net, struct sk_buff *in_skb,
                       struct tcf_proto *tp, unsigned long base,
                       u32 handle, struct nlattr **tca,
@@ -187,6 +167,7 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
 {
        struct cls_mall_head *head = rtnl_dereference(tp->root);
        struct nlattr *tb[TCA_MATCHALL_MAX + 1];
+       bool bound_to_filter = false;
        struct cls_mall_head *new;
        u32 userflags = 0;
        int err;
@@ -226,11 +207,17 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
                goto err_alloc_percpu;
        }
 
-       err = mall_set_parms(net, tp, new, base, tb, tca[TCA_RATE],
-                            flags, new->flags, extack);
-       if (err)
+       err = tcf_exts_validate_ex(net, tp, tb, tca[TCA_RATE],
+                                  &new->exts, flags, new->flags, extack);
+       if (err < 0)
                goto err_set_parms;
 
+       if (tb[TCA_MATCHALL_CLASSID]) {
+               new->res.classid = nla_get_u32(tb[TCA_MATCHALL_CLASSID]);
+               tcf_bind_filter(tp, &new->res, base);
+               bound_to_filter = true;
+       }
+
        if (!tc_skip_hw(new->flags)) {
                err = mall_replace_hw_filter(tp, new, (unsigned long)new,
                                             extack);
@@ -246,6 +233,8 @@ static int mall_change(struct net *net, struct sk_buff *in_skb,
        return 0;
 
 err_replace_hw_filter:
+       if (bound_to_filter)
+               tcf_unbind_filter(tp, &new->res);
 err_set_parms:
        free_percpu(new->pf);
 err_alloc_percpu:
index d0c5372..1e20bbd 100644 (file)
@@ -513,7 +513,6 @@ static int route4_change(struct net *net, struct sk_buff *in_skb,
        if (fold) {
                f->id = fold->id;
                f->iif = fold->iif;
-               f->res = fold->res;
                f->handle = fold->handle;
 
                f->tp = fold->tp;
index d15d50d..da4c179 100644 (file)
@@ -712,8 +712,23 @@ static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = {
        [TCA_U32_FLAGS]         = { .type = NLA_U32 },
 };
 
+static void u32_unbind_filter(struct tcf_proto *tp, struct tc_u_knode *n,
+                             struct nlattr **tb)
+{
+       if (tb[TCA_U32_CLASSID])
+               tcf_unbind_filter(tp, &n->res);
+}
+
+static void u32_bind_filter(struct tcf_proto *tp, struct tc_u_knode *n,
+                           unsigned long base, struct nlattr **tb)
+{
+       if (tb[TCA_U32_CLASSID]) {
+               n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
+               tcf_bind_filter(tp, &n->res, base);
+       }
+}
+
 static int u32_set_parms(struct net *net, struct tcf_proto *tp,
-                        unsigned long base,
                         struct tc_u_knode *n, struct nlattr **tb,
                         struct nlattr *est, u32 flags, u32 fl_flags,
                         struct netlink_ext_ack *extack)
@@ -760,10 +775,6 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
                if (ht_old)
                        ht_old->refcnt--;
        }
-       if (tb[TCA_U32_CLASSID]) {
-               n->res.classid = nla_get_u32(tb[TCA_U32_CLASSID]);
-               tcf_bind_filter(tp, &n->res, base);
-       }
 
        if (ifindex >= 0)
                n->ifindex = ifindex;
@@ -815,7 +826,6 @@ static struct tc_u_knode *u32_init_knode(struct net *net, struct tcf_proto *tp,
 
        new->ifindex = n->ifindex;
        new->fshift = n->fshift;
-       new->res = n->res;
        new->flags = n->flags;
        RCU_INIT_POINTER(new->ht_down, ht);
 
@@ -903,17 +913,27 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                if (!new)
                        return -ENOMEM;
 
-               err = u32_set_parms(net, tp, base, new, tb,
-                                   tca[TCA_RATE], flags, new->flags,
-                                   extack);
+               err = u32_set_parms(net, tp, new, tb, tca[TCA_RATE],
+                                   flags, new->flags, extack);
 
                if (err) {
                        __u32_destroy_key(new);
                        return err;
                }
 
+               u32_bind_filter(tp, new, base, tb);
+
                err = u32_replace_hw_knode(tp, new, flags, extack);
                if (err) {
+                       u32_unbind_filter(tp, new, tb);
+
+                       if (tb[TCA_U32_LINK]) {
+                               struct tc_u_hnode *ht_old;
+
+                               ht_old = rtnl_dereference(n->ht_down);
+                               if (ht_old)
+                                       ht_old->refcnt++;
+                       }
                        __u32_destroy_key(new);
                        return err;
                }
@@ -1003,18 +1023,62 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                return -EINVAL;
        }
 
+       /* At this point, we need to derive the new handle that will be used to
+        * uniquely map the identity of this table match entry. The
+        * identity of the entry that we need to construct is 32 bits made of:
+        *     htid(12b):bucketid(8b):node/entryid(12b)
+        *
+        * At this point _we have the table(ht)_ in which we will insert this
+        * entry. We carry the table's id in variable "htid".
+        * Note that earlier code picked the ht selection either by a) the user
+        * providing the htid specified via TCA_U32_HASH attribute or b) when
+        * no such attribute is passed then the root ht, is default to at ID
+        * 0x[800][00][000]. Rule: the root table has a single bucket with ID 0.
+        * If OTOH the user passed us the htid, they may also pass a bucketid of
+        * choice. 0 is fine. For example a user htid is 0x[600][01][000] it is
+        * indicating hash bucketid of 1. Rule: the entry/node ID _cannot_ be
+        * passed via the htid, so even if it was non-zero it will be ignored.
+        *
+        * We may also have a handle, if the user passed one. The handle also
+        * carries the same addressing of htid(12b):bucketid(8b):node/entryid(12b).
+        * Rule: the bucketid on the handle is ignored even if one was passed;
+        * rather the value on "htid" is always assumed to be the bucketid.
+        */
        if (handle) {
+               /* Rule: The htid from handle and tableid from htid must match */
                if (TC_U32_HTID(handle) && TC_U32_HTID(handle ^ htid)) {
                        NL_SET_ERR_MSG_MOD(extack, "Handle specified hash table address mismatch");
                        return -EINVAL;
                }
-               handle = htid | TC_U32_NODE(handle);
-               err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, handle,
-                                   GFP_KERNEL);
-               if (err)
-                       return err;
-       } else
+               /* Ok, so far we have a valid htid(12b):bucketid(8b) but we
+                * need to finalize the table entry identification with the last
+                * part - the node/entryid(12b)). Rule: Nodeid _cannot be 0_ for
+                * entries. Rule: nodeid of 0 is reserved only for tables(see
+                * earlier code which processes TC_U32_DIVISOR attribute).
+                * Rule: The nodeid can only be derived from the handle (and not
+                * htid).
+                * Rule: if the handle specified zero for the node id example
+                * 0x60000000, then pick a new nodeid from the pool of IDs
+                * this hash table has been allocating from.
+                * If OTOH it is specified (i.e for example the user passed a
+                * handle such as 0x60000123), then we use it generate our final
+                * handle which is used to uniquely identify the match entry.
+                */
+               if (!TC_U32_NODE(handle)) {
+                       handle = gen_new_kid(ht, htid);
+               } else {
+                       handle = htid | TC_U32_NODE(handle);
+                       err = idr_alloc_u32(&ht->handle_idr, NULL, &handle,
+                                           handle, GFP_KERNEL);
+                       if (err)
+                               return err;
+               }
+       } else {
+               /* The user did not give us a handle; lets just generate one
+                * from the table's pool of nodeids.
+                */
                handle = gen_new_kid(ht, htid);
+       }
 
        if (tb[TCA_U32_SEL] == NULL) {
                NL_SET_ERR_MSG_MOD(extack, "Selector not specified");
@@ -1074,15 +1138,18 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
        }
 #endif
 
-       err = u32_set_parms(net, tp, base, n, tb, tca[TCA_RATE],
+       err = u32_set_parms(net, tp, n, tb, tca[TCA_RATE],
                            flags, n->flags, extack);
+
+       u32_bind_filter(tp, n, base, tb);
+
        if (err == 0) {
                struct tc_u_knode __rcu **ins;
                struct tc_u_knode *pins;
 
                err = u32_replace_hw_knode(tp, n, flags, extack);
                if (err)
-                       goto errhw;
+                       goto errunbind;
 
                if (!tc_in_hw(n->flags))
                        n->flags |= TCA_CLS_FLAGS_NOT_IN_HW;
@@ -1100,7 +1167,9 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                return 0;
        }
 
-errhw:
+errunbind:
+       u32_unbind_filter(tp, n, tb);
+
 #ifdef CONFIG_CLS_U32_MARK
        free_percpu(n->pcpu_success);
 #endif
index af85a73..6fdba06 100644 (file)
@@ -568,7 +568,7 @@ META_COLLECTOR(int_sk_rcvtimeo)
                *err = -1;
                return;
        }
-       dst->value = sk->sk_rcvtimeo / HZ;
+       dst->value = READ_ONCE(sk->sk_rcvtimeo) / HZ;
 }
 
 META_COLLECTOR(int_sk_sndtimeo)
@@ -579,7 +579,7 @@ META_COLLECTOR(int_sk_sndtimeo)
                *err = -1;
                return;
        }
-       dst->value = sk->sk_sndtimeo / HZ;
+       dst->value = READ_ONCE(sk->sk_sndtimeo) / HZ;
 }
 
 META_COLLECTOR(int_sk_sendmsg_off)
index ab69ff7..793009f 100644 (file)
@@ -290,6 +290,13 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt,
                                                    "Attribute type expected to be TCA_MQPRIO_MIN_RATE64");
                                return -EINVAL;
                        }
+
+                       if (nla_len(attr) != sizeof(u64)) {
+                               NL_SET_ERR_MSG_ATTR(extack, attr,
+                                                   "Attribute TCA_MQPRIO_MIN_RATE64 expected to have 8 bytes length");
+                               return -EINVAL;
+                       }
+
                        if (i >= qopt->num_tc)
                                break;
                        priv->min_rate[i] = nla_get_u64(attr);
@@ -312,6 +319,13 @@ static int mqprio_parse_nlattr(struct Qdisc *sch, struct tc_mqprio_qopt *qopt,
                                                    "Attribute type expected to be TCA_MQPRIO_MAX_RATE64");
                                return -EINVAL;
                        }
+
+                       if (nla_len(attr) != sizeof(u64)) {
+                               NL_SET_ERR_MSG_ATTR(extack, attr,
+                                                   "Attribute TCA_MQPRIO_MAX_RATE64 expected to have 8 bytes length");
+                               return -EINVAL;
+                       }
+
                        if (i >= qopt->num_tc)
                                break;
                        priv->max_rate[i] = nla_get_u64(attr);
index 717ae51..8c9cfff 100644 (file)
@@ -1015,6 +1015,11 @@ static const struct nla_policy taprio_tc_policy[TCA_TAPRIO_TC_ENTRY_MAX + 1] = {
                                                              TC_FP_PREEMPTIBLE),
 };
 
+static struct netlink_range_validation_signed taprio_cycle_time_range = {
+       .min = 0,
+       .max = INT_MAX,
+};
+
 static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
        [TCA_TAPRIO_ATTR_PRIOMAP]              = {
                .len = sizeof(struct tc_mqprio_qopt)
@@ -1023,7 +1028,8 @@ static const struct nla_policy taprio_policy[TCA_TAPRIO_ATTR_MAX + 1] = {
        [TCA_TAPRIO_ATTR_SCHED_BASE_TIME]            = { .type = NLA_S64 },
        [TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY]         = { .type = NLA_NESTED },
        [TCA_TAPRIO_ATTR_SCHED_CLOCKID]              = { .type = NLA_S32 },
-       [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]           = { .type = NLA_S64 },
+       [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME]           =
+               NLA_POLICY_FULL_RANGE_SIGNED(NLA_S64, &taprio_cycle_time_range),
        [TCA_TAPRIO_ATTR_SCHED_CYCLE_TIME_EXTENSION] = { .type = NLA_S64 },
        [TCA_TAPRIO_ATTR_FLAGS]                      = { .type = NLA_U32 },
        [TCA_TAPRIO_ATTR_TXTIME_DELAY]               = { .type = NLA_U32 },
@@ -1159,6 +1165,11 @@ static int parse_taprio_schedule(struct taprio_sched *q, struct nlattr **tb,
                        return -EINVAL;
                }
 
+               if (cycle < 0 || cycle > INT_MAX) {
+                       NL_SET_ERR_MSG(extack, "'cycle_time' is too big");
+                       return -EINVAL;
+               }
+
                new->cycle_time = cycle;
        }
 
@@ -1347,7 +1358,7 @@ static void setup_txtime(struct taprio_sched *q,
                         struct sched_gate_list *sched, ktime_t base)
 {
        struct sched_entry *entry;
-       u32 interval = 0;
+       u64 interval = 0;
 
        list_for_each_entry(entry, &sched->entries, list) {
                entry->next_txtime = ktime_add_ns(base, interval);
index a7f887d..0c013d2 100644 (file)
@@ -445,7 +445,7 @@ static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
        nsk->sk_rcvbuf = osk->sk_rcvbuf;
        nsk->sk_sndtimeo = osk->sk_sndtimeo;
        nsk->sk_rcvtimeo = osk->sk_rcvtimeo;
-       nsk->sk_mark = osk->sk_mark;
+       nsk->sk_mark = READ_ONCE(osk->sk_mark);
        nsk->sk_priority = osk->sk_priority;
        nsk->sk_rcvlowat = osk->sk_rcvlowat;
        nsk->sk_bound_dev_if = osk->sk_bound_dev_if;
index 577fa5a..302fd74 100644 (file)
@@ -1960,7 +1960,8 @@ rcv:
 
        skb_reset_network_header(*skb);
        skb_pull(*skb, tipc_ehdr_size(ehdr));
-       pskb_trim(*skb, (*skb)->len - aead->authsize);
+       if (pskb_trim(*skb, (*skb)->len - aead->authsize))
+               goto free_skb;
 
        /* Validate TIPCv2 message */
        if (unlikely(!tipc_msg_validate(skb))) {
index 5e000fd..a9c5b65 100644 (file)
@@ -583,7 +583,7 @@ update:
                                 n->capabilities, &n->bc_entry.inputq1,
                                 &n->bc_entry.namedq, snd_l, &n->bc_entry.link)) {
                pr_warn("Broadcast rcv link creation failed, no memory\n");
-               kfree(n);
+               tipc_node_put(n);
                n = NULL;
                goto exit;
        }
index 123b35d..86930a8 100644 (file)
@@ -289,17 +289,29 @@ static int unix_validate_addr(struct sockaddr_un *sunaddr, int addr_len)
        return 0;
 }
 
-static void unix_mkname_bsd(struct sockaddr_un *sunaddr, int addr_len)
+static int unix_mkname_bsd(struct sockaddr_un *sunaddr, int addr_len)
 {
+       struct sockaddr_storage *addr = (struct sockaddr_storage *)sunaddr;
+       short offset = offsetof(struct sockaddr_storage, __data);
+
+       BUILD_BUG_ON(offset != offsetof(struct sockaddr_un, sun_path));
+
        /* This may look like an off by one error but it is a bit more
         * subtle.  108 is the longest valid AF_UNIX path for a binding.
         * sun_path[108] doesn't as such exist.  However in kernel space
         * we are guaranteed that it is a valid memory location in our
         * kernel address buffer because syscall functions always pass
         * a pointer of struct sockaddr_storage which has a bigger buffer
-        * than 108.
+        * than 108.  Also, we must terminate sun_path for strlen() in
+        * getname_kernel().
+        */
+       addr->__data[addr_len - offset] = 0;
+
+       /* Don't pass sunaddr->sun_path to strlen().  Otherwise, 108 will
+        * cause panic if CONFIG_FORTIFY_SOURCE=y.  Let __fortify_strlen()
+        * know the actual buffer.
         */
-       ((char *)sunaddr)[addr_len] = 0;
+       return strlen(addr->__data) + offset + 1;
 }
 
 static void __unix_remove_socket(struct sock *sk)
@@ -778,7 +790,7 @@ static int unix_set_peek_off(struct sock *sk, int val)
        if (mutex_lock_interruptible(&u->iolock))
                return -EINTR;
 
-       sk->sk_peek_off = val;
+       WRITE_ONCE(sk->sk_peek_off, val);
        mutex_unlock(&u->iolock);
 
        return 0;
@@ -1208,10 +1220,7 @@ static int unix_bind_bsd(struct sock *sk, struct sockaddr_un *sunaddr,
        struct path parent;
        int err;
 
-       unix_mkname_bsd(sunaddr, addr_len);
-       addr_len = strlen(sunaddr->sun_path) +
-               offsetof(struct sockaddr_un, sun_path) + 1;
-
+       addr_len = unix_mkname_bsd(sunaddr, addr_len);
        addr = unix_create_addr(sunaddr, addr_len);
        if (!addr)
                return -ENOMEM;
index 8bf00ca..0cf1ce7 100644 (file)
@@ -657,7 +657,7 @@ static int cfg80211_parse_colocated_ap(const struct cfg80211_bss_ies *ies,
 
        ret = cfg80211_calc_short_ssid(ies, &ssid_elem, &s_ssid_tmp);
        if (ret)
-               return ret;
+               return 0;
 
        for_each_element_id(elem, WLAN_EID_REDUCED_NEIGHBOR_REPORT,
                            ies->data, ies->len) {
index 31dca4e..b89adb5 100644 (file)
@@ -505,7 +505,7 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs,
 
        skb->dev = dev;
        skb->priority = xs->sk.sk_priority;
-       skb->mark = xs->sk.sk_mark;
+       skb->mark = READ_ONCE(xs->sk.sk_mark);
        skb_shinfo(skb)->destructor_arg = (void *)(long)desc->addr;
        skb->destructor = xsk_destruct_skb;
 
index e7617c9..d6b4057 100644 (file)
@@ -2250,7 +2250,7 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
 
                match = xfrm_selector_match(&pol->selector, fl, family);
                if (match) {
-                       if ((sk->sk_mark & pol->mark.m) != pol->mark.v ||
+                       if ((READ_ONCE(sk->sk_mark) & pol->mark.m) != pol->mark.v ||
                            pol->if_id != if_id) {
                                pol = NULL;
                                goto out;
index 6413342..82e3fb1 100644 (file)
@@ -264,6 +264,9 @@ $(obj)/%.lst: $(src)/%.c FORCE
 
 rust_allowed_features := new_uninit
 
+# `--out-dir` is required to avoid temporaries being created by `rustc` in the
+# current working directory, which may be not accessible in the out-of-tree
+# modules case.
 rust_common_cmd = \
        RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \
        -Zallow-features=$(rust_allowed_features) \
@@ -272,7 +275,7 @@ rust_common_cmd = \
        --extern alloc --extern kernel \
        --crate-type rlib -L $(objtree)/rust/ \
        --crate-name $(basename $(notdir $@)) \
-       --emit=dep-info=$(depfile)
+       --out-dir $(dir $@) --emit=dep-info=$(depfile)
 
 # `--emit=obj`, `--emit=asm` and `--emit=llvm-ir` imply a single codegen unit
 # will be used. We explicitly request `-Ccodegen-units=1` in any case, and
index 7aea900..8f7f842 100644 (file)
@@ -86,7 +86,11 @@ hostc_flags    = -Wp,-MMD,$(depfile) \
 hostcxx_flags  = -Wp,-MMD,$(depfile) \
                  $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
                  $(HOSTCXXFLAGS_$(target-stem).o)
-hostrust_flags = --emit=dep-info=$(depfile) \
+
+# `--out-dir` is required to avoid temporaries being created by `rustc` in the
+# current working directory, which may be not accessible in the out-of-tree
+# modules case.
+hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \
                  $(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
                  $(HOSTRUSTFLAGS_$(target-stem))
 
index 15ba565..a84cc57 100755 (executable)
@@ -19,7 +19,7 @@ _DEFAULT_OUTPUT = 'compile_commands.json'
 _DEFAULT_LOG_LEVEL = 'WARNING'
 
 _FILENAME_PATTERN = r'^\..*\.cmd$'
-_LINE_PATTERN = r'^savedcmd_[^ ]*\.o := (.* )([^ ]*\.c) *(;|$)'
+_LINE_PATTERN = r'^savedcmd_[^ ]*\.o := (.* )([^ ]*\.[cS]) *(;|$)'
 _VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
 # The tools/ directory adopts a different build system, and produces .cmd
 # files in a different format. Do not support it.
diff --git a/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci b/scripts/coccinelle/api/debugfs/debugfs_simple_attr.cocci
deleted file mode 100644 (file)
index 7c31231..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/// Use DEFINE_DEBUGFS_ATTRIBUTE rather than DEFINE_SIMPLE_ATTRIBUTE
-/// for debugfs files.
-///
-//# Rationale: DEFINE_SIMPLE_ATTRIBUTE + debugfs_create_file()
-//# imposes some significant overhead as compared to
-//# DEFINE_DEBUGFS_ATTRIBUTE + debugfs_create_file_unsafe().
-//
-// Copyright (C): 2016 Nicolai Stange
-// Options: --no-includes
-//
-
-virtual context
-virtual patch
-virtual org
-virtual report
-
-@dsa@
-declarer name DEFINE_SIMPLE_ATTRIBUTE;
-identifier dsa_fops;
-expression dsa_get, dsa_set, dsa_fmt;
-position p;
-@@
-DEFINE_SIMPLE_ATTRIBUTE@p(dsa_fops, dsa_get, dsa_set, dsa_fmt);
-
-@dcf@
-expression name, mode, parent, data;
-identifier dsa.dsa_fops;
-@@
-debugfs_create_file(name, mode, parent, data, &dsa_fops)
-
-
-@context_dsa depends on context && dcf@
-declarer name DEFINE_DEBUGFS_ATTRIBUTE;
-identifier dsa.dsa_fops;
-expression dsa.dsa_get, dsa.dsa_set, dsa.dsa_fmt;
-@@
-* DEFINE_SIMPLE_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt);
-
-
-@patch_dcf depends on patch expression@
-expression name, mode, parent, data;
-identifier dsa.dsa_fops;
-@@
-- debugfs_create_file(name, mode, parent, data, &dsa_fops)
-+ debugfs_create_file_unsafe(name, mode, parent, data, &dsa_fops)
-
-@patch_dsa depends on patch_dcf && patch@
-identifier dsa.dsa_fops;
-expression dsa.dsa_get, dsa.dsa_set, dsa.dsa_fmt;
-@@
-- DEFINE_SIMPLE_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt);
-+ DEFINE_DEBUGFS_ATTRIBUTE(dsa_fops, dsa_get, dsa_set, dsa_fmt);
-
-
-@script:python depends on org && dcf@
-fops << dsa.dsa_fops;
-p << dsa.p;
-@@
-msg="%s should be defined with DEFINE_DEBUGFS_ATTRIBUTE" % (fops)
-coccilib.org.print_todo(p[0], msg)
-
-@script:python depends on report && dcf@
-fops << dsa.dsa_fops;
-p << dsa.p;
-@@
-msg="WARNING: %s should be defined with DEFINE_DEBUGFS_ATTRIBUTE" % (fops)
-coccilib.report.print_report(p[0], msg)
index 17adabf..9709aca 100644 (file)
@@ -636,7 +636,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
        GtkWidget *dialog;
        const gchar *intro_text =
-           "Welcome to gkc, the GTK+ graphical configuration tool\n"
+           "Welcome to gconfig, the GTK+ graphical configuration tool.\n"
            "For each option, a blank box indicates the feature is disabled, a\n"
            "check indicates it is enabled, and a dot indicates that it is to\n"
            "be compiled as a module.  Clicking on the box will cycle through the three states.\n"
@@ -647,10 +647,7 @@ void on_introduction1_activate(GtkMenuItem * menuitem, gpointer user_data)
            "Although there is no cross reference yet to help you figure out\n"
            "what other options must be enabled to support the option you\n"
            "are interested in, you can still view the help of a grayed-out\n"
-           "option.\n"
-           "\n"
-           "Toggling Show Debug Info under the Options menu will show \n"
-           "the dependencies, which you can then match by examining other options.";
+           "option.";
 
        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
                                        GTK_DIALOG_DESTROY_WITH_PARENT,
@@ -667,7 +664,7 @@ void on_about1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
        GtkWidget *dialog;
        const gchar *about_text =
-           "gkc is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
+           "gconfig is copyright (c) 2002 Romain Lievin <roms@lpg.ticalc.org>.\n"
              "Based on the source code from Roman Zippel.\n";
 
        dialog = gtk_message_dialog_new(GTK_WINDOW(main_wnd),
@@ -685,7 +682,7 @@ void on_license1_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
        GtkWidget *dialog;
        const gchar *license_text =
-           "gkc is released under the terms of the GNU GPL v2.\n"
+           "gconfig is released under the terms of the GNU GPL v2.\n"
              "For more information, please see the source code or\n"
              "visit http://www.fsf.org/licenses/licenses.html\n";
 
index fc7ba95..855c486 100644 (file)
@@ -1541,7 +1541,6 @@ temeprature||temperature
 temorary||temporary
 temproarily||temporarily
 temperture||temperature
-thead||thread
 theads||threads
 therfore||therefore
 thier||their
index d54f73c..19be69f 100644 (file)
@@ -980,14 +980,19 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
        ret = -EACCES;
        down_write(&key->sem);
 
-       if (!capable(CAP_SYS_ADMIN)) {
+       {
+               bool is_privileged_op = false;
+
                /* only the sysadmin can chown a key to some other UID */
                if (user != (uid_t) -1 && !uid_eq(key->uid, uid))
-                       goto error_put;
+                       is_privileged_op = true;
 
                /* only the sysadmin can set the key's GID to a group other
                 * than one of those that the current process subscribes to */
                if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid))
+                       is_privileged_op = true;
+
+               if (is_privileged_op && !capable(CAP_SYS_ADMIN))
                        goto error_put;
        }
 
@@ -1088,7 +1093,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
        down_write(&key->sem);
 
        /* if we're not the sysadmin, we can only change a key that we own */
-       if (capable(CAP_SYS_ADMIN) || uid_eq(key->uid, current_fsuid())) {
+       if (uid_eq(key->uid, current_fsuid()) || capable(CAP_SYS_ADMIN)) {
                key->perm = perm;
                notify_key(key, NOTIFY_KEY_SETATTR, 0);
                ret = 0;
index 9b80f82..f3f14ff 100644 (file)
@@ -149,6 +149,7 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
        write_lock_irq(&client->ports_lock);
        list_for_each_entry(p, &client->ports_list_head, list) {
                if (p->addr.port == port) {
+                       kfree(new_port);
                        num = -EBUSY;
                        goto unlock;
                }
index fe21c80..f26a181 100644 (file)
@@ -298,8 +298,7 @@ static void update_group_attrs(struct seq_ump_client *client)
        }
 
        list_for_each_entry(fb, &client->ump->block_list, list) {
-               if (fb->info.first_group < 0 ||
-                   fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
+               if (fb->info.first_group + fb->info.num_groups > SNDRV_UMP_MAX_GROUPS)
                        break;
                group = &client->groups[fb->info.first_group];
                for (i = 0; i < fb->info.num_groups; i++, group++) {
index 2ae912a..291e7fe 100644 (file)
@@ -110,8 +110,6 @@ struct pcmtst_buf_iter {
        struct timer_list timer_instance;
 };
 
-static struct pcmtst *pcmtst;
-
 static struct snd_pcm_hardware snd_pcmtst_hw = {
        .info = (SNDRV_PCM_INFO_INTERLEAVED |
                 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -552,6 +550,7 @@ _err_free_chip:
 static int pcmtst_probe(struct platform_device *pdev)
 {
        struct snd_card *card;
+       struct pcmtst *pcmtst;
        int err;
 
        err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
@@ -573,13 +572,16 @@ static int pcmtst_probe(struct platform_device *pdev)
        if (err < 0)
                return err;
 
+       platform_set_drvdata(pdev, pcmtst);
+
        return 0;
 }
 
-static int pdev_remove(struct platform_device *dev)
+static void pdev_remove(struct platform_device *pdev)
 {
+       struct pcmtst *pcmtst = platform_get_drvdata(pdev);
+
        snd_pcmtst_free(pcmtst);
-       return 0;
 }
 
 static struct platform_device pcmtst_pdev = {
@@ -589,7 +591,7 @@ static struct platform_device pcmtst_pdev = {
 
 static struct platform_driver pcmtst_pdrv = {
        .probe =        pcmtst_probe,
-       .remove =       pdev_remove,
+       .remove_new =   pdev_remove,
        .driver =       {
                .name = "pcmtest",
        },
index e2f8b60..44fccfb 100644 (file)
@@ -122,6 +122,7 @@ struct alc_spec {
        unsigned int ultra_low_power:1;
        unsigned int has_hs_key:1;
        unsigned int no_internal_mic_pin:1;
+       unsigned int en_3kpull_low:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -3622,6 +3623,7 @@ static void alc256_shutup(struct hda_codec *codec)
        if (!hp_pin)
                hp_pin = 0x21;
 
+       alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
        hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
 
        if (hp_pin_sense)
@@ -3638,8 +3640,7 @@ static void alc256_shutup(struct hda_codec *codec)
        /* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
         * when booting with headset plugged. So skip setting it for the codec alc257
         */
-       if (codec->core.vendor_id != 0x10ec0236 &&
-           codec->core.vendor_id != 0x10ec0257)
+       if (spec->en_3kpull_low)
                alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
 
        if (!spec->no_shutup_pins)
@@ -4623,6 +4624,21 @@ static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
        }
 }
 
+static void alc236_fixup_hp_mute_led_coefbit2(struct hda_codec *codec,
+                                         const struct hda_fixup *fix, int action)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+               spec->mute_led_polarity = 0;
+               spec->mute_led_coef.idx = 0x07;
+               spec->mute_led_coef.mask = 1;
+               spec->mute_led_coef.on = 1;
+               spec->mute_led_coef.off = 0;
+               snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
+       }
+}
+
 /* turn on/off mic-mute LED per capture hook by coef bit */
 static int coef_micmute_led_set(struct led_classdev *led_cdev,
                                enum led_brightness brightness)
@@ -7143,6 +7159,7 @@ enum {
        ALC285_FIXUP_HP_GPIO_LED,
        ALC285_FIXUP_HP_MUTE_LED,
        ALC285_FIXUP_HP_SPECTRE_X360_MUTE_LED,
+       ALC236_FIXUP_HP_MUTE_LED_COEFBIT2,
        ALC236_FIXUP_HP_GPIO_LED,
        ALC236_FIXUP_HP_MUTE_LED,
        ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF,
@@ -7213,6 +7230,7 @@ enum {
        ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
        ALC295_FIXUP_DELL_INSPIRON_TOP_SPEAKERS,
        ALC236_FIXUP_DELL_DUAL_CODECS,
+       ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI,
 };
 
 /* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -8632,6 +8650,10 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc285_fixup_hp_spectre_x360_mute_led,
        },
+       [ALC236_FIXUP_HP_MUTE_LED_COEFBIT2] = {
+           .type = HDA_FIXUP_FUNC,
+           .v.func = alc236_fixup_hp_mute_led_coefbit2,
+       },
        [ALC236_FIXUP_HP_GPIO_LED] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc236_fixup_hp_gpio_led,
@@ -9145,8 +9167,6 @@ static const struct hda_fixup alc269_fixups[] = {
        [ALC287_FIXUP_CS35L41_I2C_2] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = cs35l41_fixup_i2c_two,
-               .chained = true,
-               .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
        },
        [ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED] = {
                .type = HDA_FIXUP_FUNC,
@@ -9283,6 +9303,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
        },
+       [ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = cs35l41_fixup_i2c_two,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_THINKPAD_ACPI,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -9393,6 +9419,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0c1c, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
        SND_PCI_QUIRK(0x1028, 0x0c1d, "Dell Precision 3440", ALC236_FIXUP_DELL_DUAL_CODECS),
        SND_PCI_QUIRK(0x1028, 0x0c1e, "Dell Precision 3540", ALC236_FIXUP_DELL_DUAL_CODECS),
+       SND_PCI_QUIRK(0x1028, 0x0cbd, "Dell Oasis 13 CS MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cbe, "Dell Oasis 13 2-IN-1 MTL-U", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cbf, "Dell Oasis 13 Low Weight MTU-L", ALC245_FIXUP_CS35L41_SPI_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc1, "Dell Oasis 14 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc2, "Dell Oasis 14 2-in-1 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc3, "Dell Oasis 14 Low Weight MTL-U", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc4, "Dell Oasis 16 MTL-H/U", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x1028, 0x0cc5, "Dell Oasis MLK 14 RPL-P", ALC287_FIXUP_CS35L41_I2C_2),
        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),
@@ -9507,6 +9541,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8811, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
        SND_PCI_QUIRK(0x103c, 0x8812, "HP Spectre x360 15-eb1xxx", ALC285_FIXUP_HP_SPECTRE_X360_EB1),
+       SND_PCI_QUIRK(0x103c, 0x881d, "HP 250 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        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),
@@ -9516,6 +9551,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        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),
+       SND_PCI_QUIRK(0x103c, 0x887a, "HP Laptop 15s-eq2xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
        SND_PCI_QUIRK(0x103c, 0x888d, "HP ZBook Power 15.6 inch G8 Mobile Workstation PC", ALC236_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x8895, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
@@ -9636,6 +9672,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1c9f, "ASUS G614JI", ALC285_FIXUP_ASUS_HEADSET_MIC),
        SND_PCI_QUIRK(0x1043, 0x1caf, "ASUS G634JYR/JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
+       SND_PCI_QUIRK(0x1043, 0x1d1f, "ASUS ROG Strix G17 2023 (G713PV)", ALC287_FIXUP_CS35L41_I2C_2),
        SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402", ALC245_FIXUP_CS35L41_SPI_2),
@@ -9727,6 +9764,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x51b1, "Clevo NS50AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x51b3, "Clevo NS70AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x5630, "Clevo NP50RNJS", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -9810,14 +9848,14 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x22be, "Thinkpad X1 Carbon 8th", ALC285_FIXUP_THINKPAD_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x22c1, "Thinkpad P1 Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
        SND_PCI_QUIRK(0x17aa, 0x22c2, "Thinkpad X1 Extreme Gen 3", ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK),
-       SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
-       SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2),
+       SND_PCI_QUIRK(0x17aa, 0x22f1, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x22f2, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x22f3, "Thinkpad", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x2316, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x2317, "Thinkpad P1 Gen 6", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x2318, "Thinkpad Z13 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x2319, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
+       SND_PCI_QUIRK(0x17aa, 0x231a, "Thinkpad Z16 Gen2", ALC287_FIXUP_CS35L41_I2C_2_THINKPAD_ACPI),
        SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x30e2, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
        SND_PCI_QUIRK(0x17aa, 0x310c, "ThinkCentre Station", ALC294_FIXUP_LENOVO_MIC_LOCATION),
@@ -10682,6 +10720,8 @@ static int patch_alc269(struct hda_codec *codec)
                spec->shutup = alc256_shutup;
                spec->init_hook = alc256_init;
                spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
+               if (codec->bus->pci->vendor == PCI_VENDOR_ID_AMD)
+                       spec->en_3kpull_low = true;
                break;
        case 0x10ec0257:
                spec->codec_variant = ALC269_TYPE_ALC257;
index 5f2119f..12a176a 100644 (file)
@@ -173,7 +173,7 @@ int snd_amd_acp_find_config(struct pci_dev *pci);
 
 static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int direction)
 {
-       u64 byte_count, low = 0, high = 0;
+       u64 byte_count = 0, low = 0, high = 0;
 
        if (direction == SNDRV_PCM_STREAM_PLAYBACK) {
                switch (dai_id) {
@@ -191,7 +191,7 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
                        break;
                default:
                        dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
-                       return -EINVAL;
+                       goto POINTER_RETURN_BYTES;
                }
        } else {
                switch (dai_id) {
@@ -213,12 +213,13 @@ static inline u64 acp_get_byte_count(struct acp_dev_data *adata, int dai_id, int
                        break;
                default:
                        dev_err(adata->dev, "Invalid dai id %x\n", dai_id);
-                       return -EINVAL;
+                       goto POINTER_RETURN_BYTES;
                }
        }
        /* Get 64 bit value from two 32 bit registers */
        byte_count = (high << 32) | low;
 
+POINTER_RETURN_BYTES:
        return byte_count;
 }
 
index e96e6dc..8b853b8 100644 (file)
 #define ACP63_SDW0_DMA_MAX_STREAMS     6
 #define ACP63_SDW1_DMA_MAX_STREAMS     2
 #define ACP_P1_AUDIO_TX_THRESHOLD      6
+
+/*
+ * Below entries describes SDW0 instance DMA stream id and DMA irq bit mapping
+ * in ACP_EXTENAL_INTR_CNTL register.
+ * Stream id           IRQ Bit
+ * 0 (SDW0_AUDIO0_TX)  28
+ * 1 (SDW0_AUDIO1_TX)  26
+ * 2 (SDW0_AUDIO2_TX)  24
+ * 3 (SDW0_AUDIO0_RX)  27
+ * 4 (SDW0_AUDIO1_RX)  25
+ * 5 (SDW0_AUDIO2_RX)  23
+ */
 #define SDW0_DMA_TX_IRQ_MASK(i)        (ACP_AUDIO0_TX_THRESHOLD - (2 * (i)))
-#define SDW0_DMA_RX_IRQ_MASK(i)        (ACP_AUDIO0_RX_THRESHOLD - (2 * (i)))
+#define SDW0_DMA_RX_IRQ_MASK(i)        (ACP_AUDIO0_RX_THRESHOLD - (2 * ((i) - 3)))
+
+/*
+ * Below entries describes SDW1 instance DMA stream id and DMA irq bit mapping
+ * in ACP_EXTENAL_INTR_CNTL1 register.
+ * Stream id           IRQ Bit
+ * 0 (SDW1_AUDIO1_TX)  6
+ * 1 (SDW1_AUDIO1_RX)  5
+ */
 #define SDW1_DMA_IRQ_MASK(i)   (ACP_P1_AUDIO_TX_THRESHOLD - (i))
 
 #define ACP_DELAY_US           5
index 5b46dc8..4af3c36 100644 (file)
@@ -257,7 +257,7 @@ static int sdw_amd_scan_controller(struct device *dev)
                                             &sdw_manager_bitmap, 1);
 
        if (ret) {
-               dev_err(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret);
+               dev_dbg(dev, "Failed to read mipi-sdw-manager-list: %d\n", ret);
                return -EINVAL;
        }
        count = hweight32(sdw_manager_bitmap);
@@ -641,7 +641,7 @@ static int snd_acp63_probe(struct pci_dev *pci,
        ret = get_acp63_device_config(val, pci, adata);
        /* ACP PCI driver probe should be continued even PDM or SoundWire Devices are not found */
        if (ret) {
-               dev_err(&pci->dev, "get acp device config failed:%d\n", ret);
+               dev_dbg(&pci->dev, "get acp device config failed:%d\n", ret);
                goto skip_pdev_creation;
        }
        ret = create_acp63_platform_devs(pci, adata, addr);
index ade130a..324c80f 100644 (file)
@@ -30,7 +30,7 @@ static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STRE
         ACP_AUDIO2_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_TX_LINEARPOSITIONCNTR_HIGH},
        {ACP_AUDIO0_RX_DMA_SIZE, ACP_AUDIO0_RX_FIFOADDR, ACP_AUDIO0_RX_FIFOSIZE,
         ACP_AUDIO0_RX_RINGBUFSIZE, ACP_AUDIO0_RX_RINGBUFADDR, ACP_AUDIO0_RX_INTR_WATERMARK_SIZE,
-        ACP_AUDIO0_TX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_TX_LINEARPOSITIONCNTR_HIGH},
+        ACP_AUDIO0_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO0_RX_LINEARPOSITIONCNTR_HIGH},
        {ACP_AUDIO1_RX_DMA_SIZE, ACP_AUDIO1_RX_FIFOADDR, ACP_AUDIO1_RX_FIFOSIZE,
         ACP_AUDIO1_RX_RINGBUFSIZE, ACP_AUDIO1_RX_RINGBUFADDR, ACP_AUDIO1_RX_INTR_WATERMARK_SIZE,
         ACP_AUDIO1_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO1_RX_LINEARPOSITIONCNTR_HIGH},
@@ -39,6 +39,11 @@ static struct sdw_dma_ring_buf_reg sdw0_dma_ring_buf_reg[ACP63_SDW0_DMA_MAX_STRE
         ACP_AUDIO2_RX_LINEARPOSITIONCNTR_LOW, ACP_AUDIO2_RX_LINEARPOSITIONCNTR_HIGH}
 };
 
+/*
+ * SDW1 instance supports one TX stream and one RX stream.
+ * For TX/RX streams DMA registers programming for SDW1 instance, it uses ACP_P1_AUDIO1 register
+ * set as per hardware register documentation
+ */
 static struct sdw_dma_ring_buf_reg sdw1_dma_ring_buf_reg[ACP63_SDW1_DMA_MAX_STREAMS] =  {
        {ACP_P1_AUDIO1_TX_DMA_SIZE, ACP_P1_AUDIO1_TX_FIFOADDR, ACP_P1_AUDIO1_TX_FIFOSIZE,
         ACP_P1_AUDIO1_TX_RINGBUFSIZE, ACP_P1_AUDIO1_TX_RINGBUFADDR,
@@ -59,6 +64,12 @@ static u32 sdw0_dma_enable_reg[ACP63_SDW0_DMA_MAX_STREAMS] = {
        ACP_SW0_AUDIO2_RX_EN,
 };
 
+/*
+ * SDW1 instance supports one TX stream and one RX stream.
+ * For TX/RX streams DMA enable register programming for SDW1 instance,
+ * it uses ACP_SW1_AUDIO1_TX_EN and ACP_SW1_AUDIO1_RX_EN registers
+ * as per hardware register documentation.
+ */
 static u32 sdw1_dma_enable_reg[ACP63_SDW1_DMA_MAX_STREAMS] = {
        ACP_SW1_AUDIO1_TX_EN,
        ACP_SW1_AUDIO1_RX_EN,
@@ -307,12 +318,13 @@ static u64 acp63_sdw_get_byte_count(struct acp_sdw_dma_stream *stream, void __io
                pos_high_reg = sdw1_dma_ring_buf_reg[stream->stream_id].pos_high_reg;
                break;
        default:
-               return -EINVAL;
+               goto POINTER_RETURN_BYTES;
        }
        if (pos_low_reg) {
                byte_count.bcount.high = readl(acp_base + pos_high_reg);
                byte_count.bcount.low = readl(acp_base + pos_low_reg);
        }
+POINTER_RETURN_BYTES:
        return byte_count.bytescount;
 }
 
index 49930ba..69a88dc 100644 (file)
@@ -163,11 +163,14 @@ struct atmel_i2s_gck_param {
 
 #define I2S_MCK_12M288         12288000UL
 #define I2S_MCK_11M2896                11289600UL
+#define I2S_MCK_6M144          6144000UL
 
 /* mck = (32 * (imckfs+1) / (imckdiv+1)) * fs */
 static const struct atmel_i2s_gck_param gck_params[] = {
+       /* mck = 6.144Mhz */
+       {  8000, I2S_MCK_6M144,  1, 47},        /* mck =  768 fs */
+
        /* mck = 12.288MHz */
-       {  8000, I2S_MCK_12M288, 0, 47},        /* mck = 1536 fs */
        { 16000, I2S_MCK_12M288, 1, 47},        /* mck =  768 fs */
        { 24000, I2S_MCK_12M288, 3, 63},        /* mck =  512 fs */
        { 32000, I2S_MCK_12M288, 3, 47},        /* mck =  384 fs */
index 2a62dbd..c2de4ee 100644 (file)
@@ -715,6 +715,7 @@ config SND_SOC_CS35L41_I2C
 
 config SND_SOC_CS35L45
        tristate
+       select REGMAP_IRQ
 
 config SND_SOC_CS35L45_SPI
        tristate "Cirrus Logic CS35L45 CODEC (SPI)"
@@ -1942,6 +1943,7 @@ config SND_SOC_WCD934X
        tristate "WCD9340/WCD9341 Codec"
        depends on COMMON_CLK
        depends on SLIMBUS
+       select REGMAP_IRQ
        select REGMAP_SLIMBUS
        select SND_SOC_WCD_MBHC
        depends on MFD_WCD934X || COMPILE_TEST
index b2106ff..e7db7bc 100644 (file)
@@ -19,6 +19,12 @@ static struct i2c_device_id cs42l51_i2c_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id);
 
+const struct of_device_id cs42l51_of_match[] = {
+       { .compatible = "cirrus,cs42l51", },
+       { }
+};
+MODULE_DEVICE_TABLE(of, cs42l51_of_match);
+
 static int cs42l51_i2c_probe(struct i2c_client *i2c)
 {
        struct regmap_config config;
index a67cd3e..a7079ae 100644 (file)
@@ -823,13 +823,6 @@ int __maybe_unused cs42l51_resume(struct device *dev)
 }
 EXPORT_SYMBOL_GPL(cs42l51_resume);
 
-const struct of_device_id cs42l51_of_match[] = {
-       { .compatible = "cirrus,cs42l51", },
-       { }
-};
-MODULE_DEVICE_TABLE(of, cs42l51_of_match);
-EXPORT_SYMBOL_GPL(cs42l51_of_match);
-
 MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
 MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver");
 MODULE_LICENSE("GPL");
index a79343e..125703e 100644 (file)
@@ -16,7 +16,6 @@ int cs42l51_probe(struct device *dev, struct regmap *regmap);
 void cs42l51_remove(struct device *dev);
 int __maybe_unused cs42l51_suspend(struct device *dev);
 int __maybe_unused cs42l51_resume(struct device *dev);
-extern const struct of_device_id cs42l51_of_match[];
 
 #define CS42L51_CHIP_ID                        0x1B
 #define CS42L51_CHIP_REV_A             0x00
index c65256b..581b334 100644 (file)
@@ -361,11 +361,15 @@ static irqreturn_t da7219_aad_irq_thread(int irq, void *data)
        struct da7219_priv *da7219 = snd_soc_component_get_drvdata(component);
        u8 events[DA7219_AAD_IRQ_REG_MAX];
        u8 statusa;
-       int i, report = 0, mask = 0;
+       int i, ret, report = 0, mask = 0;
 
        /* Read current IRQ events */
-       regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
-                        events, DA7219_AAD_IRQ_REG_MAX);
+       ret = regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A,
+                              events, DA7219_AAD_IRQ_REG_MAX);
+       if (ret) {
+               dev_warn_ratelimited(component->dev, "Failed to read IRQ events: %d\n", ret);
+               return IRQ_NONE;
+       }
 
        if (!events[DA7219_AAD_IRQ_REG_A] && !events[DA7219_AAD_IRQ_REG_B])
                return IRQ_NONE;
@@ -944,6 +948,8 @@ void da7219_aad_suspend(struct snd_soc_component *component)
                        }
                }
        }
+
+       synchronize_irq(da7219_aad->irq);
 }
 
 void da7219_aad_resume(struct snd_soc_component *component)
index 34cf607..65e497b 100644 (file)
@@ -153,7 +153,7 @@ static const char * const es8316_dmic_txt[] = {
                "dmic data at high level",
                "dmic data at low level",
 };
-static const unsigned int es8316_dmic_values[] = { 0, 1, 2 };
+static const unsigned int es8316_dmic_values[] = { 0, 2, 3 };
 static const struct soc_enum es8316_dmic_src_enum =
        SOC_VALUE_ENUM_SINGLE(ES8316_ADC_DMIC, 0, 3,
                              ARRAY_SIZE(es8316_dmic_txt),
index 96d7588..ca6beb2 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/acpi.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/dmi.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <sound/tlv.h>
 #include "nau8821.h"
 
+#define NAU8821_JD_ACTIVE_HIGH                 BIT(0)
+
+static int nau8821_quirk;
+static int quirk_override = -1;
+module_param_named(quirk, quirk_override, uint, 0444);
+MODULE_PARM_DESC(quirk, "Board-specific quirk override");
+
 #define NAU_FREF_MAX 13500000
 #define NAU_FVCO_MAX 100000000
 #define NAU_FVCO_MIN 90000000
@@ -1792,6 +1800,33 @@ static int nau8821_setup_irq(struct nau8821 *nau8821)
        return 0;
 }
 
+/* Please keep this list alphabetically sorted */
+static const struct dmi_system_id nau8821_quirk_table[] = {
+       {
+               /* Positivo CW14Q01P-V2 */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Positivo Tecnologia SA"),
+                       DMI_MATCH(DMI_BOARD_NAME, "CW14Q01P-V2"),
+               },
+               .driver_data = (void *)(NAU8821_JD_ACTIVE_HIGH),
+       },
+       {}
+};
+
+static void nau8821_check_quirks(void)
+{
+       const struct dmi_system_id *dmi_id;
+
+       if (quirk_override != -1) {
+               nau8821_quirk = quirk_override;
+               return;
+       }
+
+       dmi_id = dmi_first_match(nau8821_quirk_table);
+       if (dmi_id)
+               nau8821_quirk = (unsigned long)dmi_id->driver_data;
+}
+
 static int nau8821_i2c_probe(struct i2c_client *i2c)
 {
        struct device *dev = &i2c->dev;
@@ -1812,6 +1847,12 @@ static int nau8821_i2c_probe(struct i2c_client *i2c)
 
        nau8821->dev = dev;
        nau8821->irq = i2c->irq;
+
+       nau8821_check_quirks();
+
+       if (nau8821_quirk & NAU8821_JD_ACTIVE_HIGH)
+               nau8821->jkdet_polarity = 0;
+
        nau8821_print_device_properties(nau8821);
 
        nau8821_reset_chip(nau8821->regmap);
index 0ed4fa2..eceed82 100644 (file)
@@ -53,7 +53,6 @@ static const struct reg_sequence init_list[] = {
        {RT5640_PR_BASE + 0x3d, 0x3600},
        {RT5640_PR_BASE + 0x12, 0x0aa8},
        {RT5640_PR_BASE + 0x14, 0x0aaa},
-       {RT5640_PR_BASE + 0x20, 0x6110},
        {RT5640_PR_BASE + 0x21, 0xe0e0},
        {RT5640_PR_BASE + 0x23, 0x1804},
 };
@@ -2567,9 +2566,10 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
        if (jack_data && jack_data->use_platform_clock)
                rt5640->use_platform_clock = jack_data->use_platform_clock;
 
-       ret = request_irq(rt5640->irq, rt5640_irq,
-                         IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                         "rt5640", rt5640);
+       ret = devm_request_threaded_irq(component->dev, rt5640->irq,
+                                       NULL, rt5640_irq,
+                                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                                       "rt5640", rt5640);
        if (ret) {
                dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
                rt5640_disable_jack_detect(component);
@@ -2622,8 +2622,9 @@ static void rt5640_enable_hda_jack_detect(
 
        rt5640->jack = jack;
 
-       ret = request_irq(rt5640->irq, rt5640_irq,
-                         IRQF_TRIGGER_RISING | IRQF_ONESHOT, "rt5640", rt5640);
+       ret = devm_request_threaded_irq(component->dev, rt5640->irq,
+                                       NULL, rt5640_irq, IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                                       "rt5640", rt5640);
        if (ret) {
                dev_warn(component->dev, "Failed to reguest IRQ %d: %d\n", rt5640->irq, ret);
                rt5640->irq = -ENXIO;
index acc7fb1..a506d94 100644 (file)
@@ -3950,7 +3950,11 @@ static int rt5645_i2c_probe(struct i2c_client *i2c)
         * read and power On.
         */
        msleep(TIME_TO_POWER_MS);
-       regmap_read(regmap, RT5645_VENDOR_ID2, &val);
+       ret = regmap_read(regmap, RT5645_VENDOR_ID2, &val);
+       if (ret < 0) {
+               dev_err(&i2c->dev, "Failed to read: 0x%02X\n, ret = %d", RT5645_VENDOR_ID2, ret);
+               goto err_enable;
+       }
 
        switch (val) {
        case RT5645_DEVICE_ID:
index 67404f4..4968a8c 100644 (file)
@@ -750,8 +750,15 @@ static int __maybe_unused rt5682_dev_resume(struct device *dev)
        if (!rt5682->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt5682->disable_irq == true) {
+                       mutex_lock(&rt5682->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
+                       rt5682->disable_irq = false;
+                       mutex_unlock(&rt5682->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
index 119e1f9..23f23f7 100644 (file)
@@ -438,8 +438,16 @@ static int __maybe_unused rt711_sdca_dev_resume(struct device *dev)
        if (!rt711->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt711->disable_irq == true) {
+                       mutex_lock(&rt711->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+                       rt711->disable_irq = false;
+                       mutex_unlock(&rt711->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT711_PROBE_TIMEOUT));
index 87dafcb..33dced3 100644 (file)
@@ -538,8 +538,15 @@ static int __maybe_unused rt711_dev_resume(struct device *dev)
        if (!rt711->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt711->disable_irq == true) {
+                       mutex_lock(&rt711->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_INTMASK1, SDW_SCP_INT1_IMPL_DEF);
+                       rt711->disable_irq = false;
+                       mutex_unlock(&rt711->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT711_PROBE_TIMEOUT));
index ad06267..6bc5039 100644 (file)
@@ -438,8 +438,16 @@ static int __maybe_unused rt712_sdca_dev_resume(struct device *dev)
        if (!rt712->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt712->disable_irq == true) {
+                       mutex_lock(&rt712->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+                       rt712->disable_irq = false;
+                       mutex_unlock(&rt712->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT712_PROBE_TIMEOUT));
index cc57e4e..e9103ff 100644 (file)
@@ -463,8 +463,16 @@ static int __maybe_unused rt722_sdca_dev_resume(struct device *dev)
        if (!rt722->first_hw_init)
                return 0;
 
-       if (!slave->unattach_request)
+       if (!slave->unattach_request) {
+               if (rt722->disable_irq == true) {
+                       mutex_lock(&rt722->disable_irq_lock);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_6);
+                       sdw_write_no_pm(slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8);
+                       rt722->disable_irq = false;
+                       mutex_unlock(&rt722->disable_irq_lock);
+               }
                goto regmap_sync;
+       }
 
        time = wait_for_completion_timeout(&slave->initialization_complete,
                                msecs_to_jiffies(RT722_PROBE_TIMEOUT));
index 1911750..5da1934 100644 (file)
@@ -1454,7 +1454,7 @@ struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
                return ERR_PTR(-EINVAL);
        }
 
-       mbhc = devm_kzalloc(dev, sizeof(*mbhc), GFP_KERNEL);
+       mbhc = kzalloc(sizeof(*mbhc), GFP_KERNEL);
        if (!mbhc)
                return ERR_PTR(-ENOMEM);
 
@@ -1474,61 +1474,76 @@ struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
 
        INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug);
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_sw_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_sw_intr, NULL,
                                        wcd_mbhc_mech_plug_detect_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "mbhc sw intr", mbhc);
        if (ret)
-               goto err;
+               goto err_free_mbhc;
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_press_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_press_intr, NULL,
                                        wcd_mbhc_btn_press_handler,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "Button Press detect", mbhc);
        if (ret)
-               goto err;
+               goto err_free_sw_intr;
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_release_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_release_intr, NULL,
                                        wcd_mbhc_btn_release_handler,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "Button Release detect", mbhc);
        if (ret)
-               goto err;
+               goto err_free_btn_press_intr;
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_ins_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_ins_intr, NULL,
                                        wcd_mbhc_adc_hs_ins_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "Elect Insert", mbhc);
        if (ret)
-               goto err;
+               goto err_free_btn_release_intr;
 
        disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_rem_intr, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_rem_intr, NULL,
                                        wcd_mbhc_adc_hs_rem_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "Elect Remove", mbhc);
        if (ret)
-               goto err;
+               goto err_free_hs_ins_intr;
 
        disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr);
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_left_ocp, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->hph_left_ocp, NULL,
                                        wcd_mbhc_hphl_ocp_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "HPH_L OCP detect", mbhc);
        if (ret)
-               goto err;
+               goto err_free_hs_rem_intr;
 
-       ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_right_ocp, NULL,
+       ret = request_threaded_irq(mbhc->intr_ids->hph_right_ocp, NULL,
                                        wcd_mbhc_hphr_ocp_irq,
                                        IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                        "HPH_R OCP detect", mbhc);
        if (ret)
-               goto err;
+               goto err_free_hph_left_ocp;
 
        return mbhc;
-err:
+
+err_free_hph_left_ocp:
+       free_irq(mbhc->intr_ids->hph_left_ocp, mbhc);
+err_free_hs_rem_intr:
+       free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
+err_free_hs_ins_intr:
+       free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
+err_free_btn_release_intr:
+       free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc);
+err_free_btn_press_intr:
+       free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc);
+err_free_sw_intr:
+       free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc);
+err_free_mbhc:
+       kfree(mbhc);
+
        dev_err(dev, "Failed to request mbhc interrupts %d\n", ret);
 
        return ERR_PTR(ret);
@@ -1537,9 +1552,19 @@ EXPORT_SYMBOL(wcd_mbhc_init);
 
 void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
 {
+       free_irq(mbhc->intr_ids->hph_right_ocp, mbhc);
+       free_irq(mbhc->intr_ids->hph_left_ocp, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc);
+       free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc);
+
        mutex_lock(&mbhc->lock);
        wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
        mutex_unlock(&mbhc->lock);
+
+       kfree(mbhc);
 }
 EXPORT_SYMBOL(wcd_mbhc_deinit);
 
index c0d1fa3..1b6e376 100644 (file)
@@ -2642,7 +2642,7 @@ static int wcd934x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon
        return rc;
 }
 
-static inline void wcd934x_mbhc_get_result_params(struct wcd934x_codec *wcd934x,
+static void wcd934x_mbhc_get_result_params(struct wcd934x_codec *wcd934x,
                                                s16 *d1_a, u16 noff,
                                                int32_t *zdet)
 {
@@ -2683,7 +2683,7 @@ static inline void wcd934x_mbhc_get_result_params(struct wcd934x_codec *wcd934x,
        else if (x1 < minCode_param[noff])
                *zdet = WCD934X_ZDET_FLOATING_IMPEDANCE;
 
-       dev_info(wcd934x->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n",
+       dev_dbg(wcd934x->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%di (milliohm)\n",
                __func__, d1, c1, x1, *zdet);
 ramp_down:
        i = 0;
@@ -2740,8 +2740,8 @@ z_right:
        *zr = zdet;
 }
 
-static inline void wcd934x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
-                                             int32_t *z_val, int flag_l_r)
+static void wcd934x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
+                                       int32_t *z_val, int flag_l_r)
 {
        s16 q1;
        int q1_cal;
@@ -3044,6 +3044,17 @@ static int wcd934x_mbhc_init(struct snd_soc_component *component)
 
        return 0;
 }
+
+static void wcd934x_mbhc_deinit(struct snd_soc_component *component)
+{
+       struct wcd934x_codec *wcd = snd_soc_component_get_drvdata(component);
+
+       if (!wcd->mbhc)
+               return;
+
+       wcd_mbhc_deinit(wcd->mbhc);
+}
+
 static int wcd934x_comp_probe(struct snd_soc_component *component)
 {
        struct wcd934x_codec *wcd = dev_get_drvdata(component->dev);
@@ -3077,6 +3088,7 @@ static void wcd934x_comp_remove(struct snd_soc_component *comp)
 {
        struct wcd934x_codec *wcd = dev_get_drvdata(comp->dev);
 
+       wcd934x_mbhc_deinit(comp);
        wcd_clsh_ctrl_free(wcd->clsh_ctrl);
 }
 
index e7d6a02..a3c6806 100644 (file)
@@ -210,7 +210,7 @@ struct wcd938x_priv {
 };
 
 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(ear_pa_gain, 600, -1800);
-static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(line_gain, 600, -3000);
+static const DECLARE_TLV_DB_SCALE(line_gain, -3000, 150, -3000);
 static const SNDRV_CTL_TLVD_DECLARE_DB_MINMAX(analog_gain, 0, 3000);
 
 struct wcd938x_mbhc_zdet_param {
@@ -2124,10 +2124,11 @@ static int wcd938x_mbhc_micb_ctrl_threshold_mic(struct snd_soc_component *compon
        return wcd938x_mbhc_micb_adjust_voltage(component, micb_mv, MIC_BIAS_2);
 }
 
-static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
+static void wcd938x_mbhc_get_result_params(struct snd_soc_component *component,
                                                s16 *d1_a, u16 noff,
                                                int32_t *zdet)
 {
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
        int i;
        int val, val1;
        s16 c1;
@@ -2154,8 +2155,8 @@ static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
                usleep_range(5000, 5050);
 
        if (!c1 || !x1) {
-               pr_err("%s: Impedance detect ramp error, c1=%d, x1=0x%x\n",
-                       __func__, c1, x1);
+               dev_err(component->dev, "Impedance detect ramp error, c1=%d, x1=0x%x\n",
+                       c1, x1);
                goto ramp_down;
        }
        d1 = d1_a[c1];
@@ -2165,7 +2166,7 @@ static inline void wcd938x_mbhc_get_result_params(struct wcd938x_priv *wcd938x,
        else if (x1 < minCode_param[noff])
                *zdet = WCD938X_ZDET_FLOATING_IMPEDANCE;
 
-       pr_err("%s: d1=%d, c1=%d, x1=0x%x, z_val=%d(milliOhm)\n",
+       dev_dbg(component->dev, "%s: d1=%d, c1=%d, x1=0x%x, z_val=%d (milliohm)\n",
                __func__, d1, c1, x1, *zdet);
 ramp_down:
        i = 0;
@@ -2210,7 +2211,7 @@ static void wcd938x_mbhc_zdet_ramp(struct snd_soc_component *component,
                           WCD938X_ANA_MBHC_ZDET, 0x80, 0x80);
        dev_dbg(component->dev, "%s: ramp for HPH_L, noff = %d\n",
                __func__, zdet_param->noff);
-       wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+       wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet);
        regmap_update_bits(wcd938x->regmap,
                           WCD938X_ANA_MBHC_ZDET, 0x80, 0x00);
 
@@ -2224,15 +2225,15 @@ z_right:
                           WCD938X_ANA_MBHC_ZDET, 0x40, 0x40);
        dev_dbg(component->dev, "%s: ramp for HPH_R, noff = %d\n",
                __func__, zdet_param->noff);
-       wcd938x_mbhc_get_result_params(wcd938x, d1_a, zdet_param->noff, &zdet);
+       wcd938x_mbhc_get_result_params(component, d1_a, zdet_param->noff, &zdet);
        regmap_update_bits(wcd938x->regmap,
                           WCD938X_ANA_MBHC_ZDET, 0x40, 0x00);
 
        *zr = zdet;
 }
 
-static inline void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
-                                             int32_t *z_val, int flag_l_r)
+static void wcd938x_wcd_mbhc_qfuse_cal(struct snd_soc_component *component,
+                                       int32_t *z_val, int flag_l_r)
 {
        s16 q1;
        int q1_cal;
@@ -2625,6 +2626,8 @@ static int wcd938x_mbhc_init(struct snd_soc_component *component)
                                                     WCD938X_IRQ_HPHR_OCP_INT);
 
        wcd938x->wcd_mbhc = wcd_mbhc_init(component, &mbhc_cb, intr_ids, wcd_mbhc_fields, true);
+       if (IS_ERR(wcd938x->wcd_mbhc))
+               return PTR_ERR(wcd938x->wcd_mbhc);
 
        snd_soc_add_component_controls(component, impedance_detect_controls,
                                       ARRAY_SIZE(impedance_detect_controls));
@@ -2633,6 +2636,14 @@ static int wcd938x_mbhc_init(struct snd_soc_component *component)
 
        return 0;
 }
+
+static void wcd938x_mbhc_deinit(struct snd_soc_component *component)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+       wcd_mbhc_deinit(wcd938x->wcd_mbhc);
+}
+
 /* END MBHC */
 
 static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
@@ -2652,8 +2663,8 @@ static const struct snd_kcontrol_new wcd938x_snd_controls[] = {
                       wcd938x_get_swr_port, wcd938x_set_swr_port),
        SOC_SINGLE_EXT("DSD_R Switch", WCD938X_DSD_R, 0, 1, 0,
                       wcd938x_get_swr_port, wcd938x_set_swr_port),
-       SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 0x18, 0, line_gain),
-       SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 0x18, 0, line_gain),
+       SOC_SINGLE_TLV("HPHL Volume", WCD938X_HPH_L_EN, 0, 0x18, 1, line_gain),
+       SOC_SINGLE_TLV("HPHR Volume", WCD938X_HPH_R_EN, 0, 0x18, 1, line_gain),
        WCD938X_EAR_PA_GAIN_TLV("EAR_PA Volume", WCD938X_ANA_EAR_COMPANDER_CTL,
                                2, 0x10, 0, ear_pa_gain),
        SOC_SINGLE_EXT("ADC1 Switch", WCD938X_ADC1, 1, 1, 0,
@@ -3080,16 +3091,33 @@ static int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev)
 static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
 {
        struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+       struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev;
        struct device *dev = component->dev;
+       unsigned long time_left;
        int ret, i;
 
+       time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
+                                               msecs_to_jiffies(2000));
+       if (!time_left) {
+               dev_err(dev, "soundwire device init timeout\n");
+               return -ETIMEDOUT;
+       }
+
        snd_soc_component_init_regmap(component, wcd938x->regmap);
 
+       ret = pm_runtime_resume_and_get(dev);
+       if (ret < 0)
+               return ret;
+
        wcd938x->variant = snd_soc_component_read_field(component,
                                                 WCD938X_DIGITAL_EFUSE_REG_0,
                                                 WCD938X_ID_MASK);
 
        wcd938x->clsh_info = wcd_clsh_ctrl_alloc(component, WCD938X);
+       if (IS_ERR(wcd938x->clsh_info)) {
+               pm_runtime_put(dev);
+               return PTR_ERR(wcd938x->clsh_info);
+       }
 
        wcd938x_io_init(wcd938x);
        /* Set all interrupts as edge triggered */
@@ -3098,6 +3126,8 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
                             (WCD938X_DIGITAL_INTR_LEVEL_0 + i), 0);
        }
 
+       pm_runtime_put(dev);
+
        wcd938x->hphr_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
                                                       WCD938X_IRQ_HPHR_PDM_WD_INT);
        wcd938x->hphl_pdm_wd_int = regmap_irq_get_virq(wcd938x->irq_chip,
@@ -3109,20 +3139,26 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
        ret = request_threaded_irq(wcd938x->hphr_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
                                   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                   "HPHR PDM WD INT", wcd938x);
-       if (ret)
+       if (ret) {
                dev_err(dev, "Failed to request HPHR WD interrupt (%d)\n", ret);
+               goto err_free_clsh_ctrl;
+       }
 
        ret = request_threaded_irq(wcd938x->hphl_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
                                   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                   "HPHL PDM WD INT", wcd938x);
-       if (ret)
+       if (ret) {
                dev_err(dev, "Failed to request HPHL WD interrupt (%d)\n", ret);
+               goto err_free_hphr_pdm_wd_int;
+       }
 
        ret = request_threaded_irq(wcd938x->aux_pdm_wd_int, NULL, wcd938x_wd_handle_irq,
                                   IRQF_ONESHOT | IRQF_TRIGGER_RISING,
                                   "AUX PDM WD INT", wcd938x);
-       if (ret)
+       if (ret) {
                dev_err(dev, "Failed to request Aux WD interrupt (%d)\n", ret);
+               goto err_free_hphl_pdm_wd_int;
+       }
 
        /* Disable watchdog interrupt for HPH and AUX */
        disable_irq_nosync(wcd938x->hphr_pdm_wd_int);
@@ -3137,7 +3173,7 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
                        dev_err(component->dev,
                                "%s: Failed to add snd ctrls for variant: %d\n",
                                __func__, wcd938x->variant);
-                       goto err;
+                       goto err_free_aux_pdm_wd_int;
                }
                break;
        case WCD9385:
@@ -3147,7 +3183,7 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
                        dev_err(component->dev,
                                "%s: Failed to add snd ctrls for variant: %d\n",
                                __func__, wcd938x->variant);
-                       goto err;
+                       goto err_free_aux_pdm_wd_int;
                }
                break;
        default:
@@ -3155,12 +3191,38 @@ static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
        }
 
        ret = wcd938x_mbhc_init(component);
-       if (ret)
+       if (ret) {
                dev_err(component->dev,  "mbhc initialization failed\n");
-err:
+               goto err_free_aux_pdm_wd_int;
+       }
+
+       return 0;
+
+err_free_aux_pdm_wd_int:
+       free_irq(wcd938x->aux_pdm_wd_int, wcd938x);
+err_free_hphl_pdm_wd_int:
+       free_irq(wcd938x->hphl_pdm_wd_int, wcd938x);
+err_free_hphr_pdm_wd_int:
+       free_irq(wcd938x->hphr_pdm_wd_int, wcd938x);
+err_free_clsh_ctrl:
+       wcd_clsh_ctrl_free(wcd938x->clsh_info);
+
        return ret;
 }
 
+static void wcd938x_soc_codec_remove(struct snd_soc_component *component)
+{
+       struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
+
+       wcd938x_mbhc_deinit(component);
+
+       free_irq(wcd938x->aux_pdm_wd_int, wcd938x);
+       free_irq(wcd938x->hphl_pdm_wd_int, wcd938x);
+       free_irq(wcd938x->hphr_pdm_wd_int, wcd938x);
+
+       wcd_clsh_ctrl_free(wcd938x->clsh_info);
+}
+
 static int wcd938x_codec_set_jack(struct snd_soc_component *comp,
                                  struct snd_soc_jack *jack, void *data)
 {
@@ -3177,6 +3239,7 @@ static int wcd938x_codec_set_jack(struct snd_soc_component *comp,
 static const struct snd_soc_component_driver soc_codec_dev_wcd938x = {
        .name = "wcd938x_codec",
        .probe = wcd938x_soc_codec_probe,
+       .remove = wcd938x_soc_codec_remove,
        .controls = wcd938x_snd_controls,
        .num_controls = ARRAY_SIZE(wcd938x_snd_controls),
        .dapm_widgets = wcd938x_dapm_widgets,
index 068e610..f2baee7 100644 (file)
@@ -2308,6 +2308,9 @@ static int wm8904_i2c_probe(struct i2c_client *i2c)
        regmap_update_bits(wm8904->regmap, WM8904_BIAS_CONTROL_0,
                            WM8904_POBCTRL, 0);
 
+       /* Fill the cache for the ADC test register */
+       regmap_read(wm8904->regmap, WM8904_ADC_TEST_0, &val);
+
        /* Can leave the device powered off until we need it */
        regcache_cache_only(wm8904->regmap, true);
        regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies), wm8904->supplies);
index 5e09f63..f7676d3 100644 (file)
@@ -507,12 +507,6 @@ static int fsl_sai_set_bclk(struct snd_soc_dai *dai, bool tx, u32 freq)
                                   savediv / 2 - 1);
        }
 
-       if (sai->soc_data->max_register >= FSL_SAI_MCTL) {
-               /* SAI is in master mode at this point, so enable MCLK */
-               regmap_update_bits(sai->regmap, FSL_SAI_MCTL,
-                                  FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN);
-       }
-
        return 0;
 }
 
@@ -719,7 +713,7 @@ static void fsl_sai_config_disable(struct fsl_sai *sai, int dir)
        u32 xcsr, count = 100;
 
        regmap_update_bits(sai->regmap, FSL_SAI_xCSR(tx, ofs),
-                          FSL_SAI_CSR_TERE, 0);
+                          FSL_SAI_CSR_TERE | FSL_SAI_CSR_BCE, 0);
 
        /* TERE will remain set till the end of current frame */
        do {
index 8254c35..550df87 100644 (file)
@@ -91,6 +91,7 @@
 /* SAI Transmit/Receive Control Register */
 #define FSL_SAI_CSR_TERE       BIT(31)
 #define FSL_SAI_CSR_SE         BIT(30)
+#define FSL_SAI_CSR_BCE                BIT(28)
 #define FSL_SAI_CSR_FR         BIT(25)
 #define FSL_SAI_CSR_SR         BIT(24)
 #define FSL_SAI_CSR_xF_SHIFT   16
index 015c370..3fd26f2 100644 (file)
@@ -751,6 +751,8 @@ static int fsl_spdif_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                regmap_update_bits(regmap, REG_SPDIF_SCR, dmaen, 0);
                regmap_update_bits(regmap, REG_SPDIF_SIE, intr, 0);
+               regmap_write(regmap, REG_SPDIF_STL, 0x0);
+               regmap_write(regmap, REG_SPDIF_STR, 0x0);
                break;
        default:
                return -EINVAL;
index 31e0bad..dbff55a 100644 (file)
@@ -476,7 +476,7 @@ static int q6afe_mi2s_set_sysclk(struct snd_soc_dai *dai,
 
 static const struct snd_soc_dapm_route q6afe_dapm_routes[] = {
        {"HDMI Playback", NULL, "HDMI_RX"},
-       {"Display Port Playback", NULL, "DISPLAY_PORT_RX"},
+       {"DISPLAY_PORT_RX_0 Playback", NULL, "DISPLAY_PORT_RX"},
        {"Slimbus Playback", NULL, "SLIMBUS_0_RX"},
        {"Slimbus1 Playback", NULL, "SLIMBUS_1_RX"},
        {"Slimbus2 Playback", NULL, "SLIMBUS_2_RX"},
index 5eb0b86..c90db6d 100644 (file)
@@ -840,6 +840,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
        .pointer        = q6apm_dai_pointer,
        .trigger        = q6apm_dai_trigger,
        .compress_ops   = &q6apm_dai_compress_ops,
+       .use_dai_pcm_id = true,
 };
 
 static int q6apm_dai_probe(struct platform_device *pdev)
index 7bfac94..5d44d07 100644 (file)
@@ -511,6 +511,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
 
        switch (hdr->opcode) {
        case DATA_CMD_RSP_WR_SH_MEM_EP_DATA_BUFFER_DONE_V2:
+               if (!graph->ar_graph)
+                       break;
                client_event = APM_CLIENT_EVENT_DATA_WRITE_DONE;
                mutex_lock(&graph->lock);
                token = hdr->token & APM_WRITE_TOKEN_MASK;
@@ -544,6 +546,8 @@ static int graph_callback(struct gpr_resp_pkt *data, void *priv, int op)
                wake_up(&graph->cmd_wait);
                break;
        case DATA_CMD_RSP_RD_SH_MEM_EP_DATA_BUFFER_V2:
+               if (!graph->ar_graph)
+                       break;
                client_event = APM_CLIENT_EVENT_DATA_READ_DONE;
                mutex_lock(&graph->lock);
                rd_done = data->payload;
@@ -649,8 +653,9 @@ int q6apm_graph_close(struct q6apm_graph *graph)
 {
        struct audioreach_graph *ar_graph = graph->ar_graph;
 
-       gpr_free_port(graph->port);
+       graph->ar_graph = NULL;
        kref_put(&ar_graph->refcount, q6apm_put_audioreach_graph);
+       gpr_free_port(graph->port);
        kfree(graph);
 
        return 0;
index cccc59b..130b22a 100644 (file)
@@ -1277,8 +1277,8 @@ int audioreach_tplg_init(struct snd_soc_component *component)
 
        ret = snd_soc_tplg_component_load(component, &audioreach_tplg_ops, fw);
        if (ret < 0) {
-               dev_err(dev, "tplg component load failed%d\n", ret);
-               ret = -EINVAL;
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "tplg component load failed: %d\n", ret);
        }
 
        release_firmware(fw);
index 11bc525..1a0bde2 100644 (file)
@@ -1988,8 +1988,10 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
        /* probe all components used by DAI links on this card */
        ret = soc_probe_link_components(card);
        if (ret < 0) {
-               dev_err(card->dev,
-                       "ASoC: failed to instantiate card %d\n", ret);
+               if (ret != -EPROBE_DEFER) {
+                       dev_err(card->dev,
+                               "ASoC: failed to instantiate card %d\n", ret);
+               }
                goto probe_end;
        }
 
index 8add361..ad08d4f 100644 (file)
@@ -1732,7 +1732,8 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
 
        ret = snd_soc_add_pcm_runtimes(tplg->comp->card, link, 1);
        if (ret < 0) {
-               dev_err(tplg->dev, "ASoC: adding FE link failed\n");
+               if (ret != -EPROBE_DEFER)
+                       dev_err(tplg->dev, "ASoC: adding FE link failed\n");
                goto err;
        }
 
@@ -2492,8 +2493,11 @@ static int soc_tplg_process_headers(struct soc_tplg *tplg)
                        /* load the header object */
                        ret = soc_tplg_load_header(tplg, hdr);
                        if (ret < 0) {
-                               dev_err(tplg->dev,
-                                       "ASoC: topology: could not load header: %d\n", ret);
+                               if (ret != -EPROBE_DEFER) {
+                                       dev_err(tplg->dev,
+                                               "ASoC: topology: could not load header: %d\n",
+                                               ret);
+                               }
                                return ret;
                        }
 
index 2ae76bc..afb5054 100644 (file)
@@ -217,6 +217,7 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
                              unsigned int image_length)
 {
        struct snd_sof_dev *sdev = adata->dev;
+       const struct sof_amd_acp_desc *desc = get_chip_info(sdev->pdata);
        unsigned int tx_count, fw_qualifier, val;
        int ret;
 
@@ -251,9 +252,12 @@ int configure_and_run_sha_dma(struct acp_dev_data *adata, void *image_addr,
                return ret;
        }
 
-       ret = psp_send_cmd(adata, MBOX_ACP_SHA_DMA_COMMAND);
-       if (ret)
-               return ret;
+       /* psp_send_cmd only required for renoir platform (rev - 3) */
+       if (desc->rev == 3) {
+               ret = psp_send_cmd(adata, MBOX_ACP_SHA_DMA_COMMAND);
+               if (ret)
+                       return ret;
+       }
 
        ret = snd_sof_dsp_read_poll_timeout(sdev, ACP_DSP_BAR, ACP_SHA_DSP_FW_QUALIFIER,
                                            fw_qualifier, fw_qualifier & DSP_FW_RUN_ENABLE,
index 1d3bca2..35da85a 100644 (file)
@@ -186,7 +186,6 @@ static ssize_t dfsentry_trace_filter_write(struct file *file, const char __user
        struct snd_sof_dfsentry *dfse = file->private_data;
        struct sof_ipc_trace_filter_elem *elems = NULL;
        struct snd_sof_dev *sdev = dfse->sdev;
-       loff_t pos = 0;
        int num_elems;
        char *string;
        int ret;
@@ -201,11 +200,11 @@ static ssize_t dfsentry_trace_filter_write(struct file *file, const char __user
        if (!string)
                return -ENOMEM;
 
-       /* assert null termination */
-       string[count] = 0;
-       ret = simple_write_to_buffer(string, count, &pos, from, count);
-       if (ret < 0)
+       if (copy_from_user(string, from, count)) {
+               ret = -EFAULT;
                goto error;
+       }
+       string[count] = '\0';
 
        ret = trace_filter_parse(sdev, string, &num_elems, &elems);
        if (ret < 0)
index bd0b10c..7d003f0 100644 (file)
@@ -2,7 +2,7 @@
 //
 // tegra210_adx.c - Tegra210 ADX driver
 //
-// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+// Copyright (c) 2021-2023 NVIDIA CORPORATION.  All rights reserved.
 
 #include <linux/clk.h>
 #include <linux/device.h>
@@ -175,10 +175,20 @@ static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
        mc = (struct soc_mixer_control *)kcontrol->private_value;
        enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32));
 
+       /*
+        * TODO: Simplify this logic to just return from bytes_map[]
+        *
+        * Presently below is required since bytes_map[] is
+        * tightly packed and cannot store the control value of 256.
+        * Byte mask state is used to know if 256 needs to be returned.
+        * Note that for control value of 256, the put() call stores 0
+        * in the bytes_map[] and disables the corresponding bit in
+        * byte_mask[].
+        */
        if (enabled)
                ucontrol->value.integer.value[0] = bytes_map[mc->reg];
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.integer.value[0] = 256;
 
        return 0;
 }
@@ -192,19 +202,19 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
        int value = ucontrol->value.integer.value[0];
        struct soc_mixer_control *mc =
                (struct soc_mixer_control *)kcontrol->private_value;
+       unsigned int mask_val = adx->byte_mask[mc->reg / 32];
 
-       if (value == bytes_map[mc->reg])
+       if (value >= 0 && value <= 255)
+               mask_val |= (1 << (mc->reg % 32));
+       else
+               mask_val &= ~(1 << (mc->reg % 32));
+
+       if (mask_val == adx->byte_mask[mc->reg / 32])
                return 0;
 
-       if (value >= 0 && value <= 255) {
-               /* update byte map and enable slot */
-               bytes_map[mc->reg] = value;
-               adx->byte_mask[mc->reg / 32] |= (1 << (mc->reg % 32));
-       } else {
-               /* reset byte map and disable slot */
-               bytes_map[mc->reg] = 0;
-               adx->byte_mask[mc->reg / 32] &= ~(1 << (mc->reg % 32));
-       }
+       /* Update byte map and slot */
+       bytes_map[mc->reg] = value % 256;
+       adx->byte_mask[mc->reg / 32] = mask_val;
 
        return 1;
 }
index 782a141..1798769 100644 (file)
@@ -2,7 +2,7 @@
 //
 // tegra210_amx.c - Tegra210 AMX driver
 //
-// Copyright (c) 2021 NVIDIA CORPORATION.  All rights reserved.
+// Copyright (c) 2021-2023 NVIDIA CORPORATION.  All rights reserved.
 
 #include <linux/clk.h>
 #include <linux/device.h>
@@ -203,10 +203,20 @@ static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol,
        else
                enabled = amx->byte_mask[0] & (1 << reg);
 
+       /*
+        * TODO: Simplify this logic to just return from bytes_map[]
+        *
+        * Presently below is required since bytes_map[] is
+        * tightly packed and cannot store the control value of 256.
+        * Byte mask state is used to know if 256 needs to be returned.
+        * Note that for control value of 256, the put() call stores 0
+        * in the bytes_map[] and disables the corresponding bit in
+        * byte_mask[].
+        */
        if (enabled)
                ucontrol->value.integer.value[0] = bytes_map[reg];
        else
-               ucontrol->value.integer.value[0] = 0;
+               ucontrol->value.integer.value[0] = 256;
 
        return 0;
 }
@@ -221,25 +231,19 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
        unsigned char *bytes_map = (unsigned char *)&amx->map;
        int reg = mc->reg;
        int value = ucontrol->value.integer.value[0];
+       unsigned int mask_val = amx->byte_mask[reg / 32];
 
-       if (value == bytes_map[reg])
+       if (value >= 0 && value <= 255)
+               mask_val |= (1 << (reg % 32));
+       else
+               mask_val &= ~(1 << (reg % 32));
+
+       if (mask_val == amx->byte_mask[reg / 32])
                return 0;
 
-       if (value >= 0 && value <= 255) {
-               /* Update byte map and enable slot */
-               bytes_map[reg] = value;
-               if (reg > 31)
-                       amx->byte_mask[1] |= (1 << (reg - 32));
-               else
-                       amx->byte_mask[0] |= (1 << reg);
-       } else {
-               /* Reset byte map and disable slot */
-               bytes_map[reg] = 0;
-               if (reg > 31)
-                       amx->byte_mask[1] &= ~(1 << (reg - 32));
-               else
-                       amx->byte_mask[0] &= ~(1 << reg);
-       }
+       /* Update byte map and slot */
+       bytes_map[reg] = value % 256;
+       amx->byte_mask[reg / 32] = mask_val;
 
        return 1;
 }
index f4bd1e8..23260aa 100644 (file)
@@ -374,6 +374,15 @@ static const struct usbmix_name_map corsair_virtuoso_map[] = {
        { 0 }
 };
 
+/* Microsoft USB Link headset */
+/* a guess work: raw playback volume values are from 2 to 129 */
+static const struct usbmix_dB_map ms_usb_link_dB = { -3225, 0, true };
+static const struct usbmix_name_map ms_usb_link_map[] = {
+       { 9, NULL, .dB = &ms_usb_link_dB },
+       { 10, NULL }, /* Headset Capture volume; seems non-working, disabled */
+       { 0 }   /* terminator */
+};
+
 /* ASUS ROG Zenith II with Realtek ALC1220-VB */
 static const struct usbmix_name_map asus_zenith_ii_map[] = {
        { 19, NULL, 12 }, /* FU, Input Gain Pad - broken response, disabled */
@@ -668,6 +677,11 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
                .id = USB_ID(0x1395, 0x0025),
                .map = sennheiser_pc8_map,
        },
+       {
+               /* Microsoft USB Link headset */
+               .id = USB_ID(0x045e, 0x083c),
+               .map = ms_usb_link_map,
+       },
        { 0 } /* terminator */
 };
 
index 30bcb80..598659d 100644 (file)
@@ -1876,8 +1876,10 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
 
        /* XMOS based USB DACs */
        switch (chip->usb_id) {
-       case USB_ID(0x1511, 0x0037): /* AURALiC VEGA */
-       case USB_ID(0x21ed, 0xd75a): /* Accuphase DAC-60 option card */
+       case USB_ID(0x139f, 0x5504): /* Nagra DAC */
+       case USB_ID(0x20b1, 0x3089): /* Mola-Mola DAC */
+       case USB_ID(0x2522, 0x0007): /* LH Labs Geek Out 1V5 */
+       case USB_ID(0x2522, 0x0009): /* LH Labs Geek Pulse X Inifinity 2V0 */
        case USB_ID(0x2522, 0x0012): /* LH Labs VI DAC Infinity */
        case USB_ID(0x2772, 0x0230): /* Pro-Ject Pre Box S2 Digital */
                if (fp->altsetting == 2)
@@ -1887,14 +1889,18 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
        case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
        case USB_ID(0x16d0, 0x06b2): /* NuPrime DAC-10 */
-       case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
+       case USB_ID(0x16d0, 0x06b4): /* NuPrime Audio HD-AVP/AVA */
        case USB_ID(0x16d0, 0x0733): /* Furutech ADL Stratos */
+       case USB_ID(0x16d0, 0x09d8): /* NuPrime IDA-8 */
        case USB_ID(0x16d0, 0x09db): /* NuPrime Audio DAC-9 */
+       case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x1db5, 0x0003): /* Bryston BDA3 */
+       case USB_ID(0x20a0, 0x4143): /* WaveIO USB Audio 2.0 */
        case USB_ID(0x22e1, 0xca01): /* HDTA Serenade DSD */
        case USB_ID(0x249c, 0x9326): /* M2Tech Young MkIII */
        case USB_ID(0x2616, 0x0106): /* PS Audio NuWave DAC */
        case USB_ID(0x2622, 0x0041): /* Audiolab M-DAC+ */
+       case USB_ID(0x278b, 0x5100): /* Rotel RC-1590 */
        case USB_ID(0x27f7, 0x3002): /* W4S DAC-2v2SE */
        case USB_ID(0x29a2, 0x0086): /* Mutec MC3+ USB */
        case USB_ID(0x6b42, 0x0042): /* MSB Technology */
@@ -1904,9 +1910,6 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
 
        /* Amanero Combo384 USB based DACs with native DSD support */
        case USB_ID(0x16d0, 0x071a):  /* Amanero - Combo384 */
-       case USB_ID(0x2ab6, 0x0004):  /* T+A DAC8DSD-V2.0, MP1000E-V2.0, MP2000R-V2.0, MP2500R-V2.0, MP3100HV-V2.0 */
-       case USB_ID(0x2ab6, 0x0005):  /* T+A USB HD Audio 1 */
-       case USB_ID(0x2ab6, 0x0006):  /* T+A USB HD Audio 2 */
                if (fp->altsetting == 2) {
                        switch (le16_to_cpu(chip->dev->descriptor.bcdDevice)) {
                        case 0x199:
@@ -2013,6 +2016,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_IGNORE_CTL_ERROR),
        DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x045e, 0x083c, /* MS USB Link headset */
+                  QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_DISABLE_AUTOSUSPEND),
        DEVICE_FLG(0x046d, 0x084c, /* Logitech ConferenceCam Connect */
                   QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_CTL_MSG_DELAY_1M),
        DEVICE_FLG(0x046d, 0x0991, /* Logitech QuickCam Pro */
@@ -2048,6 +2054,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_IFACE_DELAY),
        DEVICE_FLG(0x0644, 0x805f, /* TEAC Model 12 */
                   QUIRK_FLAG_FORCE_IFACE_RESET),
+       DEVICE_FLG(0x0644, 0x806b, /* TEAC UD-701 */
+                  QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY |
+                  QUIRK_FLAG_IFACE_DELAY),
        DEVICE_FLG(0x06f8, 0xb000, /* Hercules DJ Console (Windows Edition) */
                   QUIRK_FLAG_IGNORE_CTL_ERROR),
        DEVICE_FLG(0x06f8, 0xd002, /* Hercules DJ Console (Macintosh Edition) */
@@ -2086,6 +2095,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
        DEVICE_FLG(0x154e, 0x3006, /* Marantz SA-14S1 */
                   QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+       DEVICE_FLG(0x154e, 0x300b, /* Marantz SA-KI RUBY / SA-12 */
+                  QUIRK_FLAG_DSD_RAW),
        DEVICE_FLG(0x154e, 0x500e, /* Denon DN-X1600 */
                   QUIRK_FLAG_IGNORE_CLOCK_SOURCE),
        DEVICE_FLG(0x1686, 0x00dd, /* Zoom R16/24 */
@@ -2130,6 +2141,10 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
        DEVICE_FLG(0x21b4, 0x0081, /* AudioQuest DragonFly */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
+       DEVICE_FLG(0x21b4, 0x0230, /* Ayre QB-9 Twenty */
+                  QUIRK_FLAG_DSD_RAW),
+       DEVICE_FLG(0x21b4, 0x0232, /* Ayre QX-5 Twenty */
+                  QUIRK_FLAG_DSD_RAW),
        DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
                   QUIRK_FLAG_SET_IFACE_FIRST),
        DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
@@ -2172,12 +2187,18 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_VALIDATE_RATES),
        VENDOR_FLG(0x1235, /* Focusrite Novation */
                   QUIRK_FLAG_VALIDATE_RATES),
+       VENDOR_FLG(0x1511, /* AURALiC */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x152a, /* Thesycon devices */
                   QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x18d1, /* iBasso devices */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x1de7, /* Phoenix Audio */
                   QUIRK_FLAG_GET_SAMPLE_RATE),
        VENDOR_FLG(0x20b1, /* XMOS based devices */
                   QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x21ed, /* Accuphase Laboratory */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x22d9, /* Oppo */
                   QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x23ba, /* Playback Design */
@@ -2193,10 +2214,14 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
                   QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x2ab6, /* T+A devices */
                   QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x2d87, /* Cayin device */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x3336, /* HEM devices */
                   QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x3353, /* Khadas devices */
                   QUIRK_FLAG_DSD_RAW),
+       VENDOR_FLG(0x35f4, /* MSB Technology */
+                  QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0x3842, /* EVGA */
                   QUIRK_FLAG_DSD_RAW),
        VENDOR_FLG(0xc502, /* HiBy devices */
index 1b3a36f..3ca28d4 100644 (file)
@@ -417,11 +417,10 @@ class YnlFamily(SpecFamily):
         pad = b'\x00' * ((4 - len(attr_payload) % 4) % 4)
         return struct.pack('HH', len(attr_payload) + 4, nl_type) + attr_payload + pad
 
-    def _decode_enum(self, rsp, attr_spec):
-        raw = rsp[attr_spec['name']]
+    def _decode_enum(self, raw, attr_spec):
         enum = self.consts[attr_spec['enum']]
-        i = attr_spec.get('value-start', 0)
         if 'enum-as-flags' in attr_spec and attr_spec['enum-as-flags']:
+            i = 0
             value = set()
             while raw:
                 if raw & 1:
@@ -429,8 +428,8 @@ class YnlFamily(SpecFamily):
                 raw >>= 1
                 i += 1
         else:
-            value = enum.entries_by_val[raw - i].name
-        rsp[attr_spec['name']] = value
+            value = enum.entries_by_val[raw].name
+        return value
 
     def _decode_binary(self, attr, attr_spec):
         if attr_spec.struct_name:
@@ -438,7 +437,7 @@ class YnlFamily(SpecFamily):
             decoded = attr.as_struct(members)
             for m in members:
                 if m.enum:
-                    self._decode_enum(decoded, m)
+                    decoded[m.name] = self._decode_enum(decoded[m.name], m)
         elif attr_spec.sub_type:
             decoded = attr.as_c_array(attr_spec.sub_type)
         else:
@@ -466,6 +465,9 @@ class YnlFamily(SpecFamily):
             else:
                 raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
 
+            if 'enum' in attr_spec:
+                decoded = self._decode_enum(decoded, attr_spec)
+
             if not attr_spec.is_multi:
                 rsp[attr_spec['name']] = decoded
             elif attr_spec.name in rsp:
@@ -473,8 +475,6 @@ class YnlFamily(SpecFamily):
             else:
                 rsp[attr_spec.name] = [decoded]
 
-            if 'enum' in attr_spec:
-                self._decode_enum(rsp, attr_spec)
         return rsp
 
     def _decode_extack_path(self, attrs, attr_set, offset, target):
index 561de0c..512a8f1 100644 (file)
@@ -54,10 +54,11 @@ double perf_pmu__cpu_slots_per_cycle(void)
                perf_pmu__pathname_scnprintf(path, sizeof(path),
                                             pmu->name, "caps/slots");
                /*
-                * The value of slots is not greater than 32 bits, but sysfs__read_int
-                * can't read value with 0x prefix, so use sysfs__read_ull instead.
+                * The value of slots is not greater than 32 bits, but
+                * filename__read_int can't read value with 0x prefix,
+                * so use filename__read_ull instead.
                 */
-               sysfs__read_ull(path, &slots);
+               filename__read_ull(path, &slots);
        }
 
        return slots ? (double)slots : NAN;
index b7223fe..5f3edb3 100644 (file)
@@ -250,6 +250,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
        if (!chain || chain->nr < 3)
                return skip_slot;
 
+       addr_location__init(&al);
        ip = chain->ips[1];
 
        thread__find_symbol(thread, PERF_RECORD_MISC_USER, ip, &al);
@@ -259,6 +260,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
 
        if (!dso) {
                pr_debug("%" PRIx64 " dso is NULL\n", ip);
+               addr_location__exit(&al);
                return skip_slot;
        }
 
@@ -279,5 +281,7 @@ int arch_skip_callchain_idx(struct thread *thread, struct ip_callchain *chain)
                 */
                skip_slot = 3;
        }
+
+       addr_location__exit(&al);
        return skip_slot;
 }
index b2f8284..658fb95 100644 (file)
@@ -1631,6 +1631,16 @@ static bool test__pmu_cpu_valid(void)
        return !!perf_pmus__find("cpu");
 }
 
+static bool test__pmu_cpu_event_valid(void)
+{
+       struct perf_pmu *pmu = perf_pmus__find("cpu");
+
+       if (!pmu)
+               return false;
+
+       return perf_pmu__has_format(pmu, "event");
+}
+
 static bool test__intel_pt_valid(void)
 {
        return !!perf_pmus__find("intel_pt");
@@ -2179,7 +2189,7 @@ static const struct evlist_test test__events_pmu[] = {
        },
        {
                .name  = "cpu/name='COMPLEX_CYCLES_NAME:orig=cycles,desc=chip-clock-ticks',period=0x1,event=0x2/ukp",
-               .valid = test__pmu_cpu_valid,
+               .valid = test__pmu_cpu_event_valid,
                .check = test__checkevent_complex_name,
                /* 3 */
        },
index 00d2e0e..319f36e 100755 (executable)
@@ -4,6 +4,12 @@
 
 set -e
 
+# skip if there's no gcc
+if ! [ -x "$(command -v gcc)" ]; then
+        echo "failed: no gcc compiler"
+        exit 2
+fi
+
 temp_dir=$(mktemp -d /tmp/perf-uprobe-different-cu-sh.XXXXXXXXXX)
 
 cleanup()
@@ -11,7 +17,7 @@ cleanup()
        trap - EXIT TERM INT
        if [[ "${temp_dir}" =~ ^/tmp/perf-uprobe-different-cu-sh.*$ ]]; then
                echo "--- Cleaning up ---"
-               perf probe -x ${temp_dir}/testfile -d foo
+               perf probe -x ${temp_dir}/testfile -d foo || true
                rm -f "${temp_dir}/"*
                rmdir "${temp_dir}"
        fi
index 52e9f06..0b5075e 100644 (file)
@@ -2115,16 +2115,16 @@ __weak int arch_evlist__cmp(const struct evsel *lhs, const struct evsel *rhs)
        return lhs->core.idx - rhs->core.idx;
 }
 
-static int evlist__cmp(void *state, const struct list_head *l, const struct list_head *r)
+static int evlist__cmp(void *_fg_idx, const struct list_head *l, const struct list_head *r)
 {
        const struct perf_evsel *lhs_core = container_of(l, struct perf_evsel, node);
        const struct evsel *lhs = container_of(lhs_core, struct evsel, core);
        const struct perf_evsel *rhs_core = container_of(r, struct perf_evsel, node);
        const struct evsel *rhs = container_of(rhs_core, struct evsel, core);
-       int *leader_idx = state;
-       int lhs_leader_idx = *leader_idx, rhs_leader_idx = *leader_idx, ret;
+       int *force_grouped_idx = _fg_idx;
+       int lhs_sort_idx, rhs_sort_idx, ret;
        const char *lhs_pmu_name, *rhs_pmu_name;
-       bool lhs_has_group = false, rhs_has_group = false;
+       bool lhs_has_group, rhs_has_group;
 
        /*
         * First sort by grouping/leader. Read the leader idx only if the evsel
@@ -2136,15 +2136,25 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list
         */
        if (lhs_core->leader != lhs_core || lhs_core->nr_members > 1) {
                lhs_has_group = true;
-               lhs_leader_idx = lhs_core->leader->idx;
+               lhs_sort_idx = lhs_core->leader->idx;
+       } else {
+               lhs_has_group = false;
+               lhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(lhs)
+                       ? *force_grouped_idx
+                       : lhs_core->idx;
        }
        if (rhs_core->leader != rhs_core || rhs_core->nr_members > 1) {
                rhs_has_group = true;
-               rhs_leader_idx = rhs_core->leader->idx;
+               rhs_sort_idx = rhs_core->leader->idx;
+       } else {
+               rhs_has_group = false;
+               rhs_sort_idx = *force_grouped_idx != -1 && arch_evsel__must_be_in_group(rhs)
+                       ? *force_grouped_idx
+                       : rhs_core->idx;
        }
 
-       if (lhs_leader_idx != rhs_leader_idx)
-               return lhs_leader_idx - rhs_leader_idx;
+       if (lhs_sort_idx != rhs_sort_idx)
+               return lhs_sort_idx - rhs_sort_idx;
 
        /* Group by PMU if there is a group. Groups can't span PMUs. */
        if (lhs_has_group && rhs_has_group) {
@@ -2161,10 +2171,10 @@ static int evlist__cmp(void *state, const struct list_head *l, const struct list
 
 static int parse_events__sort_events_and_fix_groups(struct list_head *list)
 {
-       int idx = 0, unsorted_idx = -1;
+       int idx = 0, force_grouped_idx = -1;
        struct evsel *pos, *cur_leader = NULL;
        struct perf_evsel *cur_leaders_grp = NULL;
-       bool idx_changed = false;
+       bool idx_changed = false, cur_leader_force_grouped = false;
        int orig_num_leaders = 0, num_leaders = 0;
        int ret;
 
@@ -2189,12 +2199,14 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
                 */
                pos->core.idx = idx++;
 
-               if (unsorted_idx == -1 && pos == pos_leader && pos->core.nr_members < 2)
-                       unsorted_idx = pos->core.idx;
+               /* Remember an index to sort all forced grouped events together to. */
+               if (force_grouped_idx == -1 && pos == pos_leader && pos->core.nr_members < 2 &&
+                   arch_evsel__must_be_in_group(pos))
+                       force_grouped_idx = pos->core.idx;
        }
 
        /* Sort events. */
-       list_sort(&unsorted_idx, list, evlist__cmp);
+       list_sort(&force_grouped_idx, list, evlist__cmp);
 
        /*
         * Recompute groups, splitting for PMUs and adding groups for events
@@ -2204,8 +2216,9 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
        list_for_each_entry(pos, list, core.node) {
                const struct evsel *pos_leader = evsel__leader(pos);
                const char *pos_pmu_name = pos->group_pmu_name;
-               const char *cur_leader_pmu_name, *pos_leader_pmu_name;
-               bool force_grouped = arch_evsel__must_be_in_group(pos);
+               const char *cur_leader_pmu_name;
+               bool pos_force_grouped = force_grouped_idx != -1 &&
+                       arch_evsel__must_be_in_group(pos);
 
                /* Reset index and nr_members. */
                if (pos->core.idx != idx)
@@ -2221,7 +2234,8 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
                        cur_leader = pos;
 
                cur_leader_pmu_name = cur_leader->group_pmu_name;
-               if ((cur_leaders_grp != pos->core.leader && !force_grouped) ||
+               if ((cur_leaders_grp != pos->core.leader &&
+                    (!pos_force_grouped || !cur_leader_force_grouped)) ||
                    strcmp(cur_leader_pmu_name, pos_pmu_name)) {
                        /* Event is for a different group/PMU than last. */
                        cur_leader = pos;
@@ -2231,14 +2245,14 @@ static int parse_events__sort_events_and_fix_groups(struct list_head *list)
                         * group.
                         */
                        cur_leaders_grp = pos->core.leader;
-               }
-               pos_leader_pmu_name = pos_leader->group_pmu_name;
-               if (strcmp(pos_leader_pmu_name, pos_pmu_name) || force_grouped) {
                        /*
-                        * Event's PMU differs from its leader's. Groups can't
-                        * span PMUs, so update leader from the group/PMU
-                        * tracker.
+                        * Avoid forcing events into groups with events that
+                        * don't need to be in the group.
                         */
+                       cur_leader_force_grouped = pos_force_grouped;
+               }
+               if (pos_leader != cur_leader) {
+                       /* The leader changed so update it. */
                        evsel__set_leader(pos, cur_leader);
                }
        }
index b6654b9..d5406ef 100644 (file)
@@ -1440,6 +1440,17 @@ void perf_pmu__del_formats(struct list_head *formats)
        }
 }
 
+bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name)
+{
+       struct perf_pmu_format *format;
+
+       list_for_each_entry(format, &pmu->format, list) {
+               if (!strcmp(format->name, name))
+                       return true;
+       }
+       return false;
+}
+
 bool is_pmu_core(const char *name)
 {
        return !strcmp(name, "cpu") || !strcmp(name, "cpum_cf") || is_sysfs_pmu_core(name);
index 203b928..6b414ce 100644 (file)
@@ -234,6 +234,7 @@ int perf_pmu__new_format(struct list_head *list, char *name,
 void perf_pmu__set_format(unsigned long *bits, long from, long to);
 int perf_pmu__format_parse(int dirfd, struct list_head *head);
 void perf_pmu__del_formats(struct list_head *formats);
+bool perf_pmu__has_format(const struct perf_pmu *pmu, const char *name);
 
 bool is_pmu_core(const char *name);
 bool perf_pmu__supports_legacy_cache(const struct perf_pmu *pmu);
index 3cd9de4..c58ba9f 100644 (file)
@@ -152,16 +152,14 @@ static void pmu_read_sysfs(bool core_only)
        }
 
        closedir(dir);
-       if (core_only) {
-               if (!list_empty(&core_pmus))
-                       read_sysfs_core_pmus = true;
-               else {
-                       if (perf_pmu__create_placeholder_core_pmu(&core_pmus))
-                               read_sysfs_core_pmus = true;
-               }
-       } else {
+       if (list_empty(&core_pmus)) {
+               if (!perf_pmu__create_placeholder_core_pmu(&core_pmus))
+                       pr_err("Failure to set up any core PMUs\n");
+       }
+       if (!list_empty(&core_pmus)) {
                read_sysfs_core_pmus = true;
-               read_sysfs_all_pmus = true;
+               if (!core_only)
+                       read_sysfs_all_pmus = true;
        }
 }
 
index 0e78d8e..fb6ab9c 100644 (file)
@@ -999,10 +999,6 @@ static void mock_companion(struct acpi_device *adev, struct device *dev)
 #define SZ_64G (SZ_32G * 2)
 #endif
 
-#ifndef SZ_512G
-#define SZ_512G (SZ_64G * 8)
-#endif
-
 static __init int cxl_rch_init(void)
 {
        int rc, i;
index 71931b2..357adc7 100644 (file)
@@ -47,10 +47,8 @@ static int read_patterns(void)
 
                sprintf(pf, "/sys/kernel/debug/pcmtest/fill_pattern%d", i);
                fp = fopen(pf, "r");
-               if (!fp) {
-                       fclose(fpl);
+               if (!fp)
                        return -1;
-               }
                fread(patterns[i].buf, 1, patterns[i].len, fp);
                fclose(fp);
        }
index 477ba95..3517c0e 100644 (file)
@@ -22,9 +22,16 @@ static int timer_cb(void *map, int *key, struct bpf_timer *timer)
        return buf[69];
 }
 
+__attribute__((noinline))
+static int bad_timer_cb(void *map, int *key, struct bpf_timer *timer)
+{
+       volatile char buf[300] = {};
+       return buf[255] + timer_cb(NULL, NULL, NULL);
+}
+
 SEC("tc")
-__failure __msg("combined stack size of 2 calls")
-int prog(struct __sk_buff *ctx)
+__failure __msg("combined stack size of 2 calls is 576. Too large")
+int pseudo_call_check(struct __sk_buff *ctx)
 {
        struct hmap_elem *elem;
        volatile char buf[256] = {};
@@ -37,4 +44,18 @@ int prog(struct __sk_buff *ctx)
        return bpf_timer_set_callback(&elem->timer, timer_cb) + buf[0];
 }
 
+SEC("tc")
+__failure __msg("combined stack size of 2 calls is 608. Too large")
+int async_call_root_check(struct __sk_buff *ctx)
+{
+       struct hmap_elem *elem;
+       volatile char buf[256] = {};
+
+       elem = bpf_map_lookup_elem(&hmap, &(int){0});
+       if (!elem)
+               return 0;
+
+       return bpf_timer_set_callback(&elem->timer, bad_timer_cb) + buf[0];
+}
+
 char _license[] SEC("license") = "GPL";
index b89de17..f34b14e 100644 (file)
@@ -13,7 +13,7 @@ if grep -qF "f[:[<group>/][<event>]] <func-name>[%return] [<args>]" README ; the
   FPROBES=yes
 fi
 
-if [ -z "$KPROBES" -a "$FPROBES" ] ; then
+if [ -z "$KPROBES" -a -z "$FPROBES" ] ; then
   exit_unsupported
 fi
 
index 07732a1..eb1ff59 100644 (file)
@@ -362,8 +362,10 @@ static inline void read_stats_header(int stats_fd, struct kvm_stats_header *head
 {
        ssize_t ret;
 
-       ret = read(stats_fd, header, sizeof(*header));
-       TEST_ASSERT(ret == sizeof(*header), "Read stats header");
+       ret = pread(stats_fd, header, sizeof(*header), 0);
+       TEST_ASSERT(ret == sizeof(*header),
+                   "Failed to read '%lu' header bytes, ret = '%ld'",
+                   sizeof(*header), ret);
 }
 
 struct kvm_stats_desc *read_stats_descriptors(int stats_fd,
index a7001e2..698c1cf 100644 (file)
@@ -43,8 +43,10 @@ static void stats_test(int stats_fd)
        id = malloc(header.name_size);
        TEST_ASSERT(id, "Allocate memory for id string");
 
-       ret = read(stats_fd, id, header.name_size);
-       TEST_ASSERT(ret == header.name_size, "Read id string");
+       ret = pread(stats_fd, id, header.name_size, sizeof(header));
+       TEST_ASSERT(ret == header.name_size,
+                   "Expected header size '%u', read '%lu' bytes",
+                   header.name_size, ret);
 
        /* Check id string, that should start with "kvm" */
        TEST_ASSERT(!strncmp(id, "kvm", 3) && strlen(id) < header.name_size,
@@ -165,23 +167,7 @@ static void stats_test(int stats_fd)
        free(stats_data);
        free(stats_desc);
        free(id);
-}
-
-
-static void vm_stats_test(struct kvm_vm *vm)
-{
-       int stats_fd = vm_get_stats_fd(vm);
-
-       stats_test(stats_fd);
-       close(stats_fd);
-       TEST_ASSERT(fcntl(stats_fd, F_GETFD) == -1, "Stats fd not freed");
-}
-
-static void vcpu_stats_test(struct kvm_vcpu *vcpu)
-{
-       int stats_fd = vcpu_get_stats_fd(vcpu);
 
-       stats_test(stats_fd);
        close(stats_fd);
        TEST_ASSERT(fcntl(stats_fd, F_GETFD) == -1, "Stats fd not freed");
 }
@@ -199,6 +185,7 @@ static void vcpu_stats_test(struct kvm_vcpu *vcpu)
 
 int main(int argc, char *argv[])
 {
+       int vm_stats_fds, *vcpu_stats_fds;
        int i, j;
        struct kvm_vcpu **vcpus;
        struct kvm_vm **vms;
@@ -231,23 +218,58 @@ int main(int argc, char *argv[])
        vcpus = malloc(sizeof(struct kvm_vcpu *) * max_vm * max_vcpu);
        TEST_ASSERT(vcpus, "Allocate memory for storing vCPU pointers");
 
+       /*
+        * Not per-VM as the array is populated, used, and invalidated within a
+        * single for-loop iteration.
+        */
+       vcpu_stats_fds = calloc(max_vm, sizeof(*vcpu_stats_fds));
+       TEST_ASSERT(vcpu_stats_fds, "Allocate memory for VM stats fds");
+
        for (i = 0; i < max_vm; ++i) {
                vms[i] = vm_create_barebones();
                for (j = 0; j < max_vcpu; ++j)
                        vcpus[i * max_vcpu + j] = __vm_vcpu_add(vms[i], j);
        }
 
-       /* Check stats read for every VM and VCPU */
+       /*
+        * Check stats read for every VM and vCPU, with a variety of flavors.
+        * Note, stats_test() closes the passed in stats fd.
+        */
        for (i = 0; i < max_vm; ++i) {
-               vm_stats_test(vms[i]);
+               /*
+                * Verify that creating multiple userspace references to a
+                * single stats file works and doesn't cause explosions.
+                */
+               vm_stats_fds = vm_get_stats_fd(vms[i]);
+               stats_test(dup(vm_stats_fds));
+
+               /* Verify userspace can instantiate multiple stats files. */
+               stats_test(vm_get_stats_fd(vms[i]));
+
+               for (j = 0; j < max_vcpu; ++j) {
+                       vcpu_stats_fds[j] = vcpu_get_stats_fd(vcpus[i * max_vcpu + j]);
+                       stats_test(dup(vcpu_stats_fds[j]));
+                       stats_test(vcpu_get_stats_fd(vcpus[i * max_vcpu + j]));
+               }
+
+               /*
+                * Close the VM fd and redo the stats tests.  KVM should gift a
+                * reference (to the VM) to each stats fd, i.e. stats should
+                * still be accessible even after userspace has put its last
+                * _direct_ reference to the VM.
+                */
+               kvm_vm_free(vms[i]);
+
+               stats_test(vm_stats_fds);
                for (j = 0; j < max_vcpu; ++j)
-                       vcpu_stats_test(vcpus[i * max_vcpu + j]);
+                       stats_test(vcpu_stats_fds[j]);
+
                ksft_test_result_pass("vm%i\n", i);
        }
 
-       for (i = 0; i < max_vm; ++i)
-               kvm_vm_free(vms[i]);
        free(vms);
+       free(vcpus);
+       free(vcpu_stats_fds);
 
        ksft_finished();        /* Print results and exit() accordingly */
 }
index a284fce..3610981 100644 (file)
 #include "kvm_util.h"
 #include "processor.h"
 
-static void test_cr4_feature_bit(struct kvm_vcpu *vcpu, struct kvm_sregs *orig,
-                                uint64_t feature_bit)
-{
-       struct kvm_sregs sregs;
-       int rc;
-
-       /* Skip the sub-test, the feature is supported. */
-       if (orig->cr4 & feature_bit)
-               return;
-
-       memcpy(&sregs, orig, sizeof(sregs));
-       sregs.cr4 |= feature_bit;
-
-       rc = _vcpu_sregs_set(vcpu, &sregs);
-       TEST_ASSERT(rc, "KVM allowed unsupported CR4 bit (0x%lx)", feature_bit);
-
-       /* Sanity check that KVM didn't change anything. */
-       vcpu_sregs_get(vcpu, &sregs);
-       TEST_ASSERT(!memcmp(&sregs, orig, sizeof(sregs)), "KVM modified sregs");
-}
+#define TEST_INVALID_CR_BIT(vcpu, cr, orig, bit)                               \
+do {                                                                           \
+       struct kvm_sregs new;                                                   \
+       int rc;                                                                 \
+                                                                               \
+       /* Skip the sub-test, the feature/bit is supported. */                  \
+       if (orig.cr & bit)                                                      \
+               break;                                                          \
+                                                                               \
+       memcpy(&new, &orig, sizeof(sregs));                                     \
+       new.cr |= bit;                                                          \
+                                                                               \
+       rc = _vcpu_sregs_set(vcpu, &new);                                       \
+       TEST_ASSERT(rc, "KVM allowed invalid " #cr " bit (0x%lx)", bit);        \
+                                                                               \
+       /* Sanity check that KVM didn't change anything. */                     \
+       vcpu_sregs_get(vcpu, &new);                                             \
+       TEST_ASSERT(!memcmp(&new, &orig, sizeof(new)), "KVM modified sregs");   \
+} while (0)
 
 static uint64_t calc_supported_cr4_feature_bits(void)
 {
@@ -80,7 +79,7 @@ int main(int argc, char *argv[])
        struct kvm_vcpu *vcpu;
        struct kvm_vm *vm;
        uint64_t cr4;
-       int rc;
+       int rc, i;
 
        /*
         * Create a dummy VM, specifically to avoid doing KVM_SET_CPUID2, and
@@ -92,6 +91,7 @@ int main(int argc, char *argv[])
 
        vcpu_sregs_get(vcpu, &sregs);
 
+       sregs.cr0 = 0;
        sregs.cr4 |= calc_supported_cr4_feature_bits();
        cr4 = sregs.cr4;
 
@@ -103,16 +103,24 @@ int main(int argc, char *argv[])
                    sregs.cr4, cr4);
 
        /* Verify all unsupported features are rejected by KVM. */
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_UMIP);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_LA57);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_VMXE);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMXE);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_FSGSBASE);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_PCIDE);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_OSXSAVE);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMEP);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_SMAP);
-       test_cr4_feature_bit(vcpu, &sregs, X86_CR4_PKE);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_UMIP);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_LA57);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_VMXE);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMXE);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_FSGSBASE);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PCIDE);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_OSXSAVE);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMEP);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_SMAP);
+       TEST_INVALID_CR_BIT(vcpu, cr4, sregs, X86_CR4_PKE);
+
+       for (i = 32; i < 64; i++)
+               TEST_INVALID_CR_BIT(vcpu, cr0, sregs, BIT(i));
+
+       /* NW without CD is illegal, as is PG without PE. */
+       TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_NW);
+       TEST_INVALID_CR_BIT(vcpu, cr0, sregs, X86_CR0_PG);
+
        kvm_vm_free(vm);
 
        /* Create a "real" VM and verify APIC_BASE can be set. */
index e6c9d54..3c2096a 100755 (executable)
@@ -162,9 +162,7 @@ check_tools()
        elif ! iptables -V &> /dev/null; then
                echo "SKIP: Could not run all tests without iptables tool"
                exit $ksft_skip
-       fi
-
-       if ! ip6tables -V &> /dev/null; then
+       elif ! ip6tables -V &> /dev/null; then
                echo "SKIP: Could not run all tests without ip6tables tool"
                exit $ksft_skip
        fi
index 0e04f9f..a148181 100644 (file)
@@ -159,7 +159,7 @@ void create_clients(struct __test_metadata *_metadata,
                /* Make sure SYN will be processed on the i-th CPU
                 * and finally distributed to the i-th listener.
                 */
-               sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
+               ret = sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
                ASSERT_EQ(ret, 0);
 
                for (j = 0; j < CLIENT_PER_SERVER; j++) {
index 4e4aa00..a723da2 100644 (file)
 #include "../kselftest.h"
 #include "rseq.h"
 
-static const ptrdiff_t *libc_rseq_offset_p;
-static const unsigned int *libc_rseq_size_p;
-static const unsigned int *libc_rseq_flags_p;
+/*
+ * Define weak versions to play nice with binaries that are statically linked
+ * against a libc that doesn't support registering its own rseq.
+ */
+__weak ptrdiff_t __rseq_offset;
+__weak unsigned int __rseq_size;
+__weak unsigned int __rseq_flags;
+
+static const ptrdiff_t *libc_rseq_offset_p = &__rseq_offset;
+static const unsigned int *libc_rseq_size_p = &__rseq_size;
+static const unsigned int *libc_rseq_flags_p = &__rseq_flags;
 
 /* Offset from the thread pointer to the rseq area. */
 ptrdiff_t rseq_offset;
@@ -155,9 +163,17 @@ unsigned int get_rseq_feature_size(void)
 static __attribute__((constructor))
 void rseq_init(void)
 {
-       libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
-       libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
-       libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+       /*
+        * If the libc's registered rseq size isn't already valid, it may be
+        * because the binary is dynamically linked and not necessarily due to
+        * libc not having registered a restartable sequence.  Try to find the
+        * symbols if that's the case.
+        */
+       if (!*libc_rseq_size_p) {
+               libc_rseq_offset_p = dlsym(RTLD_NEXT, "__rseq_offset");
+               libc_rseq_size_p = dlsym(RTLD_NEXT, "__rseq_size");
+               libc_rseq_flags_p = dlsym(RTLD_NEXT, "__rseq_flags");
+       }
        if (libc_rseq_size_p && libc_rseq_offset_p && libc_rseq_flags_p &&
                        *libc_rseq_size_p != 0) {
                /* rseq registration owned by glibc */
index 6e73b09..7170619 100644 (file)
@@ -5,6 +5,8 @@ CONFIG_NF_CONNTRACK=m
 CONFIG_NF_CONNTRACK_MARK=y
 CONFIG_NF_CONNTRACK_ZONES=y
 CONFIG_NF_CONNTRACK_LABELS=y
+CONFIG_NF_CONNTRACK_PROCFS=y
+CONFIG_NF_FLOW_TABLE=m
 CONFIG_NF_NAT=m
 CONFIG_NETFILTER_XT_TARGET_LOG=m
 
diff --git a/tools/testing/selftests/tc-testing/settings b/tools/testing/selftests/tc-testing/settings
new file mode 100644 (file)
index 0000000..e220626
--- /dev/null
@@ -0,0 +1 @@
+timeout=900
index a444553..08d4861 100644 (file)
         "teardown": [
             "echo \"1\" > /sys/bus/netdevsim/del_device"
         ]
+    },
+    {
+        "id": "3e1e",
+        "name": "Add taprio Qdisc with an invalid cycle-time",
+        "category": [
+            "qdisc",
+            "taprio"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "echo \"1 1 8\" > /sys/bus/netdevsim/new_device",
+            "$TC qdisc add dev $ETH root handle 1: taprio num_tc 3 map 2 2 1 0 2 2 2 2 2 2 2 2 2 2 2 2 queues 1@0 1@0 1@0 base-time 1000000000 sched-entry S 01 300000 flags 0x1 clockid CLOCK_TAI cycle-time 4294967296 || /bin/true",
+            "$IP link set dev $ETH up",
+            "$IP addr add 10.10.10.10/24 dev $ETH"
+        ],
+        "cmdUnderTest": "/bin/true",
+        "expExitCode": "0",
+        "verifyCmd": "$TC qdisc show dev $ETH",
+        "matchPattern": "qdisc taprio 1: root refcnt",
+        "matchCount": "0",
+        "teardown": [
+            "echo \"1\" > /sys/bus/netdevsim/del_device"
+        ]
     }
 ]
index 43a254f..21a98ba 100644 (file)
@@ -8,5 +8,5 @@ vsock_perf: vsock_perf.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 -D_GNU_SOURCE
 .PHONY: all test clean
 clean:
-       ${RM} *.o *.d vsock_test vsock_diag_test
+       ${RM} *.o *.d vsock_test vsock_diag_test vsock_perf
 -include *.d
index dfbaafb..5bbb561 100644 (file)
@@ -4035,8 +4035,17 @@ static ssize_t kvm_vcpu_stats_read(struct file *file, char __user *user_buffer,
                        sizeof(vcpu->stat), user_buffer, size, offset);
 }
 
+static int kvm_vcpu_stats_release(struct inode *inode, struct file *file)
+{
+       struct kvm_vcpu *vcpu = file->private_data;
+
+       kvm_put_kvm(vcpu->kvm);
+       return 0;
+}
+
 static const struct file_operations kvm_vcpu_stats_fops = {
        .read = kvm_vcpu_stats_read,
+       .release = kvm_vcpu_stats_release,
        .llseek = noop_llseek,
 };
 
@@ -4057,6 +4066,9 @@ static int kvm_vcpu_ioctl_get_stats_fd(struct kvm_vcpu *vcpu)
                put_unused_fd(fd);
                return PTR_ERR(file);
        }
+
+       kvm_get_kvm(vcpu->kvm);
+
        file->f_mode |= FMODE_PREAD;
        fd_install(fd, file);
 
@@ -4701,8 +4713,17 @@ static ssize_t kvm_vm_stats_read(struct file *file, char __user *user_buffer,
                                sizeof(kvm->stat), user_buffer, size, offset);
 }
 
+static int kvm_vm_stats_release(struct inode *inode, struct file *file)
+{
+       struct kvm *kvm = file->private_data;
+
+       kvm_put_kvm(kvm);
+       return 0;
+}
+
 static const struct file_operations kvm_vm_stats_fops = {
        .read = kvm_vm_stats_read,
+       .release = kvm_vm_stats_release,
        .llseek = noop_llseek,
 };
 
@@ -4721,6 +4742,9 @@ static int kvm_vm_ioctl_get_stats_fd(struct kvm *kvm)
                put_unused_fd(fd);
                return PTR_ERR(file);
        }
+
+       kvm_get_kvm(kvm);
+
        file->f_mode |= FMODE_PREAD;
        fd_install(fd, file);