Merge tag 'scmi-updates-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep...
authorArnd Bergmann <arnd@arndb.de>
Sat, 12 Aug 2023 10:04:53 +0000 (12:04 +0200)
committerArnd Bergmann <arnd@arndb.de>
Sat, 12 Aug 2023 10:04:53 +0000 (12:04 +0200)
Arm SCMI updates for v6.6

The main addition this time is the support for SCMI v3.2 perf level
indexing mode. SCMI v3.2 adds support for hardware which works on
performance indices, instead of levels. Certain platforms use indices
to identify performance levels. Level Indexing Mode is used to describe
such platform behavior. All commands which utilize performance level
as a parameter need to specify the corresponding level index instead of
the performance level when Level Indexing Mode is used.

While at it, these changes also include hardening of all the internal
accesses to the performance domain information.

* tag 'scmi-updates-6.6' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  firmware: arm_scmi: Add v3.2 perf level indexing mode support
  firmware: arm_scmi: Harden perf domain info access

Link: https://lore.kernel.org/r/20230804123231.3258141-1-sudeep.holla@arm.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
414 files changed:
.mailmap
Documentation/ABI/testing/sysfs-driver-ufs
Documentation/devicetree/bindings/watchdog/loongson,ls1x-wdt.yaml [new file with mode: 0644]
Documentation/process/maintainer-netdev.rst
Documentation/riscv/hwprobe.rst
Documentation/wmi/devices/dell-wmi-ddv.rst
MAINTAINERS
Makefile
arch/arm/mach-ux500/Makefile
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/pm_domains.h [deleted file]
arch/arm64/Kconfig
arch/arm64/include/asm/ftrace.h
arch/arm64/include/asm/syscall.h
arch/arm64/kernel/syscall.c
arch/openrisc/include/uapi/asm/sigcontext.h
arch/openrisc/kernel/signal.c
arch/powerpc/include/asm/book3s/64/hash-4k.h
arch/powerpc/include/asm/book3s/64/hash-64k.h
arch/powerpc/include/asm/book3s/64/hash.h
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/kernel/security.c
arch/powerpc/mm/book3s64/hash_native.c
arch/riscv/kernel/cpufeature.c
arch/riscv/mm/init.c
arch/riscv/net/bpf_jit.h
arch/riscv/net/bpf_jit_core.c
arch/sh/boards/mach-dreamcast/irq.c
arch/sh/boards/mach-highlander/setup.c
arch/sh/boards/mach-r2d/irq.c
arch/sh/cchips/Kconfig
arch/sh/include/asm/hd64461.h
arch/sparc/include/asm/cmpxchg_32.h
arch/sparc/include/asm/cmpxchg_64.h
arch/um/kernel/um_arch.c
arch/x86/entry/entry_32.S
arch/x86/entry/entry_64.S
arch/x86/events/intel/core.c
arch/x86/include/asm/alternative.h
arch/x86/include/asm/ibt.h
arch/x86/include/asm/nospec-branch.h
arch/x86/include/asm/switch_to.h
arch/x86/kernel/alternative.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/module.c
arch/x86/kernel/process.c
arch/x86/xen/xen-head.S
arch/xtensa/kernel/align.S
arch/xtensa/kernel/traps.c
arch/xtensa/platforms/iss/network.c
block/blk-crypto-profile.c
block/blk-flush.c
block/blk-mq.c
block/blk-zoned.c
block/mq-deadline.c
block/partitions/amiga.c
crypto/af_alg.c
crypto/algif_hash.c
crypto/asymmetric_keys/public_key.c
drivers/Makefile
drivers/accel/ivpu/ivpu_drv.h
drivers/accel/ivpu/ivpu_hw_mtl.c
drivers/base/regmap/regmap-irq.c
drivers/block/null_blk/zoned.c
drivers/block/virtio_blk.c
drivers/bus/tegra-gmi.c
drivers/bus/vexpress-config.c
drivers/cpufreq/sparc-us2e-cpufreq.c
drivers/cpufreq/sparc-us3-cpufreq.c
drivers/dma-buf/dma-fence-unwrap.c
drivers/dma-buf/dma-fence.c
drivers/genpd/Makefile [new file with mode: 0644]
drivers/genpd/actions/Makefile [new file with mode: 0644]
drivers/genpd/actions/owl-sps-helper.c [moved from drivers/soc/actions/owl-sps-helper.c with 100% similarity]
drivers/genpd/actions/owl-sps.c [moved from drivers/soc/actions/owl-sps.c with 100% similarity]
drivers/genpd/amlogic/Makefile [new file with mode: 0644]
drivers/genpd/amlogic/meson-ee-pwrc.c [moved from drivers/soc/amlogic/meson-ee-pwrc.c with 100% similarity]
drivers/genpd/amlogic/meson-gx-pwrc-vpu.c [moved from drivers/soc/amlogic/meson-gx-pwrc-vpu.c with 100% similarity]
drivers/genpd/amlogic/meson-secure-pwrc.c [moved from drivers/soc/amlogic/meson-secure-pwrc.c with 100% similarity]
drivers/genpd/apple/Makefile [new file with mode: 0644]
drivers/genpd/apple/pmgr-pwrstate.c [moved from drivers/soc/apple/apple-pmgr-pwrstate.c with 100% similarity]
drivers/genpd/bcm/Makefile [new file with mode: 0644]
drivers/genpd/bcm/bcm-pmb.c [moved from drivers/soc/bcm/bcm63xx/bcm-pmb.c with 100% similarity]
drivers/genpd/bcm/bcm2835-power.c [moved from drivers/soc/bcm/bcm2835-power.c with 100% similarity]
drivers/genpd/bcm/bcm63xx-power.c [moved from drivers/soc/bcm/bcm63xx/bcm63xx-power.c with 100% similarity]
drivers/genpd/bcm/raspberrypi-power.c [moved from drivers/soc/bcm/raspberrypi-power.c with 100% similarity]
drivers/genpd/imx/Makefile [new file with mode: 0644]
drivers/genpd/imx/gpc.c [moved from drivers/soc/imx/gpc.c with 100% similarity]
drivers/genpd/imx/gpcv2.c [moved from drivers/soc/imx/gpcv2.c with 100% similarity]
drivers/genpd/imx/imx8m-blk-ctrl.c [moved from drivers/soc/imx/imx8m-blk-ctrl.c with 100% similarity]
drivers/genpd/imx/imx8mp-blk-ctrl.c [moved from drivers/soc/imx/imx8mp-blk-ctrl.c with 100% similarity]
drivers/genpd/imx/imx93-blk-ctrl.c [moved from drivers/soc/imx/imx93-blk-ctrl.c with 100% similarity]
drivers/genpd/imx/imx93-pd.c [moved from drivers/soc/imx/imx93-pd.c with 100% similarity]
drivers/genpd/mediatek/Makefile [new file with mode: 0644]
drivers/genpd/mediatek/mt6795-pm-domains.h [moved from drivers/soc/mediatek/mt6795-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mt8167-pm-domains.h [moved from drivers/soc/mediatek/mt8167-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mt8173-pm-domains.h [moved from drivers/soc/mediatek/mt8173-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mt8183-pm-domains.h [moved from drivers/soc/mediatek/mt8183-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mt8186-pm-domains.h [moved from drivers/soc/mediatek/mt8186-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mt8188-pm-domains.h [moved from drivers/soc/mediatek/mt8188-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mt8192-pm-domains.h [moved from drivers/soc/mediatek/mt8192-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mt8195-pm-domains.h [moved from drivers/soc/mediatek/mt8195-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mtk-pm-domains.c [moved from drivers/soc/mediatek/mtk-pm-domains.c with 100% similarity]
drivers/genpd/mediatek/mtk-pm-domains.h [moved from drivers/soc/mediatek/mtk-pm-domains.h with 100% similarity]
drivers/genpd/mediatek/mtk-scpsys.c [moved from drivers/soc/mediatek/mtk-scpsys.c with 100% similarity]
drivers/genpd/qcom/Makefile [new file with mode: 0644]
drivers/genpd/qcom/cpr.c [moved from drivers/soc/qcom/cpr.c with 100% similarity]
drivers/genpd/qcom/rpmhpd.c [moved from drivers/soc/qcom/rpmhpd.c with 100% similarity]
drivers/genpd/qcom/rpmpd.c [moved from drivers/soc/qcom/rpmpd.c with 100% similarity]
drivers/genpd/renesas/Makefile [new file with mode: 0644]
drivers/genpd/renesas/r8a7742-sysc.c [moved from drivers/soc/renesas/r8a7742-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7743-sysc.c [moved from drivers/soc/renesas/r8a7743-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7745-sysc.c [moved from drivers/soc/renesas/r8a7745-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a77470-sysc.c [moved from drivers/soc/renesas/r8a77470-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a774a1-sysc.c [moved from drivers/soc/renesas/r8a774a1-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a774b1-sysc.c [moved from drivers/soc/renesas/r8a774b1-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a774c0-sysc.c [moved from drivers/soc/renesas/r8a774c0-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a774e1-sysc.c [moved from drivers/soc/renesas/r8a774e1-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7779-sysc.c [moved from drivers/soc/renesas/r8a7779-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7790-sysc.c [moved from drivers/soc/renesas/r8a7790-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7791-sysc.c [moved from drivers/soc/renesas/r8a7791-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7792-sysc.c [moved from drivers/soc/renesas/r8a7792-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7794-sysc.c [moved from drivers/soc/renesas/r8a7794-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7795-sysc.c [moved from drivers/soc/renesas/r8a7795-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a7796-sysc.c [moved from drivers/soc/renesas/r8a7796-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a77965-sysc.c [moved from drivers/soc/renesas/r8a77965-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a77970-sysc.c [moved from drivers/soc/renesas/r8a77970-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a77980-sysc.c [moved from drivers/soc/renesas/r8a77980-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a77990-sysc.c [moved from drivers/soc/renesas/r8a77990-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a77995-sysc.c [moved from drivers/soc/renesas/r8a77995-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a779a0-sysc.c [moved from drivers/soc/renesas/r8a779a0-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a779f0-sysc.c [moved from drivers/soc/renesas/r8a779f0-sysc.c with 100% similarity]
drivers/genpd/renesas/r8a779g0-sysc.c [moved from drivers/soc/renesas/r8a779g0-sysc.c with 100% similarity]
drivers/genpd/renesas/rcar-gen4-sysc.c [moved from drivers/soc/renesas/rcar-gen4-sysc.c with 100% similarity]
drivers/genpd/renesas/rcar-gen4-sysc.h [moved from drivers/soc/renesas/rcar-gen4-sysc.h with 100% similarity]
drivers/genpd/renesas/rcar-sysc.c [moved from drivers/soc/renesas/rcar-sysc.c with 100% similarity]
drivers/genpd/renesas/rcar-sysc.h [moved from drivers/soc/renesas/rcar-sysc.h with 100% similarity]
drivers/genpd/renesas/rmobile-sysc.c [moved from drivers/soc/renesas/rmobile-sysc.c with 100% similarity]
drivers/genpd/rockchip/Makefile [new file with mode: 0644]
drivers/genpd/rockchip/pm-domains.c [moved from drivers/soc/rockchip/pm_domains.c with 100% similarity]
drivers/genpd/samsung/Makefile [new file with mode: 0644]
drivers/genpd/samsung/exynos-pm-domains.c [moved from drivers/soc/samsung/pm_domains.c with 100% similarity]
drivers/genpd/st/Makefile [new file with mode: 0644]
drivers/genpd/st/ste-ux500-pm-domain.c [moved from arch/arm/mach-ux500/pm_domains.c with 75% similarity]
drivers/genpd/starfive/Makefile [new file with mode: 0644]
drivers/genpd/starfive/jh71xx-pmu.c [moved from drivers/soc/starfive/jh71xx_pmu.c with 100% similarity]
drivers/genpd/sunxi/Makefile [new file with mode: 0644]
drivers/genpd/sunxi/sun20i-ppu.c [moved from drivers/soc/sunxi/sun20i-ppu.c with 100% similarity]
drivers/genpd/tegra/Makefile [new file with mode: 0644]
drivers/genpd/tegra/powergate-bpmp.c [moved from drivers/soc/tegra/powergate-bpmp.c with 100% similarity]
drivers/genpd/ti/Makefile [new file with mode: 0644]
drivers/genpd/ti/omap_prm.c [moved from drivers/soc/ti/omap_prm.c with 100% similarity]
drivers/genpd/ti/ti_sci_pm_domains.c [moved from drivers/soc/ti/ti_sci_pm_domains.c with 100% similarity]
drivers/genpd/xilinx/Makefile [new file with mode: 0644]
drivers/genpd/xilinx/zynqmp-pm-domains.c [moved from drivers/soc/xilinx/zynqmp_pm_domains.c with 100% similarity]
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/pm/swsmu/inc/smu_v13_0.h
drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
drivers/gpu/drm/armada/armada_fbdev.c
drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
drivers/gpu/drm/bridge/ti-sn65dsi86.c
drivers/gpu/drm/drm_client.c
drivers/gpu/drm/drm_fbdev_dma.c
drivers/gpu/drm/drm_fbdev_generic.c
drivers/gpu/drm/drm_syncobj.c
drivers/gpu/drm/exynos/exynos_drm_fbdev.c
drivers/gpu/drm/gma500/fbdev.c
drivers/gpu/drm/i915/display/intel_display.c
drivers/gpu/drm/i915/gt/gen8_ppgtt.c
drivers/gpu/drm/i915/gt/intel_gtt.c
drivers/gpu/drm/i915/i915_perf.c
drivers/gpu/drm/msm/msm_fbdev.c
drivers/gpu/drm/nouveau/dispnv50/disp.c
drivers/gpu/drm/nouveau/nouveau_chan.c
drivers/gpu/drm/nouveau/nouveau_chan.h
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c
drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c
drivers/gpu/drm/nouveau/nvkm/subdev/acr/base.c
drivers/gpu/drm/omapdrm/omap_fbdev.c
drivers/gpu/drm/panel/panel-simple.c
drivers/gpu/drm/radeon/radeon_fbdev.c
drivers/gpu/drm/scheduler/sched_entity.c
drivers/gpu/drm/scheduler/sched_fence.c
drivers/gpu/drm/scheduler/sched_main.c
drivers/gpu/drm/tegra/fbdev.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_resource.c
drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
drivers/hid/hid-hyperv.c
drivers/hid/hid-input.c
drivers/hid/hid-logitech-hidpp.c
drivers/hid/hid-nvidia-shield.c
drivers/iommu/iommu-sva.c
drivers/iommu/iommu.c
drivers/net/dsa/ocelot/felix.c
drivers/net/dsa/ocelot/felix.h
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/dsa/qca/qca8k-8xxx.c
drivers/net/ethernet/amazon/ena/ena_com.c
drivers/net/ethernet/broadcom/bgmac.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/google/gve/gve.h
drivers/net/ethernet/google/gve/gve_ethtool.c
drivers/net/ethernet/google/gve/gve_main.c
drivers/net/ethernet/intel/ice/ice_main.c
drivers/net/ethernet/intel/ice/ice_tc_lib.c
drivers/net/ethernet/intel/ice/ice_tc_lib.h
drivers/net/ethernet/intel/igc/igc.h
drivers/net/ethernet/intel/igc/igc_ethtool.c
drivers/net/ethernet/intel/igc/igc_main.c
drivers/net/ethernet/intel/igc/igc_ptp.c
drivers/net/ethernet/intel/igc/igc_tsn.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/marvell/octeontx2/af/ptp.c
drivers/net/ethernet/marvell/octeontx2/af/rvu.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_hash.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c
drivers/net/ethernet/mellanox/mlx5/core/en/fs_tt_redirect.c
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.h
drivers/net/ethernet/mellanox/mlx5/core/en/xdp.c
drivers/net/ethernet/mellanox/mlx5/core/en_accel/fs_tcp.c
drivers/net/ethernet/mellanox/mlx5/core/en_rx.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/thermal.c
drivers/net/ethernet/microchip/Kconfig
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot_mm.c
drivers/net/ethernet/pensando/ionic/ionic_bus_pci.c
drivers/net/ethernet/pensando/ionic/ionic_lif.c
drivers/net/ethernet/wangxun/txgbe/txgbe_hw.c
drivers/net/netdevsim/dev.c
drivers/net/wireless/cisco/airo.c
drivers/net/wireless/intel/iwlwifi/cfg/22000.c
drivers/net/wireless/intel/iwlwifi/iwl-config.h
drivers/net/wireless/intel/iwlwifi/iwl-fh.h
drivers/net/wireless/intel/iwlwifi/iwl-trans.c
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c
drivers/net/wireless/intel/iwlwifi/queue/tx.c
drivers/net/wireless/intel/iwlwifi/queue/tx.h
drivers/net/wireless/mediatek/mt76/mt7921/dma.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/pci.c
drivers/net/wireless/realtek/rtw89/debug.c
drivers/nvme/host/core.c
drivers/nvme/host/fault_inject.c
drivers/nvme/host/fc.c
drivers/nvme/host/pci.c
drivers/nvme/host/sysfs.c
drivers/nvme/host/zns.c
drivers/nvme/target/loop.c
drivers/nvme/target/passthru.c
drivers/perf/riscv_pmu.c
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-amd.h
drivers/pinctrl/renesas/pinctrl-rzg2l.c
drivers/pinctrl/renesas/pinctrl-rzv2m.c
drivers/platform/x86/amd/Makefile
drivers/platform/x86/amd/pmc-quirks.c [new file with mode: 0644]
drivers/platform/x86/amd/pmc.c
drivers/platform/x86/amd/pmc.h [new file with mode: 0644]
drivers/platform/x86/amd/pmf/core.c
drivers/platform/x86/dell/dell-wmi-ddv.c
drivers/platform/x86/intel/int3472/clk_and_regulator.c
drivers/platform/x86/intel/tpmi.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/touchscreen_dmi.c
drivers/platform/x86/wmi.c
drivers/s390/net/ism_drv.c
drivers/scsi/aacraid/aacraid.h
drivers/scsi/fnic/fnic_trace.c
drivers/scsi/lpfc/lpfc_hbadisc.c
drivers/scsi/qla2xxx/qla_def.h
drivers/scsi/qla2xxx/qla_init.c
drivers/scsi/qla2xxx/qla_iocb.c
drivers/scsi/scsi_debug.c
drivers/scsi/sd_zbc.c
drivers/scsi/storvsc_drv.c
drivers/soc/Makefile
drivers/soc/actions/Makefile [deleted file]
drivers/soc/amlogic/Makefile
drivers/soc/apple/Makefile
drivers/soc/bcm/Kconfig
drivers/soc/bcm/Makefile
drivers/soc/bcm/bcm63xx/Kconfig [deleted file]
drivers/soc/bcm/bcm63xx/Makefile [deleted file]
drivers/soc/imx/Makefile
drivers/soc/mediatek/Makefile
drivers/soc/qcom/Makefile
drivers/soc/renesas/Makefile
drivers/soc/rockchip/Makefile
drivers/soc/samsung/Makefile
drivers/soc/starfive/Makefile [deleted file]
drivers/soc/sunxi/Makefile
drivers/soc/tegra/Makefile
drivers/soc/tegra/cbb/tegra-cbb.c
drivers/soc/tegra/cbb/tegra194-cbb.c
drivers/soc/tegra/cbb/tegra234-cbb.c
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/fuse/fuse-tegra20.c
drivers/soc/tegra/fuse/fuse-tegra30.c
drivers/soc/tegra/fuse/tegra-apbmisc.c
drivers/soc/ti/Makefile
drivers/soc/xilinx/Makefile
drivers/soc/xilinx/xlnx_event_manager.c
drivers/soc/xilinx/zynqmp_power.c
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-s3c64xx.c
drivers/ufs/core/ufshcd.c
drivers/ufs/host/Kconfig
drivers/xen/grant-dma-ops.c
fs/erofs/decompressor.c
fs/erofs/inode.c
fs/erofs/zdata.c
fs/smb/client/cifsglob.h
fs/smb/client/cifssmb.c
fs/smb/client/connect.c
fs/smb/client/dfs.c
fs/smb/client/file.c
fs/smb/client/smb2ops.c
fs/smb/client/smb2transport.c
include/asm-generic/vmlinux.lds.h
include/drm/gpu_scheduler.h
include/linux/blk-crypto-profile.h
include/linux/blk-mq.h
include/linux/dma-fence.h
include/linux/ftrace.h
include/linux/ism.h
include/linux/nvme.h
include/linux/psi.h
include/linux/psi_types.h
include/linux/rethook.h
include/net/netfilter/nf_conntrack_tuple.h
include/net/netfilter/nf_tables.h
include/net/pkt_sched.h
include/soc/mscc/ocelot.h
include/uapi/scsi/scsi_bsg_ufs.h
include/ufs/ufs.h
io_uring/io_uring.c
kernel/bpf/cpumap.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup.c
kernel/kallsyms.c
kernel/kprobes.c
kernel/power/hibernate.c
kernel/power/qos.c
kernel/sched/fair.c
kernel/sched/psi.c
kernel/trace/fgraph.c
kernel/trace/fprobe.c
kernel/trace/ftrace.c
kernel/trace/ftrace_internal.h
kernel/trace/rethook.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_eprobe.c
kernel/trace/trace_events_hist.c
kernel/trace/trace_events_user.c
kernel/trace/trace_kprobe_selftest.c
kernel/trace/trace_probe.c
kernel/trace/trace_probe_kernel.h
kernel/trace/trace_probe_tmpl.h
kernel/trace/trace_uprobe.c
lib/iov_iter.c
net/ceph/messenger_v2.c
net/core/net-traces.c
net/core/skbuff.c
net/core/xdp.c
net/ipv6/addrconf.c
net/ipv6/icmp.c
net/ipv6/udp.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_byteorder.c
net/netfilter/nft_flow_offload.c
net/netfilter/nft_immediate.c
net/netfilter/nft_objref.c
net/sched/act_api.c
net/sched/cls_flower.c
net/sched/cls_fw.c
net/sched/sch_qfq.c
net/wireless/util.c
samples/ftrace/ftrace-direct-modify.c
samples/ftrace/ftrace-direct-multi-modify.c
samples/ftrace/ftrace-direct-multi.c
samples/ftrace/ftrace-direct-too.c
samples/ftrace/ftrace-direct.c
scripts/kallsyms.c
tools/objtool/elf.c
tools/testing/selftests/bpf/prog_tests/async_stack_depth.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/async_stack_depth.c [new file with mode: 0644]
tools/testing/selftests/hid/vmtest.sh
tools/testing/selftests/tc-testing/tc-tests/qdiscs/qfq.json
tools/testing/selftests/user_events/dyn_test.c

index 1bce47a..89b7f33 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -246,6 +246,7 @@ John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
 John Stultz <johnstul@us.ibm.com>
 <jon.toppins+linux@gmail.com> <jtoppins@cumulusnetworks.com>
 <jon.toppins+linux@gmail.com> <jtoppins@redhat.com>
+Jonas Gorski <jonas.gorski@gmail.com> <jogo@openwrt.org>
 Jordan Crouse <jordan@cosmicpenguin.net> <jcrouse@codeaurora.org>
 <josh@joshtriplett.org> <josh@freedesktop.org>
 <josh@joshtriplett.org> <josh@kernel.org>
index d5f44fc..e487f96 100644 (file)
@@ -994,7 +994,7 @@ Description:        This file shows the amount of physical memory needed
 What:          /sys/bus/platform/drivers/ufshcd/*/rpm_lvl
 What:          /sys/bus/platform/devices/*.ufs/rpm_lvl
 Date:          September 2014
-Contact:       Subhash Jadavani <subhashj@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This entry could be used to set or show the UFS device
                runtime power management level. The current driver
                implementation supports 7 levels with next target states:
@@ -1021,7 +1021,7 @@ Description:      This entry could be used to set or show the UFS device
 What:          /sys/bus/platform/drivers/ufshcd/*/rpm_target_dev_state
 What:          /sys/bus/platform/devices/*.ufs/rpm_target_dev_state
 Date:          February 2018
-Contact:       Subhash Jadavani <subhashj@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This entry shows the target power mode of an UFS device
                for the chosen runtime power management level.
 
@@ -1030,7 +1030,7 @@ Description:      This entry shows the target power mode of an UFS device
 What:          /sys/bus/platform/drivers/ufshcd/*/rpm_target_link_state
 What:          /sys/bus/platform/devices/*.ufs/rpm_target_link_state
 Date:          February 2018
-Contact:       Subhash Jadavani <subhashj@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This entry shows the target state of an UFS UIC link
                for the chosen runtime power management level.
 
@@ -1039,7 +1039,7 @@ Description:      This entry shows the target state of an UFS UIC link
 What:          /sys/bus/platform/drivers/ufshcd/*/spm_lvl
 What:          /sys/bus/platform/devices/*.ufs/spm_lvl
 Date:          September 2014
-Contact:       Subhash Jadavani <subhashj@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This entry could be used to set or show the UFS device
                system power management level. The current driver
                implementation supports 7 levels with next target states:
@@ -1066,7 +1066,7 @@ Description:      This entry could be used to set or show the UFS device
 What:          /sys/bus/platform/drivers/ufshcd/*/spm_target_dev_state
 What:          /sys/bus/platform/devices/*.ufs/spm_target_dev_state
 Date:          February 2018
-Contact:       Subhash Jadavani <subhashj@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This entry shows the target power mode of an UFS device
                for the chosen system power management level.
 
@@ -1075,7 +1075,7 @@ Description:      This entry shows the target power mode of an UFS device
 What:          /sys/bus/platform/drivers/ufshcd/*/spm_target_link_state
 What:          /sys/bus/platform/devices/*.ufs/spm_target_link_state
 Date:          February 2018
-Contact:       Subhash Jadavani <subhashj@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This entry shows the target state of an UFS UIC link
                for the chosen system power management level.
 
@@ -1084,7 +1084,7 @@ Description:      This entry shows the target state of an UFS UIC link
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/monitor_enable
 What:          /sys/bus/platform/devices/*.ufs/monitor/monitor_enable
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the status of performance monitor enablement
                and it can be used to start/stop the monitor. When the monitor
                is stopped, the performance data collected is also cleared.
@@ -1092,7 +1092,7 @@ Description:      This file shows the status of performance monitor enablement
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/monitor_chunk_size
 What:          /sys/bus/platform/devices/*.ufs/monitor/monitor_chunk_size
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file tells the monitor to focus on requests transferring
                data of specific chunk size (in Bytes). 0 means any chunk size.
                It can only be changed when monitor is disabled.
@@ -1100,7 +1100,7 @@ Description:      This file tells the monitor to focus on requests transferring
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/read_total_sectors
 What:          /sys/bus/platform/devices/*.ufs/monitor/read_total_sectors
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows how many sectors (in 512 Bytes) have been
                sent from device to host after monitor gets started.
 
@@ -1109,7 +1109,7 @@ Description:      This file shows how many sectors (in 512 Bytes) have been
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/read_total_busy
 What:          /sys/bus/platform/devices/*.ufs/monitor/read_total_busy
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows how long (in micro seconds) has been spent
                sending data from device to host after monitor gets started.
 
@@ -1118,7 +1118,7 @@ Description:      This file shows how long (in micro seconds) has been spent
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/read_nr_requests
 What:          /sys/bus/platform/devices/*.ufs/monitor/read_nr_requests
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows how many read requests have been sent after
                monitor gets started.
 
@@ -1127,7 +1127,7 @@ Description:      This file shows how many read requests have been sent after
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_max
 What:          /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_max
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the maximum latency (in micro seconds) of
                read requests after monitor gets started.
 
@@ -1136,7 +1136,7 @@ Description:      This file shows the maximum latency (in micro seconds) of
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_min
 What:          /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_min
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the minimum latency (in micro seconds) of
                read requests after monitor gets started.
 
@@ -1145,7 +1145,7 @@ Description:      This file shows the minimum latency (in micro seconds) of
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_avg
 What:          /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_avg
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the average latency (in micro seconds) of
                read requests after monitor gets started.
 
@@ -1154,7 +1154,7 @@ Description:      This file shows the average latency (in micro seconds) of
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/read_req_latency_sum
 What:          /sys/bus/platform/devices/*.ufs/monitor/read_req_latency_sum
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the total latency (in micro seconds) of
                read requests sent after monitor gets started.
 
@@ -1163,7 +1163,7 @@ Description:      This file shows the total latency (in micro seconds) of
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/write_total_sectors
 What:          /sys/bus/platform/devices/*.ufs/monitor/write_total_sectors
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows how many sectors (in 512 Bytes) have been sent
                from host to device after monitor gets started.
 
@@ -1172,7 +1172,7 @@ Description:      This file shows how many sectors (in 512 Bytes) have been sent
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/write_total_busy
 What:          /sys/bus/platform/devices/*.ufs/monitor/write_total_busy
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows how long (in micro seconds) has been spent
                sending data from host to device after monitor gets started.
 
@@ -1181,7 +1181,7 @@ Description:      This file shows how long (in micro seconds) has been spent
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/write_nr_requests
 What:          /sys/bus/platform/devices/*.ufs/monitor/write_nr_requests
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows how many write requests have been sent after
                monitor gets started.
 
@@ -1190,7 +1190,7 @@ Description:      This file shows how many write requests have been sent after
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_max
 What:          /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_max
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the maximum latency (in micro seconds) of write
                requests after monitor gets started.
 
@@ -1199,7 +1199,7 @@ Description:      This file shows the maximum latency (in micro seconds) of write
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_min
 What:          /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_min
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the minimum latency (in micro seconds) of write
                requests after monitor gets started.
 
@@ -1208,7 +1208,7 @@ Description:      This file shows the minimum latency (in micro seconds) of write
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_avg
 What:          /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_avg
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the average latency (in micro seconds) of write
                requests after monitor gets started.
 
@@ -1217,7 +1217,7 @@ Description:      This file shows the average latency (in micro seconds) of write
 What:          /sys/bus/platform/drivers/ufshcd/*/monitor/write_req_latency_sum
 What:          /sys/bus/platform/devices/*.ufs/monitor/write_req_latency_sum
 Date:          January 2021
-Contact:       Can Guo <cang@codeaurora.org>
+Contact:       Can Guo <quic_cang@quicinc.com>
 Description:   This file shows the total latency (in micro seconds) of write
                requests after monitor gets started.
 
@@ -1226,7 +1226,7 @@ Description:      This file shows the total latency (in micro seconds) of write
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_presv_us_en
 What:          /sys/bus/platform/devices/*.ufs/device_descriptor/wb_presv_us_en
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows if preserve user-space was configured
 
                The file is read only.
@@ -1234,7 +1234,7 @@ Description:      This entry shows if preserve user-space was configured
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_shared_alloc_units
 What:          /sys/bus/platform/devices/*.ufs/device_descriptor/wb_shared_alloc_units
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the shared allocated units of WB buffer
 
                The file is read only.
@@ -1242,7 +1242,7 @@ Description:      This entry shows the shared allocated units of WB buffer
 What:          /sys/bus/platform/drivers/ufshcd/*/device_descriptor/wb_type
 What:          /sys/bus/platform/devices/*.ufs/device_descriptor/wb_type
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the configured WB type.
                0x1 for shared buffer mode. 0x0 for dedicated buffer mode.
 
@@ -1251,7 +1251,7 @@ Description:      This entry shows the configured WB type.
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_buff_cap_adj
 What:          /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_buff_cap_adj
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the total user-space decrease in shared
                buffer mode.
                The value of this parameter is 3 for TLC NAND when SLC mode
@@ -1262,7 +1262,7 @@ Description:      This entry shows the total user-space decrease in shared
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_alloc_units
 What:          /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_max_alloc_units
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the Maximum total WriteBooster Buffer size
                which is supported by the entire device.
 
@@ -1271,7 +1271,7 @@ Description:      This entry shows the Maximum total WriteBooster Buffer size
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_max_wb_luns
 What:          /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_max_wb_luns
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the maximum number of luns that can support
                WriteBooster.
 
@@ -1280,7 +1280,7 @@ Description:      This entry shows the maximum number of luns that can support
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_red_type
 What:          /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_sup_red_type
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   The supportability of user space reduction mode
                and preserve user space mode.
                00h: WriteBooster Buffer can be configured only in
@@ -1295,7 +1295,7 @@ Description:      The supportability of user space reduction mode
 What:          /sys/bus/platform/drivers/ufshcd/*/geometry_descriptor/wb_sup_wb_type
 What:          /sys/bus/platform/devices/*.ufs/geometry_descriptor/wb_sup_wb_type
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   The supportability of WriteBooster Buffer type.
 
                ===  ==========================================================
@@ -1310,7 +1310,7 @@ Description:      The supportability of WriteBooster Buffer type.
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/wb_enable
 What:          /sys/bus/platform/devices/*.ufs/flags/wb_enable
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the status of WriteBooster.
 
                == ============================
@@ -1323,7 +1323,7 @@ Description:      This entry shows the status of WriteBooster.
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_en
 What:          /sys/bus/platform/devices/*.ufs/flags/wb_flush_en
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows if flush is enabled.
 
                == =================================
@@ -1336,7 +1336,7 @@ Description:      This entry shows if flush is enabled.
 What:          /sys/bus/platform/drivers/ufshcd/*/flags/wb_flush_during_h8
 What:          /sys/bus/platform/devices/*.ufs/flags/wb_flush_during_h8
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   Flush WriteBooster Buffer during hibernate state.
 
                == =================================================
@@ -1351,7 +1351,7 @@ Description:      Flush WriteBooster Buffer during hibernate state.
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/wb_avail_buf
 What:          /sys/bus/platform/devices/*.ufs/attributes/wb_avail_buf
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the amount of unused WriteBooster buffer
                available.
 
@@ -1360,7 +1360,7 @@ Description:      This entry shows the amount of unused WriteBooster buffer
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/wb_cur_buf
 What:          /sys/bus/platform/devices/*.ufs/attributes/wb_cur_buf
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the amount of unused current buffer.
 
                The file is read only.
@@ -1368,7 +1368,7 @@ Description:      This entry shows the amount of unused current buffer.
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/wb_flush_status
 What:          /sys/bus/platform/devices/*.ufs/attributes/wb_flush_status
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the flush operation status.
 
 
@@ -1385,7 +1385,7 @@ Description:      This entry shows the flush operation status.
 What:          /sys/bus/platform/drivers/ufshcd/*/attributes/wb_life_time_est
 What:          /sys/bus/platform/devices/*.ufs/attributes/wb_life_time_est
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows an indication of the WriteBooster Buffer
                lifetime based on the amount of performed program/erase cycles
 
@@ -1399,7 +1399,7 @@ Description:      This entry shows an indication of the WriteBooster Buffer
 
 What:          /sys/class/scsi_device/*/device/unit_descriptor/wb_buf_alloc_units
 Date:          June 2020
-Contact:       Asutosh Das <asutoshd@codeaurora.org>
+Contact:       Asutosh Das <quic_asutoshd@quicinc.com>
 Description:   This entry shows the configured size of WriteBooster buffer.
                0400h corresponds to 4GB.
 
diff --git a/Documentation/devicetree/bindings/watchdog/loongson,ls1x-wdt.yaml b/Documentation/devicetree/bindings/watchdog/loongson,ls1x-wdt.yaml
new file mode 100644 (file)
index 0000000..81690d4
--- /dev/null
@@ -0,0 +1,42 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/loongson,ls1x-wdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Loongson-1 Watchdog Timer
+
+maintainers:
+  - Keguang Zhang <keguang.zhang@gmail.com>
+
+allOf:
+  - $ref: watchdog.yaml#
+
+properties:
+  compatible:
+    enum:
+      - loongson,ls1b-wdt
+      - loongson,ls1c-wdt
+
+  reg:
+    maxItems: 1
+
+  clocks:
+    maxItems: 1
+
+required:
+  - compatible
+  - reg
+  - clocks
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    #include <dt-bindings/clock/loongson,ls1x-clk.h>
+    watchdog: watchdog@1fe5c060 {
+        compatible = "loongson,ls1b-wdt";
+        reg = <0x1fe5c060 0xc>;
+
+        clocks = <&clkc LS1X_CLKID_APB>;
+    };
index 2397b31..2ab843c 100644 (file)
@@ -98,7 +98,7 @@ If you aren't subscribed to netdev and/or are simply unsure if
 repository link above for any new networking-related commits.  You may
 also check the following website for the current status:
 
-  http://vger.kernel.org/~davem/net-next.html
+  https://patchwork.hopto.org/net-next.html
 
 The ``net`` tree continues to collect fixes for the vX.Y content, and is
 fed back to Linus at regular (~weekly) intervals.  Meaning that the
index 19165eb..933c715 100644 (file)
@@ -49,7 +49,7 @@ The following keys are defined:
     privileged ISA, with the following known exceptions (more exceptions may be
     added, but only if it can be demonstrated that the user ABI is not broken):
 
-    * The :fence.i: instruction cannot be directly executed by userspace
+    * The ``fence.i`` instruction cannot be directly executed by userspace
       programs (it may still be executed in userspace via a
       kernel-controlled mechanism such as the vDSO).
 
index d8aa64e..bf963d9 100644 (file)
@@ -187,7 +187,8 @@ WMI method BatteryeRawAnalytics()
 
 Returns a buffer usually containg 12 blocks of analytics data.
 Those blocks contain:
-- block number starting with 0 (u8)
+
+- a block number starting with 0 (u8)
 - 31 bytes of unknown data
 
 .. note::
index 3be1bdf..892b237 100644 (file)
@@ -1843,6 +1843,7 @@ F:        Documentation/devicetree/bindings/phy/amlogic*
 F:     arch/arm/boot/dts/amlogic/
 F:     arch/arm/mach-meson/
 F:     arch/arm64/boot/dts/amlogic/
+F:     drivers/genpd/amlogic/
 F:     drivers/mmc/host/meson*
 F:     drivers/phy/amlogic/
 F:     drivers/pinctrl/meson/
@@ -1903,6 +1904,7 @@ F:        drivers/bluetooth/hci_bcm4377.c
 F:     drivers/clk/clk-apple-nco.c
 F:     drivers/cpufreq/apple-soc-cpufreq.c
 F:     drivers/dma/apple-admac.c
+F:     drivers/genpd/apple/
 F:     drivers/i2c/busses/i2c-pasemi-core.c
 F:     drivers/i2c/busses/i2c-pasemi-platform.c
 F:     drivers/iommu/apple-dart.c
@@ -2419,6 +2421,7 @@ F:        arch/arm/mach-ux500/
 F:     drivers/clk/clk-nomadik.c
 F:     drivers/clocksource/clksrc-dbx500-prcmu.c
 F:     drivers/dma/ste_dma40*
+F:     drivers/genpd/st/ste-ux500-pm-domain.c
 F:     drivers/hwspinlock/u8500_hsem.c
 F:     drivers/i2c/busses/i2c-nomadik.c
 F:     drivers/iio/adc/ab8500-gpadc.c
@@ -2591,6 +2594,7 @@ F:        arch/arm/include/debug/renesas-scif.S
 F:     arch/arm/mach-shmobile/
 F:     arch/arm64/boot/dts/renesas/
 F:     arch/riscv/boot/dts/renesas/
+F:     drivers/genpd/renesas/
 F:     drivers/soc/renesas/
 F:     include/linux/soc/renesas/
 K:     \brenesas,
@@ -2927,14 +2931,13 @@ M:      Sudeep Holla <sudeep.holla@arm.com>
 M:     Lorenzo Pieralisi <lpieralisi@kernel.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     */*/*/vexpress*
-F:     */*/vexpress*
-F:     arch/arm/boot/dts/arm/vexpress*
+N:     mps2
+N:     vexpress
 F:     arch/arm/mach-versatile/
 F:     arch/arm64/boot/dts/arm/
-F:     drivers/clk/versatile/clk-vexpress-osc.c
 F:     drivers/clocksource/timer-versatile.c
-N:     mps2
+X:     drivers/cpufreq/vexpress-spc-cpufreq.c
+X:     Documentation/devicetree/bindings/arm/arm,vexpress-juno.yaml
 
 ARM/VFP SUPPORT
 M:     Russell King <linux@armlinux.org.uk>
@@ -4007,7 +4010,7 @@ F:        arch/mips/kernel/*bmips*
 F:     drivers/irqchip/irq-bcm63*
 F:     drivers/irqchip/irq-bcm7*
 F:     drivers/irqchip/irq-brcmstb*
-F:     drivers/soc/bcm/bcm63xx
+F:     drivers/genpd/bcm/bcm63xx-power.c
 F:     include/linux/bcm963xx_nvram.h
 F:     include/linux/bcm963xx_tag.h
 
@@ -4121,6 +4124,13 @@ F:       Documentation/devicetree/bindings/spi/brcm,bcm63xx-hsspi.yaml
 F:     drivers/spi/spi-bcm63xx-hsspi.c
 F:     drivers/spi/spi-bcmbca-hsspi.c
 
+BROADCOM BCM6348/BCM6358 SPI controller DRIVER
+M:     Jonas Gorski <jonas.gorski@gmail.com>
+L:     linux-spi@vger.kernel.org
+S:     Odd Fixes
+F:     Documentation/devicetree/bindings/spi/spi-bcm63xx.txt
+F:     drivers/spi/spi-bcm63xx.c
+
 BROADCOM ETHERNET PHY DRIVERS
 M:     Florian Fainelli <florian.fainelli@broadcom.com>
 R:     Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
@@ -4222,7 +4232,7 @@ R:        Broadcom internal kernel review list <bcm-kernel-feedback-list@broadcom.com>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
 T:     git https://github.com/broadcom/stblinux.git
-F:     drivers/soc/bcm/bcm63xx/bcm-pmb.c
+F:     drivers/genpd/bcm/bcm-pmb.c
 F:     include/dt-bindings/soc/bcm-pmb.h
 
 BROADCOM SPECIFIC AMBA DRIVER (BCMA)
@@ -8665,6 +8675,13 @@ F:       Documentation/devicetree/bindings/power/power?domain*
 F:     drivers/base/power/domain*.c
 F:     include/linux/pm_domain.h
 
+GENERIC PM DOMAIN PROVIDERS
+M:     Ulf Hansson <ulf.hansson@linaro.org>
+L:     linux-pm@vger.kernel.org
+S:     Supported
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ulfh/linux-pm.git
+F:     drivers/genpd/
+
 GENERIC RESISTIVE TOUCHSCREEN ADC DRIVER
 M:     Eugen Hristev <eugen.hristev@microchip.com>
 L:     linux-input@vger.kernel.org
@@ -8672,8 +8689,11 @@ S:       Maintained
 F:     drivers/input/touchscreen/resistive-adc-touch.c
 
 GENERIC STRING LIBRARY
+M:     Kees Cook <keescook@chromium.org>
 R:     Andy Shevchenko <andy@kernel.org>
-S:     Maintained
+L:     linux-hardening@vger.kernel.org
+S:     Supported
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
 F:     include/linux/string.h
 F:     include/linux/string_choices.h
 F:     include/linux/string_helpers.h
@@ -13968,7 +13988,7 @@ T:      git https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux.git/
 F:     drivers/soc/microchip/
 
 MICROCHIP SPI DRIVER
-M:     Tudor Ambarus <tudor.ambarus@linaro.org>
+M:     Ryan Wanner <ryan.wanner@microchip.com>
 S:     Supported
 F:     drivers/spi/spi-atmel.*
 
@@ -17515,7 +17535,7 @@ L:      linux-pm@vger.kernel.org
 L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/power/avs/qcom,cpr.yaml
-F:     drivers/soc/qcom/cpr.c
+F:     drivers/genpd/qcom/cpr.c
 
 QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096
 M:     Ilia Lin <ilia.lin@kernel.org>
@@ -17543,6 +17563,7 @@ QUALCOMM ETHQOS ETHERNET DRIVER
 M:     Vinod Koul <vkoul@kernel.org>
 R:     Bhupesh Sharma <bhupesh.sharma@linaro.org>
 L:     netdev@vger.kernel.org
+L:     linux-arm-msm@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/net/qcom,ethqos.yaml
 F:     drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -20313,7 +20334,7 @@ STARFIVE JH71XX PMU CONTROLLER DRIVER
 M:     Walker Chen <walker.chen@starfivetech.com>
 S:     Supported
 F:     Documentation/devicetree/bindings/power/starfive*
-F:     drivers/soc/starfive/jh71xx_pmu.c
+F:     drivers/genpd/starfive/jh71xx_pmu.c
 F:     include/dt-bindings/power/starfive,jh7110-pmu.h
 
 STARFIVE SOC DRIVERS
@@ -21097,7 +21118,7 @@ F:      drivers/irqchip/irq-ti-sci-inta.c
 F:     drivers/irqchip/irq-ti-sci-intr.c
 F:     drivers/reset/reset-ti-sci.c
 F:     drivers/soc/ti/ti_sci_inta_msi.c
-F:     drivers/soc/ti/ti_sci_pm_domains.c
+F:     drivers/genpd/ti/ti_sci_pm_domains.c
 F:     include/dt-bindings/soc/ti,sci_pm_domain.h
 F:     include/linux/soc/ti/ti_sci_inta_msi.h
 F:     include/linux/soc/ti/ti_sci_protocol.h
@@ -21331,6 +21352,7 @@ L:      linux-kernel@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/ti/linux.git
+F:     drivers/genpd/ti/omap_prm.c
 F:     drivers/soc/ti/*
 
 TI LM49xxx FAMILY ASoC CODEC DRIVERS
index 47690c2..658ec2b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 6
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc2
 NAME = Hurr durr I'ma ninja sloth
 
 # *DOCUMENTATION*
index 5e90324..270e567 100644 (file)
@@ -6,4 +6,3 @@
 obj-y                          := pm.o
 obj-$(CONFIG_UX500_SOC_DB8500) += cpu-db8500.o
 obj-$(CONFIG_SMP)              += platsmp.o
-obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
index 7cc0dd8..b1a70f2 100644 (file)
@@ -26,8 +26,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
 
-#include "pm_domains.h"
-
 static int __init ux500_l2x0_unlock(void)
 {
        int i;
@@ -115,9 +113,6 @@ static const struct of_device_id u8500_local_bus_nodes[] = {
 
 static void __init u8500_init_machine(void)
 {
-       /* Initialize ux500 power domains */
-       ux500_pm_domains_init();
-
        of_platform_populate(NULL, u8500_local_bus_nodes,
                             NULL, NULL);
 }
diff --git a/arch/arm/mach-ux500/pm_domains.h b/arch/arm/mach-ux500/pm_domains.h
deleted file mode 100644 (file)
index 33c55f2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2014 Linaro Ltd.
- *
- * Author: Ulf Hansson <ulf.hansson@linaro.org>
- */
-
-#ifndef __MACH_UX500_PM_DOMAINS_H
-#define __MACH_UX500_PM_DOMAINS_H
-
-#ifdef CONFIG_PM_GENERIC_DOMAINS
-extern int __init ux500_pm_domains_init(void);
-#else
-static inline int ux500_pm_domains_init(void) { return 0; }
-#endif
-
-#endif
index 7856c3a..a2511b3 100644 (file)
@@ -197,6 +197,8 @@ config ARM64
                    !CC_OPTIMIZE_FOR_SIZE)
        select FTRACE_MCOUNT_USE_PATCHABLE_FUNCTION_ENTRY \
                if DYNAMIC_FTRACE_WITH_ARGS
+       select HAVE_SAMPLE_FTRACE_DIRECT
+       select HAVE_SAMPLE_FTRACE_DIRECT_MULTI
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
        select HAVE_FAST_GUP
        select HAVE_FTRACE_MCOUNT_RECORD
index 21ac1c5..ab15819 100644 (file)
@@ -211,6 +211,10 @@ static inline unsigned long fgraph_ret_regs_frame_pointer(struct fgraph_ret_regs
 {
        return ret_regs->fp;
 }
+
+void prepare_ftrace_return(unsigned long self_addr, unsigned long *parent,
+                          unsigned long frame_pointer);
+
 #endif /* ifdef CONFIG_FUNCTION_GRAPH_TRACER  */
 #endif
 
index 4cfe9b4..ab8e14b 100644 (file)
@@ -85,4 +85,7 @@ static inline int syscall_get_arch(struct task_struct *task)
        return AUDIT_ARCH_AARCH64;
 }
 
+int syscall_trace_enter(struct pt_regs *regs);
+void syscall_trace_exit(struct pt_regs *regs);
+
 #endif /* __ASM_SYSCALL_H */
index 5a668d7..b1ae2f2 100644 (file)
@@ -75,9 +75,6 @@ static inline bool has_syscall_work(unsigned long flags)
        return unlikely(flags & _TIF_SYSCALL_WORK);
 }
 
-int syscall_trace_enter(struct pt_regs *regs);
-void syscall_trace_exit(struct pt_regs *regs);
-
 static void el0_svc_common(struct pt_regs *regs, int scno, int sc_nr,
                           const syscall_fn_t syscall_table[])
 {
index ca585e4..e7ffb58 100644 (file)
 
 struct sigcontext {
        struct user_regs_struct regs;  /* needs to be first */
-       struct __or1k_fpu_state fpu;
-       unsigned long oldmask;
+       union {
+               unsigned long fpcsr;
+               unsigned long oldmask;  /* unused */
+       };
 };
 
 #endif /* __ASM_OPENRISC_SIGCONTEXT_H */
index 4664a18..2e7257a 100644 (file)
@@ -50,7 +50,7 @@ static int restore_sigcontext(struct pt_regs *regs,
        err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));
        err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long));
        err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
-       err |= __copy_from_user(&regs->fpcsr, &sc->fpu.fpcsr, sizeof(unsigned long));
+       err |= __copy_from_user(&regs->fpcsr, &sc->fpcsr, sizeof(unsigned long));
 
        /* make sure the SM-bit is cleared so user-mode cannot fool us */
        regs->sr &= ~SPR_SR_SM;
@@ -113,7 +113,7 @@ static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
        err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
        err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
        err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
-       err |= __copy_to_user(&sc->fpu.fpcsr, &regs->fpcsr, sizeof(unsigned long));
+       err |= __copy_to_user(&sc->fpcsr, &regs->fpcsr, sizeof(unsigned long));
 
        return err;
 }
index b6ac4f8..6472b08 100644 (file)
@@ -136,12 +136,6 @@ static inline int hash__pmd_trans_huge(pmd_t pmd)
        return 0;
 }
 
-static inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b)
-{
-       BUG();
-       return 0;
-}
-
 static inline pmd_t hash__pmd_mkhuge(pmd_t pmd)
 {
        BUG();
index 338e62f..0bf6fd0 100644 (file)
@@ -263,11 +263,6 @@ static inline int hash__pmd_trans_huge(pmd_t pmd)
                  (_PAGE_PTE | H_PAGE_THP_HUGE));
 }
 
-static inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b)
-{
-       return (((pmd_raw(pmd_a) ^ pmd_raw(pmd_b)) & ~cpu_to_be64(_PAGE_HPTEFLAGS)) == 0);
-}
-
 static inline pmd_t hash__pmd_mkhuge(pmd_t pmd)
 {
        return __pmd(pmd_val(pmd) | (_PAGE_PTE | H_PAGE_THP_HUGE));
index 17e7a77..d4a19e6 100644 (file)
@@ -132,6 +132,11 @@ static inline int get_region_id(unsigned long ea)
        return region_id;
 }
 
+static inline int hash__pmd_same(pmd_t pmd_a, pmd_t pmd_b)
+{
+       return (((pmd_raw(pmd_a) ^ pmd_raw(pmd_b)) & ~cpu_to_be64(_PAGE_HPTEFLAGS)) == 0);
+}
+
 #define        hash__pmd_bad(pmd)              (pmd_val(pmd) & H_PMD_BAD_BITS)
 #define        hash__pud_bad(pud)              (pud_val(pud) & H_PUD_BAD_BITS)
 static inline int hash__p4d_bad(p4d_t p4d)
index 3f86091..7ab4c8c 100644 (file)
@@ -5,6 +5,7 @@
  *  Copyright (C) 2007 Ben. Herrenschmidt (benh@kernel.crashing.org), IBM Corp.
  */
 
+#include <linux/linkage.h>
 #include <linux/threads.h>
 #include <asm/reg.h>
 #include <asm/page.h>
@@ -66,7 +67,7 @@
 #define SPECIAL_EXC_LOAD(reg, name) \
        ld      reg, (SPECIAL_EXC_##name * 8 + SPECIAL_EXC_FRAME_OFFS)(r1)
 
-special_reg_save:
+SYM_CODE_START_LOCAL(special_reg_save)
        /*
         * We only need (or have stack space) to save this stuff if
         * we interrupted the kernel.
@@ -131,8 +132,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
        SPECIAL_EXC_STORE(r10,CSRR1)
 
        blr
+SYM_CODE_END(special_reg_save)
 
-ret_from_level_except:
+SYM_CODE_START_LOCAL(ret_from_level_except)
        ld      r3,_MSR(r1)
        andi.   r3,r3,MSR_PR
        beq     1f
@@ -206,6 +208,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
        mtxer   r11
 
        blr
+SYM_CODE_END(ret_from_level_except)
 
 .macro ret_from_level srr0 srr1 paca_ex scratch
        bl      ret_from_level_except
@@ -232,13 +235,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
        mfspr   r13,\scratch
 .endm
 
-ret_from_crit_except:
+SYM_CODE_START_LOCAL(ret_from_crit_except)
        ret_from_level SPRN_CSRR0 SPRN_CSRR1 PACA_EXCRIT SPRN_SPRG_CRIT_SCRATCH
        rfci
+SYM_CODE_END(ret_from_crit_except)
 
-ret_from_mc_except:
+SYM_CODE_START_LOCAL(ret_from_mc_except)
        ret_from_level SPRN_MCSRR0 SPRN_MCSRR1 PACA_EXMC SPRN_SPRG_MC_SCRATCH
        rfmci
+SYM_CODE_END(ret_from_mc_except)
 
 /* Exception prolog code for all exceptions */
 #define EXCEPTION_PROLOG(n, intnum, type, addition)                        \
@@ -978,20 +983,22 @@ masked_interrupt_book3e_0x2c0:
  * r14 and r15 containing the fault address and error code, with the
  * original values stashed away in the PACA
  */
-storage_fault_common:
+SYM_CODE_START_LOCAL(storage_fault_common)
        addi    r3,r1,STACK_INT_FRAME_REGS
        bl      do_page_fault
        b       interrupt_return
+SYM_CODE_END(storage_fault_common)
 
 /*
  * Alignment exception doesn't fit entirely in the 0x100 bytes so it
  * continues here.
  */
-alignment_more:
+SYM_CODE_START_LOCAL(alignment_more)
        addi    r3,r1,STACK_INT_FRAME_REGS
        bl      alignment_exception
        REST_NVGPRS(r1)
        b       interrupt_return
+SYM_CODE_END(alignment_more)
 
 /*
  * Trampolines used when spotting a bad kernel stack pointer in
@@ -1030,8 +1037,7 @@ BAD_STACK_TRAMPOLINE(0xe00)
 BAD_STACK_TRAMPOLINE(0xf00)
 BAD_STACK_TRAMPOLINE(0xf20)
 
-       .globl  bad_stack_book3e
-bad_stack_book3e:
+_GLOBAL(bad_stack_book3e)
        /* XXX: Needs to make SPRN_SPRG_GEN depend on exception type */
        mfspr   r10,SPRN_SRR0;            /* read SRR0 before touching stack */
        ld      r1,PACAEMERGSP(r13)
@@ -1285,8 +1291,7 @@ have_hes:
         * ever takes any parameters, the SCOM code must also be updated to
         * provide them.
         */
-       .globl a2_tlbinit_code_start
-a2_tlbinit_code_start:
+_GLOBAL(a2_tlbinit_code_start)
 
        ori     r11,r3,MAS0_WQ_ALLWAYS
        oris    r11,r11,MAS0_ESEL(3)@h /* Use way 3: workaround A2 erratum 376 */
@@ -1479,8 +1484,7 @@ _GLOBAL(book3e_secondary_thread_init)
        mflr    r28
        b       3b
 
-       .globl init_core_book3e
-init_core_book3e:
+_GLOBAL(init_core_book3e)
        /* Establish the interrupt vector base */
        tovirt(r2,r2)
        LOAD_REG_ADDR(r3, interrupt_base_book3e)
@@ -1488,7 +1492,7 @@ init_core_book3e:
        sync
        blr
 
-init_thread_book3e:
+SYM_CODE_START_LOCAL(init_thread_book3e)
        lis     r3,(SPRN_EPCR_ICM | SPRN_EPCR_GICM)@h
        mtspr   SPRN_EPCR,r3
 
@@ -1502,6 +1506,7 @@ init_thread_book3e:
        mtspr   SPRN_TSR,r3
 
        blr
+SYM_CODE_END(init_thread_book3e)
 
 _GLOBAL(__setup_base_ivors)
        SET_IVOR(0, 0x020) /* Critical Input */
index 206475e..4856e1a 100644 (file)
@@ -364,26 +364,27 @@ ssize_t cpu_show_spec_store_bypass(struct device *dev, struct device_attribute *
 
 static int ssb_prctl_get(struct task_struct *task)
 {
+       /*
+        * The STF_BARRIER feature is on by default, so if it's off that means
+        * firmware has explicitly said the CPU is not vulnerable via either
+        * the hypercall or device tree.
+        */
+       if (!security_ftr_enabled(SEC_FTR_STF_BARRIER))
+               return PR_SPEC_NOT_AFFECTED;
+
+       /*
+        * If the system's CPU has no known barrier (see setup_stf_barrier())
+        * then assume that the CPU is not vulnerable.
+        */
        if (stf_enabled_flush_types == STF_BARRIER_NONE)
-               /*
-                * We don't have an explicit signal from firmware that we're
-                * vulnerable or not, we only have certain CPU revisions that
-                * are known to be vulnerable.
-                *
-                * We assume that if we're on another CPU, where the barrier is
-                * NONE, then we are not vulnerable.
-                */
                return PR_SPEC_NOT_AFFECTED;
-       else
-               /*
-                * If we do have a barrier type then we are vulnerable. The
-                * barrier is not a global or per-process mitigation, so the
-                * only value we can report here is PR_SPEC_ENABLE, which
-                * appears as "vulnerable" in /proc.
-                */
-               return PR_SPEC_ENABLE;
-
-       return -EINVAL;
+
+       /*
+        * Otherwise the CPU is vulnerable. The barrier is not a global or
+        * per-process mitigation, so the only value that can be reported here
+        * is PR_SPEC_ENABLE, which appears as "vulnerable" in /proc.
+        */
+       return PR_SPEC_ENABLE;
 }
 
 int arch_prctl_spec_ctrl_get(struct task_struct *task, unsigned long which)
index 9342e79..430d1d9 100644 (file)
@@ -328,10 +328,12 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn,
 
 static long native_hpte_remove(unsigned long hpte_group)
 {
+       unsigned long hpte_v, flags;
        struct hash_pte *hptep;
        int i;
        int slot_offset;
-       unsigned long hpte_v;
+
+       local_irq_save(flags);
 
        DBG_LOW("    remove(group=%lx)\n", hpte_group);
 
@@ -356,13 +358,16 @@ static long native_hpte_remove(unsigned long hpte_group)
                slot_offset &= 0x7;
        }
 
-       if (i == HPTES_PER_GROUP)
-               return -1;
+       if (i == HPTES_PER_GROUP) {
+               i = -1;
+               goto out;
+       }
 
        /* Invalidate the hpte. NOTE: this also unlocks it */
        release_hpte_lock();
        hptep->v = 0;
-
+out:
+       local_irq_restore(flags);
        return i;
 }
 
index bdcf460..a8f66c0 100644 (file)
@@ -318,18 +318,13 @@ void __init riscv_fill_hwcap(void)
                }
 
                /*
-                * Linux requires the following extensions, so we may as well
-                * always set them.
-                */
-               set_bit(RISCV_ISA_EXT_ZICSR, isainfo->isa);
-               set_bit(RISCV_ISA_EXT_ZIFENCEI, isainfo->isa);
-
-               /*
                 * These ones were as they were part of the base ISA when the
                 * port & dt-bindings were upstreamed, and so can be set
                 * unconditionally where `i` is in riscv,isa on DT systems.
                 */
                if (acpi_disabled) {
+                       set_bit(RISCV_ISA_EXT_ZICSR, isainfo->isa);
+                       set_bit(RISCV_ISA_EXT_ZIFENCEI, isainfo->isa);
                        set_bit(RISCV_ISA_EXT_ZICNTR, isainfo->isa);
                        set_bit(RISCV_ISA_EXT_ZIHPM, isainfo->isa);
                }
index 70fb319..9ce5047 100644 (file)
@@ -1346,7 +1346,7 @@ static void __init reserve_crashkernel(void)
         */
        crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
                                               search_start,
-                                              min(search_end, (unsigned long) SZ_4G));
+                                              min(search_end, (unsigned long)(SZ_4G - 1)));
        if (crash_base == 0) {
                /* Try again without restricting region to 32bit addressible memory */
                crash_base = memblock_phys_alloc_range(crash_size, PMD_SIZE,
index bf9802a..2717f54 100644 (file)
@@ -69,7 +69,7 @@ struct rv_jit_context {
        struct bpf_prog *prog;
        u16 *insns;             /* RV insns */
        int ninsns;
-       int body_len;
+       int prologue_len;
        int epilogue_offset;
        int *offset;            /* BPF to RV */
        int nexentries;
@@ -216,8 +216,8 @@ static inline int rv_offset(int insn, int off, struct rv_jit_context *ctx)
        int from, to;
 
        off++; /* BPF branch is from PC+1, RV is from PC */
-       from = (insn > 0) ? ctx->offset[insn - 1] : 0;
-       to = (insn + off > 0) ? ctx->offset[insn + off - 1] : 0;
+       from = (insn > 0) ? ctx->offset[insn - 1] : ctx->prologue_len;
+       to = (insn + off > 0) ? ctx->offset[insn + off - 1] : ctx->prologue_len;
        return ninsns_rvoff(to - from);
 }
 
index 737baf8..7a26a3e 100644 (file)
@@ -44,7 +44,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        unsigned int prog_size = 0, extable_size = 0;
        bool tmp_blinded = false, extra_pass = false;
        struct bpf_prog *tmp, *orig_prog = prog;
-       int pass = 0, prev_ninsns = 0, prologue_len, i;
+       int pass = 0, prev_ninsns = 0, i;
        struct rv_jit_data *jit_data;
        struct rv_jit_context *ctx;
 
@@ -83,6 +83,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
                prog = orig_prog;
                goto out_offset;
        }
+
+       if (build_body(ctx, extra_pass, NULL)) {
+               prog = orig_prog;
+               goto out_offset;
+       }
+
        for (i = 0; i < prog->len; i++) {
                prev_ninsns += 32;
                ctx->offset[i] = prev_ninsns;
@@ -91,12 +97,15 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
        for (i = 0; i < NR_JIT_ITERATIONS; i++) {
                pass++;
                ctx->ninsns = 0;
+
+               bpf_jit_build_prologue(ctx);
+               ctx->prologue_len = ctx->ninsns;
+
                if (build_body(ctx, extra_pass, ctx->offset)) {
                        prog = orig_prog;
                        goto out_offset;
                }
-               ctx->body_len = ctx->ninsns;
-               bpf_jit_build_prologue(ctx);
+
                ctx->epilogue_offset = ctx->ninsns;
                bpf_jit_build_epilogue(ctx);
 
@@ -162,10 +171,8 @@ skip_init_ctx:
 
        if (!prog->is_func || extra_pass) {
                bpf_jit_binary_lock_ro(jit_data->header);
-               prologue_len = ctx->epilogue_offset - ctx->body_len;
                for (i = 0; i < prog->len; i++)
-                       ctx->offset[i] = ninsns_rvoff(prologue_len +
-                                                     ctx->offset[i]);
+                       ctx->offset[i] = ninsns_rvoff(ctx->offset[i]);
                bpf_prog_fill_jited_linfo(prog, ctx->offset);
 out_offset:
                kfree(ctx->offset);
index cc06e4c..0eec82f 100644 (file)
@@ -108,13 +108,13 @@ int systemasic_irq_demux(int irq)
        __u32 j, bit;
 
        switch (irq) {
-       case 13:
+       case 13 + 16:
                level = 0;
                break;
-       case 11:
+       case 11 + 16:
                level = 1;
                break;
-       case  9:
+       case 9 + 16:
                level = 2;
                break;
        default:
index 533393d..0156566 100644 (file)
@@ -389,10 +389,10 @@ static unsigned char irl2irq[HL_NR_IRL];
 
 static int highlander_irq_demux(int irq)
 {
-       if (irq >= HL_NR_IRL || irq < 0 || !irl2irq[irq])
+       if (irq >= HL_NR_IRL + 16 || irq < 16 || !irl2irq[irq - 16])
                return irq;
 
-       return irl2irq[irq];
+       return irl2irq[irq - 16];
 }
 
 static void __init highlander_init_irq(void)
index e34f81e..d0a54a9 100644 (file)
@@ -117,10 +117,10 @@ static unsigned char irl2irq[R2D_NR_IRL];
 
 int rts7751r2d_irq_demux(int irq)
 {
-       if (irq >= R2D_NR_IRL || irq < 0 || !irl2irq[irq])
+       if (irq >= R2D_NR_IRL + 16 || irq < 16 || !irl2irq[irq - 16])
                return irq;
 
-       return irl2irq[irq];
+       return irl2irq[irq - 16];
 }
 
 /*
index efde2ed..9659a0b 100644 (file)
@@ -29,9 +29,9 @@ endchoice
 config HD64461_IRQ
        int "HD64461 IRQ"
        depends on HD64461
-       default "36"
+       default "52"
        help
-         The default setting of the HD64461 IRQ is 36.
+         The default setting of the HD64461 IRQ is 52.
 
          Do not change this unless you know what you are doing.
 
index afb24cb..d2c485f 100644 (file)
 #define        HD64461_NIMR            HD64461_IO_OFFSET(0x5002)
 
 #define        HD64461_IRQBASE         OFFCHIP_IRQ_BASE
-#define        OFFCHIP_IRQ_BASE        64
+#define        OFFCHIP_IRQ_BASE        (64 + 16)
 #define        HD64461_IRQ_NUM         16
 
 #define        HD64461_IRQ_UART        (HD64461_IRQBASE+5)
index 7a13395..d0af82c 100644 (file)
@@ -15,7 +15,7 @@
 unsigned long __xchg_u32(volatile u32 *m, u32 new);
 void __xchg_called_with_bad_pointer(void);
 
-static inline unsigned long __arch_xchg(unsigned long x, __volatile__ void * ptr, int size)
+static __always_inline unsigned long __arch_xchg(unsigned long x, __volatile__ void * ptr, int size)
 {
        switch (size) {
        case 4:
index 66cd61d..3de2526 100644 (file)
@@ -87,7 +87,7 @@ xchg16(__volatile__ unsigned short *m, unsigned short val)
        return (load32 & mask) >> bit_shift;
 }
 
-static inline unsigned long
+static __always_inline unsigned long
 __arch_xchg(unsigned long x, __volatile__ void * ptr, int size)
 {
        switch (size) {
index 918fed7..b1bfed0 100644 (file)
@@ -437,7 +437,7 @@ void __init arch_cpu_finalize_init(void)
        os_check_bugs();
 }
 
-void apply_ibt_endbr(s32 *start, s32 *end)
+void apply_seal_endbr(s32 *start, s32 *end)
 {
 }
 
index 91397f5..6e6af42 100644 (file)
@@ -720,26 +720,6 @@ SYM_CODE_END(__switch_to_asm)
 .popsection
 
 /*
- * The unwinder expects the last frame on the stack to always be at the same
- * offset from the end of the page, which allows it to validate the stack.
- * Calling schedule_tail() directly would break that convention because its an
- * asmlinkage function so its argument has to be pushed on the stack.  This
- * wrapper creates a proper "end of stack" frame header before the call.
- */
-.pushsection .text, "ax"
-SYM_FUNC_START(schedule_tail_wrapper)
-       FRAME_BEGIN
-
-       pushl   %eax
-       call    schedule_tail
-       popl    %eax
-
-       FRAME_END
-       RET
-SYM_FUNC_END(schedule_tail_wrapper)
-.popsection
-
-/*
  * A newly forked process directly context switches into this address.
  *
  * eax: prev task we switched from
@@ -747,29 +727,22 @@ SYM_FUNC_END(schedule_tail_wrapper)
  * edi: kernel thread arg
  */
 .pushsection .text, "ax"
-SYM_CODE_START(ret_from_fork)
-       call    schedule_tail_wrapper
+SYM_CODE_START(ret_from_fork_asm)
+       movl    %esp, %edx      /* regs */
 
-       testl   %ebx, %ebx
-       jnz     1f              /* kernel threads are uncommon */
+       /* return address for the stack unwinder */
+       pushl   $.Lsyscall_32_done
 
-2:
-       /* When we fork, we trace the syscall return in the child, too. */
-       movl    %esp, %eax
-       call    syscall_exit_to_user_mode
-       jmp     .Lsyscall_32_done
+       FRAME_BEGIN
+       /* prev already in EAX */
+       movl    %ebx, %ecx      /* fn */
+       pushl   %edi            /* fn_arg */
+       call    ret_from_fork
+       addl    $4, %esp
+       FRAME_END
 
-       /* kernel thread */
-1:     movl    %edi, %eax
-       CALL_NOSPEC ebx
-       /*
-        * A kernel thread is allowed to return here after successfully
-        * calling kernel_execve().  Exit to userspace to complete the execve()
-        * syscall.
-        */
-       movl    $0, PT_EAX(%esp)
-       jmp     2b
-SYM_CODE_END(ret_from_fork)
+       RET
+SYM_CODE_END(ret_from_fork_asm)
 .popsection
 
 SYM_ENTRY(__begin_SYSENTER_singlestep_region, SYM_L_GLOBAL, SYM_A_NONE)
index f31e286..91f6818 100644 (file)
@@ -284,36 +284,19 @@ SYM_FUNC_END(__switch_to_asm)
  * r12: kernel thread arg
  */
 .pushsection .text, "ax"
-       __FUNC_ALIGN
-SYM_CODE_START_NOALIGN(ret_from_fork)
-       UNWIND_HINT_END_OF_STACK
+SYM_CODE_START(ret_from_fork_asm)
+       UNWIND_HINT_REGS
        ANNOTATE_NOENDBR // copy_thread
        CALL_DEPTH_ACCOUNT
-       movq    %rax, %rdi
-       call    schedule_tail                   /* rdi: 'prev' task parameter */
 
-       testq   %rbx, %rbx                      /* from kernel_thread? */
-       jnz     1f                              /* kernel threads are uncommon */
+       movq    %rax, %rdi              /* prev */
+       movq    %rsp, %rsi              /* regs */
+       movq    %rbx, %rdx              /* fn */
+       movq    %r12, %rcx              /* fn_arg */
+       call    ret_from_fork
 
-2:
-       UNWIND_HINT_REGS
-       movq    %rsp, %rdi
-       call    syscall_exit_to_user_mode       /* returns with IRQs disabled */
        jmp     swapgs_restore_regs_and_return_to_usermode
-
-1:
-       /* kernel thread */
-       UNWIND_HINT_END_OF_STACK
-       movq    %r12, %rdi
-       CALL_NOSPEC rbx
-       /*
-        * A kernel thread is allowed to return here after successfully
-        * calling kernel_execve().  Exit to userspace to complete the execve()
-        * syscall.
-        */
-       movq    $0, RAX(%rsp)
-       jmp     2b
-SYM_CODE_END(ret_from_fork)
+SYM_CODE_END(ret_from_fork_asm)
 .popsection
 
 .macro DEBUG_ENTRY_ASSERT_IRQS_OFF
index a149faf..2a284ba 100644 (file)
@@ -3993,6 +3993,13 @@ static int intel_pmu_hw_config(struct perf_event *event)
                struct perf_event *leader = event->group_leader;
                struct perf_event *sibling = NULL;
 
+               /*
+                * When this memload event is also the first event (no group
+                * exists yet), then there is no aux event before it.
+                */
+               if (leader == event)
+                       return -ENODATA;
+
                if (!is_mem_loads_aux_event(leader)) {
                        for_each_sibling_event(sibling, leader) {
                                if (is_mem_loads_aux_event(sibling))
index 6c15a62..9c4da69 100644 (file)
@@ -96,7 +96,7 @@ extern void alternative_instructions(void);
 extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
 extern void apply_retpolines(s32 *start, s32 *end);
 extern void apply_returns(s32 *start, s32 *end);
-extern void apply_ibt_endbr(s32 *start, s32 *end);
+extern void apply_seal_endbr(s32 *start, s32 *end);
 extern void apply_fineibt(s32 *start_retpoline, s32 *end_retpoine,
                          s32 *start_cfi, s32 *end_cfi);
 
index baae6b4..1e59581 100644 (file)
@@ -34,7 +34,7 @@
 /*
  * Create a dummy function pointer reference to prevent objtool from marking
  * the function as needing to be "sealed" (i.e. ENDBR converted to NOP by
- * apply_ibt_endbr()).
+ * apply_seal_endbr()).
  */
 #define IBT_NOSEAL(fname)                              \
        ".pushsection .discard.ibt_endbr_noseal\n\t"    \
index 55388c9..1a65cf4 100644 (file)
  * JMP_NOSPEC and CALL_NOSPEC macros can be used instead of a simple
  * indirect jmp/call which may be susceptible to the Spectre variant 2
  * attack.
+ *
+ * NOTE: these do not take kCFI into account and are thus not comparable to C
+ * indirect calls, take care when using. The target of these should be an ENDBR
+ * instruction irrespective of kCFI.
  */
 .macro JMP_NOSPEC reg:req
 #ifdef CONFIG_RETPOLINE
index 5c91305..f42dbf1 100644 (file)
@@ -12,7 +12,9 @@ struct task_struct *__switch_to_asm(struct task_struct *prev,
 __visible struct task_struct *__switch_to(struct task_struct *prev,
                                          struct task_struct *next);
 
-asmlinkage void ret_from_fork(void);
+asmlinkage void ret_from_fork_asm(void);
+__visible void ret_from_fork(struct task_struct *prev, struct pt_regs *regs,
+                            int (*fn)(void *), void *fn_arg);
 
 /*
  * This is the structure pointed to by thread.sp for an inactive task.  The
index 72646d7..2dcf3a0 100644 (file)
@@ -778,6 +778,8 @@ void __init_or_module noinline apply_returns(s32 *start, s32 *end) { }
 
 #ifdef CONFIG_X86_KERNEL_IBT
 
+static void poison_cfi(void *addr);
+
 static void __init_or_module poison_endbr(void *addr, bool warn)
 {
        u32 endbr, poison = gen_endbr_poison();
@@ -802,8 +804,11 @@ static void __init_or_module poison_endbr(void *addr, bool warn)
 
 /*
  * Generated by: objtool --ibt
+ *
+ * Seal the functions for indirect calls by clobbering the ENDBR instructions
+ * and the kCFI hash value.
  */
-void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end)
+void __init_or_module noinline apply_seal_endbr(s32 *start, s32 *end)
 {
        s32 *s;
 
@@ -812,13 +817,13 @@ void __init_or_module noinline apply_ibt_endbr(s32 *start, s32 *end)
 
                poison_endbr(addr, true);
                if (IS_ENABLED(CONFIG_FINEIBT))
-                       poison_endbr(addr - 16, false);
+                       poison_cfi(addr - 16);
        }
 }
 
 #else
 
-void __init_or_module apply_ibt_endbr(s32 *start, s32 *end) { }
+void __init_or_module apply_seal_endbr(s32 *start, s32 *end) { }
 
 #endif /* CONFIG_X86_KERNEL_IBT */
 
@@ -1063,6 +1068,17 @@ static int cfi_rewrite_preamble(s32 *start, s32 *end)
        return 0;
 }
 
+static void cfi_rewrite_endbr(s32 *start, s32 *end)
+{
+       s32 *s;
+
+       for (s = start; s < end; s++) {
+               void *addr = (void *)s + *s;
+
+               poison_endbr(addr+16, false);
+       }
+}
+
 /* .retpoline_sites */
 static int cfi_rand_callers(s32 *start, s32 *end)
 {
@@ -1157,14 +1173,19 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
                return;
 
        case CFI_FINEIBT:
+               /* place the FineIBT preamble at func()-16 */
                ret = cfi_rewrite_preamble(start_cfi, end_cfi);
                if (ret)
                        goto err;
 
+               /* rewrite the callers to target func()-16 */
                ret = cfi_rewrite_callers(start_retpoline, end_retpoline);
                if (ret)
                        goto err;
 
+               /* now that nobody targets func()+0, remove ENDBR there */
+               cfi_rewrite_endbr(start_cfi, end_cfi);
+
                if (builtin)
                        pr_info("Using FineIBT CFI\n");
                return;
@@ -1177,6 +1198,41 @@ err:
        pr_err("Something went horribly wrong trying to rewrite the CFI implementation.\n");
 }
 
+static inline void poison_hash(void *addr)
+{
+       *(u32 *)addr = 0;
+}
+
+static void poison_cfi(void *addr)
+{
+       switch (cfi_mode) {
+       case CFI_FINEIBT:
+               /*
+                * __cfi_\func:
+                *      osp nopl (%rax)
+                *      subl    $0, %r10d
+                *      jz      1f
+                *      ud2
+                * 1:   nop
+                */
+               poison_endbr(addr, false);
+               poison_hash(addr + fineibt_preamble_hash);
+               break;
+
+       case CFI_KCFI:
+               /*
+                * __cfi_\func:
+                *      movl    $0, %eax
+                *      .skip   11, 0x90
+                */
+               poison_hash(addr + 1);
+               break;
+
+       default:
+               break;
+       }
+}
+
 #else
 
 static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
@@ -1184,6 +1240,10 @@ static void __apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
 {
 }
 
+#ifdef CONFIG_X86_KERNEL_IBT
+static void poison_cfi(void *addr) { }
+#endif
+
 #endif
 
 void apply_fineibt(s32 *start_retpoline, s32 *end_retpoline,
@@ -1565,7 +1625,10 @@ void __init alternative_instructions(void)
         */
        callthunks_patch_builtin_calls();
 
-       apply_ibt_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end);
+       /*
+        * Seal all functions that do not have their address taken.
+        */
+       apply_seal_endbr(__ibt_endbr_seal, __ibt_endbr_seal_end);
 
 #ifdef CONFIG_SMP
        /* Patch to UP if other cpus not imminent. */
index 01e8f34..12df54f 100644 (file)
@@ -282,7 +282,6 @@ static inline void tramp_free(void *tramp) { }
 
 /* Defined as markers to the end of the ftrace default trampolines */
 extern void ftrace_regs_caller_end(void);
-extern void ftrace_regs_caller_ret(void);
 extern void ftrace_caller_end(void);
 extern void ftrace_caller_op_ptr(void);
 extern void ftrace_regs_caller_op_ptr(void);
index b05f62e..5f71a0c 100644 (file)
@@ -358,7 +358,7 @@ int module_finalize(const Elf_Ehdr *hdr,
        }
        if (ibt_endbr) {
                void *iseg = (void *)ibt_endbr->sh_addr;
-               apply_ibt_endbr(iseg, iseg + ibt_endbr->sh_size);
+               apply_seal_endbr(iseg, iseg + ibt_endbr->sh_size);
        }
        if (locks) {
                void *lseg = (void *)locks->sh_addr;
index ff9b80a..72015db 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/static_call.h>
 #include <trace/events/power.h>
 #include <linux/hw_breakpoint.h>
+#include <linux/entry-common.h>
 #include <asm/cpu.h>
 #include <asm/apic.h>
 #include <linux/uaccess.h>
@@ -134,6 +135,25 @@ static int set_new_tls(struct task_struct *p, unsigned long tls)
                return do_set_thread_area_64(p, ARCH_SET_FS, tls);
 }
 
+__visible void ret_from_fork(struct task_struct *prev, struct pt_regs *regs,
+                                    int (*fn)(void *), void *fn_arg)
+{
+       schedule_tail(prev);
+
+       /* Is this a kernel thread? */
+       if (unlikely(fn)) {
+               fn(fn_arg);
+               /*
+                * A kernel thread is allowed to return here after successfully
+                * calling kernel_execve().  Exit to userspace to complete the
+                * execve() syscall.
+                */
+               regs->ax = 0;
+       }
+
+       syscall_exit_to_user_mode(regs);
+}
+
 int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
 {
        unsigned long clone_flags = args->flags;
@@ -149,7 +169,7 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
        frame = &fork_frame->frame;
 
        frame->bp = encode_frame_pointer(childregs);
-       frame->ret_addr = (unsigned long) ret_from_fork;
+       frame->ret_addr = (unsigned long) ret_from_fork_asm;
        p->thread.sp = (unsigned long) fork_frame;
        p->thread.io_bitmap = NULL;
        p->thread.iopl_warn = 0;
index 643d029..a0ea285 100644 (file)
@@ -90,30 +90,35 @@ SYM_CODE_END(xen_cpu_bringup_again)
        ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
        ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION,  .asciz "2.6")
        ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION,    .asciz "xen-3.0")
-#ifdef CONFIG_X86_32
-       ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      _ASM_PTR __PAGE_OFFSET)
-#else
+#ifdef CONFIG_XEN_PV
        ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE,      _ASM_PTR __START_KERNEL_map)
        /* Map the p2m table to a 512GB-aligned user address. */
        ELFNOTE(Xen, XEN_ELFNOTE_INIT_P2M,       .quad (PUD_SIZE * PTRS_PER_PUD))
-#endif
-#ifdef CONFIG_XEN_PV
        ELFNOTE(Xen, XEN_ELFNOTE_ENTRY,          _ASM_PTR startup_xen)
-#endif
-       ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
-       ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,
-               .ascii "!writable_page_tables|pae_pgdir_above_4gb")
-       ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,
-               .long (1 << XENFEAT_writable_page_tables) |       \
-                     (1 << XENFEAT_dom0) |                       \
-                     (1 << XENFEAT_linux_rsdp_unrestricted))
+       ELFNOTE(Xen, XEN_ELFNOTE_FEATURES,       .ascii "!writable_page_tables")
        ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE,       .asciz "yes")
-       ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
        ELFNOTE(Xen, XEN_ELFNOTE_L1_MFN_VALID,
                .quad _PAGE_PRESENT; .quad _PAGE_PRESENT)
-       ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
        ELFNOTE(Xen, XEN_ELFNOTE_MOD_START_PFN,  .long 1)
-       ELFNOTE(Xen, XEN_ELFNOTE_HV_START_LOW,   _ASM_PTR __HYPERVISOR_VIRT_START)
        ELFNOTE(Xen, XEN_ELFNOTE_PADDR_OFFSET,   _ASM_PTR 0)
+# define FEATURES_PV (1 << XENFEAT_writable_page_tables)
+#else
+# define FEATURES_PV 0
+#endif
+#ifdef CONFIG_XEN_PVH
+# define FEATURES_PVH (1 << XENFEAT_linux_rsdp_unrestricted)
+#else
+# define FEATURES_PVH 0
+#endif
+#ifdef CONFIG_XEN_DOM0
+# define FEATURES_DOM0 (1 << XENFEAT_dom0)
+#else
+# define FEATURES_DOM0 0
+#endif
+       ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, _ASM_PTR hypercall_page)
+       ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,
+               .long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0)
+       ELFNOTE(Xen, XEN_ELFNOTE_LOADER,         .asciz "generic")
+       ELFNOTE(Xen, XEN_ELFNOTE_SUSPEND_CANCEL, .long 1)
 
 #endif /*CONFIG_XEN */
index 20d6b49..ee97edc 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * arch/xtensa/kernel/align.S
  *
- * Handle unalignment exceptions in kernel space.
+ * Handle unalignment and load/store exceptions.
  *
  * This file is subject to the terms and conditions of the GNU General
  * Public License.  See the file "COPYING" in the main directory of
 #define LOAD_EXCEPTION_HANDLER
 #endif
 
-#if XCHAL_UNALIGNED_STORE_EXCEPTION || defined LOAD_EXCEPTION_HANDLER
+#if XCHAL_UNALIGNED_STORE_EXCEPTION || defined CONFIG_XTENSA_LOAD_STORE
+#define STORE_EXCEPTION_HANDLER
+#endif
+
+#if defined LOAD_EXCEPTION_HANDLER || defined STORE_EXCEPTION_HANDLER
 #define ANY_EXCEPTION_HANDLER
 #endif
 
-#if XCHAL_HAVE_WINDOWED
+#if XCHAL_HAVE_WINDOWED && defined CONFIG_MMU
 #define UNALIGNED_USER_EXCEPTION
 #endif
 
-/*  First-level exception handler for unaligned exceptions.
- *
- *  Note: This handler works only for kernel exceptions.  Unaligned user
- *        access should get a seg fault.
- */
-
 /* Big and little endian 16-bit values are located in
  * different halves of a register.  HWORD_START helps to
  * abstract the notion of extracting a 16-bit value from a
@@ -228,8 +226,6 @@ ENDPROC(fast_load_store)
 #ifdef ANY_EXCEPTION_HANDLER
 ENTRY(fast_unaligned)
 
-#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
-
        call0   .Lsave_and_load_instruction
 
        /* Analyze the instruction (load or store?). */
@@ -244,8 +240,7 @@ ENTRY(fast_unaligned)
        /* 'store indicator bit' not set, jump */
        _bbci.l a4, OP1_SI_BIT + INSN_OP1, .Lload
 
-#endif
-#if XCHAL_UNALIGNED_STORE_EXCEPTION
+#ifdef STORE_EXCEPTION_HANDLER
 
        /* Store: Jump to table entry to get the value in the source register.*/
 
@@ -254,7 +249,7 @@ ENTRY(fast_unaligned)
        addx8   a5, a6, a5
        jx      a5                      # jump into table
 #endif
-#if XCHAL_UNALIGNED_LOAD_EXCEPTION
+#ifdef LOAD_EXCEPTION_HANDLER
 
        /* Load: Load memory address. */
 
@@ -328,7 +323,7 @@ ENTRY(fast_unaligned)
        mov     a14, a3         ;       _j .Lexit;      .align 8
        mov     a15, a3         ;       _j .Lexit;      .align 8
 #endif
-#if XCHAL_UNALIGNED_STORE_EXCEPTION
+#ifdef STORE_EXCEPTION_HANDLER
 .Lstore_table:
        l32i    a3, a2, PT_AREG0;       _j .Lstore_w;   .align 8
        mov     a3, a1;                 _j .Lstore_w;   .align 8        # fishy??
@@ -348,7 +343,6 @@ ENTRY(fast_unaligned)
        mov     a3, a15         ;       _j .Lstore_w;   .align 8
 #endif
 
-#ifdef ANY_EXCEPTION_HANDLER
        /* We cannot handle this exception. */
 
        .extern _kernel_exception
@@ -377,8 +371,8 @@ ENTRY(fast_unaligned)
 
 2:     movi    a0, _user_exception
        jx      a0
-#endif
-#if XCHAL_UNALIGNED_STORE_EXCEPTION
+
+#ifdef STORE_EXCEPTION_HANDLER
 
        # a7: instruction pointer, a4: instruction, a3: value
 .Lstore_w:
@@ -444,7 +438,7 @@ ENTRY(fast_unaligned)
        s32i    a6, a4, 4
 #endif
 #endif
-#ifdef ANY_EXCEPTION_HANDLER
+
 .Lexit:
 #if XCHAL_HAVE_LOOPS
        rsr     a4, lend                # check if we reached LEND
@@ -539,7 +533,7 @@ ENTRY(fast_unaligned)
        __src_b a4, a4, a5      # a4 has the instruction
 
        ret
-#endif
+
 ENDPROC(fast_unaligned)
 
 ENTRY(fast_unaligned_fixup)
index 17eb180..427c125 100644 (file)
@@ -102,7 +102,8 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = {
 #endif
 { EXCCAUSE_INTEGER_DIVIDE_BY_ZERO, 0,     do_div0 },
 /* EXCCAUSE_PRIVILEGED unhandled */
-#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION
+#if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION || \
+               IS_ENABLED(CONFIG_XTENSA_LOAD_STORE)
 #ifdef CONFIG_XTENSA_UNALIGNED_USER
 { EXCCAUSE_UNALIGNED,          USER,      fast_unaligned },
 #endif
index 9ac46ab..85c82cd 100644 (file)
@@ -237,7 +237,7 @@ static int tuntap_probe(struct iss_net_private *lp, int index, char *init)
 
        init += sizeof(TRANSPORT_TUNTAP_NAME) - 1;
        if (*init == ',') {
-               rem = split_if_spec(init + 1, &mac_str, &dev_name);
+               rem = split_if_spec(init + 1, &mac_str, &dev_name, NULL);
                if (rem != NULL) {
                        pr_err("%s: extra garbage on specification : '%s'\n",
                               dev->name, rem);
@@ -540,6 +540,7 @@ static void iss_net_configure(int index, char *init)
                rtnl_unlock();
                pr_err("%s: error registering net device!\n", dev->name);
                platform_device_unregister(&lp->pdev);
+               /* dev is freed by the iss_net_pdev_release callback */
                return;
        }
        rtnl_unlock();
index 2a67d3f..7fabc88 100644 (file)
@@ -79,7 +79,14 @@ int blk_crypto_profile_init(struct blk_crypto_profile *profile,
        unsigned int slot_hashtable_size;
 
        memset(profile, 0, sizeof(*profile));
-       init_rwsem(&profile->lock);
+
+       /*
+        * profile->lock of an underlying device can nest inside profile->lock
+        * of a device-mapper device, so use a dynamic lock class to avoid
+        * false-positive lockdep reports.
+        */
+       lockdep_register_key(&profile->lockdep_key);
+       __init_rwsem(&profile->lock, "&profile->lock", &profile->lockdep_key);
 
        if (num_slots == 0)
                return 0;
@@ -89,7 +96,7 @@ int blk_crypto_profile_init(struct blk_crypto_profile *profile,
        profile->slots = kvcalloc(num_slots, sizeof(profile->slots[0]),
                                  GFP_KERNEL);
        if (!profile->slots)
-               return -ENOMEM;
+               goto err_destroy;
 
        profile->num_slots = num_slots;
 
@@ -435,6 +442,7 @@ void blk_crypto_profile_destroy(struct blk_crypto_profile *profile)
 {
        if (!profile)
                return;
+       lockdep_unregister_key(&profile->lockdep_key);
        kvfree(profile->slot_hashtable);
        kvfree_sensitive(profile->slots,
                         sizeof(profile->slots[0]) * profile->num_slots);
index dba392c..8220517 100644 (file)
@@ -189,7 +189,7 @@ static void blk_flush_complete_seq(struct request *rq,
        case REQ_FSEQ_DATA:
                list_move_tail(&rq->flush.list, &fq->flush_data_in_flight);
                spin_lock(&q->requeue_lock);
-               list_add_tail(&rq->queuelist, &q->flush_list);
+               list_add(&rq->queuelist, &q->requeue_list);
                spin_unlock(&q->requeue_lock);
                blk_mq_kick_requeue_list(q);
                break;
index 5504719..d50b1d6 100644 (file)
@@ -328,8 +328,24 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
 }
 EXPORT_SYMBOL(blk_rq_init);
 
+/* Set start and alloc time when the allocated request is actually used */
+static inline void blk_mq_rq_time_init(struct request *rq, u64 alloc_time_ns)
+{
+       if (blk_mq_need_time_stamp(rq))
+               rq->start_time_ns = ktime_get_ns();
+       else
+               rq->start_time_ns = 0;
+
+#ifdef CONFIG_BLK_RQ_ALLOC_TIME
+       if (blk_queue_rq_alloc_time(rq->q))
+               rq->alloc_time_ns = alloc_time_ns ?: rq->start_time_ns;
+       else
+               rq->alloc_time_ns = 0;
+#endif
+}
+
 static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
-               struct blk_mq_tags *tags, unsigned int tag, u64 alloc_time_ns)
+               struct blk_mq_tags *tags, unsigned int tag)
 {
        struct blk_mq_ctx *ctx = data->ctx;
        struct blk_mq_hw_ctx *hctx = data->hctx;
@@ -356,14 +372,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
        }
        rq->timeout = 0;
 
-       if (blk_mq_need_time_stamp(rq))
-               rq->start_time_ns = ktime_get_ns();
-       else
-               rq->start_time_ns = 0;
        rq->part = NULL;
-#ifdef CONFIG_BLK_RQ_ALLOC_TIME
-       rq->alloc_time_ns = alloc_time_ns;
-#endif
        rq->io_start_time_ns = 0;
        rq->stats_sectors = 0;
        rq->nr_phys_segments = 0;
@@ -393,8 +402,7 @@ static struct request *blk_mq_rq_ctx_init(struct blk_mq_alloc_data *data,
 }
 
 static inline struct request *
-__blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data,
-               u64 alloc_time_ns)
+__blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data)
 {
        unsigned int tag, tag_offset;
        struct blk_mq_tags *tags;
@@ -413,7 +421,7 @@ __blk_mq_alloc_requests_batch(struct blk_mq_alloc_data *data,
                tag = tag_offset + i;
                prefetch(tags->static_rqs[tag]);
                tag_mask &= ~(1UL << i);
-               rq = blk_mq_rq_ctx_init(data, tags, tag, alloc_time_ns);
+               rq = blk_mq_rq_ctx_init(data, tags, tag);
                rq_list_add(data->cached_rq, rq);
                nr++;
        }
@@ -474,9 +482,11 @@ retry:
         * Try batched alloc if we want more than 1 tag.
         */
        if (data->nr_tags > 1) {
-               rq = __blk_mq_alloc_requests_batch(data, alloc_time_ns);
-               if (rq)
+               rq = __blk_mq_alloc_requests_batch(data);
+               if (rq) {
+                       blk_mq_rq_time_init(rq, alloc_time_ns);
                        return rq;
+               }
                data->nr_tags = 1;
        }
 
@@ -499,8 +509,9 @@ retry:
                goto retry;
        }
 
-       return blk_mq_rq_ctx_init(data, blk_mq_tags_from_data(data), tag,
-                                       alloc_time_ns);
+       rq = blk_mq_rq_ctx_init(data, blk_mq_tags_from_data(data), tag);
+       blk_mq_rq_time_init(rq, alloc_time_ns);
+       return rq;
 }
 
 static struct request *blk_mq_rq_cache_fill(struct request_queue *q,
@@ -555,6 +566,7 @@ static struct request *blk_mq_alloc_cached_request(struct request_queue *q,
                        return NULL;
 
                plug->cached_rq = rq_list_next(rq);
+               blk_mq_rq_time_init(rq, 0);
        }
 
        rq->cmd_flags = opf;
@@ -656,8 +668,8 @@ struct request *blk_mq_alloc_request_hctx(struct request_queue *q,
        tag = blk_mq_get_tag(&data);
        if (tag == BLK_MQ_NO_TAG)
                goto out_queue_exit;
-       rq = blk_mq_rq_ctx_init(&data, blk_mq_tags_from_data(&data), tag,
-                                       alloc_time_ns);
+       rq = blk_mq_rq_ctx_init(&data, blk_mq_tags_from_data(&data), tag);
+       blk_mq_rq_time_init(rq, alloc_time_ns);
        rq->__data_len = 0;
        rq->__sector = (sector_t) -1;
        rq->bio = rq->biotail = NULL;
@@ -2896,6 +2908,7 @@ static inline struct request *blk_mq_get_cached_request(struct request_queue *q,
        plug->cached_rq = rq_list_next(rq);
        rq_qos_throttle(q, *bio);
 
+       blk_mq_rq_time_init(rq, 0);
        rq->cmd_flags = (*bio)->bi_opf;
        INIT_LIST_HEAD(&rq->queuelist);
        return rq;
index 0f9f97c..619ee41 100644 (file)
@@ -442,7 +442,6 @@ struct blk_revalidate_zone_args {
        unsigned long   *conv_zones_bitmap;
        unsigned long   *seq_zones_wlock;
        unsigned int    nr_zones;
-       sector_t        zone_sectors;
        sector_t        sector;
 };
 
@@ -456,38 +455,34 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx,
        struct gendisk *disk = args->disk;
        struct request_queue *q = disk->queue;
        sector_t capacity = get_capacity(disk);
+       sector_t zone_sectors = q->limits.chunk_sectors;
+
+       /* Check for bad zones and holes in the zone report */
+       if (zone->start != args->sector) {
+               pr_warn("%s: Zone gap at sectors %llu..%llu\n",
+                       disk->disk_name, args->sector, zone->start);
+               return -ENODEV;
+       }
+
+       if (zone->start >= capacity || !zone->len) {
+               pr_warn("%s: Invalid zone start %llu, length %llu\n",
+                       disk->disk_name, zone->start, zone->len);
+               return -ENODEV;
+       }
 
        /*
         * All zones must have the same size, with the exception on an eventual
         * smaller last zone.
         */
-       if (zone->start == 0) {
-               if (zone->len == 0 || !is_power_of_2(zone->len)) {
-                       pr_warn("%s: Invalid zoned device with non power of two zone size (%llu)\n",
-                               disk->disk_name, zone->len);
-                       return -ENODEV;
-               }
-
-               args->zone_sectors = zone->len;
-               args->nr_zones = (capacity + zone->len - 1) >> ilog2(zone->len);
-       } else if (zone->start + args->zone_sectors < capacity) {
-               if (zone->len != args->zone_sectors) {
+       if (zone->start + zone->len < capacity) {
+               if (zone->len != zone_sectors) {
                        pr_warn("%s: Invalid zoned device with non constant zone size\n",
                                disk->disk_name);
                        return -ENODEV;
                }
-       } else {
-               if (zone->len > args->zone_sectors) {
-                       pr_warn("%s: Invalid zoned device with larger last zone size\n",
-                               disk->disk_name);
-                       return -ENODEV;
-               }
-       }
-
-       /* Check for holes in the zone report */
-       if (zone->start != args->sector) {
-               pr_warn("%s: Zone gap at sectors %llu..%llu\n",
-                       disk->disk_name, args->sector, zone->start);
+       } else if (zone->len > zone_sectors) {
+               pr_warn("%s: Invalid zoned device with larger last zone size\n",
+                       disk->disk_name);
                return -ENODEV;
        }
 
@@ -526,11 +521,13 @@ static int blk_revalidate_zone_cb(struct blk_zone *zone, unsigned int idx,
  * @disk:      Target disk
  * @update_driver_data:        Callback to update driver data on the frozen disk
  *
- * Helper function for low-level device drivers to (re) allocate and initialize
- * a disk request queue zone bitmaps. This functions should normally be called
- * within the disk ->revalidate method for blk-mq based drivers.  For BIO based
- * drivers only q->nr_zones needs to be updated so that the sysfs exposed value
- * is correct.
+ * Helper function for low-level device drivers to check and (re) allocate and
+ * initialize a disk request queue zone bitmaps. This functions should normally
+ * be called within the disk ->revalidate method for blk-mq based drivers.
+ * Before calling this function, the device driver must already have set the
+ * device zone size (chunk_sector limit) and the max zone append limit.
+ * For BIO based drivers, this function cannot be used. BIO based device drivers
+ * only need to set disk->nr_zones so that the sysfs exposed value is correct.
  * If the @update_driver_data callback function is not NULL, the callback is
  * executed with the device request queue frozen after all zones have been
  * checked.
@@ -539,9 +536,9 @@ int blk_revalidate_disk_zones(struct gendisk *disk,
                              void (*update_driver_data)(struct gendisk *disk))
 {
        struct request_queue *q = disk->queue;
-       struct blk_revalidate_zone_args args = {
-               .disk           = disk,
-       };
+       sector_t zone_sectors = q->limits.chunk_sectors;
+       sector_t capacity = get_capacity(disk);
+       struct blk_revalidate_zone_args args = { };
        unsigned int noio_flag;
        int ret;
 
@@ -550,13 +547,31 @@ int blk_revalidate_disk_zones(struct gendisk *disk,
        if (WARN_ON_ONCE(!queue_is_mq(q)))
                return -EIO;
 
-       if (!get_capacity(disk))
-               return -EIO;
+       if (!capacity)
+               return -ENODEV;
+
+       /*
+        * Checks that the device driver indicated a valid zone size and that
+        * the max zone append limit is set.
+        */
+       if (!zone_sectors || !is_power_of_2(zone_sectors)) {
+               pr_warn("%s: Invalid non power of two zone size (%llu)\n",
+                       disk->disk_name, zone_sectors);
+               return -ENODEV;
+       }
+
+       if (!q->limits.max_zone_append_sectors) {
+               pr_warn("%s: Invalid 0 maximum zone append limit\n",
+                       disk->disk_name);
+               return -ENODEV;
+       }
 
        /*
         * Ensure that all memory allocations in this context are done as if
         * GFP_NOIO was specified.
         */
+       args.disk = disk;
+       args.nr_zones = (capacity + zone_sectors - 1) >> ilog2(zone_sectors);
        noio_flag = memalloc_noio_save();
        ret = disk->fops->report_zones(disk, 0, UINT_MAX,
                                       blk_revalidate_zone_cb, &args);
@@ -570,7 +585,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk,
         * If zones where reported, make sure that the entire disk capacity
         * has been checked.
         */
-       if (ret > 0 && args.sector != get_capacity(disk)) {
+       if (ret > 0 && args.sector != capacity) {
                pr_warn("%s: Missing zones from sector %llu\n",
                        disk->disk_name, args.sector);
                ret = -ENODEV;
@@ -583,7 +598,6 @@ int blk_revalidate_disk_zones(struct gendisk *disk,
         */
        blk_mq_freeze_queue(q);
        if (ret > 0) {
-               blk_queue_chunk_sectors(q, args.zone_sectors);
                disk->nr_zones = args.nr_zones;
                swap(disk->seq_zones_wlock, args.seq_zones_wlock);
                swap(disk->conv_zones_bitmap, args.conv_zones_bitmap);
index 6aa5daf..02a916b 100644 (file)
@@ -176,7 +176,7 @@ static inline struct request *deadline_from_pos(struct dd_per_prio *per_prio,
         * zoned writes, start searching from the start of a zone.
         */
        if (blk_rq_is_seq_zoned_write(rq))
-               pos -= round_down(pos, rq->q->limits.chunk_sectors);
+               pos = round_down(pos, rq->q->limits.chunk_sectors);
 
        while (node) {
                rq = rb_entry_rq(node);
index ed222b9..5069210 100644 (file)
@@ -90,7 +90,7 @@ int amiga_partition(struct parsed_partitions *state)
        }
        blk = be32_to_cpu(rdb->rdb_PartitionList);
        put_dev_sector(sect);
-       for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
+       for (part = 1; (s32) blk>0 && part<=16; part++, put_dev_sector(sect)) {
                /* Read in terms partition table understands */
                if (check_mul_overflow(blk, (sector_t) blksize, &blk)) {
                        pr_err("Dev %s: overflow calculating partition block %llu! Skipping partitions %u and beyond\n",
index 6218c77..06b15b9 100644 (file)
@@ -992,7 +992,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
                ssize_t plen;
 
                /* use the existing memory in an allocated page */
-               if (ctx->merge) {
+               if (ctx->merge && !(msg->msg_flags & MSG_SPLICE_PAGES)) {
                        sgl = list_entry(ctx->tsgl_list.prev,
                                         struct af_alg_tsgl, list);
                        sg = sgl->sg + sgl->cur - 1;
@@ -1054,6 +1054,7 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
                        ctx->used += plen;
                        copied += plen;
                        size -= plen;
+                       ctx->merge = 0;
                } else {
                        do {
                                struct page *pg;
@@ -1085,12 +1086,12 @@ int af_alg_sendmsg(struct socket *sock, struct msghdr *msg, size_t size,
                                size -= plen;
                                sgl->cur++;
                        } while (len && sgl->cur < MAX_SGL_ENTS);
+
+                       ctx->merge = plen & (PAGE_SIZE - 1);
                }
 
                if (!size)
                        sg_mark_end(sg + sgl->cur - 1);
-
-               ctx->merge = plen & (PAGE_SIZE - 1);
        }
 
        err = 0;
index 0ab43e1..82c44d4 100644 (file)
@@ -68,13 +68,15 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
        struct hash_ctx *ctx = ask->private;
        ssize_t copied = 0;
        size_t len, max_pages, npages;
-       bool continuing = ctx->more, need_init = false;
+       bool continuing, need_init = false;
        int err;
 
        max_pages = min_t(size_t, ALG_MAX_PAGES,
                          DIV_ROUND_UP(sk->sk_sndbuf, PAGE_SIZE));
 
        lock_sock(sk);
+       continuing = ctx->more;
+
        if (!continuing) {
                /* Discard a previous request that wasn't marked MSG_MORE. */
                hash_free_result(sk, ctx);
index e787598..773e159 100644 (file)
@@ -185,8 +185,10 @@ static int software_key_query(const struct kernel_pkey_params *params,
 
        if (issig) {
                sig = crypto_alloc_sig(alg_name, 0, 0);
-               if (IS_ERR(sig))
+               if (IS_ERR(sig)) {
+                       ret = PTR_ERR(sig);
                        goto error_free_key;
+               }
 
                if (pkey->key_is_private)
                        ret = crypto_sig_set_privkey(sig, key, pkey->keylen);
@@ -208,8 +210,10 @@ static int software_key_query(const struct kernel_pkey_params *params,
                }
        } else {
                tfm = crypto_alloc_akcipher(alg_name, 0, 0);
-               if (IS_ERR(tfm))
+               if (IS_ERR(tfm)) {
+                       ret = PTR_ERR(tfm);
                        goto error_free_key;
+               }
 
                if (pkey->key_is_private)
                        ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
@@ -300,8 +304,10 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
 
        if (issig) {
                sig = crypto_alloc_sig(alg_name, 0, 0);
-               if (IS_ERR(sig))
+               if (IS_ERR(sig)) {
+                       ret = PTR_ERR(sig);
                        goto error_free_key;
+               }
 
                if (pkey->key_is_private)
                        ret = crypto_sig_set_privkey(sig, key, pkey->keylen);
@@ -313,8 +319,10 @@ static int software_key_eds_op(struct kernel_pkey_params *params,
                ksz = crypto_sig_maxsize(sig);
        } else {
                tfm = crypto_alloc_akcipher(alg_name, 0, 0);
-               if (IS_ERR(tfm))
+               if (IS_ERR(tfm)) {
+                       ret = PTR_ERR(tfm);
                        goto error_free_key;
+               }
 
                if (pkey->key_is_private)
                        ret = crypto_akcipher_set_priv_key(tfm, key, pkey->keylen);
@@ -411,8 +419,10 @@ int public_key_verify_signature(const struct public_key *pkey,
 
        key = kmalloc(pkey->keylen + sizeof(u32) * 2 + pkey->paramlen,
                      GFP_KERNEL);
-       if (!key)
+       if (!key) {
+               ret = -ENOMEM;
                goto error_free_tfm;
+       }
 
        memcpy(key, pkey->key, pkey->keylen);
        ptr = key + pkey->keylen;
index 7241d80..cffac5b 100644 (file)
@@ -45,6 +45,7 @@ obj-$(CONFIG_DMADEVICES)      += dma/
 
 # SOC specific infrastructure drivers.
 obj-y                          += soc/
+obj-$(CONFIG_PM_GENERIC_DOMAINS)       += genpd/
 
 obj-y                          += virtio/
 obj-$(CONFIG_VDPA)             += vdpa/
index d3013fb..399dc5d 100644 (file)
@@ -75,6 +75,7 @@ struct ivpu_wa_table {
        bool punit_disabled;
        bool clear_runtime_mem;
        bool d3hot_after_power_off;
+       bool interrupt_clear_with_0;
 };
 
 struct ivpu_hw_info;
index fef3542..2a5dd3a 100644 (file)
@@ -101,6 +101,9 @@ static void ivpu_hw_wa_init(struct ivpu_device *vdev)
        vdev->wa.punit_disabled = ivpu_is_fpga(vdev);
        vdev->wa.clear_runtime_mem = false;
        vdev->wa.d3hot_after_power_off = true;
+
+       if (ivpu_device_id(vdev) == PCI_DEVICE_ID_MTL && ivpu_revision(vdev) < 4)
+               vdev->wa.interrupt_clear_with_0 = true;
 }
 
 static void ivpu_hw_timeouts_init(struct ivpu_device *vdev)
@@ -885,7 +888,7 @@ static void ivpu_hw_mtl_irq_disable(struct ivpu_device *vdev)
        REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x1);
        REGB_WR32(MTL_BUTTRESS_LOCAL_INT_MASK, BUTTRESS_IRQ_DISABLE_MASK);
        REGV_WR64(MTL_VPU_HOST_SS_ICB_ENABLE_0, 0x0ull);
-       REGB_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0);
+       REGV_WR32(MTL_VPU_HOST_SS_FW_SOC_IRQ_EN, 0x0);
 }
 
 static void ivpu_hw_mtl_irq_wdt_nce_handler(struct ivpu_device *vdev)
@@ -973,12 +976,15 @@ static u32 ivpu_hw_mtl_irqb_handler(struct ivpu_device *vdev, int irq)
                schedule_recovery = true;
        }
 
-       /*
-        * Clear local interrupt status by writing 0 to all bits.
-        * This must be done after interrupts are cleared at the source.
-        * Writing 1 triggers an interrupt, so we can't perform read update write.
-        */
-       REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0);
+       /* This must be done after interrupts are cleared at the source. */
+       if (IVPU_WA(interrupt_clear_with_0))
+               /*
+                * Writing 1 triggers an interrupt, so we can't perform read update write.
+                * Clear local interrupt status by writing 0 to all bits.
+                */
+               REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, 0x0);
+       else
+               REGB_WR32(MTL_BUTTRESS_INTERRUPT_STAT, status);
 
        /* Re-enable global interrupt */
        REGB_WR32(MTL_BUTTRESS_GLOBAL_INT_MASK, 0x0);
index ced0dcf..45fd13e 100644 (file)
@@ -717,7 +717,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
                if (!d->config_buf)
                        goto err_alloc;
 
-               for (i = 0; i < chip->num_config_regs; i++) {
+               for (i = 0; i < chip->num_config_bases; i++) {
                        d->config_buf[i] = kcalloc(chip->num_config_regs,
                                                   sizeof(**d->config_buf),
                                                   GFP_KERNEL);
index 635ce06..55c5b48 100644 (file)
@@ -162,21 +162,15 @@ int null_register_zoned_dev(struct nullb *nullb)
        disk_set_zoned(nullb->disk, BLK_ZONED_HM);
        blk_queue_flag_set(QUEUE_FLAG_ZONE_RESETALL, q);
        blk_queue_required_elevator_features(q, ELEVATOR_F_ZBD_SEQ_WRITE);
-
-       if (queue_is_mq(q)) {
-               int ret = blk_revalidate_disk_zones(nullb->disk, NULL);
-
-               if (ret)
-                       return ret;
-       } else {
-               blk_queue_chunk_sectors(q, dev->zone_size_sects);
-               nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0);
-       }
-
+       blk_queue_chunk_sectors(q, dev->zone_size_sects);
+       nullb->disk->nr_zones = bdev_nr_zones(nullb->disk->part0);
        blk_queue_max_zone_append_sectors(q, dev->zone_size_sects);
        disk_set_max_open_zones(nullb->disk, dev->zone_max_open);
        disk_set_max_active_zones(nullb->disk, dev->zone_max_active);
 
+       if (queue_is_mq(q))
+               return blk_revalidate_disk_zones(nullb->disk, NULL);
+
        return 0;
 }
 
index b47358d..1fe0116 100644 (file)
@@ -751,7 +751,6 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
 {
        u32 v, wg;
        u8 model;
-       int ret;
 
        virtio_cread(vdev, struct virtio_blk_config,
                     zoned.model, &model);
@@ -806,6 +805,7 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
                        vblk->zone_sectors);
                return -ENODEV;
        }
+       blk_queue_chunk_sectors(q, vblk->zone_sectors);
        dev_dbg(&vdev->dev, "zone sectors = %u\n", vblk->zone_sectors);
 
        if (virtio_has_feature(vdev, VIRTIO_BLK_F_DISCARD)) {
@@ -814,26 +814,22 @@ static int virtblk_probe_zoned_device(struct virtio_device *vdev,
                blk_queue_max_discard_sectors(q, 0);
        }
 
-       ret = blk_revalidate_disk_zones(vblk->disk, NULL);
-       if (!ret) {
-               virtio_cread(vdev, struct virtio_blk_config,
-                            zoned.max_append_sectors, &v);
-               if (!v) {
-                       dev_warn(&vdev->dev, "zero max_append_sectors reported\n");
-                       return -ENODEV;
-               }
-               if ((v << SECTOR_SHIFT) < wg) {
-                       dev_err(&vdev->dev,
-                               "write granularity %u exceeds max_append_sectors %u limit\n",
-                               wg, v);
-                       return -ENODEV;
-               }
-
-               blk_queue_max_zone_append_sectors(q, v);
-               dev_dbg(&vdev->dev, "max append sectors = %u\n", v);
+       virtio_cread(vdev, struct virtio_blk_config,
+                    zoned.max_append_sectors, &v);
+       if (!v) {
+               dev_warn(&vdev->dev, "zero max_append_sectors reported\n");
+               return -ENODEV;
+       }
+       if ((v << SECTOR_SHIFT) < wg) {
+               dev_err(&vdev->dev,
+                       "write granularity %u exceeds max_append_sectors %u limit\n",
+                       wg, v);
+               return -ENODEV;
        }
+       blk_queue_max_zone_append_sectors(q, v);
+       dev_dbg(&vdev->dev, "max append sectors = %u\n", v);
 
-       return ret;
+       return blk_revalidate_disk_zones(vblk->disk, NULL);
 }
 
 #else
index e3506ef..59919e9 100644 (file)
@@ -211,7 +211,6 @@ static int tegra_gmi_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct tegra_gmi *gmi;
-       struct resource *res;
        int err;
 
        gmi = devm_kzalloc(dev, sizeof(*gmi), GFP_KERNEL);
@@ -221,8 +220,7 @@ static int tegra_gmi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, gmi);
        gmi->dev = dev;
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       gmi->base = devm_ioremap_resource(dev, res);
+       gmi->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(gmi->base))
                return PTR_ERR(gmi->base);
 
index 472a570..c4e1bec 100644 (file)
@@ -350,7 +350,6 @@ static struct vexpress_config_bridge_ops vexpress_syscfg_bridge_ops = {
 static int vexpress_syscfg_probe(struct platform_device *pdev)
 {
        struct vexpress_syscfg *syscfg;
-       struct resource *res;
        struct vexpress_config_bridge *bridge;
        struct device_node *node;
        int master;
@@ -362,8 +361,7 @@ static int vexpress_syscfg_probe(struct platform_device *pdev)
        syscfg->dev = &pdev->dev;
        INIT_LIST_HEAD(&syscfg->funcs);
 
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       syscfg->base = devm_ioremap_resource(&pdev->dev, res);
+       syscfg->base = devm_platform_ioremap_resource(pdev, 0);
        if (IS_ERR(syscfg->base))
                return PTR_ERR(syscfg->base);
 
index d3510cf..2783d3d 100644 (file)
@@ -269,7 +269,7 @@ static int us2e_freq_target(struct cpufreq_policy *policy, unsigned int index)
        return smp_call_function_single(cpu, __us2e_freq_target, &index, 1);
 }
 
-static int __init us2e_freq_cpu_init(struct cpufreq_policy *policy)
+static int us2e_freq_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int cpu = policy->cpu;
        unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
index 91d1ed5..6c36576 100644 (file)
@@ -117,7 +117,7 @@ static int us3_freq_target(struct cpufreq_policy *policy, unsigned int index)
        return smp_call_function_single(cpu, update_safari_cfg, &new_bits, 1);
 }
 
-static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
+static int us3_freq_cpu_init(struct cpufreq_policy *policy)
 {
        unsigned int cpu = policy->cpu;
        unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
index 7002bca..c625bb2 100644 (file)
@@ -66,18 +66,36 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
 {
        struct dma_fence_array *result;
        struct dma_fence *tmp, **array;
+       ktime_t timestamp;
        unsigned int i;
        size_t count;
 
        count = 0;
+       timestamp = ns_to_ktime(0);
        for (i = 0; i < num_fences; ++i) {
-               dma_fence_unwrap_for_each(tmp, &iter[i], fences[i])
-                       if (!dma_fence_is_signaled(tmp))
+               dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) {
+                       if (!dma_fence_is_signaled(tmp)) {
                                ++count;
+                       } else if (test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT,
+                                           &tmp->flags)) {
+                               if (ktime_after(tmp->timestamp, timestamp))
+                                       timestamp = tmp->timestamp;
+                       } else {
+                               /*
+                                * Use the current time if the fence is
+                                * currently signaling.
+                                */
+                               timestamp = ktime_get();
+                       }
+               }
        }
 
+       /*
+        * If we couldn't find a pending fence just return a private signaled
+        * fence with the timestamp of the last signaled one.
+        */
        if (count == 0)
-               return dma_fence_get_stub();
+               return dma_fence_allocate_private_stub(timestamp);
 
        array = kmalloc_array(count, sizeof(*array), GFP_KERNEL);
        if (!array)
@@ -138,7 +156,7 @@ restart:
        } while (tmp);
 
        if (count == 0) {
-               tmp = dma_fence_get_stub();
+               tmp = dma_fence_allocate_private_stub(ktime_get());
                goto return_tmp;
        }
 
index f177c56..8aa8f8c 100644 (file)
@@ -150,16 +150,17 @@ EXPORT_SYMBOL(dma_fence_get_stub);
 
 /**
  * dma_fence_allocate_private_stub - return a private, signaled fence
+ * @timestamp: timestamp when the fence was signaled
  *
  * Return a newly allocated and signaled stub fence.
  */
-struct dma_fence *dma_fence_allocate_private_stub(void)
+struct dma_fence *dma_fence_allocate_private_stub(ktime_t timestamp)
 {
        struct dma_fence *fence;
 
        fence = kzalloc(sizeof(*fence), GFP_KERNEL);
        if (fence == NULL)
-               return ERR_PTR(-ENOMEM);
+               return NULL;
 
        dma_fence_init(fence,
                       &dma_fence_stub_ops,
@@ -169,7 +170,7 @@ struct dma_fence *dma_fence_allocate_private_stub(void)
        set_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT,
                &fence->flags);
 
-       dma_fence_signal(fence);
+       dma_fence_signal_timestamp(fence, timestamp);
 
        return fence;
 }
diff --git a/drivers/genpd/Makefile b/drivers/genpd/Makefile
new file mode 100644 (file)
index 0000000..c429485
--- /dev/null
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y                                  += actions/
+obj-y                                  += amlogic/
+obj-y                                  += apple/
+obj-y                                  += bcm/
+obj-y                                  += mediatek/
+obj-y                                  += qcom/
+obj-y                                  += renesas/
+obj-y                                  += rockchip/
+obj-y                                  += samsung/
+obj-y                                  += st/
+obj-y                                  += starfive/
+obj-y                                  += sunxi/
+obj-y                                  += tegra/
+obj-y                                  += ti/
+obj-y                                  += xilinx/
diff --git a/drivers/genpd/actions/Makefile b/drivers/genpd/actions/Makefile
new file mode 100644 (file)
index 0000000..7e8aa47
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+obj-$(CONFIG_OWL_PM_DOMAINS_HELPER)    += owl-sps-helper.o
+obj-$(CONFIG_OWL_PM_DOMAINS)           += owl-sps.o
diff --git a/drivers/genpd/amlogic/Makefile b/drivers/genpd/amlogic/Makefile
new file mode 100644 (file)
index 0000000..3d58abd
--- /dev/null
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
+obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o
+obj-$(CONFIG_MESON_SECURE_PM_DOMAINS) += meson-secure-pwrc.o
diff --git a/drivers/genpd/apple/Makefile b/drivers/genpd/apple/Makefile
new file mode 100644 (file)
index 0000000..53665af
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_APPLE_PMGR_PWRSTATE)      += pmgr-pwrstate.o
diff --git a/drivers/genpd/bcm/Makefile b/drivers/genpd/bcm/Makefile
new file mode 100644 (file)
index 0000000..6bfbe4e
--- /dev/null
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_BCM_PMB)                  += bcm-pmb.o
+obj-$(CONFIG_BCM2835_POWER)            += bcm2835-power.o
+obj-$(CONFIG_BCM63XX_POWER)            += bcm63xx-power.o
+obj-$(CONFIG_RASPBERRYPI_POWER)                += raspberrypi-power.o
diff --git a/drivers/genpd/imx/Makefile b/drivers/genpd/imx/Makefile
new file mode 100644 (file)
index 0000000..5f01271
--- /dev/null
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
+obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
+obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
+obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o
+obj-$(CONFIG_SOC_IMX9) += imx93-pd.o
+obj-$(CONFIG_IMX9_BLK_CTRL) += imx93-blk-ctrl.o
diff --git a/drivers/genpd/mediatek/Makefile b/drivers/genpd/mediatek/Makefile
new file mode 100644 (file)
index 0000000..8cde09e
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_MTK_SCPSYS)               += mtk-scpsys.o
+obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS)    += mtk-pm-domains.o
diff --git a/drivers/genpd/qcom/Makefile b/drivers/genpd/qcom/Makefile
new file mode 100644 (file)
index 0000000..403dfc5
--- /dev/null
@@ -0,0 +1,4 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_QCOM_CPR)         += cpr.o
+obj-$(CONFIG_QCOM_RPMPD)       += rpmpd.o
+obj-$(CONFIG_QCOM_RPMHPD)      += rpmhpd.o
diff --git a/drivers/genpd/renesas/Makefile b/drivers/genpd/renesas/Makefile
new file mode 100644 (file)
index 0000000..e306e39
--- /dev/null
@@ -0,0 +1,30 @@
+# SPDX-License-Identifier: GPL-2.0
+# SoC
+obj-$(CONFIG_SYSC_R8A7742)     += r8a7742-sysc.o
+obj-$(CONFIG_SYSC_R8A7743)     += r8a7743-sysc.o
+obj-$(CONFIG_SYSC_R8A7745)     += r8a7745-sysc.o
+obj-$(CONFIG_SYSC_R8A77470)    += r8a77470-sysc.o
+obj-$(CONFIG_SYSC_R8A774A1)    += r8a774a1-sysc.o
+obj-$(CONFIG_SYSC_R8A774B1)    += r8a774b1-sysc.o
+obj-$(CONFIG_SYSC_R8A774C0)    += r8a774c0-sysc.o
+obj-$(CONFIG_SYSC_R8A774E1)    += r8a774e1-sysc.o
+obj-$(CONFIG_SYSC_R8A7779)     += r8a7779-sysc.o
+obj-$(CONFIG_SYSC_R8A7790)     += r8a7790-sysc.o
+obj-$(CONFIG_SYSC_R8A7791)     += r8a7791-sysc.o
+obj-$(CONFIG_SYSC_R8A7792)     += r8a7792-sysc.o
+obj-$(CONFIG_SYSC_R8A7794)     += r8a7794-sysc.o
+obj-$(CONFIG_SYSC_R8A7795)     += r8a7795-sysc.o
+obj-$(CONFIG_SYSC_R8A77960)    += r8a7796-sysc.o
+obj-$(CONFIG_SYSC_R8A77961)    += r8a7796-sysc.o
+obj-$(CONFIG_SYSC_R8A77965)    += r8a77965-sysc.o
+obj-$(CONFIG_SYSC_R8A77970)    += r8a77970-sysc.o
+obj-$(CONFIG_SYSC_R8A77980)    += r8a77980-sysc.o
+obj-$(CONFIG_SYSC_R8A77990)    += r8a77990-sysc.o
+obj-$(CONFIG_SYSC_R8A77995)    += r8a77995-sysc.o
+obj-$(CONFIG_SYSC_R8A779A0)    += r8a779a0-sysc.o
+obj-$(CONFIG_SYSC_R8A779F0)    += r8a779f0-sysc.o
+obj-$(CONFIG_SYSC_R8A779G0)    += r8a779g0-sysc.o
+# Family
+obj-$(CONFIG_SYSC_RCAR)                += rcar-sysc.o
+obj-$(CONFIG_SYSC_RCAR_GEN4)   += rcar-gen4-sysc.o
+obj-$(CONFIG_SYSC_RMOBILE)     += rmobile-sysc.o
diff --git a/drivers/genpd/rockchip/Makefile b/drivers/genpd/rockchip/Makefile
new file mode 100644 (file)
index 0000000..8fb9d88
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ROCKCHIP_PM_DOMAINS)      += pm-domains.o
diff --git a/drivers/genpd/samsung/Makefile b/drivers/genpd/samsung/Makefile
new file mode 100644 (file)
index 0000000..397aa59
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_EXYNOS_PM_DOMAINS)                += exynos-pm-domains.o
diff --git a/drivers/genpd/st/Makefile b/drivers/genpd/st/Makefile
new file mode 100644 (file)
index 0000000..8fa5f98
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_ARCH_U8500)               += ste-ux500-pm-domain.o
similarity index 75%
rename from arch/arm/mach-ux500/pm_domains.c
rename to drivers/genpd/st/ste-ux500-pm-domain.c
index 427b9ac..3d4f111 100644 (file)
@@ -6,6 +6,9 @@
  *
  * Implements PM domains using the generic PM domain for ux500.
  */
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
 #include <linux/printk.h>
 #include <linux/slab.h>
 #include <linux/err.h>
@@ -13,7 +16,6 @@
 #include <linux/pm_domain.h>
 
 #include <dt-bindings/arm/ux500_pm_domains.h>
-#include "pm_domains.h"
 
 static int pd_power_off(struct generic_pm_domain *domain)
 {
@@ -49,18 +51,17 @@ static struct generic_pm_domain *ux500_pm_domains[NR_DOMAINS] = {
        [DOMAIN_VAPE] = &ux500_pm_domain_vape,
 };
 
-static const struct of_device_id ux500_pm_domain_matches[] __initconst = {
+static const struct of_device_id ux500_pm_domain_matches[] = {
        { .compatible = "stericsson,ux500-pm-domains", },
        { },
 };
 
-int __init ux500_pm_domains_init(void)
+static int ux500_pm_domains_probe(struct platform_device *pdev)
 {
-       struct device_node *np;
+       struct device_node *np = pdev->dev.of_node;
        struct genpd_onecell_data *genpd_data;
        int i;
 
-       np = of_find_matching_node(NULL, ux500_pm_domain_matches);
        if (!np)
                return -ENODEV;
 
@@ -77,3 +78,17 @@ int __init ux500_pm_domains_init(void)
        of_genpd_add_provider_onecell(np, genpd_data);
        return 0;
 }
+
+static struct platform_driver ux500_pm_domains_driver = {
+       .probe  = ux500_pm_domains_probe,
+       .driver = {
+               .name = "ux500_pm_domains",
+               .of_match_table = ux500_pm_domain_matches,
+       },
+};
+
+static int __init ux500_pm_domains_init(void)
+{
+       return platform_driver_register(&ux500_pm_domains_driver);
+}
+arch_initcall(ux500_pm_domains_init);
diff --git a/drivers/genpd/starfive/Makefile b/drivers/genpd/starfive/Makefile
new file mode 100644 (file)
index 0000000..975bba2
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_JH71XX_PMU)               += jh71xx-pmu.o
diff --git a/drivers/genpd/sunxi/Makefile b/drivers/genpd/sunxi/Makefile
new file mode 100644 (file)
index 0000000..ec1d7a2
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-$(CONFIG_SUN20I_PPU)               += sun20i-ppu.o
diff --git a/drivers/genpd/tegra/Makefile b/drivers/genpd/tegra/Makefile
new file mode 100644 (file)
index 0000000..ec8acfd
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_SOC_TEGRA_POWERGATE_BPMP) += powergate-bpmp.o
diff --git a/drivers/genpd/ti/Makefile b/drivers/genpd/ti/Makefile
new file mode 100644 (file)
index 0000000..69580af
--- /dev/null
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_ARCH_OMAP2PLUS)           += omap_prm.o
+obj-$(CONFIG_TI_SCI_PM_DOMAINS)                += ti_sci_pm_domains.o
diff --git a/drivers/genpd/xilinx/Makefile b/drivers/genpd/xilinx/Makefile
new file mode 100644 (file)
index 0000000..a706ab6
--- /dev/null
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0
+obj-$(CONFIG_ZYNQMP_PM_DOMAINS)                += zynqmp-pm-domains.o
index 2f9c14a..a3b86b8 100644 (file)
@@ -1296,6 +1296,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev,
 void amdgpu_device_pci_config_reset(struct amdgpu_device *adev);
 int amdgpu_device_pci_reset(struct amdgpu_device *adev);
 bool amdgpu_device_need_post(struct amdgpu_device *adev);
+bool amdgpu_device_pcie_dynamic_switching_supported(void);
 bool amdgpu_device_should_use_aspm(struct amdgpu_device *adev);
 bool amdgpu_device_aspm_support_quirk(void);
 
index f61527b..a7f314d 100644 (file)
@@ -2881,6 +2881,9 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef)
                        if (!attachment->is_mapped)
                                continue;
 
+                       if (attachment->bo_va->base.bo->tbo.pin_count)
+                               continue;
+
                        kfd_mem_dmaunmap_attachment(mem, attachment);
                        ret = update_gpuvm_pte(mem, attachment, &sync_obj);
                        if (ret) {
index a92c618..a2cdde0 100644 (file)
@@ -1458,6 +1458,25 @@ bool amdgpu_device_need_post(struct amdgpu_device *adev)
        return true;
 }
 
+/*
+ * Intel hosts such as Raptor Lake and Sapphire Rapids don't support dynamic
+ * speed switching. Until we have confirmation from Intel that a specific host
+ * supports it, it's safer that we keep it disabled for all.
+ *
+ * https://edc.intel.com/content/www/us/en/design/products/platforms/details/raptor-lake-s/13th-generation-core-processors-datasheet-volume-1-of-2/005/pci-express-support/
+ * https://gitlab.freedesktop.org/drm/amd/-/issues/2663
+ */
+bool amdgpu_device_pcie_dynamic_switching_supported(void)
+{
+#if IS_ENABLED(CONFIG_X86)
+       struct cpuinfo_x86 *c = &cpu_data(0);
+
+       if (c->x86_vendor == X86_VENDOR_INTEL)
+               return false;
+#endif
+       return true;
+}
+
 /**
  * amdgpu_device_should_use_aspm - check if the device should program ASPM
  *
index 6a0ac0b..355c156 100644 (file)
@@ -295,5 +295,9 @@ int smu_v13_0_get_pptable_from_firmware(struct smu_context *smu,
                                        uint32_t *size,
                                        uint32_t pptable_id);
 
+int smu_v13_0_update_pcie_parameters(struct smu_context *smu,
+                                    uint32_t pcie_gen_cap,
+                                    uint32_t pcie_width_cap);
+
 #endif
 #endif
index 9cd0051..3bb1839 100644 (file)
@@ -2113,7 +2113,6 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        mutex_lock(&adev->pm.mutex);
        r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
-       mutex_unlock(&adev->pm.mutex);
        if (r)
                goto fail;
 
@@ -2130,6 +2129,7 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        r = num_msgs;
 fail:
+       mutex_unlock(&adev->pm.mutex);
        kfree(req);
        return r;
 }
index c94d825..95f6d82 100644 (file)
@@ -3021,7 +3021,6 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        mutex_lock(&adev->pm.mutex);
        r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
-       mutex_unlock(&adev->pm.mutex);
        if (r)
                goto fail;
 
@@ -3038,6 +3037,7 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        r = num_msgs;
 fail:
+       mutex_unlock(&adev->pm.mutex);
        kfree(req);
        return r;
 }
index f7ed3e6..f6599c0 100644 (file)
@@ -2077,89 +2077,36 @@ static int sienna_cichlid_display_disable_memory_clock_switch(struct smu_context
        return ret;
 }
 
-static void sienna_cichlid_get_override_pcie_settings(struct smu_context *smu,
-                                                     uint32_t *gen_speed_override,
-                                                     uint32_t *lane_width_override)
-{
-       struct amdgpu_device *adev = smu->adev;
-
-       *gen_speed_override = 0xff;
-       *lane_width_override = 0xff;
-
-       switch (adev->pdev->device) {
-       case 0x73A0:
-       case 0x73A1:
-       case 0x73A2:
-       case 0x73A3:
-       case 0x73AB:
-       case 0x73AE:
-               /* Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32 */
-               *lane_width_override = 6;
-               break;
-       case 0x73E0:
-       case 0x73E1:
-       case 0x73E3:
-               *lane_width_override = 4;
-               break;
-       case 0x7420:
-       case 0x7421:
-       case 0x7422:
-       case 0x7423:
-       case 0x7424:
-               *lane_width_override = 3;
-               break;
-       default:
-               break;
-       }
-}
-
-#define MAX(a, b)      ((a) > (b) ? (a) : (b))
-
 static int sienna_cichlid_update_pcie_parameters(struct smu_context *smu,
                                         uint32_t pcie_gen_cap,
                                         uint32_t pcie_width_cap)
 {
        struct smu_11_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
        struct smu_11_0_pcie_table *pcie_table = &dpm_context->dpm_tables.pcie_table;
-       uint32_t gen_speed_override, lane_width_override;
-       uint8_t *table_member1, *table_member2;
-       uint32_t min_gen_speed, max_gen_speed;
-       uint32_t min_lane_width, max_lane_width;
-       uint32_t smu_pcie_arg;
+       u32 smu_pcie_arg;
        int ret, i;
 
-       GET_PPTABLE_MEMBER(PcieGenSpeed, &table_member1);
-       GET_PPTABLE_MEMBER(PcieLaneCount, &table_member2);
-
-       sienna_cichlid_get_override_pcie_settings(smu,
-                                                 &gen_speed_override,
-                                                 &lane_width_override);
+       /* PCIE gen speed and lane width override */
+       if (!amdgpu_device_pcie_dynamic_switching_supported()) {
+               if (pcie_table->pcie_gen[NUM_LINK_LEVELS - 1] < pcie_gen_cap)
+                       pcie_gen_cap = pcie_table->pcie_gen[NUM_LINK_LEVELS - 1];
 
-       /* PCIE gen speed override */
-       if (gen_speed_override != 0xff) {
-               min_gen_speed = MIN(pcie_gen_cap, gen_speed_override);
-               max_gen_speed = MIN(pcie_gen_cap, gen_speed_override);
-       } else {
-               min_gen_speed = MAX(0, table_member1[0]);
-               max_gen_speed = MIN(pcie_gen_cap, table_member1[1]);
-               min_gen_speed = min_gen_speed > max_gen_speed ?
-                               max_gen_speed : min_gen_speed;
-       }
-       pcie_table->pcie_gen[0] = min_gen_speed;
-       pcie_table->pcie_gen[1] = max_gen_speed;
+               if (pcie_table->pcie_lane[NUM_LINK_LEVELS - 1] < pcie_width_cap)
+                       pcie_width_cap = pcie_table->pcie_lane[NUM_LINK_LEVELS - 1];
 
-       /* PCIE lane width override */
-       if (lane_width_override != 0xff) {
-               min_lane_width = MIN(pcie_width_cap, lane_width_override);
-               max_lane_width = MIN(pcie_width_cap, lane_width_override);
+               /* Force all levels to use the same settings */
+               for (i = 0; i < NUM_LINK_LEVELS; i++) {
+                       pcie_table->pcie_gen[i] = pcie_gen_cap;
+                       pcie_table->pcie_lane[i] = pcie_width_cap;
+               }
        } else {
-               min_lane_width = MAX(1, table_member2[0]);
-               max_lane_width = MIN(pcie_width_cap, table_member2[1]);
-               min_lane_width = min_lane_width > max_lane_width ?
-                                max_lane_width : min_lane_width;
+               for (i = 0; i < NUM_LINK_LEVELS; i++) {
+                       if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+                               pcie_table->pcie_gen[i] = pcie_gen_cap;
+                       if (pcie_table->pcie_lane[i] > pcie_width_cap)
+                               pcie_table->pcie_lane[i] = pcie_width_cap;
+               }
        }
-       pcie_table->pcie_lane[0] = min_lane_width;
-       pcie_table->pcie_lane[1] = max_lane_width;
 
        for (i = 0; i < NUM_LINK_LEVELS; i++) {
                smu_pcie_arg = (i << 16 |
@@ -3842,7 +3789,6 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        mutex_lock(&adev->pm.mutex);
        r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
-       mutex_unlock(&adev->pm.mutex);
        if (r)
                goto fail;
 
@@ -3859,6 +3805,7 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        r = num_msgs;
 fail:
+       mutex_unlock(&adev->pm.mutex);
        kfree(req);
        return r;
 }
index e80f122..ce50ef4 100644 (file)
@@ -1525,7 +1525,6 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        mutex_lock(&adev->pm.mutex);
        r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
-       mutex_unlock(&adev->pm.mutex);
        if (r)
                goto fail;
 
@@ -1542,6 +1541,7 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        r = num_msgs;
 fail:
+       mutex_unlock(&adev->pm.mutex);
        kfree(req);
        return r;
 }
index 3856da6..9b62b45 100644 (file)
@@ -2424,3 +2424,51 @@ int smu_v13_0_mode1_reset(struct smu_context *smu)
 
        return ret;
 }
+
+int smu_v13_0_update_pcie_parameters(struct smu_context *smu,
+                                    uint32_t pcie_gen_cap,
+                                    uint32_t pcie_width_cap)
+{
+       struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
+       struct smu_13_0_pcie_table *pcie_table =
+                               &dpm_context->dpm_tables.pcie_table;
+       int num_of_levels = pcie_table->num_of_link_levels;
+       uint32_t smu_pcie_arg;
+       int ret, i;
+
+       if (!amdgpu_device_pcie_dynamic_switching_supported()) {
+               if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap)
+                       pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1];
+
+               if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap)
+                       pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1];
+
+               /* Force all levels to use the same settings */
+               for (i = 0; i < num_of_levels; i++) {
+                       pcie_table->pcie_gen[i] = pcie_gen_cap;
+                       pcie_table->pcie_lane[i] = pcie_width_cap;
+               }
+       } else {
+               for (i = 0; i < num_of_levels; i++) {
+                       if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+                               pcie_table->pcie_gen[i] = pcie_gen_cap;
+                       if (pcie_table->pcie_lane[i] > pcie_width_cap)
+                               pcie_table->pcie_lane[i] = pcie_width_cap;
+               }
+       }
+
+       for (i = 0; i < num_of_levels; i++) {
+               smu_pcie_arg = i << 16;
+               smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
+               smu_pcie_arg |= pcie_table->pcie_lane[i];
+
+               ret = smu_cmn_send_smc_msg_with_param(smu,
+                                                     SMU_MSG_OverridePcieParameters,
+                                                     smu_pcie_arg,
+                                                     NULL);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
index 124287c..b9bde5f 100644 (file)
@@ -1645,37 +1645,6 @@ static int smu_v13_0_0_force_clk_levels(struct smu_context *smu,
        return ret;
 }
 
-static int smu_v13_0_0_update_pcie_parameters(struct smu_context *smu,
-                                             uint32_t pcie_gen_cap,
-                                             uint32_t pcie_width_cap)
-{
-       struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
-       struct smu_13_0_pcie_table *pcie_table =
-                               &dpm_context->dpm_tables.pcie_table;
-       uint32_t smu_pcie_arg;
-       int ret, i;
-
-       for (i = 0; i < pcie_table->num_of_link_levels; i++) {
-               if (pcie_table->pcie_gen[i] > pcie_gen_cap)
-                       pcie_table->pcie_gen[i] = pcie_gen_cap;
-               if (pcie_table->pcie_lane[i] > pcie_width_cap)
-                       pcie_table->pcie_lane[i] = pcie_width_cap;
-
-               smu_pcie_arg = i << 16;
-               smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
-               smu_pcie_arg |= pcie_table->pcie_lane[i];
-
-               ret = smu_cmn_send_smc_msg_with_param(smu,
-                                                     SMU_MSG_OverridePcieParameters,
-                                                     smu_pcie_arg,
-                                                     NULL);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
 static const struct smu_temperature_range smu13_thermal_policy[] = {
        {-273150,  99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
        { 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000, 120000},
@@ -2320,7 +2289,6 @@ static int smu_v13_0_0_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        mutex_lock(&adev->pm.mutex);
        r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
-       mutex_unlock(&adev->pm.mutex);
        if (r)
                goto fail;
 
@@ -2337,6 +2305,7 @@ static int smu_v13_0_0_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        r = num_msgs;
 fail:
+       mutex_unlock(&adev->pm.mutex);
        kfree(req);
        return r;
 }
@@ -2654,7 +2623,7 @@ static const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
        .feature_is_enabled = smu_cmn_feature_is_enabled,
        .print_clk_levels = smu_v13_0_0_print_clk_levels,
        .force_clk_levels = smu_v13_0_0_force_clk_levels,
-       .update_pcie_parameters = smu_v13_0_0_update_pcie_parameters,
+       .update_pcie_parameters = smu_v13_0_update_pcie_parameters,
        .get_thermal_temperature_range = smu_v13_0_0_get_thermal_temperature_range,
        .register_irq_handler = smu_v13_0_register_irq_handler,
        .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
index 6ef1225..1ac5521 100644 (file)
@@ -1763,7 +1763,6 @@ static int smu_v13_0_6_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        mutex_lock(&adev->pm.mutex);
        r = smu_v13_0_6_request_i2c_xfer(smu, req);
-       mutex_unlock(&adev->pm.mutex);
        if (r)
                goto fail;
 
@@ -1780,6 +1779,7 @@ static int smu_v13_0_6_i2c_xfer(struct i2c_adapter *i2c_adap,
        }
        r = num_msgs;
 fail:
+       mutex_unlock(&adev->pm.mutex);
        kfree(req);
        return r;
 }
index cda4e81..3ba0213 100644 (file)
@@ -1635,37 +1635,6 @@ static int smu_v13_0_7_force_clk_levels(struct smu_context *smu,
        return ret;
 }
 
-static int smu_v13_0_7_update_pcie_parameters(struct smu_context *smu,
-                                             uint32_t pcie_gen_cap,
-                                             uint32_t pcie_width_cap)
-{
-       struct smu_13_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
-       struct smu_13_0_pcie_table *pcie_table =
-                               &dpm_context->dpm_tables.pcie_table;
-       uint32_t smu_pcie_arg;
-       int ret, i;
-
-       for (i = 0; i < pcie_table->num_of_link_levels; i++) {
-               if (pcie_table->pcie_gen[i] > pcie_gen_cap)
-                       pcie_table->pcie_gen[i] = pcie_gen_cap;
-               if (pcie_table->pcie_lane[i] > pcie_width_cap)
-                       pcie_table->pcie_lane[i] = pcie_width_cap;
-
-               smu_pcie_arg = i << 16;
-               smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
-               smu_pcie_arg |= pcie_table->pcie_lane[i];
-
-               ret = smu_cmn_send_smc_msg_with_param(smu,
-                                                     SMU_MSG_OverridePcieParameters,
-                                                     smu_pcie_arg,
-                                                     NULL);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
 static const struct smu_temperature_range smu13_thermal_policy[] =
 {
        {-273150,  99000, 99000, -273150, 99000, 99000, -273150, 99000, 99000},
@@ -2234,7 +2203,7 @@ static const struct pptable_funcs smu_v13_0_7_ppt_funcs = {
        .feature_is_enabled = smu_cmn_feature_is_enabled,
        .print_clk_levels = smu_v13_0_7_print_clk_levels,
        .force_clk_levels = smu_v13_0_7_force_clk_levels,
-       .update_pcie_parameters = smu_v13_0_7_update_pcie_parameters,
+       .update_pcie_parameters = smu_v13_0_update_pcie_parameters,
        .get_thermal_temperature_range = smu_v13_0_7_get_thermal_temperature_range,
        .register_irq_handler = smu_v13_0_register_irq_handler,
        .enable_thermal_alert = smu_v13_0_enable_thermal_alert,
index 3943e89..e40a95e 100644 (file)
@@ -209,10 +209,6 @@ void armada_fbdev_setup(struct drm_device *dev)
                goto err_drm_client_init;
        }
 
-       ret = armada_fbdev_client_hotplug(&fbh->client);
-       if (ret)
-               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&fbh->client);
 
        return;
index 9d6dcaf..7b66f36 100644 (file)
@@ -1426,9 +1426,9 @@ void dw_hdmi_set_high_tmds_clock_ratio(struct dw_hdmi *hdmi,
        /* Control for TMDS Bit Period/TMDS Clock-Period Ratio */
        if (dw_hdmi_support_scdc(hdmi, display)) {
                if (mtmdsclock > HDMI14_MAX_TMDSCLK)
-                       drm_scdc_set_high_tmds_clock_ratio(&hdmi->connector, 1);
+                       drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, 1);
                else
-                       drm_scdc_set_high_tmds_clock_ratio(&hdmi->connector, 0);
+                       drm_scdc_set_high_tmds_clock_ratio(hdmi->curr_conn, 0);
        }
 }
 EXPORT_SYMBOL_GPL(dw_hdmi_set_high_tmds_clock_ratio);
@@ -2116,7 +2116,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
                                min_t(u8, bytes, SCDC_MIN_SOURCE_VERSION));
 
                        /* Enabled Scrambling in the Sink */
-                       drm_scdc_set_scrambling(&hdmi->connector, 1);
+                       drm_scdc_set_scrambling(hdmi->curr_conn, 1);
 
                        /*
                         * To activate the scrambler feature, you must ensure
@@ -2132,7 +2132,7 @@ static void hdmi_av_composer(struct dw_hdmi *hdmi,
                        hdmi_writeb(hdmi, 0, HDMI_FC_SCRAMBLER_CTRL);
                        hdmi_writeb(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ,
                                    HDMI_MC_SWRSTZ);
-                       drm_scdc_set_scrambling(&hdmi->connector, 0);
+                       drm_scdc_set_scrambling(hdmi->curr_conn, 0);
                }
        }
 
@@ -3553,6 +3553,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
        hdmi->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID
                         | DRM_BRIDGE_OP_HPD;
        hdmi->bridge.interlace_allowed = true;
+       hdmi->bridge.ddc = hdmi->ddc;
 #ifdef CONFIG_OF
        hdmi->bridge.of_node = pdev->dev.of_node;
 #endif
index c499a14..f448b90 100644 (file)
  * @pwm_refclk_freq: Cache for the reference clock input to the PWM.
  */
 struct ti_sn65dsi86 {
-       struct auxiliary_device         bridge_aux;
-       struct auxiliary_device         gpio_aux;
-       struct auxiliary_device         aux_aux;
-       struct auxiliary_device         pwm_aux;
+       struct auxiliary_device         *bridge_aux;
+       struct auxiliary_device         *gpio_aux;
+       struct auxiliary_device         *aux_aux;
+       struct auxiliary_device         *pwm_aux;
 
        struct device                   *dev;
        struct regmap                   *regmap;
@@ -468,27 +468,34 @@ static void ti_sn65dsi86_delete_aux(void *data)
        auxiliary_device_delete(data);
 }
 
-/*
- * AUX bus docs say that a non-NULL release is mandatory, but it makes no
- * sense for the model used here where all of the aux devices are allocated
- * in the single shared structure. We'll use this noop as a workaround.
- */
-static void ti_sn65dsi86_noop(struct device *dev) {}
+static void ti_sn65dsi86_aux_device_release(struct device *dev)
+{
+       struct auxiliary_device *aux = container_of(dev, struct auxiliary_device, dev);
+
+       kfree(aux);
+}
 
 static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata,
-                                      struct auxiliary_device *aux,
+                                      struct auxiliary_device **aux_out,
                                       const char *name)
 {
        struct device *dev = pdata->dev;
+       struct auxiliary_device *aux;
        int ret;
 
+       aux = kzalloc(sizeof(*aux), GFP_KERNEL);
+       if (!aux)
+               return -ENOMEM;
+
        aux->name = name;
        aux->dev.parent = dev;
-       aux->dev.release = ti_sn65dsi86_noop;
+       aux->dev.release = ti_sn65dsi86_aux_device_release;
        device_set_of_node_from_dev(&aux->dev, dev);
        ret = auxiliary_device_init(aux);
-       if (ret)
+       if (ret) {
+               kfree(aux);
                return ret;
+       }
        ret = devm_add_action_or_reset(dev, ti_sn65dsi86_uninit_aux, aux);
        if (ret)
                return ret;
@@ -497,6 +504,8 @@ static int ti_sn65dsi86_add_aux_device(struct ti_sn65dsi86 *pdata,
        if (ret)
                return ret;
        ret = devm_add_action_or_reset(dev, ti_sn65dsi86_delete_aux, aux);
+       if (!ret)
+               *aux_out = aux;
 
        return ret;
 }
index f6292ba..037e36f 100644 (file)
@@ -122,13 +122,34 @@ EXPORT_SYMBOL(drm_client_init);
  * drm_client_register() it is no longer permissible to call drm_client_release()
  * directly (outside the unregister callback), instead cleanup will happen
  * automatically on driver unload.
+ *
+ * Registering a client generates a hotplug event that allows the client
+ * to set up its display from pre-existing outputs. The client must have
+ * initialized its state to able to handle the hotplug event successfully.
  */
 void drm_client_register(struct drm_client_dev *client)
 {
        struct drm_device *dev = client->dev;
+       int ret;
 
        mutex_lock(&dev->clientlist_mutex);
        list_add(&client->list, &dev->clientlist);
+
+       if (client->funcs && client->funcs->hotplug) {
+               /*
+                * Perform an initial hotplug event to pick up the
+                * display configuration for the client. This step
+                * has to be performed *after* registering the client
+                * in the list of clients, or a concurrent hotplug
+                * event might be lost; leaving the display off.
+                *
+                * Hold the clientlist_mutex as for a regular hotplug
+                * event.
+                */
+               ret = client->funcs->hotplug(client);
+               if (ret)
+                       drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
+       }
        mutex_unlock(&dev->clientlist_mutex);
 }
 EXPORT_SYMBOL(drm_client_register);
index d86773f..f353daf 100644 (file)
@@ -217,7 +217,7 @@ static const struct drm_client_funcs drm_fbdev_dma_client_funcs = {
  * drm_fbdev_dma_setup() - Setup fbdev emulation for GEM DMA helpers
  * @dev: DRM device
  * @preferred_bpp: Preferred bits per pixel for the device.
- *                 @dev->mode_config.preferred_depth is used if this is zero.
+ *                 32 is used if this is zero.
  *
  * This function sets up fbdev emulation for GEM DMA drivers that support
  * dumb buffers with a virtual address and that can be mmap'ed.
@@ -252,10 +252,6 @@ void drm_fbdev_dma_setup(struct drm_device *dev, unsigned int preferred_bpp)
                goto err_drm_client_init;
        }
 
-       ret = drm_fbdev_dma_client_hotplug(&fb_helper->client);
-       if (ret)
-               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&fb_helper->client);
 
        return;
index 98ae703..b9343fb 100644 (file)
@@ -339,10 +339,6 @@ void drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
                goto err_drm_client_init;
        }
 
-       ret = drm_fbdev_generic_client_hotplug(&fb_helper->client);
-       if (ret)
-               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&fb_helper->client);
 
        return;
index 0c2be83..e592c5d 100644 (file)
@@ -353,10 +353,10 @@ EXPORT_SYMBOL(drm_syncobj_replace_fence);
  */
 static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
 {
-       struct dma_fence *fence = dma_fence_allocate_private_stub();
+       struct dma_fence *fence = dma_fence_allocate_private_stub(ktime_get());
 
-       if (IS_ERR(fence))
-               return PTR_ERR(fence);
+       if (!fence)
+               return -ENOMEM;
 
        drm_syncobj_replace_fence(syncobj, fence);
        dma_fence_put(fence);
index fdf6558..226310c 100644 (file)
@@ -215,10 +215,6 @@ void exynos_drm_fbdev_setup(struct drm_device *dev)
        if (ret)
                goto err_drm_client_init;
 
-       ret = exynos_drm_fbdev_client_hotplug(&fb_helper->client);
-       if (ret)
-               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&fb_helper->client);
 
        return;
index 955cbe9..0544265 100644 (file)
@@ -328,10 +328,6 @@ void psb_fbdev_setup(struct drm_psb_private *dev_priv)
                goto err_drm_fb_helper_unprepare;
        }
 
-       ret = psb_fbdev_client_hotplug(&fb_helper->client);
-       if (ret)
-               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&fb_helper->client);
 
        return;
index d853360..16603d5 100644 (file)
@@ -4564,7 +4564,6 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state,
        saved_state->uapi = slave_crtc_state->uapi;
        saved_state->scaler_state = slave_crtc_state->scaler_state;
        saved_state->shared_dpll = slave_crtc_state->shared_dpll;
-       saved_state->dpll_hw_state = slave_crtc_state->dpll_hw_state;
        saved_state->crc_enabled = slave_crtc_state->crc_enabled;
 
        intel_crtc_free_hw_state(slave_crtc_state);
index f948d33..c8568e5 100644 (file)
@@ -37,9 +37,6 @@ static u64 gen8_pte_encode(dma_addr_t addr,
        if (unlikely(flags & PTE_READ_ONLY))
                pte &= ~GEN8_PAGE_RW;
 
-       if (flags & PTE_LM)
-               pte |= GEN12_PPGTT_PTE_LM;
-
        /*
         * For pre-gen12 platforms pat_index is the same as enum
         * i915_cache_level, so the switch-case here is still valid.
index 2f6a9be..731d9f2 100644 (file)
@@ -670,7 +670,7 @@ __vm_create_scratch_for_read(struct i915_address_space *vm, unsigned long size)
        if (IS_ERR(obj))
                return ERR_CAST(obj);
 
-       i915_gem_object_set_cache_coherency(obj, I915_CACHING_CACHED);
+       i915_gem_object_set_cache_coherency(obj, I915_CACHE_LLC);
 
        vma = i915_vma_instance(obj, vm, NULL);
        if (IS_ERR(vma)) {
index 0a111b2..7413c11 100644 (file)
@@ -868,8 +868,17 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
                        oa_report_id_clear(stream, report32);
                        oa_timestamp_clear(stream, report32);
                } else {
+                       u8 *oa_buf_end = stream->oa_buffer.vaddr +
+                                        OA_BUFFER_SIZE;
+                       u32 part = oa_buf_end - (u8 *)report32;
+
                        /* Zero out the entire report */
-                       memset(report32, 0, report_size);
+                       if (report_size <= part) {
+                               memset(report32, 0, report_size);
+                       } else {
+                               memset(report32, 0, part);
+                               memset(oa_buf_base, 0, report_size - part);
+                       }
                }
        }
 
index b933a85..bf1e17d 100644 (file)
@@ -246,10 +246,6 @@ void msm_fbdev_setup(struct drm_device *dev)
                goto err_drm_fb_helper_unprepare;
        }
 
-       ret = msm_fbdev_client_hotplug(&helper->client);
-       if (ret)
-               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&helper->client);
 
        return;
index 42e1665..38d3fad 100644 (file)
@@ -910,15 +910,19 @@ nv50_msto_prepare(struct drm_atomic_state *state,
        struct nouveau_drm *drm = nouveau_drm(msto->encoder.dev);
        struct nv50_mstc *mstc = msto->mstc;
        struct nv50_mstm *mstm = mstc->mstm;
-       struct drm_dp_mst_atomic_payload *payload;
+       struct drm_dp_mst_topology_state *old_mst_state;
+       struct drm_dp_mst_atomic_payload *payload, *old_payload;
 
        NV_ATOMIC(drm, "%s: msto prepare\n", msto->encoder.name);
 
+       old_mst_state = drm_atomic_get_old_mst_topology_state(state, mgr);
+
        payload = drm_atomic_get_mst_payload_state(mst_state, mstc->port);
+       old_payload = drm_atomic_get_mst_payload_state(old_mst_state, mstc->port);
 
        // TODO: Figure out if we want to do a better job of handling VCPI allocation failures here?
        if (msto->disabled) {
-               drm_dp_remove_payload(mgr, mst_state, payload, payload);
+               drm_dp_remove_payload(mgr, mst_state, old_payload, payload);
 
                nvif_outp_dp_mst_vcpi(&mstm->outp->outp, msto->head->base.index, 0, 0, 0, 0);
        } else {
index e648ecd..3dfbc37 100644 (file)
@@ -90,6 +90,7 @@ nouveau_channel_del(struct nouveau_channel **pchan)
                if (cli)
                        nouveau_svmm_part(chan->vmm->svmm, chan->inst);
 
+               nvif_object_dtor(&chan->blit);
                nvif_object_dtor(&chan->nvsw);
                nvif_object_dtor(&chan->gart);
                nvif_object_dtor(&chan->vram);
index e06a8ff..bad7466 100644 (file)
@@ -53,6 +53,7 @@ struct nouveau_channel {
        u32 user_put;
 
        struct nvif_object user;
+       struct nvif_object blit;
 
        struct nvif_event kill;
        atomic_t killed;
index 7aac938..40fb9a8 100644 (file)
@@ -375,15 +375,29 @@ nouveau_accel_gr_init(struct nouveau_drm *drm)
                ret = nvif_object_ctor(&drm->channel->user, "drmNvsw",
                                       NVDRM_NVSW, nouveau_abi16_swclass(drm),
                                       NULL, 0, &drm->channel->nvsw);
+
+               if (ret == 0 && device->info.chipset >= 0x11) {
+                       ret = nvif_object_ctor(&drm->channel->user, "drmBlit",
+                                              0x005f, 0x009f,
+                                              NULL, 0, &drm->channel->blit);
+               }
+
                if (ret == 0) {
                        struct nvif_push *push = drm->channel->chan.push;
-                       ret = PUSH_WAIT(push, 2);
-                       if (ret == 0)
+                       ret = PUSH_WAIT(push, 8);
+                       if (ret == 0) {
+                               if (device->info.chipset >= 0x11) {
+                                       PUSH_NVSQ(push, NV05F, 0x0000, drm->channel->blit.handle);
+                                       PUSH_NVSQ(push, NV09F, 0x0120, 0,
+                                                              0x0124, 1,
+                                                              0x0128, 2);
+                               }
                                PUSH_NVSQ(push, NV_SW, 0x0000, drm->channel->nvsw.handle);
+                       }
                }
 
                if (ret) {
-                       NV_ERROR(drm, "failed to allocate sw class, %d\n", ret);
+                       NV_ERROR(drm, "failed to allocate sw or blit class, %d\n", ret);
                        nouveau_accel_gr_fini(drm);
                        return;
                }
index a4853c4..67ef889 100644 (file)
@@ -295,6 +295,7 @@ g94_sor = {
        .clock = nv50_sor_clock,
        .war_2 = g94_sor_war_2,
        .war_3 = g94_sor_war_3,
+       .hdmi = &g84_sor_hdmi,
        .dp = &g94_sor_dp,
 };
 
index a2c7c6f..506ffbe 100644 (file)
@@ -125,7 +125,7 @@ gt215_sor_hdmi_infoframe_avi(struct nvkm_ior *ior, int head, void *data, u32 siz
        pack_hdmi_infoframe(&avi, data, size);
 
        nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000);
-       if (size)
+       if (!size)
                return;
 
        nvkm_wr32(device, 0x61c528 + soff, avi.header);
index 795f3a6..9b8ca4e 100644 (file)
@@ -224,7 +224,7 @@ nvkm_acr_oneinit(struct nvkm_subdev *subdev)
        u64 falcons;
        int ret, i;
 
-       if (list_empty(&acr->hsfw)) {
+       if (list_empty(&acr->hsfw) || !acr->func || !acr->func->wpr_layout) {
                nvkm_debug(subdev, "No HSFW(s)\n");
                nvkm_acr_cleanup(acr);
                return 0;
index b7ccce0..fe6639c 100644 (file)
@@ -318,10 +318,6 @@ void omap_fbdev_setup(struct drm_device *dev)
 
        INIT_WORK(&fbdev->work, pan_worker);
 
-       ret = omap_fbdev_client_hotplug(&helper->client);
-       if (ret)
-               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&helper->client);
 
        return;
index a247a0e..aaba36b 100644 (file)
@@ -2178,6 +2178,7 @@ static const struct panel_desc innolux_at043tn24 = {
                .height = 54,
        },
        .bus_format = MEDIA_BUS_FMT_RGB888_1X24,
+       .connector_type = DRM_MODE_CONNECTOR_DPI,
        .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
 };
 
@@ -3202,6 +3203,7 @@ static const struct drm_display_mode powertip_ph800480t013_idf02_mode = {
        .vsync_start = 480 + 49,
        .vsync_end = 480 + 49 + 2,
        .vtotal = 480 + 49 + 2 + 22,
+       .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
 };
 
 static const struct panel_desc powertip_ph800480t013_idf02  = {
index ab9c1ab..f941e2e 100644 (file)
@@ -383,10 +383,6 @@ void radeon_fbdev_setup(struct radeon_device *rdev)
                goto err_drm_client_init;
        }
 
-       ret = radeon_fbdev_client_hotplug(&fb_helper->client);
-       if (ret)
-               drm_dbg_kms(rdev->ddev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&fb_helper->client);
 
        return;
index b2bbc8a..a42763e 100644 (file)
@@ -176,16 +176,32 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f,
 {
        struct drm_sched_job *job = container_of(cb, struct drm_sched_job,
                                                 finish_cb);
-       int r;
+       unsigned long index;
 
        dma_fence_put(f);
 
        /* Wait for all dependencies to avoid data corruptions */
-       while (!xa_empty(&job->dependencies)) {
-               f = xa_erase(&job->dependencies, job->last_dependency++);
-               r = dma_fence_add_callback(f, &job->finish_cb,
-                                          drm_sched_entity_kill_jobs_cb);
-               if (!r)
+       xa_for_each(&job->dependencies, index, f) {
+               struct drm_sched_fence *s_fence = to_drm_sched_fence(f);
+
+               if (s_fence && f == &s_fence->scheduled) {
+                       /* The dependencies array had a reference on the scheduled
+                        * fence, and the finished fence refcount might have
+                        * dropped to zero. Use dma_fence_get_rcu() so we get
+                        * a NULL fence in that case.
+                        */
+                       f = dma_fence_get_rcu(&s_fence->finished);
+
+                       /* Now that we have a reference on the finished fence,
+                        * we can release the reference the dependencies array
+                        * had on the scheduled fence.
+                        */
+                       dma_fence_put(&s_fence->scheduled);
+               }
+
+               xa_erase(&job->dependencies, index);
+               if (f && !dma_fence_add_callback(f, &job->finish_cb,
+                                                drm_sched_entity_kill_jobs_cb))
                        return;
 
                dma_fence_put(f);
@@ -415,8 +431,17 @@ static struct dma_fence *
 drm_sched_job_dependency(struct drm_sched_job *job,
                         struct drm_sched_entity *entity)
 {
-       if (!xa_empty(&job->dependencies))
-               return xa_erase(&job->dependencies, job->last_dependency++);
+       struct dma_fence *f;
+
+       /* We keep the fence around, so we can iterate over all dependencies
+        * in drm_sched_entity_kill_jobs_cb() to ensure all deps are signaled
+        * before killing the job.
+        */
+       f = xa_load(&job->dependencies, job->last_dependency);
+       if (f) {
+               job->last_dependency++;
+               return dma_fence_get(f);
+       }
 
        if (job->sched->ops->prepare_job)
                return job->sched->ops->prepare_job(job, entity);
index ef12047..06cedfe 100644 (file)
@@ -48,8 +48,32 @@ static void __exit drm_sched_fence_slab_fini(void)
        kmem_cache_destroy(sched_fence_slab);
 }
 
-void drm_sched_fence_scheduled(struct drm_sched_fence *fence)
+static void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence,
+                                      struct dma_fence *fence)
 {
+       /*
+        * smp_store_release() to ensure another thread racing us
+        * in drm_sched_fence_set_deadline_finished() sees the
+        * fence's parent set before test_bit()
+        */
+       smp_store_release(&s_fence->parent, dma_fence_get(fence));
+       if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT,
+                    &s_fence->finished.flags))
+               dma_fence_set_deadline(fence, s_fence->deadline);
+}
+
+void drm_sched_fence_scheduled(struct drm_sched_fence *fence,
+                              struct dma_fence *parent)
+{
+       /* Set the parent before signaling the scheduled fence, such that,
+        * any waiter expecting the parent to be filled after the job has
+        * been scheduled (which is the case for drivers delegating waits
+        * to some firmware) doesn't have to busy wait for parent to show
+        * up.
+        */
+       if (!IS_ERR_OR_NULL(parent))
+               drm_sched_fence_set_parent(fence, parent);
+
        dma_fence_signal(&fence->scheduled);
 }
 
@@ -181,20 +205,6 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f)
 }
 EXPORT_SYMBOL(to_drm_sched_fence);
 
-void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence,
-                               struct dma_fence *fence)
-{
-       /*
-        * smp_store_release() to ensure another thread racing us
-        * in drm_sched_fence_set_deadline_finished() sees the
-        * fence's parent set before test_bit()
-        */
-       smp_store_release(&s_fence->parent, dma_fence_get(fence));
-       if (test_bit(DRM_SCHED_FENCE_FLAG_HAS_DEADLINE_BIT,
-                    &s_fence->finished.flags))
-               dma_fence_set_deadline(fence, s_fence->deadline);
-}
-
 struct drm_sched_fence *drm_sched_fence_alloc(struct drm_sched_entity *entity,
                                              void *owner)
 {
index 7b2bfc1..506371c 100644 (file)
@@ -1043,10 +1043,9 @@ static int drm_sched_main(void *param)
                trace_drm_run_job(sched_job, entity);
                fence = sched->ops->run_job(sched_job);
                complete_all(&entity->entity_idle);
-               drm_sched_fence_scheduled(s_fence);
+               drm_sched_fence_scheduled(s_fence, fence);
 
                if (!IS_ERR_OR_NULL(fence)) {
-                       drm_sched_fence_set_parent(s_fence, fence);
                        /* Drop for original kref_init of the fence */
                        dma_fence_put(fence);
 
index e74d9be..d042234 100644 (file)
@@ -225,10 +225,6 @@ void tegra_fbdev_setup(struct drm_device *dev)
        if (ret)
                goto err_drm_client_init;
 
-       ret = tegra_fbdev_client_hotplug(&helper->client);
-       if (ret)
-               drm_dbg_kms(dev, "client hotplug ret=%d\n", ret);
-
        drm_client_register(&helper->client);
 
        return;
index bd5dae4..7139a52 100644 (file)
@@ -458,18 +458,18 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo,
                goto out;
        }
 
-bounce:
-       ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop);
-       if (ret == -EMULTIHOP) {
+       do {
+               ret = ttm_bo_handle_move_mem(bo, evict_mem, true, ctx, &hop);
+               if (ret != -EMULTIHOP)
+                       break;
+
                ret = ttm_bo_bounce_temp_buffer(bo, &evict_mem, ctx, &hop);
-               if (ret) {
-                       if (ret != -ERESTARTSYS && ret != -EINTR)
-                               pr_err("Buffer eviction failed\n");
-                       ttm_resource_free(bo, &evict_mem);
-                       goto out;
-               }
-               /* try and move to final place now. */
-               goto bounce;
+       } while (!ret);
+
+       if (ret) {
+               ttm_resource_free(bo, &evict_mem);
+               if (ret != -ERESTARTSYS && ret != -EINTR)
+                       pr_err("Buffer eviction failed\n");
        }
 out:
        return ret;
@@ -517,6 +517,12 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo,
 {
        bool ret = false;
 
+       if (bo->pin_count) {
+               *locked = false;
+               *busy = false;
+               return false;
+       }
+
        if (bo->base.resv == ctx->resv) {
                dma_resv_assert_held(bo->base.resv);
                if (ctx->allow_res_evict)
@@ -1167,6 +1173,7 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx,
                ret = ttm_bo_handle_move_mem(bo, evict_mem, true, &ctx, &hop);
                if (unlikely(ret != 0)) {
                        WARN(ret == -EMULTIHOP, "Unexpected multihop in swaput - likely driver bug.\n");
+                       ttm_resource_free(bo, &evict_mem);
                        goto out;
                }
        }
index 7333f7a..46ff9c7 100644 (file)
@@ -86,6 +86,8 @@ static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos,
                                       struct ttm_resource *res)
 {
        if (pos->last != res) {
+               if (pos->first == res)
+                       pos->first = list_next_entry(res, lru);
                list_move(&res->lru, &pos->last->lru);
                pos->last = res;
        }
@@ -111,7 +113,8 @@ static void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk,
 {
        struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res);
 
-       if (unlikely(pos->first == res && pos->last == res)) {
+       if (unlikely(WARN_ON(!pos->first || !pos->last) ||
+                    (pos->first == res && pos->last == res))) {
                pos->first = NULL;
                pos->last = NULL;
        } else if (pos->first == res) {
index 6f0d332..06bdcf0 100644 (file)
@@ -132,29 +132,45 @@ static void get_common_inputs(struct common_input_property *common, int report_i
        common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
 }
 
-static int float_to_int(u32 float32)
+static int float_to_int(u32 flt32_val)
 {
        int fraction, shift, mantissa, sign, exp, zeropre;
 
-       mantissa = float32 & GENMASK(22, 0);
-       sign = (float32 & BIT(31)) ? -1 : 1;
-       exp = (float32 & ~BIT(31)) >> 23;
+       mantissa = flt32_val & GENMASK(22, 0);
+       sign = (flt32_val & BIT(31)) ? -1 : 1;
+       exp = (flt32_val & ~BIT(31)) >> 23;
 
        if (!exp && !mantissa)
                return 0;
 
+       /*
+        * Calculate the exponent and fraction part of floating
+        * point representation.
+        */
        exp -= 127;
        if (exp < 0) {
                exp = -exp;
+               if (exp >= BITS_PER_TYPE(u32))
+                       return 0;
                zeropre = (((BIT(23) + mantissa) * 100) >> 23) >> exp;
                return zeropre >= 50 ? sign : 0;
        }
 
        shift = 23 - exp;
-       float32 = BIT(exp) + (mantissa >> shift);
-       fraction = mantissa & GENMASK(shift - 1, 0);
+       if (abs(shift) >= BITS_PER_TYPE(u32))
+               return 0;
+
+       if (shift < 0) {
+               shift = -shift;
+               flt32_val = BIT(exp) + (mantissa << shift);
+               shift = 0;
+       } else {
+               flt32_val = BIT(exp) + (mantissa >> shift);
+       }
+
+       fraction = (shift == 0) ? 0 : mantissa & GENMASK(shift - 1, 0);
 
-       return (((fraction * 100) >> shift) >= 50) ? sign * (float32 + 1) : sign * float32;
+       return (((fraction * 100) >> shift) >= 50) ? sign * (flt32_val + 1) : sign * flt32_val;
 }
 
 static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
index 49d4a26..f33485d 100644 (file)
@@ -258,19 +258,17 @@ static void mousevsc_on_receive(struct hv_device *device,
 
        switch (hid_msg_hdr->type) {
        case SYNTH_HID_PROTOCOL_RESPONSE:
+               len = struct_size(pipe_msg, data, pipe_msg->size);
+
                /*
                 * While it will be impossible for us to protect against
                 * malicious/buggy hypervisor/host, add a check here to
                 * ensure we don't corrupt memory.
                 */
-               if (struct_size(pipe_msg, data, pipe_msg->size)
-                       > sizeof(struct mousevsc_prt_msg)) {
-                       WARN_ON(1);
+               if (WARN_ON(len > sizeof(struct mousevsc_prt_msg)))
                        break;
-               }
 
-               memcpy(&input_dev->protocol_resp, pipe_msg,
-                               struct_size(pipe_msg, data, pipe_msg->size));
+               memcpy(&input_dev->protocol_resp, pipe_msg, len);
                complete(&input_dev->wait_event);
                break;
 
index a1d2690..851ee86 100644 (file)
@@ -1093,6 +1093,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x074: map_key_clear(KEY_BRIGHTNESS_MAX);          break;
                case 0x075: map_key_clear(KEY_BRIGHTNESS_AUTO);         break;
 
+               case 0x076: map_key_clear(KEY_CAMERA_ACCESS_ENABLE);    break;
+               case 0x077: map_key_clear(KEY_CAMERA_ACCESS_DISABLE);   break;
+               case 0x078: map_key_clear(KEY_CAMERA_ACCESS_TOGGLE);    break;
+
                case 0x079: map_key_clear(KEY_KBDILLUMUP);      break;
                case 0x07a: map_key_clear(KEY_KBDILLUMDOWN);    break;
                case 0x07c: map_key_clear(KEY_KBDILLUMTOGGLE);  break;
@@ -1139,9 +1143,6 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
                case 0x0cd: map_key_clear(KEY_PLAYPAUSE);       break;
                case 0x0cf: map_key_clear(KEY_VOICECOMMAND);    break;
 
-               case 0x0d5: map_key_clear(KEY_CAMERA_ACCESS_ENABLE);            break;
-               case 0x0d6: map_key_clear(KEY_CAMERA_ACCESS_DISABLE);           break;
-               case 0x0d7: map_key_clear(KEY_CAMERA_ACCESS_TOGGLE);            break;
                case 0x0d8: map_key_clear(KEY_DICTATE);         break;
                case 0x0d9: map_key_clear(KEY_EMOJI_PICKER);    break;
 
index dfe8e09..129b01b 100644 (file)
@@ -4598,6 +4598,8 @@ static const struct hid_device_id hidpp_devices[] = {
 
        { /* Logitech G403 Wireless Gaming Mouse over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC082) },
+       { /* Logitech G502 Lightspeed Wireless Gaming Mouse over USB */
+         HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC08D) },
        { /* Logitech G703 Gaming Mouse over USB */
          HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, 0xC087) },
        { /* Logitech G703 Hero Gaming Mouse over USB */
index 85700ce..a928ad2 100644 (file)
@@ -63,12 +63,12 @@ static_assert(sizeof(enum thunderstrike_led_state) == 1);
 struct thunderstrike_hostcmd_board_info {
        __le16 revision;
        __le16 serial[7];
-};
+} __packed;
 
 struct thunderstrike_hostcmd_haptics {
        u8 motor_left;
        u8 motor_right;
-};
+} __packed;
 
 struct thunderstrike_hostcmd_resp_report {
        u8 report_id; /* THUNDERSTRIKE_HOSTCMD_RESP_REPORT_ID */
@@ -81,7 +81,7 @@ struct thunderstrike_hostcmd_resp_report {
                __le16 fw_version;
                enum thunderstrike_led_state led_state;
                u8 payload[30];
-       };
+       } __packed;
 } __packed;
 static_assert(sizeof(struct thunderstrike_hostcmd_resp_report) ==
              THUNDERSTRIKE_HOSTCMD_REPORT_SIZE);
@@ -92,15 +92,15 @@ struct thunderstrike_hostcmd_req_report {
        u8 reserved_at_10;
 
        union {
-               struct {
+               struct __packed {
                        u8 update;
                        enum thunderstrike_led_state state;
                } led;
-               struct {
+               struct __packed {
                        u8 update;
                        struct thunderstrike_hostcmd_haptics motors;
                } haptics;
-       };
+       } __packed;
        u8 reserved_at_30[27];
 } __packed;
 static_assert(sizeof(struct thunderstrike_hostcmd_req_report) ==
index 3ebd4b6..05c0fb2 100644 (file)
@@ -34,8 +34,9 @@ static int iommu_sva_alloc_pasid(struct mm_struct *mm, ioasid_t min, ioasid_t ma
        }
 
        ret = ida_alloc_range(&iommu_global_pasid_ida, min, max, GFP_KERNEL);
-       if (ret < min)
+       if (ret < 0)
                goto out;
+
        mm->pasid = ret;
        ret = 0;
 out:
index da340f1..caaf563 100644 (file)
@@ -2891,14 +2891,11 @@ static int iommu_setup_default_domain(struct iommu_group *group,
                ret = __iommu_group_set_domain_internal(
                        group, dom, IOMMU_SET_DOMAIN_MUST_SUCCEED);
                if (WARN_ON(ret))
-                       goto out_free;
+                       goto out_free_old;
        } else {
                ret = __iommu_group_set_domain(group, dom);
-               if (ret) {
-                       iommu_domain_free(dom);
-                       group->default_domain = old_dom;
-                       return ret;
-               }
+               if (ret)
+                       goto err_restore_def_domain;
        }
 
        /*
@@ -2911,20 +2908,24 @@ static int iommu_setup_default_domain(struct iommu_group *group,
                for_each_group_device(group, gdev) {
                        ret = iommu_create_device_direct_mappings(dom, gdev->dev);
                        if (ret)
-                               goto err_restore;
+                               goto err_restore_domain;
                }
        }
 
-err_restore:
-       if (old_dom) {
+out_free_old:
+       if (old_dom)
+               iommu_domain_free(old_dom);
+       return ret;
+
+err_restore_domain:
+       if (old_dom)
                __iommu_group_set_domain_internal(
                        group, old_dom, IOMMU_SET_DOMAIN_MUST_SUCCEED);
+err_restore_def_domain:
+       if (old_dom) {
                iommu_domain_free(dom);
-               old_dom = NULL;
+               group->default_domain = old_dom;
        }
-out_free:
-       if (old_dom)
-               iommu_domain_free(old_dom);
        return ret;
 }
 
index 70c0e2b..8da46d2 100644 (file)
@@ -1286,7 +1286,6 @@ static int felix_parse_ports_node(struct felix *felix,
                if (err < 0) {
                        dev_info(dev, "Unsupported PHY mode %s on port %d\n",
                                 phy_modes(phy_mode), port);
-                       of_node_put(child);
 
                        /* Leave port_phy_modes[port] = 0, which is also
                         * PHY_INTERFACE_MODE_NA. This will perform a
@@ -1786,16 +1785,15 @@ static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
 {
        struct ocelot *ocelot = ds->priv;
        struct ocelot_port *ocelot_port = ocelot->ports[port];
-       struct felix *felix = ocelot_to_felix(ocelot);
 
        ocelot_port_set_maxlen(ocelot, port, new_mtu);
 
-       mutex_lock(&ocelot->tas_lock);
+       mutex_lock(&ocelot->fwd_domain_lock);
 
-       if (ocelot_port->taprio && felix->info->tas_guard_bands_update)
-               felix->info->tas_guard_bands_update(ocelot, port);
+       if (ocelot_port->taprio && ocelot->ops->tas_guard_bands_update)
+               ocelot->ops->tas_guard_bands_update(ocelot, port);
 
-       mutex_unlock(&ocelot->tas_lock);
+       mutex_unlock(&ocelot->fwd_domain_lock);
 
        return 0;
 }
index 96008c0..1d4befe 100644 (file)
@@ -57,7 +57,6 @@ struct felix_info {
        void    (*mdio_bus_free)(struct ocelot *ocelot);
        int     (*port_setup_tc)(struct dsa_switch *ds, int port,
                                 enum tc_setup_type type, void *type_data);
-       void    (*tas_guard_bands_update)(struct ocelot *ocelot, int port);
        void    (*port_sched_speed_set)(struct ocelot *ocelot, int port,
                                        u32 speed);
        void    (*phylink_mac_config)(struct ocelot *ocelot, int port,
index bb39fed..1c11395 100644 (file)
@@ -1209,15 +1209,17 @@ static u32 vsc9959_tas_tc_max_sdu(struct tc_taprio_qopt_offload *taprio, int tc)
 static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
 {
        struct ocelot_port *ocelot_port = ocelot->ports[port];
+       struct ocelot_mm_state *mm = &ocelot->mm[port];
        struct tc_taprio_qopt_offload *taprio;
        u64 min_gate_len[OCELOT_NUM_TC];
+       u32 val, maxlen, add_frag_size;
+       u64 needed_min_frag_time_ps;
        int speed, picos_per_byte;
        u64 needed_bit_time_ps;
-       u32 val, maxlen;
        u8 tas_speed;
        int tc;
 
-       lockdep_assert_held(&ocelot->tas_lock);
+       lockdep_assert_held(&ocelot->fwd_domain_lock);
 
        taprio = ocelot_port->taprio;
 
@@ -1253,14 +1255,21 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
         */
        needed_bit_time_ps = (u64)(maxlen + 24) * picos_per_byte;
 
+       /* Preemptible TCs don't need to pass a full MTU, the port will
+        * automatically emit a HOLD request when a preemptible TC gate closes
+        */
+       val = ocelot_read_rix(ocelot, QSYS_PREEMPTION_CFG, port);
+       add_frag_size = QSYS_PREEMPTION_CFG_MM_ADD_FRAG_SIZE_X(val);
+       needed_min_frag_time_ps = picos_per_byte *
+               (u64)(24 + 2 * ethtool_mm_frag_size_add_to_min(add_frag_size));
+
        dev_dbg(ocelot->dev,
-               "port %d: max frame size %d needs %llu ps at speed %d\n",
-               port, maxlen, needed_bit_time_ps, speed);
+               "port %d: max frame size %d needs %llu ps, %llu ps for mPackets at speed %d\n",
+               port, maxlen, needed_bit_time_ps, needed_min_frag_time_ps,
+               speed);
 
        vsc9959_tas_min_gate_lengths(taprio, min_gate_len);
 
-       mutex_lock(&ocelot->fwd_domain_lock);
-
        for (tc = 0; tc < OCELOT_NUM_TC; tc++) {
                u32 requested_max_sdu = vsc9959_tas_tc_max_sdu(taprio, tc);
                u64 remaining_gate_len_ps;
@@ -1269,7 +1278,9 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
                remaining_gate_len_ps =
                        vsc9959_tas_remaining_gate_len_ps(min_gate_len[tc]);
 
-               if (remaining_gate_len_ps > needed_bit_time_ps) {
+               if ((mm->active_preemptible_tcs & BIT(tc)) ?
+                   remaining_gate_len_ps > needed_min_frag_time_ps :
+                   remaining_gate_len_ps > needed_bit_time_ps) {
                        /* Setting QMAXSDU_CFG to 0 disables oversized frame
                         * dropping.
                         */
@@ -1323,8 +1334,6 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
        ocelot_write_rix(ocelot, maxlen, QSYS_PORT_MAX_SDU, port);
 
        ocelot->ops->cut_through_fwd(ocelot);
-
-       mutex_unlock(&ocelot->fwd_domain_lock);
 }
 
 static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
@@ -1351,7 +1360,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
                break;
        }
 
-       mutex_lock(&ocelot->tas_lock);
+       mutex_lock(&ocelot->fwd_domain_lock);
 
        ocelot_rmw_rix(ocelot,
                       QSYS_TAG_CONFIG_LINK_SPEED(tas_speed),
@@ -1361,7 +1370,7 @@ static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,
        if (ocelot_port->taprio)
                vsc9959_tas_guard_bands_update(ocelot, port);
 
-       mutex_unlock(&ocelot->tas_lock);
+       mutex_unlock(&ocelot->fwd_domain_lock);
 }
 
 static void vsc9959_new_base_time(struct ocelot *ocelot, ktime_t base_time,
@@ -1409,7 +1418,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
        int ret, i;
        u32 val;
 
-       mutex_lock(&ocelot->tas_lock);
+       mutex_lock(&ocelot->fwd_domain_lock);
 
        if (taprio->cmd == TAPRIO_CMD_DESTROY) {
                ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
@@ -1421,7 +1430,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
 
                vsc9959_tas_guard_bands_update(ocelot, port);
 
-               mutex_unlock(&ocelot->tas_lock);
+               mutex_unlock(&ocelot->fwd_domain_lock);
                return 0;
        } else if (taprio->cmd != TAPRIO_CMD_REPLACE) {
                ret = -EOPNOTSUPP;
@@ -1504,7 +1513,7 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
        ocelot_port->taprio = taprio_offload_get(taprio);
        vsc9959_tas_guard_bands_update(ocelot, port);
 
-       mutex_unlock(&ocelot->tas_lock);
+       mutex_unlock(&ocelot->fwd_domain_lock);
 
        return 0;
 
@@ -1512,7 +1521,7 @@ err_reset_tc:
        taprio->mqprio.qopt.num_tc = 0;
        ocelot_port_mqprio(ocelot, port, &taprio->mqprio);
 err_unlock:
-       mutex_unlock(&ocelot->tas_lock);
+       mutex_unlock(&ocelot->fwd_domain_lock);
 
        return ret;
 }
@@ -1525,7 +1534,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)
        int port;
        u32 val;
 
-       mutex_lock(&ocelot->tas_lock);
+       mutex_lock(&ocelot->fwd_domain_lock);
 
        for (port = 0; port < ocelot->num_phys_ports; port++) {
                ocelot_port = ocelot->ports[port];
@@ -1563,7 +1572,7 @@ static void vsc9959_tas_clock_adjust(struct ocelot *ocelot)
                               QSYS_TAG_CONFIG_ENABLE,
                               QSYS_TAG_CONFIG, port);
        }
-       mutex_unlock(&ocelot->tas_lock);
+       mutex_unlock(&ocelot->fwd_domain_lock);
 }
 
 static int vsc9959_qos_port_cbs_set(struct dsa_switch *ds, int port,
@@ -1634,6 +1643,18 @@ static int vsc9959_qos_query_caps(struct tc_query_caps_base *base)
        }
 }
 
+static int vsc9959_qos_port_mqprio(struct ocelot *ocelot, int port,
+                                  struct tc_mqprio_qopt_offload *mqprio)
+{
+       int ret;
+
+       mutex_lock(&ocelot->fwd_domain_lock);
+       ret = ocelot_port_mqprio(ocelot, port, mqprio);
+       mutex_unlock(&ocelot->fwd_domain_lock);
+
+       return ret;
+}
+
 static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
                                 enum tc_setup_type type,
                                 void *type_data)
@@ -1646,7 +1667,7 @@ static int vsc9959_port_setup_tc(struct dsa_switch *ds, int port,
        case TC_SETUP_QDISC_TAPRIO:
                return vsc9959_qos_port_tas_set(ocelot, port, type_data);
        case TC_SETUP_QDISC_MQPRIO:
-               return ocelot_port_mqprio(ocelot, port, type_data);
+               return vsc9959_qos_port_mqprio(ocelot, port, type_data);
        case TC_SETUP_QDISC_CBS:
                return vsc9959_qos_port_cbs_set(ds, port, type_data);
        default:
@@ -2591,6 +2612,7 @@ static const struct ocelot_ops vsc9959_ops = {
        .cut_through_fwd        = vsc9959_cut_through_fwd,
        .tas_clock_adjust       = vsc9959_tas_clock_adjust,
        .update_stats           = vsc9959_update_stats,
+       .tas_guard_bands_update = vsc9959_tas_guard_bands_update,
 };
 
 static const struct felix_info felix_info_vsc9959 = {
@@ -2616,7 +2638,6 @@ static const struct felix_info felix_info_vsc9959 = {
        .port_modes             = vsc9959_port_modes,
        .port_setup_tc          = vsc9959_port_setup_tc,
        .port_sched_speed_set   = vsc9959_sched_speed_set,
-       .tas_guard_bands_update = vsc9959_tas_guard_bands_update,
 };
 
 /* The INTB interrupt is shared between for PTP TX timestamp availability
index f7d7cfb..09b8064 100644 (file)
@@ -588,6 +588,9 @@ qca8k_phy_eth_busy_wait(struct qca8k_mgmt_eth_data *mgmt_eth_data,
        bool ack;
        int ret;
 
+       if (!skb)
+               return -ENOMEM;
+
        reinit_completion(&mgmt_eth_data->rw_done);
 
        /* Increment seq_num and set it in the copy pkt */
index 451c3a1..633b321 100644 (file)
@@ -35,6 +35,8 @@
 
 #define ENA_REGS_ADMIN_INTR_MASK 1
 
+#define ENA_MAX_BACKOFF_DELAY_EXP 16U
+
 #define ENA_MIN_ADMIN_POLL_US 100
 
 #define ENA_MAX_ADMIN_POLL_US 5000
@@ -536,6 +538,7 @@ static int ena_com_comp_status_to_errno(struct ena_com_admin_queue *admin_queue,
 
 static void ena_delay_exponential_backoff_us(u32 exp, u32 delay_us)
 {
+       exp = min_t(u32, exp, ENA_MAX_BACKOFF_DELAY_EXP);
        delay_us = max_t(u32, ENA_MIN_ADMIN_POLL_US, delay_us);
        delay_us = min_t(u32, delay_us * (1U << exp), ENA_MAX_ADMIN_POLL_US);
        usleep_range(delay_us, 2 * delay_us);
index 1761df8..10c7c23 100644 (file)
@@ -1492,8 +1492,6 @@ int bgmac_enet_probe(struct bgmac *bgmac)
 
        bgmac->in_init = true;
 
-       bgmac_chip_intrs_off(bgmac);
-
        net_dev->irq = bgmac->irq;
        SET_NETDEV_DEV(net_dev, bgmac->dev);
        dev_set_drvdata(bgmac->dev, bgmac);
@@ -1511,6 +1509,8 @@ int bgmac_enet_probe(struct bgmac *bgmac)
         */
        bgmac_clk_enable(bgmac, 0);
 
+       bgmac_chip_intrs_off(bgmac);
+
        /* This seems to be fixing IRQ by assigning OOB #6 to the core */
        if (!(bgmac->feature_flags & BGMAC_FEAT_IDM_MASK)) {
                if (bgmac->feature_flags & BGMAC_FEAT_IRQ_ID_OOB_6)
index 9939cca..63a053d 100644 (file)
@@ -355,7 +355,7 @@ struct bufdesc_ex {
 #define RX_RING_SIZE           (FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
 #define FEC_ENET_TX_FRSIZE     2048
 #define FEC_ENET_TX_FRPPG      (PAGE_SIZE / FEC_ENET_TX_FRSIZE)
-#define TX_RING_SIZE           512     /* Must be power of two */
+#define TX_RING_SIZE           1024    /* Must be power of two */
 #define TX_RING_MOD_MASK       511     /*   for this to work */
 
 #define BD_ENET_RX_INT         0x00800000
@@ -544,10 +544,23 @@ enum {
        XDP_STATS_TOTAL,
 };
 
+enum fec_txbuf_type {
+       FEC_TXBUF_T_SKB,
+       FEC_TXBUF_T_XDP_NDO,
+};
+
+struct fec_tx_buffer {
+       union {
+               struct sk_buff *skb;
+               struct xdp_frame *xdp;
+       };
+       enum fec_txbuf_type type;
+};
+
 struct fec_enet_priv_tx_q {
        struct bufdesc_prop bd;
        unsigned char *tx_bounce[TX_RING_SIZE];
-       struct  sk_buff *tx_skbuff[TX_RING_SIZE];
+       struct fec_tx_buffer tx_buf[TX_RING_SIZE];
 
        unsigned short tx_stop_threshold;
        unsigned short tx_wake_threshold;
index 8fbe477..ec9e4bd 100644 (file)
@@ -397,7 +397,7 @@ static void fec_dump(struct net_device *ndev)
                        fec16_to_cpu(bdp->cbd_sc),
                        fec32_to_cpu(bdp->cbd_bufaddr),
                        fec16_to_cpu(bdp->cbd_datlen),
-                       txq->tx_skbuff[index]);
+                       txq->tx_buf[index].skb);
                bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
                index++;
        } while (bdp != txq->bd.base);
@@ -654,7 +654,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 
        index = fec_enet_get_bd_index(last_bdp, &txq->bd);
        /* Save skb pointer */
-       txq->tx_skbuff[index] = skb;
+       txq->tx_buf[index].skb = skb;
 
        /* Make sure the updates to rest of the descriptor are performed before
         * transferring ownership.
@@ -672,9 +672,7 @@ static int fec_enet_txq_submit_skb(struct fec_enet_priv_tx_q *txq,
 
        skb_tx_timestamp(skb);
 
-       /* Make sure the update to bdp and tx_skbuff are performed before
-        * txq->bd.cur.
-        */
+       /* Make sure the update to bdp is performed before txq->bd.cur. */
        wmb();
        txq->bd.cur = bdp;
 
@@ -862,7 +860,7 @@ static int fec_enet_txq_submit_tso(struct fec_enet_priv_tx_q *txq,
        }
 
        /* Save skb pointer */
-       txq->tx_skbuff[index] = skb;
+       txq->tx_buf[index].skb = skb;
 
        skb_tx_timestamp(skb);
        txq->bd.cur = bdp;
@@ -952,16 +950,33 @@ static void fec_enet_bd_init(struct net_device *dev)
                for (i = 0; i < txq->bd.ring_size; i++) {
                        /* Initialize the BD for every fragment in the page. */
                        bdp->cbd_sc = cpu_to_fec16(0);
-                       if (bdp->cbd_bufaddr &&
-                           !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
-                               dma_unmap_single(&fep->pdev->dev,
-                                                fec32_to_cpu(bdp->cbd_bufaddr),
-                                                fec16_to_cpu(bdp->cbd_datlen),
-                                                DMA_TO_DEVICE);
-                       if (txq->tx_skbuff[i]) {
-                               dev_kfree_skb_any(txq->tx_skbuff[i]);
-                               txq->tx_skbuff[i] = NULL;
+                       if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) {
+                               if (bdp->cbd_bufaddr &&
+                                   !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
+                                       dma_unmap_single(&fep->pdev->dev,
+                                                        fec32_to_cpu(bdp->cbd_bufaddr),
+                                                        fec16_to_cpu(bdp->cbd_datlen),
+                                                        DMA_TO_DEVICE);
+                               if (txq->tx_buf[i].skb) {
+                                       dev_kfree_skb_any(txq->tx_buf[i].skb);
+                                       txq->tx_buf[i].skb = NULL;
+                               }
+                       } else {
+                               if (bdp->cbd_bufaddr)
+                                       dma_unmap_single(&fep->pdev->dev,
+                                                        fec32_to_cpu(bdp->cbd_bufaddr),
+                                                        fec16_to_cpu(bdp->cbd_datlen),
+                                                        DMA_TO_DEVICE);
+
+                               if (txq->tx_buf[i].xdp) {
+                                       xdp_return_frame(txq->tx_buf[i].xdp);
+                                       txq->tx_buf[i].xdp = NULL;
+                               }
+
+                               /* restore default tx buffer type: FEC_TXBUF_T_SKB */
+                               txq->tx_buf[i].type = FEC_TXBUF_T_SKB;
                        }
+
                        bdp->cbd_bufaddr = cpu_to_fec32(0);
                        bdp = fec_enet_get_nextdesc(bdp, &txq->bd);
                }
@@ -1360,6 +1375,7 @@ static void
 fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 {
        struct  fec_enet_private *fep;
+       struct xdp_frame *xdpf;
        struct bufdesc *bdp;
        unsigned short status;
        struct  sk_buff *skb;
@@ -1387,16 +1403,31 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
 
                index = fec_enet_get_bd_index(bdp, &txq->bd);
 
-               skb = txq->tx_skbuff[index];
-               txq->tx_skbuff[index] = NULL;
-               if (!IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
-                       dma_unmap_single(&fep->pdev->dev,
-                                        fec32_to_cpu(bdp->cbd_bufaddr),
-                                        fec16_to_cpu(bdp->cbd_datlen),
-                                        DMA_TO_DEVICE);
-               bdp->cbd_bufaddr = cpu_to_fec32(0);
-               if (!skb)
-                       goto skb_done;
+               if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) {
+                       skb = txq->tx_buf[index].skb;
+                       txq->tx_buf[index].skb = NULL;
+                       if (bdp->cbd_bufaddr &&
+                           !IS_TSO_HEADER(txq, fec32_to_cpu(bdp->cbd_bufaddr)))
+                               dma_unmap_single(&fep->pdev->dev,
+                                                fec32_to_cpu(bdp->cbd_bufaddr),
+                                                fec16_to_cpu(bdp->cbd_datlen),
+                                                DMA_TO_DEVICE);
+                       bdp->cbd_bufaddr = cpu_to_fec32(0);
+                       if (!skb)
+                               goto tx_buf_done;
+               } else {
+                       xdpf = txq->tx_buf[index].xdp;
+                       if (bdp->cbd_bufaddr)
+                               dma_unmap_single(&fep->pdev->dev,
+                                                fec32_to_cpu(bdp->cbd_bufaddr),
+                                                fec16_to_cpu(bdp->cbd_datlen),
+                                                DMA_TO_DEVICE);
+                       bdp->cbd_bufaddr = cpu_to_fec32(0);
+                       if (!xdpf) {
+                               txq->tx_buf[index].type = FEC_TXBUF_T_SKB;
+                               goto tx_buf_done;
+                       }
+               }
 
                /* Check for errors. */
                if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
@@ -1415,21 +1446,11 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
                                ndev->stats.tx_carrier_errors++;
                } else {
                        ndev->stats.tx_packets++;
-                       ndev->stats.tx_bytes += skb->len;
-               }
-
-               /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who
-                * are to time stamp the packet, so we still need to check time
-                * stamping enabled flag.
-                */
-               if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
-                            fep->hwts_tx_en) &&
-                   fep->bufdesc_ex) {
-                       struct skb_shared_hwtstamps shhwtstamps;
-                       struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
 
-                       fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps);
-                       skb_tstamp_tx(skb, &shhwtstamps);
+                       if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB)
+                               ndev->stats.tx_bytes += skb->len;
+                       else
+                               ndev->stats.tx_bytes += xdpf->len;
                }
 
                /* Deferred means some collisions occurred during transmit,
@@ -1438,10 +1459,32 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id)
                if (status & BD_ENET_TX_DEF)
                        ndev->stats.collisions++;
 
-               /* Free the sk buffer associated with this last transmit */
-               dev_kfree_skb_any(skb);
-skb_done:
-               /* Make sure the update to bdp and tx_skbuff are performed
+               if (txq->tx_buf[index].type == FEC_TXBUF_T_SKB) {
+                       /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who
+                        * are to time stamp the packet, so we still need to check time
+                        * stamping enabled flag.
+                        */
+                       if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS &&
+                                    fep->hwts_tx_en) && fep->bufdesc_ex) {
+                               struct skb_shared_hwtstamps shhwtstamps;
+                               struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp;
+
+                               fec_enet_hwtstamp(fep, fec32_to_cpu(ebdp->ts), &shhwtstamps);
+                               skb_tstamp_tx(skb, &shhwtstamps);
+                       }
+
+                       /* Free the sk buffer associated with this last transmit */
+                       dev_kfree_skb_any(skb);
+               } else {
+                       xdp_return_frame(xdpf);
+
+                       txq->tx_buf[index].xdp = NULL;
+                       /* restore default tx buffer type: FEC_TXBUF_T_SKB */
+                       txq->tx_buf[index].type = FEC_TXBUF_T_SKB;
+               }
+
+tx_buf_done:
+               /* Make sure the update to bdp and tx_buf are performed
                 * before dirty_tx
                 */
                wmb();
@@ -3249,9 +3292,19 @@ static void fec_enet_free_buffers(struct net_device *ndev)
                for (i = 0; i < txq->bd.ring_size; i++) {
                        kfree(txq->tx_bounce[i]);
                        txq->tx_bounce[i] = NULL;
-                       skb = txq->tx_skbuff[i];
-                       txq->tx_skbuff[i] = NULL;
-                       dev_kfree_skb(skb);
+
+                       if (txq->tx_buf[i].type == FEC_TXBUF_T_SKB) {
+                               skb = txq->tx_buf[i].skb;
+                               txq->tx_buf[i].skb = NULL;
+                               dev_kfree_skb(skb);
+                       } else {
+                               if (txq->tx_buf[i].xdp) {
+                                       xdp_return_frame(txq->tx_buf[i].xdp);
+                                       txq->tx_buf[i].xdp = NULL;
+                               }
+
+                               txq->tx_buf[i].type = FEC_TXBUF_T_SKB;
+                       }
                }
        }
 }
@@ -3296,8 +3349,7 @@ static int fec_enet_alloc_queue(struct net_device *ndev)
                fep->total_tx_ring_size += fep->tx_queue[i]->bd.ring_size;
 
                txq->tx_stop_threshold = FEC_MAX_SKB_DESCS;
-               txq->tx_wake_threshold =
-                       (txq->bd.ring_size - txq->tx_stop_threshold) / 2;
+               txq->tx_wake_threshold = FEC_MAX_SKB_DESCS + 2 * MAX_SKB_FRAGS;
 
                txq->tso_hdrs = dma_alloc_coherent(&fep->pdev->dev,
                                        txq->bd.ring_size * TSO_HEADER_SIZE,
@@ -3732,12 +3784,18 @@ static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf)
                if (fep->quirks & FEC_QUIRK_SWAP_FRAME)
                        return -EOPNOTSUPP;
 
+               if (!bpf->prog)
+                       xdp_features_clear_redirect_target(dev);
+
                if (is_run) {
                        napi_disable(&fep->napi);
                        netif_tx_disable(dev);
                }
 
                old_prog = xchg(&fep->xdp_prog, bpf->prog);
+               if (old_prog)
+                       bpf_prog_put(old_prog);
+
                fec_restart(dev);
 
                if (is_run) {
@@ -3745,8 +3803,8 @@ static int fec_enet_bpf(struct net_device *dev, struct netdev_bpf *bpf)
                        netif_tx_start_all_queues(dev);
                }
 
-               if (old_prog)
-                       bpf_prog_put(old_prog);
+               if (bpf->prog)
+                       xdp_features_set_redirect_target(dev, false);
 
                return 0;
 
@@ -3778,7 +3836,7 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
 
        entries_free = fec_enet_get_free_txdesc_num(txq);
        if (entries_free < MAX_SKB_FRAGS + 1) {
-               netdev_err(fep->netdev, "NOT enough BD for SG!\n");
+               netdev_err_once(fep->netdev, "NOT enough BD for SG!\n");
                return -EBUSY;
        }
 
@@ -3811,7 +3869,8 @@ static int fec_enet_txq_xmit_frame(struct fec_enet_private *fep,
                ebdp->cbd_esc = cpu_to_fec32(estatus);
        }
 
-       txq->tx_skbuff[index] = NULL;
+       txq->tx_buf[index].type = FEC_TXBUF_T_XDP_NDO;
+       txq->tx_buf[index].xdp = frame;
 
        /* Make sure the updates to rest of the descriptor are performed before
         * transferring ownership.
@@ -4016,8 +4075,7 @@ static int fec_enet_init(struct net_device *ndev)
 
        if (!(fep->quirks & FEC_QUIRK_SWAP_FRAME))
                ndev->xdp_features = NETDEV_XDP_ACT_BASIC |
-                                    NETDEV_XDP_ACT_REDIRECT |
-                                    NETDEV_XDP_ACT_NDO_XMIT;
+                                    NETDEV_XDP_ACT_REDIRECT;
 
        fec_restart(ndev);
 
index 98eb78d..4b425bf 100644 (file)
@@ -964,5 +964,6 @@ void gve_handle_report_stats(struct gve_priv *priv);
 /* exported by ethtool.c */
 extern const struct ethtool_ops gve_ethtool_ops;
 /* needed by ethtool */
+extern char gve_driver_name[];
 extern const char gve_version_str[];
 #endif /* _GVE_H_ */
index cfd4b8d..233e594 100644 (file)
@@ -15,7 +15,7 @@ static void gve_get_drvinfo(struct net_device *netdev,
 {
        struct gve_priv *priv = netdev_priv(netdev);
 
-       strscpy(info->driver, "gve", sizeof(info->driver));
+       strscpy(info->driver, gve_driver_name, sizeof(info->driver));
        strscpy(info->version, gve_version_str, sizeof(info->version));
        strscpy(info->bus_info, pci_name(priv->pdev), sizeof(info->bus_info));
 }
@@ -590,6 +590,9 @@ static int gve_get_link_ksettings(struct net_device *netdev,
                err = gve_adminq_report_link_speed(priv);
 
        cmd->base.speed = priv->link_speed;
+
+       cmd->base.duplex = DUPLEX_FULL;
+
        return err;
 }
 
index 8fb70db..e6f1711 100644 (file)
@@ -33,6 +33,7 @@
 #define MIN_TX_TIMEOUT_GAP (1000 * 10)
 #define DQO_TX_MAX     0x3FFFF
 
+char gve_driver_name[] = "gve";
 const char gve_version_str[] = GVE_VERSION;
 static const char gve_version_prefix[] = GVE_VERSION_PREFIX;
 
@@ -2200,7 +2201,7 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                return err;
 
-       err = pci_request_regions(pdev, "gvnic-cfg");
+       err = pci_request_regions(pdev, gve_driver_name);
        if (err)
                goto abort_with_enabled;
 
@@ -2393,8 +2394,8 @@ static const struct pci_device_id gve_id_table[] = {
        { }
 };
 
-static struct pci_driver gvnic_driver = {
-       .name           = "gvnic",
+static struct pci_driver gve_driver = {
+       .name           = gve_driver_name,
        .id_table       = gve_id_table,
        .probe          = gve_probe,
        .remove         = gve_remove,
@@ -2405,10 +2406,10 @@ static struct pci_driver gvnic_driver = {
 #endif
 };
 
-module_pci_driver(gvnic_driver);
+module_pci_driver(gve_driver);
 
 MODULE_DEVICE_TABLE(pci, gve_id_table);
 MODULE_AUTHOR("Google, Inc.");
-MODULE_DESCRIPTION("gVNIC Driver");
+MODULE_DESCRIPTION("Google Virtual NIC Driver");
 MODULE_LICENSE("Dual MIT/GPL");
 MODULE_VERSION(GVE_VERSION);
index 93979ab..19a5e7f 100644 (file)
@@ -5739,6 +5739,13 @@ ice_set_tx_maxrate(struct net_device *netdev, int queue_index, u32 maxrate)
        q_handle = vsi->tx_rings[queue_index]->q_handle;
        tc = ice_dcb_get_tc(vsi, queue_index);
 
+       vsi = ice_locate_vsi_using_queue(vsi, queue_index);
+       if (!vsi) {
+               netdev_err(netdev, "Invalid VSI for given queue %d\n",
+                          queue_index);
+               return -EINVAL;
+       }
+
        /* Set BW back to default, when user set maxrate to 0 */
        if (!maxrate)
                status = ice_cfg_q_bw_dflt_lmt(vsi->port_info, vsi->idx, tc,
@@ -7872,10 +7879,10 @@ static int
 ice_validate_mqprio_qopt(struct ice_vsi *vsi,
                         struct tc_mqprio_qopt_offload *mqprio_qopt)
 {
-       u64 sum_max_rate = 0, sum_min_rate = 0;
        int non_power_of_2_qcount = 0;
        struct ice_pf *pf = vsi->back;
        int max_rss_q_cnt = 0;
+       u64 sum_min_rate = 0;
        struct device *dev;
        int i, speed;
        u8 num_tc;
@@ -7891,6 +7898,7 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
        dev = ice_pf_to_dev(pf);
        vsi->ch_rss_size = 0;
        num_tc = mqprio_qopt->qopt.num_tc;
+       speed = ice_get_link_speed_kbps(vsi);
 
        for (i = 0; num_tc; i++) {
                int qcount = mqprio_qopt->qopt.count[i];
@@ -7931,7 +7939,6 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
                 */
                max_rate = mqprio_qopt->max_rate[i];
                max_rate = div_u64(max_rate, ICE_BW_KBPS_DIVISOR);
-               sum_max_rate += max_rate;
 
                /* min_rate is minimum guaranteed rate and it can't be zero */
                min_rate = mqprio_qopt->min_rate[i];
@@ -7944,6 +7951,12 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
                        return -EINVAL;
                }
 
+               if (max_rate && max_rate > speed) {
+                       dev_err(dev, "TC%d: max_rate(%llu Kbps) > link speed of %u Kbps\n",
+                               i, max_rate, speed);
+                       return -EINVAL;
+               }
+
                iter_div_u64_rem(min_rate, ICE_MIN_BW_LIMIT, &rem);
                if (rem) {
                        dev_err(dev, "TC%d: Min Rate not multiple of %u Kbps",
@@ -7981,12 +7994,6 @@ ice_validate_mqprio_qopt(struct ice_vsi *vsi,
            (mqprio_qopt->qopt.offset[i] + mqprio_qopt->qopt.count[i]))
                return -EINVAL;
 
-       speed = ice_get_link_speed_kbps(vsi);
-       if (sum_max_rate && sum_max_rate > (u64)speed) {
-               dev_err(dev, "Invalid max Tx rate(%llu) Kbps > speed(%u) Kbps specified\n",
-                       sum_max_rate, speed);
-               return -EINVAL;
-       }
        if (sum_min_rate && sum_min_rate > (u64)speed) {
                dev_err(dev, "Invalid min Tx rate(%llu) Kbps > speed (%u) Kbps specified\n",
                        sum_min_rate, speed);
index b54052e..4a34ef5 100644 (file)
@@ -750,17 +750,16 @@ exit:
 /**
  * ice_locate_vsi_using_queue - locate VSI using queue (forward to queue action)
  * @vsi: Pointer to VSI
- * @tc_fltr: Pointer to tc_flower_filter
+ * @queue: Queue index
  *
- * Locate the VSI using specified queue. When ADQ is not enabled, always
- * return input VSI, otherwise locate corresponding VSI based on per channel
- * offset and qcount
+ * Locate the VSI using specified "queue". When ADQ is not enabled,
+ * always return input VSI, otherwise locate corresponding
+ * VSI based on per channel "offset" and "qcount"
  */
-static struct ice_vsi *
-ice_locate_vsi_using_queue(struct ice_vsi *vsi,
-                          struct ice_tc_flower_fltr *tc_fltr)
+struct ice_vsi *
+ice_locate_vsi_using_queue(struct ice_vsi *vsi, int queue)
 {
-       int num_tc, tc, queue;
+       int num_tc, tc;
 
        /* if ADQ is not active, passed VSI is the candidate VSI */
        if (!ice_is_adq_active(vsi->back))
@@ -770,7 +769,6 @@ ice_locate_vsi_using_queue(struct ice_vsi *vsi,
         * upon queue number)
         */
        num_tc = vsi->mqprio_qopt.qopt.num_tc;
-       queue = tc_fltr->action.fwd.q.queue;
 
        for (tc = 0; tc < num_tc; tc++) {
                int qcount = vsi->mqprio_qopt.qopt.count[tc];
@@ -812,6 +810,7 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
        struct ice_pf *pf = vsi->back;
        struct device *dev;
        u32 tc_class;
+       int q;
 
        dev = ice_pf_to_dev(pf);
 
@@ -840,7 +839,8 @@ ice_tc_forward_action(struct ice_vsi *vsi, struct ice_tc_flower_fltr *tc_fltr)
                /* Determine destination VSI even though the action is
                 * FWD_TO_QUEUE, because QUEUE is associated with VSI
                 */
-               dest_vsi = tc_fltr->dest_vsi;
+               q = tc_fltr->action.fwd.q.queue;
+               dest_vsi = ice_locate_vsi_using_queue(vsi, q);
                break;
        default:
                dev_err(dev,
@@ -1716,7 +1716,7 @@ ice_tc_forward_to_queue(struct ice_vsi *vsi, struct ice_tc_flower_fltr *fltr,
        /* If ADQ is configured, and the queue belongs to ADQ VSI, then prepare
         * ADQ switch filter
         */
-       ch_vsi = ice_locate_vsi_using_queue(vsi, fltr);
+       ch_vsi = ice_locate_vsi_using_queue(vsi, fltr->action.fwd.q.queue);
        if (!ch_vsi)
                return -EINVAL;
        fltr->dest_vsi = ch_vsi;
index 8bbc1a6..65d3871 100644 (file)
@@ -204,6 +204,7 @@ static inline int ice_chnl_dmac_fltr_cnt(struct ice_pf *pf)
        return pf->num_dmac_chnl_fltrs;
 }
 
+struct ice_vsi *ice_locate_vsi_using_queue(struct ice_vsi *vsi, int queue);
 int
 ice_add_cls_flower(struct net_device *netdev, struct ice_vsi *vsi,
                   struct flow_cls_offload *cls_flower);
index 00a5ee4..9db384f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/timecounter.h>
 #include <linux/net_tstamp.h>
 #include <linux/bitfield.h>
+#include <linux/hrtimer.h>
 
 #include "igc_hw.h"
 
@@ -101,6 +102,8 @@ struct igc_ring {
        u32 start_time;
        u32 end_time;
        u32 max_sdu;
+       bool oper_gate_closed;          /* Operating gate. True if the TX Queue is closed */
+       bool admin_gate_closed;         /* Future gate. True if the TX Queue will be closed */
 
        /* CBS parameters */
        bool cbs_enable;                /* indicates if CBS is enabled */
@@ -160,6 +163,7 @@ struct igc_adapter {
        struct timer_list watchdog_timer;
        struct timer_list dma_err_timer;
        struct timer_list phy_info_timer;
+       struct hrtimer hrtimer;
 
        u32 wol;
        u32 en_mng_pt;
@@ -184,10 +188,13 @@ struct igc_adapter {
        u32 max_frame_size;
        u32 min_frame_size;
 
+       int tc_setup_type;
        ktime_t base_time;
        ktime_t cycle_time;
-       bool qbv_enable;
+       bool taprio_offload_enable;
        u32 qbv_config_change_errors;
+       bool qbv_transition;
+       unsigned int qbv_count;
 
        /* OS defined structs */
        struct pci_dev *pdev;
index 0e2cb00..93bce72 100644 (file)
@@ -1708,6 +1708,8 @@ static int igc_ethtool_get_link_ksettings(struct net_device *netdev,
        /* twisted pair */
        cmd->base.port = PORT_TP;
        cmd->base.phy_address = hw->phy.addr;
+       ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+       ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
 
        /* advertising link modes */
        if (hw->phy.autoneg_advertised & ADVERTISE_10_HALF)
index 019ce91..9f93f0f 100644 (file)
@@ -711,7 +711,6 @@ static void igc_configure_tx_ring(struct igc_adapter *adapter,
        /* disable the queue */
        wr32(IGC_TXDCTL(reg_idx), 0);
        wrfl();
-       mdelay(10);
 
        wr32(IGC_TDLEN(reg_idx),
             ring->count * sizeof(union igc_adv_tx_desc));
@@ -1017,7 +1016,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime,
        ktime_t base_time = adapter->base_time;
        ktime_t now = ktime_get_clocktai();
        ktime_t baset_est, end_of_cycle;
-       u32 launchtime;
+       s32 launchtime;
        s64 n;
 
        n = div64_s64(ktime_sub_ns(now, base_time), cycle_time);
@@ -1030,7 +1029,7 @@ static __le32 igc_tx_launchtime(struct igc_ring *ring, ktime_t txtime,
                        *first_flag = true;
                        ring->last_ff_cycle = baset_est;
 
-                       if (ktime_compare(txtime, ring->last_tx_cycle) > 0)
+                       if (ktime_compare(end_of_cycle, ring->last_tx_cycle) > 0)
                                *insert_empty = true;
                }
        }
@@ -1573,16 +1572,12 @@ done:
        first->bytecount = skb->len;
        first->gso_segs = 1;
 
-       if (tx_ring->max_sdu > 0) {
-               u32 max_sdu = 0;
-
-               max_sdu = tx_ring->max_sdu +
-                         (skb_vlan_tagged(first->skb) ? VLAN_HLEN : 0);
+       if (adapter->qbv_transition || tx_ring->oper_gate_closed)
+               goto out_drop;
 
-               if (first->bytecount > max_sdu) {
-                       adapter->stats.txdrop++;
-                       goto out_drop;
-               }
+       if (tx_ring->max_sdu > 0 && first->bytecount > tx_ring->max_sdu) {
+               adapter->stats.txdrop++;
+               goto out_drop;
        }
 
        if (unlikely(test_bit(IGC_RING_FLAG_TX_HWTSTAMP, &tx_ring->flags) &&
@@ -3012,8 +3007,8 @@ static bool igc_clean_tx_irq(struct igc_q_vector *q_vector, int napi_budget)
                    time_after(jiffies, tx_buffer->time_stamp +
                    (adapter->tx_timeout_factor * HZ)) &&
                    !(rd32(IGC_STATUS) & IGC_STATUS_TXOFF) &&
-                   (rd32(IGC_TDH(tx_ring->reg_idx)) !=
-                    readl(tx_ring->tail))) {
+                   (rd32(IGC_TDH(tx_ring->reg_idx)) != readl(tx_ring->tail)) &&
+                   !tx_ring->oper_gate_closed) {
                        /* detected Tx unit hang */
                        netdev_err(tx_ring->netdev,
                                   "Detected Tx Unit Hang\n"
@@ -6102,7 +6097,10 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
 
        adapter->base_time = 0;
        adapter->cycle_time = NSEC_PER_SEC;
+       adapter->taprio_offload_enable = false;
        adapter->qbv_config_change_errors = 0;
+       adapter->qbv_transition = false;
+       adapter->qbv_count = 0;
 
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct igc_ring *ring = adapter->tx_ring[i];
@@ -6110,6 +6108,8 @@ static int igc_tsn_clear_schedule(struct igc_adapter *adapter)
                ring->start_time = 0;
                ring->end_time = NSEC_PER_SEC;
                ring->max_sdu = 0;
+               ring->oper_gate_closed = false;
+               ring->admin_gate_closed = false;
        }
 
        return 0;
@@ -6121,27 +6121,20 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
        bool queue_configured[IGC_MAX_TX_QUEUES] = { };
        struct igc_hw *hw = &adapter->hw;
        u32 start_time = 0, end_time = 0;
+       struct timespec64 now;
        size_t n;
        int i;
 
-       switch (qopt->cmd) {
-       case TAPRIO_CMD_REPLACE:
-               adapter->qbv_enable = true;
-               break;
-       case TAPRIO_CMD_DESTROY:
-               adapter->qbv_enable = false;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       if (!adapter->qbv_enable)
+       if (qopt->cmd == TAPRIO_CMD_DESTROY)
                return igc_tsn_clear_schedule(adapter);
 
+       if (qopt->cmd != TAPRIO_CMD_REPLACE)
+               return -EOPNOTSUPP;
+
        if (qopt->base_time < 0)
                return -ERANGE;
 
-       if (igc_is_device_id_i225(hw) && adapter->base_time)
+       if (igc_is_device_id_i225(hw) && adapter->taprio_offload_enable)
                return -EALREADY;
 
        if (!validate_schedule(adapter, qopt))
@@ -6149,6 +6142,9 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
 
        adapter->cycle_time = qopt->cycle_time;
        adapter->base_time = qopt->base_time;
+       adapter->taprio_offload_enable = true;
+
+       igc_ptp_read(adapter, &now);
 
        for (n = 0; n < qopt->num_entries; n++) {
                struct tc_taprio_sched_entry *e = &qopt->entries[n];
@@ -6184,7 +6180,10 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
                                ring->start_time = start_time;
                        ring->end_time = end_time;
 
-                       queue_configured[i] = true;
+                       if (ring->start_time >= adapter->cycle_time)
+                               queue_configured[i] = false;
+                       else
+                               queue_configured[i] = true;
                }
 
                start_time += e->interval;
@@ -6194,8 +6193,20 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
         * If not, set the start and end time to be end time.
         */
        for (i = 0; i < adapter->num_tx_queues; i++) {
+               struct igc_ring *ring = adapter->tx_ring[i];
+
+               if (!is_base_time_past(qopt->base_time, &now)) {
+                       ring->admin_gate_closed = false;
+               } else {
+                       ring->oper_gate_closed = false;
+                       ring->admin_gate_closed = false;
+               }
+
                if (!queue_configured[i]) {
-                       struct igc_ring *ring = adapter->tx_ring[i];
+                       if (!is_base_time_past(qopt->base_time, &now))
+                               ring->admin_gate_closed = true;
+                       else
+                               ring->oper_gate_closed = true;
 
                        ring->start_time = end_time;
                        ring->end_time = end_time;
@@ -6207,7 +6218,7 @@ static int igc_save_qbv_schedule(struct igc_adapter *adapter,
                struct net_device *dev = adapter->netdev;
 
                if (qopt->max_sdu[i])
-                       ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len;
+                       ring->max_sdu = qopt->max_sdu[i] + dev->hard_header_len - ETH_TLEN;
                else
                        ring->max_sdu = 0;
        }
@@ -6327,6 +6338,8 @@ static int igc_setup_tc(struct net_device *dev, enum tc_setup_type type,
 {
        struct igc_adapter *adapter = netdev_priv(dev);
 
+       adapter->tc_setup_type = type;
+
        switch (type) {
        case TC_QUERY_CAPS:
                return igc_tc_query_caps(adapter, type_data);
@@ -6574,6 +6587,27 @@ static const struct xdp_metadata_ops igc_xdp_metadata_ops = {
        .xmo_rx_timestamp               = igc_xdp_rx_timestamp,
 };
 
+static enum hrtimer_restart igc_qbv_scheduling_timer(struct hrtimer *timer)
+{
+       struct igc_adapter *adapter = container_of(timer, struct igc_adapter,
+                                                  hrtimer);
+       unsigned int i;
+
+       adapter->qbv_transition = true;
+       for (i = 0; i < adapter->num_tx_queues; i++) {
+               struct igc_ring *tx_ring = adapter->tx_ring[i];
+
+               if (tx_ring->admin_gate_closed) {
+                       tx_ring->admin_gate_closed = false;
+                       tx_ring->oper_gate_closed = true;
+               } else {
+                       tx_ring->oper_gate_closed = false;
+               }
+       }
+       adapter->qbv_transition = false;
+       return HRTIMER_NORESTART;
+}
+
 /**
  * igc_probe - Device Initialization Routine
  * @pdev: PCI device information struct
@@ -6752,6 +6786,9 @@ static int igc_probe(struct pci_dev *pdev,
        INIT_WORK(&adapter->reset_task, igc_reset_task);
        INIT_WORK(&adapter->watchdog_task, igc_watchdog_task);
 
+       hrtimer_init(&adapter->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       adapter->hrtimer.function = &igc_qbv_scheduling_timer;
+
        /* Initialize link properties that are user-changeable */
        adapter->fc_autoneg = true;
        hw->mac.autoneg = true;
@@ -6855,6 +6892,7 @@ static void igc_remove(struct pci_dev *pdev)
 
        cancel_work_sync(&adapter->reset_task);
        cancel_work_sync(&adapter->watchdog_task);
+       hrtimer_cancel(&adapter->hrtimer);
 
        /* Release control of h/w to f/w.  If f/w is AMT enabled, this
         * would have already happened in close and is redundant.
index 32ef112..f0b979a 100644 (file)
@@ -356,16 +356,35 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
                        tsim &= ~IGC_TSICR_TT0;
                }
                if (on) {
+                       struct timespec64 safe_start;
                        int i = rq->perout.index;
 
                        igc_pin_perout(igc, i, pin, use_freq);
-                       igc->perout[i].start.tv_sec = rq->perout.start.sec;
+                       igc_ptp_read(igc, &safe_start);
+
+                       /* PPS output start time is triggered by Target time(TT)
+                        * register. Programming any past time value into TT
+                        * register will cause PPS to never start. Need to make
+                        * sure we program the TT register a time ahead in
+                        * future. There isn't a stringent need to fire PPS out
+                        * right away. Adding +2 seconds should take care of
+                        * corner cases. Let's say if the SYSTIML is close to
+                        * wrap up and the timer keeps ticking as we program the
+                        * register, adding +2seconds is safe bet.
+                        */
+                       safe_start.tv_sec += 2;
+
+                       if (rq->perout.start.sec < safe_start.tv_sec)
+                               igc->perout[i].start.tv_sec = safe_start.tv_sec;
+                       else
+                               igc->perout[i].start.tv_sec = rq->perout.start.sec;
                        igc->perout[i].start.tv_nsec = rq->perout.start.nsec;
                        igc->perout[i].period.tv_sec = ts.tv_sec;
                        igc->perout[i].period.tv_nsec = ts.tv_nsec;
-                       wr32(trgttimh, rq->perout.start.sec);
+                       wr32(trgttimh, (u32)igc->perout[i].start.tv_sec);
                        /* For now, always select timer 0 as source. */
-                       wr32(trgttiml, rq->perout.start.nsec | IGC_TT_IO_TIMER_SEL_SYSTIM0);
+                       wr32(trgttiml, (u32)(igc->perout[i].start.tv_nsec |
+                                            IGC_TT_IO_TIMER_SEL_SYSTIM0));
                        if (use_freq)
                                wr32(freqout, ns);
                        tsauxc |= tsauxc_mask;
index 94a2b0d..a9c0832 100644 (file)
@@ -37,7 +37,7 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)
 {
        unsigned int new_flags = adapter->flags & ~IGC_FLAG_TSN_ANY_ENABLED;
 
-       if (adapter->qbv_enable)
+       if (adapter->taprio_offload_enable)
                new_flags |= IGC_FLAG_TSN_QBV_ENABLED;
 
        if (is_any_launchtime(adapter))
@@ -114,7 +114,6 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)
 static int igc_tsn_enable_offload(struct igc_adapter *adapter)
 {
        struct igc_hw *hw = &adapter->hw;
-       bool tsn_mode_reconfig = false;
        u32 tqavctrl, baset_l, baset_h;
        u32 sec, nsec, cycle;
        ktime_t base_time, systim;
@@ -133,8 +132,28 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)
                wr32(IGC_STQT(i), ring->start_time);
                wr32(IGC_ENDQT(i), ring->end_time);
 
-               txqctl |= IGC_TXQCTL_STRICT_CYCLE |
-                       IGC_TXQCTL_STRICT_END;
+               if (adapter->taprio_offload_enable) {
+                       /* If taprio_offload_enable is set we are in "taprio"
+                        * mode and we need to be strict about the
+                        * cycles: only transmit a packet if it can be
+                        * completed during that cycle.
+                        *
+                        * If taprio_offload_enable is NOT true when
+                        * enabling TSN offload, the cycle should have
+                        * no external effects, but is only used internally
+                        * to adapt the base time register after a second
+                        * has passed.
+                        *
+                        * Enabling strict mode in this case would
+                        * unnecessarily prevent the transmission of
+                        * certain packets (i.e. at the boundary of a
+                        * second) and thus interfere with the launchtime
+                        * feature that promises transmission at a
+                        * certain point in time.
+                        */
+                       txqctl |= IGC_TXQCTL_STRICT_CYCLE |
+                               IGC_TXQCTL_STRICT_END;
+               }
 
                if (ring->launchtime_enable)
                        txqctl |= IGC_TXQCTL_QUEUE_MODE_LAUNCHT;
@@ -228,11 +247,10 @@ skip_cbs:
 
        tqavctrl = rd32(IGC_TQAVCTRL) & ~IGC_TQAVCTRL_FUTSCDDIS;
 
-       if (tqavctrl & IGC_TQAVCTRL_TRANSMIT_MODE_TSN)
-               tsn_mode_reconfig = true;
-
        tqavctrl |= IGC_TQAVCTRL_TRANSMIT_MODE_TSN | IGC_TQAVCTRL_ENHANCED_QAV;
 
+       adapter->qbv_count++;
+
        cycle = adapter->cycle_time;
        base_time = adapter->base_time;
 
@@ -249,17 +267,29 @@ skip_cbs:
                 * Gate Control List (GCL) is running.
                 */
                if ((rd32(IGC_BASET_H) || rd32(IGC_BASET_L)) &&
-                   tsn_mode_reconfig)
+                   (adapter->tc_setup_type == TC_SETUP_QDISC_TAPRIO) &&
+                   (adapter->qbv_count > 1))
                        adapter->qbv_config_change_errors++;
        } else {
-               /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
-                * has to be configured before the cycle time and base time.
-                * Tx won't hang if there is a GCL is already running,
-                * so in this case we don't need to set FutScdDis.
-                */
-               if (igc_is_device_id_i226(hw) &&
-                   !(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
-                       tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
+               if (igc_is_device_id_i226(hw)) {
+                       ktime_t adjust_time, expires_time;
+
+                      /* According to datasheet section 7.5.2.9.3.3, FutScdDis bit
+                       * has to be configured before the cycle time and base time.
+                       * Tx won't hang if a GCL is already running,
+                       * so in this case we don't need to set FutScdDis.
+                       */
+                       if (!(rd32(IGC_BASET_H) || rd32(IGC_BASET_L)))
+                               tqavctrl |= IGC_TQAVCTRL_FUTSCDDIS;
+
+                       nsec = rd32(IGC_SYSTIML);
+                       sec = rd32(IGC_SYSTIMH);
+                       systim = ktime_set(sec, nsec);
+
+                       adjust_time = adapter->base_time;
+                       expires_time = ktime_sub_ns(adjust_time, systim);
+                       hrtimer_start(&adapter->hrtimer, expires_time, HRTIMER_MODE_REL);
+               }
        }
 
        wr32(IGC_TQAVCTRL, tqavctrl);
@@ -305,7 +335,11 @@ int igc_tsn_offload_apply(struct igc_adapter *adapter)
 {
        struct igc_hw *hw = &adapter->hw;
 
-       if (netif_running(adapter->netdev) && igc_is_device_id_i225(hw)) {
+       /* Per I225/6 HW Design Section 7.5.2.1, transmit mode
+        * cannot be changed dynamically. Require reset the adapter.
+        */
+       if (netif_running(adapter->netdev) &&
+           (igc_is_device_id_i225(hw) || !adapter->qbv_count)) {
                schedule_work(&adapter->reset_task);
                return 0;
        }
index ff5647b..acf4f6b 100644 (file)
@@ -1511,7 +1511,7 @@ static void mvneta_defaults_set(struct mvneta_port *pp)
                         */
                        if (txq_number == 1)
                                txq_map = (cpu == pp->rxq_def) ?
-                                       MVNETA_CPU_TXQ_ACCESS(1) : 0;
+                                       MVNETA_CPU_TXQ_ACCESS(0) : 0;
 
                } else {
                        txq_map = MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
@@ -4356,7 +4356,7 @@ static void mvneta_percpu_elect(struct mvneta_port *pp)
                 */
                if (txq_number == 1)
                        txq_map = (cpu == elected_cpu) ?
-                               MVNETA_CPU_TXQ_ACCESS(1) : 0;
+                               MVNETA_CPU_TXQ_ACCESS(0) : 0;
                else
                        txq_map = mvreg_read(pp, MVNETA_CPU_MAP(cpu)) &
                                MVNETA_CPU_TXQ_ACCESS_ALL_MASK;
index 3411e2e..0ee420a 100644 (file)
@@ -208,7 +208,7 @@ struct ptp *ptp_get(void)
        /* Check driver is bound to PTP block */
        if (!ptp)
                ptp = ERR_PTR(-EPROBE_DEFER);
-       else
+       else if (!IS_ERR(ptp))
                pci_dev_get(ptp->pdev);
 
        return ptp;
@@ -388,11 +388,10 @@ static int ptp_extts_on(struct ptp *ptp, int on)
 static int ptp_probe(struct pci_dev *pdev,
                     const struct pci_device_id *ent)
 {
-       struct device *dev = &pdev->dev;
        struct ptp *ptp;
        int err;
 
-       ptp = devm_kzalloc(dev, sizeof(*ptp), GFP_KERNEL);
+       ptp = kzalloc(sizeof(*ptp), GFP_KERNEL);
        if (!ptp) {
                err = -ENOMEM;
                goto error;
@@ -428,20 +427,19 @@ static int ptp_probe(struct pci_dev *pdev,
        return 0;
 
 error_free:
-       devm_kfree(dev, ptp);
+       kfree(ptp);
 
 error:
        /* For `ptp_get()` we need to differentiate between the case
         * when the core has not tried to probe this device and the case when
-        * the probe failed.  In the later case we pretend that the
-        * initialization was successful and keep the error in
+        * the probe failed.  In the later case we keep the error in
         * `dev->driver_data`.
         */
        pci_set_drvdata(pdev, ERR_PTR(err));
        if (!first_ptp_block)
                first_ptp_block = ERR_PTR(err);
 
-       return 0;
+       return err;
 }
 
 static void ptp_remove(struct pci_dev *pdev)
@@ -449,16 +447,17 @@ static void ptp_remove(struct pci_dev *pdev)
        struct ptp *ptp = pci_get_drvdata(pdev);
        u64 clock_cfg;
 
-       if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer))
-               hrtimer_cancel(&ptp->hrtimer);
-
        if (IS_ERR_OR_NULL(ptp))
                return;
 
+       if (cn10k_ptp_errata(ptp) && hrtimer_active(&ptp->hrtimer))
+               hrtimer_cancel(&ptp->hrtimer);
+
        /* Disable PTP clock */
        clock_cfg = readq(ptp->reg_base + PTP_CLOCK_CFG);
        clock_cfg &= ~PTP_CLOCK_CFG_PTP_EN;
        writeq(clock_cfg, ptp->reg_base + PTP_CLOCK_CFG);
+       kfree(ptp);
 }
 
 static const struct pci_device_id ptp_id_table[] = {
index 8dbc35c..73df2d5 100644 (file)
@@ -3252,7 +3252,7 @@ static int rvu_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        rvu->ptp = ptp_get();
        if (IS_ERR(rvu->ptp)) {
                err = PTR_ERR(rvu->ptp);
-               if (err == -EPROBE_DEFER)
+               if (err)
                        goto err_release_regions;
                rvu->ptp = NULL;
        }
index 0d745ae..04b0e88 100644 (file)
@@ -4069,21 +4069,14 @@ int rvu_mbox_handler_nix_set_rx_mode(struct rvu *rvu, struct nix_rx_mode *req,
        }
 
        /* install/uninstall promisc entry */
-       if (promisc) {
+       if (promisc)
                rvu_npc_install_promisc_entry(rvu, pcifunc, nixlf,
                                              pfvf->rx_chan_base,
                                              pfvf->rx_chan_cnt);
-
-               if (rvu_npc_exact_has_match_table(rvu))
-                       rvu_npc_exact_promisc_enable(rvu, pcifunc);
-       } else {
+       else
                if (!nix_rx_multicast)
                        rvu_npc_enable_promisc_entry(rvu, pcifunc, nixlf, false);
 
-               if (rvu_npc_exact_has_match_table(rvu))
-                       rvu_npc_exact_promisc_disable(rvu, pcifunc);
-       }
-
        return 0;
 }
 
index 9f11c1e..6fe67f3 100644 (file)
@@ -1164,8 +1164,10 @@ static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_i
 {
        struct npc_exact_table *table;
        u16 *cnt, old_cnt;
+       bool promisc;
 
        table = rvu->hw->table;
+       promisc = table->promisc_mode[drop_mcam_idx];
 
        cnt = &table->cnt_cmd_rules[drop_mcam_idx];
        old_cnt = *cnt;
@@ -1177,13 +1179,18 @@ static u16 __rvu_npc_exact_cmd_rules_cnt_update(struct rvu *rvu, int drop_mcam_i
 
        *enable_or_disable_cam = false;
 
-       /* If all rules are deleted, disable cam */
+       if (promisc)
+               goto done;
+
+       /* If all rules are deleted and not already in promisc mode;
+        * disable cam
+        */
        if (!*cnt && val < 0) {
                *enable_or_disable_cam = true;
                goto done;
        }
 
-       /* If rule got added, enable cam */
+       /* If rule got added and not already in promisc mode; enable cam */
        if (!old_cnt && val > 0) {
                *enable_or_disable_cam = true;
                goto done;
@@ -1462,6 +1469,12 @@ int rvu_npc_exact_promisc_disable(struct rvu *rvu, u16 pcifunc)
        *promisc = false;
        mutex_unlock(&table->lock);
 
+       /* Enable drop rule */
+       rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX,
+                                          true);
+
+       dev_dbg(rvu->dev, "%s: disabled  promisc mode (cgx=%d lmac=%d)\n",
+               __func__, cgx_id, lmac_id);
        return 0;
 }
 
@@ -1503,6 +1516,12 @@ int rvu_npc_exact_promisc_enable(struct rvu *rvu, u16 pcifunc)
        *promisc = true;
        mutex_unlock(&table->lock);
 
+       /*  disable drop rule */
+       rvu_npc_enable_mcam_by_entry_index(rvu, drop_mcam_idx, NIX_INTF_RX,
+                                          false);
+
+       dev_dbg(rvu->dev, "%s: Enabled promisc mode (cgx=%d lmac=%d)\n",
+               __func__, cgx_id, lmac_id);
        return 0;
 }
 
index 10e1126..2d7713a 100644 (file)
@@ -872,6 +872,14 @@ static int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
                                return -EINVAL;
 
                        vlan_etype = be16_to_cpu(fsp->h_ext.vlan_etype);
+
+                       /* Drop rule with vlan_etype == 802.1Q
+                        * and vlan_id == 0 is not supported
+                        */
+                       if (vlan_etype == ETH_P_8021Q && !fsp->m_ext.vlan_tci &&
+                           fsp->ring_cookie == RX_CLS_FLOW_DISC)
+                               return -EINVAL;
+
                        /* Only ETH_P_8021Q and ETH_P_802AD types supported */
                        if (vlan_etype != ETH_P_8021Q &&
                            vlan_etype != ETH_P_8021AD)
index 8a13df5..5e56b6c 100644 (file)
@@ -597,6 +597,21 @@ static int otx2_tc_prepare_flow(struct otx2_nic *nic, struct otx2_tc_flow *node,
                        return -EOPNOTSUPP;
                }
 
+               if (!match.mask->vlan_id) {
+                       struct flow_action_entry *act;
+                       int i;
+
+                       flow_action_for_each(i, act, &rule->action) {
+                               if (act->id == FLOW_ACTION_DROP) {
+                                       netdev_err(nic->netdev,
+                                                  "vlan tpid 0x%x with vlan_id %d is not supported for DROP rule.\n",
+                                                  ntohs(match.key->vlan_tpid),
+                                                  match.key->vlan_id);
+                                       return -EOPNOTSUPP;
+                               }
+                       }
+               }
+
                if (match.mask->vlan_id ||
                    match.mask->vlan_dei ||
                    match.mask->vlan_priority) {
index 03cb79a..be83ad9 100644 (file)
@@ -594,7 +594,7 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs)
 
        err = fs_any_create_table(fs);
        if (err)
-               return err;
+               goto err_free_any;
 
        err = fs_any_enable(fs);
        if (err)
@@ -606,8 +606,8 @@ int mlx5e_fs_tt_redirect_any_create(struct mlx5e_flow_steering *fs)
 
 err_destroy_table:
        fs_any_destroy_table(fs_any);
-
-       kfree(fs_any);
+err_free_any:
        mlx5e_fs_set_any(fs, NULL);
+       kfree(fs_any);
        return err;
 }
index 3cbebfb..b0b429a 100644 (file)
@@ -729,8 +729,10 @@ int mlx5e_ptp_open(struct mlx5e_priv *priv, struct mlx5e_params *params,
 
        c = kvzalloc_node(sizeof(*c), GFP_KERNEL, dev_to_node(mlx5_core_dma_dev(mdev)));
        cparams = kvzalloc(sizeof(*cparams), GFP_KERNEL);
-       if (!c || !cparams)
-               return -ENOMEM;
+       if (!c || !cparams) {
+               err = -ENOMEM;
+               goto err_free;
+       }
 
        c->priv     = priv;
        c->mdev     = priv->mdev;
index a254e72..fadfa8b 100644 (file)
@@ -1545,7 +1545,8 @@ mlx5_tc_ct_parse_action(struct mlx5_tc_ct_priv *priv,
 
        attr->ct_attr.ct_action |= act->ct.action; /* So we can have clear + ct */
        attr->ct_attr.zone = act->ct.zone;
-       attr->ct_attr.nf_ft = act->ct.flow_table;
+       if (!(act->ct.action & TCA_CT_ACT_CLEAR))
+               attr->ct_attr.nf_ft = act->ct.flow_table;
        attr->ct_attr.act_miss_cookie = act->miss_cookie;
 
        return 0;
@@ -1990,6 +1991,9 @@ mlx5_tc_ct_flow_offload(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *att
        if (!priv)
                return -EOPNOTSUPP;
 
+       if (attr->ct_attr.offloaded)
+               return 0;
+
        if (attr->ct_attr.ct_action & TCA_CT_ACT_CLEAR) {
                err = mlx5_tc_ct_entry_set_registers(priv, &attr->parse_attr->mod_hdr_acts,
                                                     0, 0, 0, 0);
@@ -1999,11 +2003,15 @@ mlx5_tc_ct_flow_offload(struct mlx5_tc_ct_priv *priv, struct mlx5_flow_attr *att
                attr->action |= MLX5_FLOW_CONTEXT_ACTION_MOD_HDR;
        }
 
-       if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */
+       if (!attr->ct_attr.nf_ft) { /* means only ct clear action, and not ct_clear,ct() */
+               attr->ct_attr.offloaded = true;
                return 0;
+       }
 
        mutex_lock(&priv->control_lock);
        err = __mlx5_tc_ct_flow_offload(priv, attr);
+       if (!err)
+               attr->ct_attr.offloaded = true;
        mutex_unlock(&priv->control_lock);
 
        return err;
@@ -2021,7 +2029,7 @@ void
 mlx5_tc_ct_delete_flow(struct mlx5_tc_ct_priv *priv,
                       struct mlx5_flow_attr *attr)
 {
-       if (!attr->ct_attr.ft) /* no ct action, return */
+       if (!attr->ct_attr.offloaded) /* no ct action, return */
                return;
        if (!attr->ct_attr.nf_ft) /* means only ct clear action, and not ct_clear,ct() */
                return;
index 8e9316f..b66c5f9 100644 (file)
@@ -29,6 +29,7 @@ struct mlx5_ct_attr {
        u32 ct_labels_id;
        u32 act_miss_mapping;
        u64 act_miss_cookie;
+       bool offloaded;
        struct mlx5_ct_ft *ft;
 };
 
index f0e6095..40589ce 100644 (file)
@@ -662,8 +662,7 @@ static void mlx5e_free_xdpsq_desc(struct mlx5e_xdpsq *sq,
                                /* No need to check ((page->pp_magic & ~0x3UL) == PP_SIGNATURE)
                                 * as we know this is a page_pool page.
                                 */
-                               page_pool_put_defragged_page(page->pp,
-                                                            page, -1, true);
+                               page_pool_recycle_direct(page->pp, page);
                        } while (++n < num);
 
                        break;
index 88a5aed..c7d191f 100644 (file)
@@ -190,6 +190,7 @@ static int accel_fs_tcp_create_groups(struct mlx5e_flow_table *ft,
        in = kvzalloc(inlen, GFP_KERNEL);
        if  (!in || !ft->g) {
                kfree(ft->g);
+               ft->g = NULL;
                kvfree(in);
                return -ENOMEM;
        }
index 704b022..41d3715 100644 (file)
@@ -390,10 +390,18 @@ static void mlx5e_dealloc_rx_wqe(struct mlx5e_rq *rq, u16 ix)
 {
        struct mlx5e_wqe_frag_info *wi = get_frag(rq, ix);
 
-       if (rq->xsk_pool)
+       if (rq->xsk_pool) {
                mlx5e_xsk_free_rx_wqe(wi);
-       else
+       } else {
                mlx5e_free_rx_wqe(rq, wi);
+
+               /* Avoid a second release of the wqe pages: dealloc is called
+                * for the same missing wqes on regular RQ flush and on regular
+                * RQ close. This happens when XSK RQs come into play.
+                */
+               for (int i = 0; i < rq->wqe.info.num_frags; i++, wi++)
+                       wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
+       }
 }
 
 static void mlx5e_xsk_free_rx_wqes(struct mlx5e_rq *rq, u16 ix, int wqe_bulk)
@@ -1743,11 +1751,11 @@ mlx5e_skb_from_cqe_nonlinear(struct mlx5e_rq *rq, struct mlx5e_wqe_frag_info *wi
 
        prog = rcu_dereference(rq->xdp_prog);
        if (prog && mlx5e_xdp_handle(rq, prog, &mxbuf)) {
-               if (test_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
+               if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
                        struct mlx5e_wqe_frag_info *pwi;
 
                        for (pwi = head_wi; pwi < wi; pwi++)
-                               pwi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
+                               pwi->frag_page->frags++;
                }
                return NULL; /* page/packet was consumed by XDP */
        }
@@ -1817,12 +1825,8 @@ static void mlx5e_handle_rx_cqe(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
                              rq, wi, cqe, cqe_bcnt);
        if (!skb) {
                /* probably for XDP */
-               if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
-                       /* do not return page to cache,
-                        * it will be returned on XDP_TX completion.
-                        */
-                       wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
-               }
+               if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
+                       wi->frag_page->frags++;
                goto wq_cyc_pop;
        }
 
@@ -1868,12 +1872,8 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe)
                              rq, wi, cqe, cqe_bcnt);
        if (!skb) {
                /* probably for XDP */
-               if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
-                       /* do not return page to cache,
-                        * it will be returned on XDP_TX completion.
-                        */
-                       wi->flags |= BIT(MLX5E_WQE_FRAG_SKIP_RELEASE);
-               }
+               if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
+                       wi->frag_page->frags++;
                goto wq_cyc_pop;
        }
 
@@ -2052,12 +2052,12 @@ mlx5e_skb_from_cqe_mpwrq_nonlinear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *w
        if (prog) {
                if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
                        if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags)) {
-                               int i;
+                               struct mlx5e_frag_page *pfp;
+
+                               for (pfp = head_page; pfp < frag_page; pfp++)
+                                       pfp->frags++;
 
-                               for (i = 0; i < sinfo->nr_frags; i++)
-                                       /* non-atomic */
-                                       __set_bit(page_idx + i, wi->skip_release_bitmap);
-                               return NULL;
+                               wi->linear_page.frags++;
                        }
                        mlx5e_page_release_fragmented(rq, &wi->linear_page);
                        return NULL; /* page/packet was consumed by XDP */
@@ -2155,7 +2155,7 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,
                                 cqe_bcnt, &mxbuf);
                if (mlx5e_xdp_handle(rq, prog, &mxbuf)) {
                        if (__test_and_clear_bit(MLX5E_RQ_FLAG_XDP_XMIT, rq->flags))
-                               __set_bit(page_idx, wi->skip_release_bitmap); /* non-atomic */
+                               frag_page->frags++;
                        return NULL; /* page/packet was consumed by XDP */
                }
 
index 41dc268..8d0a3f6 100644 (file)
@@ -1639,7 +1639,8 @@ static void remove_unready_flow(struct mlx5e_tc_flow *flow)
        uplink_priv = &rpriv->uplink_priv;
 
        mutex_lock(&uplink_priv->unready_flows_lock);
-       unready_flow_del(flow);
+       if (flow_flag_test(flow, NOT_READY))
+               unready_flow_del(flow);
        mutex_unlock(&uplink_priv->unready_flows_lock);
 }
 
@@ -1932,8 +1933,7 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
        esw_attr = attr->esw_attr;
        mlx5e_put_flow_tunnel_id(flow);
 
-       if (flow_flag_test(flow, NOT_READY))
-               remove_unready_flow(flow);
+       remove_unready_flow(flow);
 
        if (mlx5e_is_offloaded_flow(flow)) {
                if (flow_flag_test(flow, SLOW))
index faec7d7..243c455 100644 (file)
@@ -807,6 +807,9 @@ static int mlx5_esw_vport_caps_get(struct mlx5_eswitch *esw, struct mlx5_vport *
        hca_caps = MLX5_ADDR_OF(query_hca_cap_out, query_ctx, capability);
        vport->info.roce_enabled = MLX5_GET(cmd_hca_cap, hca_caps, roce);
 
+       if (!MLX5_CAP_GEN_MAX(esw->dev, hca_cap_2))
+               goto out_free;
+
        memset(query_ctx, 0, query_out_sz);
        err = mlx5_vport_get_other_func_cap(esw->dev, vport->vport, query_ctx,
                                            MLX5_CAP_GENERAL_2);
index 20bb5eb..52199d3 100644 (file)
@@ -68,14 +68,19 @@ static struct thermal_zone_device_ops mlx5_thermal_ops = {
 
 int mlx5_thermal_init(struct mlx5_core_dev *mdev)
 {
+       char data[THERMAL_NAME_LENGTH];
        struct mlx5_thermal *thermal;
-       struct thermal_zone_device *tzd;
-       const char *data = "mlx5";
+       int err;
 
-       tzd = thermal_zone_get_zone_by_name(data);
-       if (!IS_ERR(tzd))
+       if (!mlx5_core_is_pf(mdev) && !mlx5_core_is_ecpf(mdev))
                return 0;
 
+       err = snprintf(data, sizeof(data), "mlx5_%s", dev_name(mdev->device));
+       if (err < 0 || err >= sizeof(data)) {
+               mlx5_core_err(mdev, "Failed to setup thermal zone name, %d\n", err);
+               return -EINVAL;
+       }
+
        thermal = kzalloc(sizeof(*thermal), GFP_KERNEL);
        if (!thermal)
                return -ENOMEM;
@@ -89,10 +94,10 @@ int mlx5_thermal_init(struct mlx5_core_dev *mdev)
                                                                 &mlx5_thermal_ops,
                                                                 NULL, 0, MLX5_THERMAL_POLL_INT_MSEC);
        if (IS_ERR(thermal->tzdev)) {
-               dev_err(mdev->device, "Failed to register thermal zone device (%s) %ld\n",
-                       data, PTR_ERR(thermal->tzdev));
+               err = PTR_ERR(thermal->tzdev);
+               mlx5_core_err(mdev, "Failed to register thermal zone device (%s) %d\n", data, err);
                kfree(thermal);
-               return -EINVAL;
+               return err;
        }
 
        mdev->thermal = thermal;
index 24c994b..329e374 100644 (file)
@@ -46,7 +46,7 @@ config LAN743X
        tristate "LAN743x support"
        depends on PCI
        depends on PTP_1588_CLOCK_OPTIONAL
-       select PHYLIB
+       select FIXED_PHY
        select CRC16
        select CRC32
        help
index 2fa833d..56ccbd4 100644 (file)
@@ -2927,7 +2927,6 @@ int ocelot_init(struct ocelot *ocelot)
 
        mutex_init(&ocelot->mact_lock);
        mutex_init(&ocelot->fwd_domain_lock);
-       mutex_init(&ocelot->tas_lock);
        spin_lock_init(&ocelot->ptp_clock_lock);
        spin_lock_init(&ocelot->ts_id_lock);
 
index fb31451..c815ae6 100644 (file)
@@ -67,10 +67,13 @@ void ocelot_port_update_active_preemptible_tcs(struct ocelot *ocelot, int port)
                val = mm->preemptible_tcs;
 
        /* Cut through switching doesn't work for preemptible priorities,
-        * so first make sure it is disabled.
+        * so first make sure it is disabled. Also, changing the preemptible
+        * TCs affects the oversized frame dropping logic, so that needs to be
+        * re-triggered. And since tas_guard_bands_update() also implicitly
+        * calls cut_through_fwd(), we don't need to explicitly call it.
         */
        mm->active_preemptible_tcs = val;
-       ocelot->ops->cut_through_fwd(ocelot);
+       ocelot->ops->tas_guard_bands_update(ocelot, port);
 
        dev_dbg(ocelot->dev,
                "port %d %s/%s, MM TX %s, preemptible TCs 0x%x, active 0x%x\n",
@@ -89,17 +92,14 @@ void ocelot_port_change_fp(struct ocelot *ocelot, int port,
 {
        struct ocelot_mm_state *mm = &ocelot->mm[port];
 
-       mutex_lock(&ocelot->fwd_domain_lock);
+       lockdep_assert_held(&ocelot->fwd_domain_lock);
 
        if (mm->preemptible_tcs == preemptible_tcs)
-               goto out_unlock;
+               return;
 
        mm->preemptible_tcs = preemptible_tcs;
 
        ocelot_port_update_active_preemptible_tcs(ocelot, port);
-
-out_unlock:
-       mutex_unlock(&ocelot->fwd_domain_lock);
 }
 
 static void ocelot_mm_update_port_status(struct ocelot *ocelot, int port)
index b8678da..ab7d217 100644 (file)
@@ -353,12 +353,6 @@ err_out_reset:
        ionic_reset(ionic);
 err_out_teardown:
        ionic_dev_teardown(ionic);
-       pci_clear_master(pdev);
-       /* Don't fail the probe for these errors, keep
-        * the hw interface around for inspection
-        */
-       return 0;
-
 err_out_unmap_bars:
        ionic_unmap_bars(ionic);
 err_out_pci_release_regions:
index 7c20a44..612b001 100644 (file)
@@ -475,11 +475,6 @@ static void ionic_qcqs_free(struct ionic_lif *lif)
 static void ionic_link_qcq_interrupts(struct ionic_qcq *src_qcq,
                                      struct ionic_qcq *n_qcq)
 {
-       if (WARN_ON(n_qcq->flags & IONIC_QCQ_F_INTR)) {
-               ionic_intr_free(n_qcq->cq.lif->ionic, n_qcq->intr.index);
-               n_qcq->flags &= ~IONIC_QCQ_F_INTR;
-       }
-
        n_qcq->intr.vector = src_qcq->intr.vector;
        n_qcq->intr.index = src_qcq->intr.index;
        n_qcq->napi_qcq = src_qcq->napi_qcq;
index 12405d7..0772eb1 100644 (file)
@@ -186,9 +186,6 @@ static int txgbe_calc_eeprom_checksum(struct wx *wx, u16 *checksum)
        if (eeprom_ptrs)
                kvfree(eeprom_ptrs);
 
-       if (*checksum > TXGBE_EEPROM_SUM)
-               return -EINVAL;
-
        *checksum = TXGBE_EEPROM_SUM - *checksum;
 
        return 0;
index 6045bec..b4d3b9c 100644 (file)
@@ -184,13 +184,10 @@ static ssize_t nsim_dev_trap_fa_cookie_write(struct file *file,
        cookie_len = (count - 1) / 2;
        if ((count - 1) % 2)
                return -EINVAL;
-       buf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN);
-       if (!buf)
-               return -ENOMEM;
 
-       ret = simple_write_to_buffer(buf, count, ppos, data, count);
-       if (ret < 0)
-               goto free_buf;
+       buf = memdup_user(data, count);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
 
        fa_cookie = kmalloc(sizeof(*fa_cookie) + cookie_len,
                            GFP_KERNEL | __GFP_NOWARN);
index 7c4cc5f..dbd13f7 100644 (file)
@@ -6157,8 +6157,11 @@ static int airo_get_rate(struct net_device *dev,
        struct iw_param *vwrq = &wrqu->bitrate;
        struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
+       int ret;
 
-       readStatusRid(local, &status_rid, 1);
+       ret = readStatusRid(local, &status_rid, 1);
+       if (ret)
+               return -EBUSY;
 
        vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000;
        /* If more than one rate, set auto */
index aa4320c..d594694 100644 (file)
@@ -84,7 +84,6 @@ const struct iwl_ht_params iwl_22000_ht_params = {
        .mac_addr_from_csr = 0x380,                                     \
        .ht_params = &iwl_22000_ht_params,                              \
        .nvm_ver = IWL_22000_NVM_VERSION,                               \
-       .trans.use_tfh = true,                                          \
        .trans.rf_id = true,                                            \
        .trans.gen2 = true,                                             \
        .nvm_type = IWL_NVM_EXT,                                        \
@@ -122,7 +121,6 @@ const struct iwl_ht_params iwl_22000_ht_params = {
 
 const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
        .mq_rx_supported = true,
-       .use_tfh = true,
        .rf_id = true,
        .gen2 = true,
        .device_family = IWL_DEVICE_FAMILY_22000,
@@ -134,7 +132,6 @@ const struct iwl_cfg_trans_params iwl_qu_trans_cfg = {
 
 const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
        .mq_rx_supported = true,
-       .use_tfh = true,
        .rf_id = true,
        .gen2 = true,
        .device_family = IWL_DEVICE_FAMILY_22000,
@@ -146,7 +143,6 @@ const struct iwl_cfg_trans_params iwl_qu_medium_latency_trans_cfg = {
 
 const struct iwl_cfg_trans_params iwl_qu_long_latency_trans_cfg = {
        .mq_rx_supported = true,
-       .use_tfh = true,
        .rf_id = true,
        .gen2 = true,
        .device_family = IWL_DEVICE_FAMILY_22000,
@@ -200,7 +196,6 @@ const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = {
        .device_family = IWL_DEVICE_FAMILY_22000,
        .base_params = &iwl_22000_base_params,
        .mq_rx_supported = true,
-       .use_tfh = true,
        .rf_id = true,
        .gen2 = true,
        .bisr_workaround = 1,
index 742096c..241a9e3 100644 (file)
@@ -256,7 +256,6 @@ enum iwl_cfg_trans_ltr_delay {
  * @xtal_latency: power up latency to get the xtal stabilized
  * @extra_phy_cfg_flags: extra configuration flags to pass to the PHY
  * @rf_id: need to read rf_id to determine the firmware image
- * @use_tfh: use TFH
  * @gen2: 22000 and on transport operation
  * @mq_rx_supported: multi-queue rx support
  * @integrated: discrete or integrated
@@ -271,7 +270,6 @@ struct iwl_cfg_trans_params {
        u32 xtal_latency;
        u32 extra_phy_cfg_flags;
        u32 rf_id:1,
-           use_tfh:1,
            gen2:1,
            mq_rx_supported:1,
            integrated:1,
index bedd78a..4e4a60d 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2005-2014, 2018-2021 Intel Corporation
+ * Copyright (C) 2005-2014, 2018-2021, 2023 Intel Corporation
  * Copyright (C) 2015-2017 Intel Deutschland GmbH
  */
 #ifndef __iwl_fh_h__
@@ -71,7 +71,7 @@
 static inline unsigned int FH_MEM_CBBC_QUEUE(struct iwl_trans *trans,
                                             unsigned int chnl)
 {
-       if (trans->trans_cfg->use_tfh) {
+       if (trans->trans_cfg->gen2) {
                WARN_ON_ONCE(chnl >= 64);
                return TFH_TFDQ_CBB_TABLE + 8 * chnl;
        }
index b1af935..4bd7594 100644 (file)
@@ -2,7 +2,7 @@
 /*
  * Copyright (C) 2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
- * Copyright (C) 2019-2021 Intel Corporation
+ * Copyright (C) 2019-2021, 2023 Intel Corporation
  */
 #include <linux/kernel.h>
 #include <linux/bsearch.h>
@@ -42,7 +42,7 @@ struct iwl_trans *iwl_trans_alloc(unsigned int priv_size,
 
        WARN_ON(!ops->wait_txq_empty && !ops->wait_tx_queues_empty);
 
-       if (trans->trans_cfg->use_tfh) {
+       if (trans->trans_cfg->gen2) {
                trans->txqs.tfd.addr_size = 64;
                trans->txqs.tfd.max_tbs = IWL_TFH_NUM_TBS;
                trans->txqs.tfd.size = sizeof(struct iwl_tfh_tfd);
@@ -101,7 +101,7 @@ int iwl_trans_init(struct iwl_trans *trans)
 
        /* Some things must not change even if the config does */
        WARN_ON(trans->txqs.tfd.addr_size !=
-               (trans->trans_cfg->use_tfh ? 64 : 36));
+               (trans->trans_cfg->gen2 ? 64 : 36));
 
        snprintf(trans->dev_cmd_pool_name, sizeof(trans->dev_cmd_pool_name),
                 "iwl_cmd_pool:%s", dev_name(trans->dev));
index b83df06..b18c91c 100644 (file)
@@ -1450,7 +1450,7 @@ static inline bool iwl_mvm_has_new_station_api(const struct iwl_fw *fw)
 static inline bool iwl_mvm_has_new_tx_api(struct iwl_mvm *mvm)
 {
        /* TODO - replace with TLV once defined */
-       return mvm->trans->trans_cfg->use_tfh;
+       return mvm->trans->trans_cfg->gen2;
 }
 
 static inline bool iwl_mvm_has_unified_ucode(struct iwl_mvm *mvm)
index eacbbdb..3e988da 100644 (file)
@@ -819,7 +819,7 @@ static int iwl_pcie_load_cpu_sections_8000(struct iwl_trans *trans,
 
        iwl_enable_interrupts(trans);
 
-       if (trans->trans_cfg->use_tfh) {
+       if (trans->trans_cfg->gen2) {
                if (cpu == 1)
                        iwl_write_prph(trans, UREG_UCODE_LOAD_STATUS,
                                       0xFFFF);
@@ -3394,7 +3394,7 @@ iwl_trans_pcie_dump_data(struct iwl_trans *trans,
                        u8 tfdidx;
                        u32 caplen, cmdlen;
 
-                       if (trans->trans_cfg->use_tfh)
+                       if (trans->trans_cfg->gen2)
                                tfdidx = idx;
                        else
                                tfdidx = ptr;
index 1337fa9..790e5b1 100644 (file)
@@ -364,7 +364,7 @@ void iwl_trans_pcie_tx_reset(struct iwl_trans *trans)
        for (txq_id = 0; txq_id < trans->trans_cfg->base_params->num_of_queues;
             txq_id++) {
                struct iwl_txq *txq = trans->txqs.txq[txq_id];
-               if (trans->trans_cfg->use_tfh)
+               if (trans->trans_cfg->gen2)
                        iwl_write_direct64(trans,
                                           FH_MEM_CBBC_QUEUE(trans, txq_id),
                                           txq->dma_addr);
index fbacbe9..5bb3cc3 100644 (file)
@@ -985,7 +985,7 @@ void iwl_txq_log_scd_error(struct iwl_trans *trans, struct iwl_txq *txq)
        bool active;
        u8 fifo;
 
-       if (trans->trans_cfg->use_tfh) {
+       if (trans->trans_cfg->gen2) {
                IWL_ERR(trans, "Queue %d is stuck %d %d\n", txq_id,
                        txq->read_ptr, txq->write_ptr);
                /* TODO: access new SCD registers and dump them */
@@ -1040,7 +1040,7 @@ int iwl_txq_alloc(struct iwl_trans *trans, struct iwl_txq *txq, int slots_num,
        if (WARN_ON(txq->entries || txq->tfds))
                return -EINVAL;
 
-       if (trans->trans_cfg->use_tfh)
+       if (trans->trans_cfg->gen2)
                tfd_sz = trans->txqs.tfd.size * slots_num;
 
        timer_setup(&txq->stuck_timer, iwl_txq_stuck_timer, 0);
@@ -1347,7 +1347,7 @@ static inline dma_addr_t iwl_txq_gen1_tfd_tb_get_addr(struct iwl_trans *trans,
        dma_addr_t addr;
        dma_addr_t hi_len;
 
-       if (trans->trans_cfg->use_tfh) {
+       if (trans->trans_cfg->gen2) {
                struct iwl_tfh_tfd *tfh_tfd = _tfd;
                struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx];
 
@@ -1408,7 +1408,7 @@ void iwl_txq_gen1_tfd_unmap(struct iwl_trans *trans,
 
        meta->tbs = 0;
 
-       if (trans->trans_cfg->use_tfh) {
+       if (trans->trans_cfg->gen2) {
                struct iwl_tfh_tfd *tfd_fh = (void *)tfd;
 
                tfd_fh->num_tbs = 0;
@@ -1625,7 +1625,7 @@ void iwl_txq_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
 
                txq->entries[read_ptr].skb = NULL;
 
-               if (!trans->trans_cfg->use_tfh)
+               if (!trans->trans_cfg->gen2)
                        iwl_txq_gen1_inval_byte_cnt_tbl(trans, txq);
 
                iwl_txq_free_tfd(trans, txq);
index eca53bf..1e4a24a 100644 (file)
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
 /*
- * Copyright (C) 2020-2022 Intel Corporation
+ * Copyright (C) 2020-2023 Intel Corporation
  */
 #ifndef __iwl_trans_queue_tx_h__
 #define __iwl_trans_queue_tx_h__
@@ -38,7 +38,7 @@ static inline void iwl_wake_queue(struct iwl_trans *trans,
 static inline void *iwl_txq_get_tfd(struct iwl_trans *trans,
                                    struct iwl_txq *txq, int idx)
 {
-       if (trans->trans_cfg->use_tfh)
+       if (trans->trans_cfg->gen2)
                idx = iwl_txq_get_cmd_index(txq, idx);
 
        return (u8 *)txq->tfds + trans->txqs.tfd.size * idx;
@@ -135,7 +135,7 @@ static inline u8 iwl_txq_gen1_tfd_get_num_tbs(struct iwl_trans *trans,
 {
        struct iwl_tfd *tfd;
 
-       if (trans->trans_cfg->use_tfh) {
+       if (trans->trans_cfg->gen2) {
                struct iwl_tfh_tfd *tfh_tfd = _tfd;
 
                return le16_to_cpu(tfh_tfd->num_tbs) & 0x1f;
@@ -151,7 +151,7 @@ static inline u16 iwl_txq_gen1_tfd_tb_get_len(struct iwl_trans *trans,
        struct iwl_tfd *tfd;
        struct iwl_tfd_tb *tb;
 
-       if (trans->trans_cfg->use_tfh) {
+       if (trans->trans_cfg->gen2) {
                struct iwl_tfh_tfd *tfh_tfd = _tfd;
                struct iwl_tfh_tb *tfh_tb = &tfh_tfd->tbs[idx];
 
index f0a80c2..4153cd6 100644 (file)
@@ -231,10 +231,6 @@ int mt7921_dma_init(struct mt7921_dev *dev)
        if (ret)
                return ret;
 
-       ret = mt7921_wfsys_reset(dev);
-       if (ret)
-               return ret;
-
        /* init tx queue */
        ret = mt76_connac_init_tx_queues(dev->phy.mt76, MT7921_TXQ_BAND0,
                                         MT7921_TX_RING_SIZE,
index c69ce6d..f55caa0 100644 (file)
@@ -476,12 +476,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
 {
        int ret;
 
-       ret = mt76_get_field(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_N9_RDY);
-       if (ret && mt76_is_mmio(&dev->mt76)) {
-               dev_dbg(dev->mt76.dev, "Firmware is already download\n");
-               goto fw_loaded;
-       }
-
        ret = mt76_connac2_load_patch(&dev->mt76, mt7921_patch_name(dev));
        if (ret)
                return ret;
@@ -504,8 +498,6 @@ static int mt7921_load_firmware(struct mt7921_dev *dev)
                return -EIO;
        }
 
-fw_loaded:
-
 #ifdef CONFIG_PM
        dev->mt76.hw->wiphy->wowlan = &mt76_connac_wowlan_support;
 #endif /* CONFIG_PM */
index ddb1fa4..95610a1 100644 (file)
@@ -325,6 +325,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
        bus_ops->rmw = mt7921_rmw;
        dev->mt76.bus = bus_ops;
 
+       ret = mt7921e_mcu_fw_pmctrl(dev);
+       if (ret)
+               goto err_free_dev;
+
        ret = __mt7921e_mcu_drv_pmctrl(dev);
        if (ret)
                goto err_free_dev;
@@ -333,6 +337,10 @@ static int mt7921_pci_probe(struct pci_dev *pdev,
                    (mt7921_l1_rr(dev, MT_HW_REV) & 0xff);
        dev_info(mdev->dev, "ASIC revision: %04x\n", mdev->rev);
 
+       ret = mt7921_wfsys_reset(dev);
+       if (ret)
+               goto err_free_dev;
+
        mt76_wr(dev, MT_WFDMA0_HOST_INT_ENA, 0);
 
        mt76_wr(dev, MT_PCIE_MAC_INT_ENABLE, 0xff);
index 1db2d59..a4bbac9 100644 (file)
@@ -3026,17 +3026,18 @@ static ssize_t rtw89_debug_priv_send_h2c_set(struct file *filp,
        struct rtw89_debugfs_priv *debugfs_priv = filp->private_data;
        struct rtw89_dev *rtwdev = debugfs_priv->rtwdev;
        u8 *h2c;
+       int ret;
        u16 h2c_len = count / 2;
 
        h2c = rtw89_hex2bin_user(rtwdev, user_buf, count);
        if (IS_ERR(h2c))
                return -EFAULT;
 
-       rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len);
+       ret = rtw89_fw_h2c_raw(rtwdev, h2c, h2c_len);
 
        kfree(h2c);
 
-       return count;
+       return ret ? ret : count;
 }
 
 static int
index 47d7ba2..37b6fa7 100644 (file)
@@ -3431,10 +3431,40 @@ static int nvme_init_ns_head(struct nvme_ns *ns, struct nvme_ns_info *info)
 
        ret = nvme_global_check_duplicate_ids(ctrl->subsys, &info->ids);
        if (ret) {
-               dev_err(ctrl->device,
-                       "globally duplicate IDs for nsid %d\n", info->nsid);
+               /*
+                * We've found two different namespaces on two different
+                * subsystems that report the same ID.  This is pretty nasty
+                * for anything that actually requires unique device
+                * identification.  In the kernel we need this for multipathing,
+                * and in user space the /dev/disk/by-id/ links rely on it.
+                *
+                * If the device also claims to be multi-path capable back off
+                * here now and refuse the probe the second device as this is a
+                * recipe for data corruption.  If not this is probably a
+                * cheap consumer device if on the PCIe bus, so let the user
+                * proceed and use the shiny toy, but warn that with changing
+                * probing order (which due to our async probing could just be
+                * device taking longer to startup) the other device could show
+                * up at any time.
+                */
                nvme_print_device_info(ctrl);
-               return ret;
+               if ((ns->ctrl->ops->flags & NVME_F_FABRICS) || /* !PCIe */
+                   ((ns->ctrl->subsys->cmic & NVME_CTRL_CMIC_MULTI_CTRL) &&
+                    info->is_shared)) {
+                       dev_err(ctrl->device,
+                               "ignoring nsid %d because of duplicate IDs\n",
+                               info->nsid);
+                       return ret;
+               }
+
+               dev_err(ctrl->device,
+                       "clearing duplicate IDs for nsid %d\n", info->nsid);
+               dev_err(ctrl->device,
+                       "use of /dev/disk/by-id/ may cause data corruption\n");
+               memset(&info->ids.nguid, 0, sizeof(info->ids.nguid));
+               memset(&info->ids.uuid, 0, sizeof(info->ids.uuid));
+               memset(&info->ids.eui64, 0, sizeof(info->ids.eui64));
+               ctrl->quirks |= NVME_QUIRK_BOGUS_NID;
        }
 
        mutex_lock(&ctrl->subsys->lock);
index 83d2e68..1ba10a5 100644 (file)
@@ -27,7 +27,7 @@ void nvme_fault_inject_init(struct nvme_fault_inject *fault_inj,
 
        /* create debugfs directory and attribute */
        parent = debugfs_create_dir(dev_name, NULL);
-       if (!parent) {
+       if (IS_ERR(parent)) {
                pr_warn("%s: failed to create debugfs directory\n", dev_name);
                return;
        }
index 691f2df..1cd2bf8 100644 (file)
@@ -2548,14 +2548,24 @@ nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)
         * the controller.  Abort any ios on the association and let the
         * create_association error path resolve things.
         */
-       if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) {
-               __nvme_fc_abort_outstanding_ios(ctrl, true);
+       enum nvme_ctrl_state state;
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctrl->lock, flags);
+       state = ctrl->ctrl.state;
+       if (state == NVME_CTRL_CONNECTING) {
                set_bit(ASSOC_FAILED, &ctrl->flags);
+               spin_unlock_irqrestore(&ctrl->lock, flags);
+               __nvme_fc_abort_outstanding_ios(ctrl, true);
+               dev_warn(ctrl->ctrl.device,
+                       "NVME-FC{%d}: transport error during (re)connect\n",
+                       ctrl->cnum);
                return;
        }
+       spin_unlock_irqrestore(&ctrl->lock, flags);
 
        /* Otherwise, only proceed if in LIVE state - e.g. on first error */
-       if (ctrl->ctrl.state != NVME_CTRL_LIVE)
+       if (state != NVME_CTRL_LIVE)
                return;
 
        dev_warn(ctrl->ctrl.device,
@@ -3110,7 +3120,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
         */
 
        ret = nvme_enable_ctrl(&ctrl->ctrl);
-       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
+       if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
+               ret = -EIO;
+       if (ret)
                goto out_disconnect_admin_queue;
 
        ctrl->ctrl.max_segments = ctrl->lport->ops->max_sgl_segments;
@@ -3120,7 +3132,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        nvme_unquiesce_admin_queue(&ctrl->ctrl);
 
        ret = nvme_init_ctrl_finish(&ctrl->ctrl, false);
-       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
+       if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
+               ret = -EIO;
+       if (ret)
                goto out_disconnect_admin_queue;
 
        /* sanity checks */
@@ -3165,10 +3179,16 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
                else
                        ret = nvme_fc_recreate_io_queues(ctrl);
        }
-       if (ret || test_bit(ASSOC_FAILED, &ctrl->flags))
-               goto out_term_aen_ops;
 
+       spin_lock_irqsave(&ctrl->lock, flags);
+       if (!ret && test_bit(ASSOC_FAILED, &ctrl->flags))
+               ret = -EIO;
+       if (ret) {
+               spin_unlock_irqrestore(&ctrl->lock, flags);
+               goto out_term_aen_ops;
+       }
        changed = nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_LIVE);
+       spin_unlock_irqrestore(&ctrl->lock, flags);
 
        ctrl->ctrl.nr_reconnects = 0;
 
@@ -3180,6 +3200,9 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
 out_term_aen_ops:
        nvme_fc_term_aen_ops(ctrl);
 out_disconnect_admin_queue:
+       dev_warn(ctrl->ctrl.device,
+               "NVME-FC{%d}: create_assoc failed, assoc_id %llx ret %d\n",
+               ctrl->cnum, ctrl->association_id, ret);
        /* send a Disconnect(association) LS to fc-nvme target */
        nvme_fc_xmt_disconnect_assoc(ctrl);
        spin_lock_irqsave(&ctrl->lock, flags);
index 7272572..baf69af 100644 (file)
@@ -967,7 +967,7 @@ static __always_inline void nvme_pci_unmap_rq(struct request *req)
                struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
 
                dma_unmap_page(dev->dev, iod->meta_dma,
-                              rq_integrity_vec(req)->bv_len, rq_data_dir(req));
+                              rq_integrity_vec(req)->bv_len, rq_dma_dir(req));
        }
 
        if (blk_rq_nr_phys_segments(req))
@@ -1298,9 +1298,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
         */
        if (nvme_should_reset(dev, csts)) {
                nvme_warn_reset(dev, csts);
-               nvme_dev_disable(dev, false);
-               nvme_reset_ctrl(&dev->ctrl);
-               return BLK_EH_DONE;
+               goto disable;
        }
 
        /*
@@ -1351,10 +1349,7 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
                         "I/O %d QID %d timeout, reset controller\n",
                         req->tag, nvmeq->qid);
                nvme_req(req)->flags |= NVME_REQ_CANCELLED;
-               nvme_dev_disable(dev, false);
-               nvme_reset_ctrl(&dev->ctrl);
-
-               return BLK_EH_DONE;
+               goto disable;
        }
 
        if (atomic_dec_return(&dev->ctrl.abort_limit) < 0) {
@@ -1391,6 +1386,15 @@ static enum blk_eh_timer_return nvme_timeout(struct request *req)
         * as the device then is in a faulty state.
         */
        return BLK_EH_RESET_TIMER;
+
+disable:
+       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING))
+               return BLK_EH_DONE;
+
+       nvme_dev_disable(dev, false);
+       if (nvme_try_sched_reset(&dev->ctrl))
+               nvme_unquiesce_io_queues(&dev->ctrl);
+       return BLK_EH_DONE;
 }
 
 static void nvme_free_queue(struct nvme_queue *nvmeq)
@@ -3278,6 +3282,10 @@ static pci_ers_result_t nvme_error_detected(struct pci_dev *pdev,
        case pci_channel_io_frozen:
                dev_warn(dev->ctrl.device,
                        "frozen state error detected, reset controller\n");
+               if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_RESETTING)) {
+                       nvme_dev_disable(dev, true);
+                       return PCI_ERS_RESULT_DISCONNECT;
+               }
                nvme_dev_disable(dev, false);
                return PCI_ERS_RESULT_NEED_RESET;
        case pci_channel_io_perm_failure:
@@ -3294,7 +3302,8 @@ static pci_ers_result_t nvme_slot_reset(struct pci_dev *pdev)
 
        dev_info(dev->ctrl.device, "restart after slot reset\n");
        pci_restore_state(pdev);
-       nvme_reset_ctrl(&dev->ctrl);
+       if (!nvme_try_sched_reset(&dev->ctrl))
+               nvme_unquiesce_io_queues(&dev->ctrl);
        return PCI_ERS_RESULT_RECOVERED;
 }
 
@@ -3396,6 +3405,8 @@ static const struct pci_device_id nvme_id_table[] = {
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x144d, 0xa809),   /* Samsung MZALQ256HBJD 256G */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
+       { PCI_DEVICE(0x144d, 0xa802),   /* Samsung SM953 */
+               .driver_data = NVME_QUIRK_BOGUS_NID, },
        { PCI_DEVICE(0x1cc4, 0x6303),   /* UMIS RPJTJ512MGE1QDY 512G */
                .driver_data = NVME_QUIRK_DISABLE_WRITE_ZEROES, },
        { PCI_DEVICE(0x1cc4, 0x6302),   /* UMIS RPJTJ256MGE1QDY 256G */
index 45e9181..212e1b0 100644 (file)
@@ -92,7 +92,7 @@ static ssize_t uuid_show(struct device *dev, struct device_attribute *attr,
         * we have no UUID set
         */
        if (uuid_is_null(&ids->uuid)) {
-               dev_warn_ratelimited(dev,
+               dev_warn_once(dev,
                        "No UUID available providing old NGUID\n");
                return sysfs_emit(buf, "%pU\n", ids->nguid);
        }
index 12316ab..ec85578 100644 (file)
 int nvme_revalidate_zones(struct nvme_ns *ns)
 {
        struct request_queue *q = ns->queue;
-       int ret;
 
-       ret = blk_revalidate_disk_zones(ns->disk, NULL);
-       if (!ret)
-               blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append);
-       return ret;
+       blk_queue_chunk_sectors(q, ns->zsze);
+       blk_queue_max_zone_append_sectors(q, ns->ctrl->max_zone_append);
+
+       return blk_revalidate_disk_zones(ns->disk, NULL);
 }
 
 static int nvme_set_max_append(struct nvme_ctrl *ctrl)
index f2d24b2..48d5df0 100644 (file)
@@ -373,7 +373,7 @@ static int nvme_loop_configure_admin_queue(struct nvme_loop_ctrl *ctrl)
                goto out_cleanup_tagset;
 
        ctrl->ctrl.max_hw_sectors =
-               (NVME_LOOP_MAX_SEGMENTS - 1) << (PAGE_SHIFT - 9);
+               (NVME_LOOP_MAX_SEGMENTS - 1) << PAGE_SECTORS_SHIFT;
 
        nvme_unquiesce_admin_queue(&ctrl->ctrl);
 
index 71a9c1c..9fe07d7 100644 (file)
@@ -102,14 +102,14 @@ static u16 nvmet_passthru_override_id_ctrl(struct nvmet_req *req)
         * which depends on the host's memory fragementation. To solve this,
         * ensure mdts is limited to the pages equal to the number of segments.
         */
-       max_hw_sectors = min_not_zero(pctrl->max_segments << (PAGE_SHIFT - 9),
+       max_hw_sectors = min_not_zero(pctrl->max_segments << PAGE_SECTORS_SHIFT,
                                      pctrl->max_hw_sectors);
 
        /*
         * nvmet_passthru_map_sg is limitted to using a single bio so limit
         * the mdts based on BIO_MAX_VECS as well
         */
-       max_hw_sectors = min_not_zero(BIO_MAX_VECS << (PAGE_SHIFT - 9),
+       max_hw_sectors = min_not_zero(BIO_MAX_VECS << PAGE_SECTORS_SHIFT,
                                      max_hw_sectors);
 
        page_shift = NVME_CAP_MPSMIN(ctrl->cap) + 12;
index ebca5ea..56897d4 100644 (file)
@@ -181,9 +181,6 @@ void riscv_pmu_start(struct perf_event *event, int flags)
        uint64_t max_period = riscv_pmu_ctr_get_width_mask(event);
        u64 init_val;
 
-       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
-               return;
-
        if (flags & PERF_EF_RELOAD)
                WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE));
 
index 3c4220b..4a8c1b5 100644 (file)
@@ -116,21 +116,19 @@ static void amd_gpio_set_value(struct gpio_chip *gc, unsigned offset, int value)
        raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 }
 
-static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
-               unsigned debounce)
+static int amd_gpio_set_debounce(struct amd_gpio *gpio_dev, unsigned int offset,
+                                unsigned int debounce)
 {
        u32 time;
        u32 pin_reg;
        int ret = 0;
-       unsigned long flags;
-       struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
-
-       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
 
        /* Use special handling for Pin0 debounce */
-       pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
-       if (pin_reg & INTERNAL_GPIO0_DEBOUNCE)
-               debounce = 0;
+       if (offset == 0) {
+               pin_reg = readl(gpio_dev->base + WAKE_INT_MASTER_REG);
+               if (pin_reg & INTERNAL_GPIO0_DEBOUNCE)
+                       debounce = 0;
+       }
 
        pin_reg = readl(gpio_dev->base + offset * 4);
 
@@ -182,23 +180,10 @@ static int amd_gpio_set_debounce(struct gpio_chip *gc, unsigned offset,
                pin_reg &= ~(DB_CNTRl_MASK << DB_CNTRL_OFF);
        }
        writel(pin_reg, gpio_dev->base + offset * 4);
-       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
        return ret;
 }
 
-static int amd_gpio_set_config(struct gpio_chip *gc, unsigned offset,
-                              unsigned long config)
-{
-       u32 debounce;
-
-       if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
-               return -ENOTSUPP;
-
-       debounce = pinconf_to_config_argument(config);
-       return amd_gpio_set_debounce(gc, offset, debounce);
-}
-
 #ifdef CONFIG_DEBUG_FS
 static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
 {
@@ -220,7 +205,6 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
        char *pin_sts;
        char *interrupt_sts;
        char *wake_sts;
-       char *pull_up_sel;
        char *orientation;
        char debounce_value[40];
        char *debounce_enable;
@@ -328,14 +312,9 @@ static void amd_gpio_dbg_show(struct seq_file *s, struct gpio_chip *gc)
                        seq_printf(s, "   %s|", wake_sts);
 
                        if (pin_reg & BIT(PULL_UP_ENABLE_OFF)) {
-                               if (pin_reg & BIT(PULL_UP_SEL_OFF))
-                                       pull_up_sel = "8k";
-                               else
-                                       pull_up_sel = "4k";
-                               seq_printf(s, "%s â†‘|",
-                                          pull_up_sel);
+                               seq_puts(s, "  â†‘ |");
                        } else if (pin_reg & BIT(PULL_DOWN_ENABLE_OFF)) {
-                               seq_puts(s, "   â†“|");
+                               seq_puts(s, "  â†“ |");
                        } else  {
                                seq_puts(s, "    |");
                        }
@@ -761,7 +740,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev,
                break;
 
        case PIN_CONFIG_BIAS_PULL_UP:
-               arg = (pin_reg >> PULL_UP_SEL_OFF) & (BIT(0) | BIT(1));
+               arg = (pin_reg >> PULL_UP_ENABLE_OFF) & BIT(0);
                break;
 
        case PIN_CONFIG_DRIVE_STRENGTH:
@@ -780,7 +759,7 @@ static int amd_pinconf_get(struct pinctrl_dev *pctldev,
 }
 
 static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
-                               unsigned long *configs, unsigned num_configs)
+                          unsigned long *configs, unsigned int num_configs)
 {
        int i;
        u32 arg;
@@ -798,9 +777,8 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
 
                switch (param) {
                case PIN_CONFIG_INPUT_DEBOUNCE:
-                       pin_reg &= ~DB_TMR_OUT_MASK;
-                       pin_reg |= arg & DB_TMR_OUT_MASK;
-                       break;
+                       ret = amd_gpio_set_debounce(gpio_dev, pin, arg);
+                       goto out_unlock;
 
                case PIN_CONFIG_BIAS_PULL_DOWN:
                        pin_reg &= ~BIT(PULL_DOWN_ENABLE_OFF);
@@ -808,10 +786,8 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
                        break;
 
                case PIN_CONFIG_BIAS_PULL_UP:
-                       pin_reg &= ~BIT(PULL_UP_SEL_OFF);
-                       pin_reg |= (arg & BIT(0)) << PULL_UP_SEL_OFF;
                        pin_reg &= ~BIT(PULL_UP_ENABLE_OFF);
-                       pin_reg |= ((arg>>1) & BIT(0)) << PULL_UP_ENABLE_OFF;
+                       pin_reg |= (arg & BIT(0)) << PULL_UP_ENABLE_OFF;
                        break;
 
                case PIN_CONFIG_DRIVE_STRENGTH:
@@ -829,6 +805,7 @@ static int amd_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
 
                writel(pin_reg, gpio_dev->base + pin*4);
        }
+out_unlock:
        raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
 
        return ret;
@@ -870,6 +847,14 @@ static int amd_pinconf_group_set(struct pinctrl_dev *pctldev,
        return 0;
 }
 
+static int amd_gpio_set_config(struct gpio_chip *gc, unsigned int pin,
+                              unsigned long config)
+{
+       struct amd_gpio *gpio_dev = gpiochip_get_data(gc);
+
+       return amd_pinconf_set(gpio_dev->pctrl, pin, &config, 1);
+}
+
 static const struct pinconf_ops amd_pinconf_ops = {
        .pin_config_get         = amd_pinconf_get,
        .pin_config_set         = amd_pinconf_set,
index 1cf2d06..34c5c3e 100644 (file)
@@ -36,7 +36,6 @@
 #define WAKE_CNTRL_OFF_S4               15
 #define PIN_STS_OFF                    16
 #define DRV_STRENGTH_SEL_OFF           17
-#define PULL_UP_SEL_OFF                        19
 #define PULL_UP_ENABLE_OFF             20
 #define PULL_DOWN_ENABLE_OFF           21
 #define OUTPUT_VALUE_OFF               22
index 9511d92..b53d261 100644 (file)
@@ -249,6 +249,7 @@ static int rzg2l_map_add_config(struct pinctrl_map *map,
 
 static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
                                   struct device_node *np,
+                                  struct device_node *parent,
                                   struct pinctrl_map **map,
                                   unsigned int *num_maps,
                                   unsigned int *index)
@@ -266,6 +267,7 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
        struct property *prop;
        int ret, gsel, fsel;
        const char **pin_fn;
+       const char *name;
        const char *pin;
 
        pinmux = of_find_property(np, "pinmux", NULL);
@@ -349,8 +351,19 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
                psel_val[i] = MUX_FUNC(value);
        }
 
+       if (parent) {
+               name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn",
+                                     parent, np);
+               if (!name) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+       } else {
+               name = np->name;
+       }
+
        /* Register a single pin group listing all the pins we read from DT */
-       gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL);
+       gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL);
        if (gsel < 0) {
                ret = gsel;
                goto done;
@@ -360,17 +373,16 @@ static int rzg2l_dt_subnode_to_map(struct pinctrl_dev *pctldev,
         * Register a single group function where the 'data' is an array PSEL
         * register values read from DT.
         */
-       pin_fn[0] = np->name;
-       fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1,
-                                          psel_val);
+       pin_fn[0] = name;
+       fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val);
        if (fsel < 0) {
                ret = fsel;
                goto remove_group;
        }
 
        maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
-       maps[idx].data.mux.group = np->name;
-       maps[idx].data.mux.function = np->name;
+       maps[idx].data.mux.group = name;
+       maps[idx].data.mux.function = name;
        idx++;
 
        dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
@@ -417,7 +429,7 @@ static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev,
        index = 0;
 
        for_each_child_of_node(np, child) {
-               ret = rzg2l_dt_subnode_to_map(pctldev, child, map,
+               ret = rzg2l_dt_subnode_to_map(pctldev, child, np, map,
                                              num_maps, &index);
                if (ret < 0) {
                        of_node_put(child);
@@ -426,7 +438,7 @@ static int rzg2l_dt_node_to_map(struct pinctrl_dev *pctldev,
        }
 
        if (*num_maps == 0) {
-               ret = rzg2l_dt_subnode_to_map(pctldev, np, map,
+               ret = rzg2l_dt_subnode_to_map(pctldev, np, NULL, map,
                                              num_maps, &index);
                if (ret < 0)
                        goto done;
index e547229..35b23c1 100644 (file)
@@ -209,6 +209,7 @@ static int rzv2m_map_add_config(struct pinctrl_map *map,
 
 static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
                                   struct device_node *np,
+                                  struct device_node *parent,
                                   struct pinctrl_map **map,
                                   unsigned int *num_maps,
                                   unsigned int *index)
@@ -226,6 +227,7 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
        struct property *prop;
        int ret, gsel, fsel;
        const char **pin_fn;
+       const char *name;
        const char *pin;
 
        pinmux = of_find_property(np, "pinmux", NULL);
@@ -309,8 +311,19 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
                psel_val[i] = MUX_FUNC(value);
        }
 
+       if (parent) {
+               name = devm_kasprintf(pctrl->dev, GFP_KERNEL, "%pOFn.%pOFn",
+                                     parent, np);
+               if (!name) {
+                       ret = -ENOMEM;
+                       goto done;
+               }
+       } else {
+               name = np->name;
+       }
+
        /* Register a single pin group listing all the pins we read from DT */
-       gsel = pinctrl_generic_add_group(pctldev, np->name, pins, num_pinmux, NULL);
+       gsel = pinctrl_generic_add_group(pctldev, name, pins, num_pinmux, NULL);
        if (gsel < 0) {
                ret = gsel;
                goto done;
@@ -320,17 +333,16 @@ static int rzv2m_dt_subnode_to_map(struct pinctrl_dev *pctldev,
         * Register a single group function where the 'data' is an array PSEL
         * register values read from DT.
         */
-       pin_fn[0] = np->name;
-       fsel = pinmux_generic_add_function(pctldev, np->name, pin_fn, 1,
-                                          psel_val);
+       pin_fn[0] = name;
+       fsel = pinmux_generic_add_function(pctldev, name, pin_fn, 1, psel_val);
        if (fsel < 0) {
                ret = fsel;
                goto remove_group;
        }
 
        maps[idx].type = PIN_MAP_TYPE_MUX_GROUP;
-       maps[idx].data.mux.group = np->name;
-       maps[idx].data.mux.function = np->name;
+       maps[idx].data.mux.group = name;
+       maps[idx].data.mux.function = name;
        idx++;
 
        dev_dbg(pctrl->dev, "Parsed %pOF with %d pins\n", np, num_pinmux);
@@ -377,7 +389,7 @@ static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev,
        index = 0;
 
        for_each_child_of_node(np, child) {
-               ret = rzv2m_dt_subnode_to_map(pctldev, child, map,
+               ret = rzv2m_dt_subnode_to_map(pctldev, child, np, map,
                                              num_maps, &index);
                if (ret < 0) {
                        of_node_put(child);
@@ -386,7 +398,7 @@ static int rzv2m_dt_node_to_map(struct pinctrl_dev *pctldev,
        }
 
        if (*num_maps == 0) {
-               ret = rzv2m_dt_subnode_to_map(pctldev, np, map,
+               ret = rzv2m_dt_subnode_to_map(pctldev, np, NULL, map,
                                              num_maps, &index);
                if (ret < 0)
                        goto done;
index 2c22919..65732f0 100644 (file)
@@ -4,7 +4,7 @@
 # AMD x86 Platform-Specific Drivers
 #
 
-amd-pmc-y                      := pmc.o
+amd-pmc-y                      := pmc.o pmc-quirks.o
 obj-$(CONFIG_AMD_PMC)          += amd-pmc.o
 amd_hsmp-y                     := hsmp.o
 obj-$(CONFIG_AMD_HSMP)         += amd_hsmp.o
diff --git a/drivers/platform/x86/amd/pmc-quirks.c b/drivers/platform/x86/amd/pmc-quirks.c
new file mode 100644 (file)
index 0000000..362e7c0
--- /dev/null
@@ -0,0 +1,176 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD SoC Power Management Controller Driver Quirks
+ *
+ * Copyright (c) 2023, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Mario Limonciello <mario.limonciello@amd.com>
+ */
+
+#include <linux/dmi.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+
+#include "pmc.h"
+
+struct quirk_entry {
+       u32 s2idle_bug_mmio;
+};
+
+static struct quirk_entry quirk_s2idle_bug = {
+       .s2idle_bug_mmio = 0xfed80380,
+};
+
+static const struct dmi_system_id fwbug_list[] = {
+       {
+               .ident = "L14 Gen2 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
+               }
+       },
+       {
+               .ident = "T14s Gen2 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
+               }
+       },
+       {
+               .ident = "X13 Gen2 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
+               }
+       },
+       {
+               .ident = "T14 Gen2 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
+               }
+       },
+       {
+               .ident = "T14 Gen1 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
+               }
+       },
+       {
+               .ident = "T14 Gen1 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
+               }
+       },
+       {
+               .ident = "T14s Gen1 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
+               }
+       },
+       {
+               .ident = "T14s Gen1 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
+               }
+       },
+       {
+               .ident = "P14s Gen1 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
+               }
+       },
+       {
+               .ident = "P14s Gen2 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
+               }
+       },
+       {
+               .ident = "P14s Gen2 AMD",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
+               }
+       },
+       /* https://gitlab.freedesktop.org/drm/amd/-/issues/2684 */
+       {
+               .ident = "HP Laptop 15s-eq2xxx",
+               .driver_data = &quirk_s2idle_bug,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "HP"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "HP Laptop 15s-eq2xxx"),
+               }
+       },
+       {}
+};
+
+/*
+ * Laptops that run a SMI handler during the D3->D0 transition that occurs
+ * specifically when exiting suspend to idle which can cause
+ * large delays during resume when the IOMMU translation layer is enabled (the default
+ * behavior) for NVME devices:
+ *
+ * To avoid this firmware problem, skip the SMI handler on these machines before the
+ * D0 transition occurs.
+ */
+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)
+               return;
+
+       addr = ioremap(s2idle_bug_mmio, 1);
+       if (!addr)
+               goto cleanup_resource;
+
+       val = ioread8(addr);
+       iowrite8(val & ~BIT(0), addr);
+
+       iounmap(addr);
+cleanup_resource:
+       release_resource(res);
+       kfree(res);
+}
+
+void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev)
+{
+       if (dev->quirks && dev->quirks->s2idle_bug_mmio)
+               amd_pmc_skip_nvme_smi_handler(dev->quirks->s2idle_bug_mmio);
+}
+
+void amd_pmc_quirks_init(struct amd_pmc_dev *dev)
+{
+       const struct dmi_system_id *dmi_id;
+
+       dmi_id = dmi_first_match(fwbug_list);
+       if (!dmi_id)
+               return;
+       dev->quirks = dmi_id->driver_data;
+       if (dev->quirks->s2idle_bug_mmio)
+               pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
+                       dmi_id->ident);
+}
index 7d3d080..c1e788b 100644 (file)
@@ -28,6 +28,8 @@
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
 
+#include "pmc.h"
+
 /* SMU communication registers */
 #define AMD_PMC_REGISTER_MESSAGE       0x538
 #define AMD_PMC_REGISTER_RESPONSE      0x980
@@ -94,6 +96,7 @@
 #define AMD_CPU_ID_CB                  0x14D8
 #define AMD_CPU_ID_PS                  0x14E8
 #define AMD_CPU_ID_SP                  0x14A4
+#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT 0x1507
 
 #define PMC_MSG_DELAY_MIN_US           50
 #define RESPONSE_REGISTER_LOOP_MAX     20000
@@ -146,29 +149,6 @@ static const struct amd_pmc_bit_map soc15_ip_blk[] = {
        {}
 };
 
-struct amd_pmc_dev {
-       void __iomem *regbase;
-       void __iomem *smu_virt_addr;
-       void __iomem *stb_virt_addr;
-       void __iomem *fch_virt_addr;
-       bool msg_port;
-       u32 base_addr;
-       u32 cpu_id;
-       u32 active_ips;
-       u32 dram_size;
-       u32 num_ips;
-       u32 s2d_msg_id;
-/* SMU version information */
-       u8 smu_program;
-       u8 major;
-       u8 minor;
-       u8 rev;
-       struct device *dev;
-       struct pci_dev *rdev;
-       struct mutex lock; /* generic mutex lock */
-       struct dentry *dbgfs_dir;
-};
-
 static bool enable_stb;
 module_param(enable_stb, bool, 0644);
 MODULE_PARM_DESC(enable_stb, "Enable the STB debug mechanism");
@@ -891,6 +871,8 @@ static void amd_pmc_s2idle_restore(void)
 
        /* Notify on failed entry */
        amd_pmc_validate_deepest(pdev);
+
+       amd_pmc_process_restore_quirks(pdev);
 }
 
 static struct acpi_s2idle_dev_ops amd_pmc_s2idle_dev_ops = {
@@ -926,6 +908,7 @@ static const struct pci_device_id pmc_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PCO) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RV) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_SP) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
        { }
 };
 
@@ -1087,6 +1070,8 @@ static int amd_pmc_probe(struct platform_device *pdev)
                err = acpi_register_lps0_dev(&amd_pmc_s2idle_dev_ops);
                if (err)
                        dev_warn(dev->dev, "failed to register LPS0 sleep handler, expect increased power consumption\n");
+               if (!disable_workarounds)
+                       amd_pmc_quirks_init(dev);
        }
 
        amd_pmc_dbgfs_register(dev);
@@ -1115,6 +1100,7 @@ static const struct acpi_device_id amd_pmc_acpi_ids[] = {
        {"AMDI0007", 0},
        {"AMDI0008", 0},
        {"AMDI0009", 0},
+       {"AMDI000A", 0},
        {"AMD0004", 0},
        {"AMD0005", 0},
        { }
diff --git a/drivers/platform/x86/amd/pmc.h b/drivers/platform/x86/amd/pmc.h
new file mode 100644 (file)
index 0000000..c27bd6a
--- /dev/null
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * AMD SoC Power Management Controller Driver
+ *
+ * Copyright (c) 2023, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Mario Limonciello <mario.limonciello@amd.com>
+ */
+
+#ifndef PMC_H
+#define PMC_H
+
+#include <linux/types.h>
+#include <linux/mutex.h>
+
+struct amd_pmc_dev {
+       void __iomem *regbase;
+       void __iomem *smu_virt_addr;
+       void __iomem *stb_virt_addr;
+       void __iomem *fch_virt_addr;
+       bool msg_port;
+       u32 base_addr;
+       u32 cpu_id;
+       u32 active_ips;
+       u32 dram_size;
+       u32 num_ips;
+       u32 s2d_msg_id;
+/* SMU version information */
+       u8 smu_program;
+       u8 major;
+       u8 minor;
+       u8 rev;
+       struct device *dev;
+       struct pci_dev *rdev;
+       struct mutex lock; /* generic mutex lock */
+       struct dentry *dbgfs_dir;
+       struct quirk_entry *quirks;
+};
+
+void amd_pmc_process_restore_quirks(struct amd_pmc_dev *dev);
+void amd_pmc_quirks_init(struct amd_pmc_dev *dev);
+
+#endif /* PMC_H */
index 7780705..d873255 100644 (file)
@@ -40,6 +40,7 @@
 /* List of supported CPU ids */
 #define AMD_CPU_ID_RMB                 0x14b5
 #define AMD_CPU_ID_PS                  0x14e8
+#define PCI_DEVICE_ID_AMD_1AH_M20H_ROOT        0x1507
 
 #define PMF_MSG_DELAY_MIN_US           50
 #define RESPONSE_REGISTER_LOOP_MAX     20000
@@ -242,6 +243,7 @@ out_unlock:
 static const struct pci_device_id pmf_pci_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_RMB) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_CPU_ID_PS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_1AH_M20H_ROOT) },
        { }
 };
 
@@ -333,6 +335,7 @@ static void amd_pmf_deinit_features(struct amd_pmf_dev *dev)
 static const struct acpi_device_id amd_pmf_acpi_ids[] = {
        {"AMDI0100", 0x100},
        {"AMDI0102", 0},
+       {"AMDI0103", 0},
        { }
 };
 MODULE_DEVICE_TABLE(acpi, amd_pmf_acpi_ids);
index 2750dee..db1e924 100644 (file)
@@ -616,7 +616,8 @@ static int dell_wmi_ddv_hwmon_add(struct dell_wmi_ddv_data *data)
        }
 
        if (index < 2) {
-               ret = -ENODEV;
+               /* Finding no available sensors is not an error */
+               ret = 0;
 
                goto err_release;
        }
@@ -841,13 +842,13 @@ static int dell_wmi_ddv_probe(struct wmi_device *wdev, const void *context)
 
        if (IS_REACHABLE(CONFIG_ACPI_BATTERY)) {
                ret = dell_wmi_ddv_battery_add(data);
-               if (ret < 0 && ret != -ENODEV)
+               if (ret < 0)
                        dev_warn(&wdev->dev, "Unable to register ACPI battery hook: %d\n", ret);
        }
 
        if (IS_REACHABLE(CONFIG_HWMON)) {
                ret = dell_wmi_ddv_hwmon_add(data);
-               if (ret < 0 && ret != -ENODEV)
+               if (ret < 0)
                        dev_warn(&wdev->dev, "Unable to register hwmon interface: %d\n", ret);
        }
 
index 61aeca8..ef4b314 100644 (file)
@@ -260,7 +260,7 @@ static_assert(ARRAY_SIZE(skl_int3472_regulator_map_supplies) ==
  * This DMI table contains the name of the second sensor. This is used to add
  * entries for the second sensor to the supply_map.
  */
-const struct dmi_system_id skl_int3472_regulator_second_sensor[] = {
+static const struct dmi_system_id skl_int3472_regulator_second_sensor[] = {
        {
                /* Lenovo Miix 510-12IKB */
                .matches = {
index 9c606ee..d1fd6e6 100644 (file)
@@ -356,9 +356,7 @@ static int intel_vsec_tpmi_init(struct auxiliary_device *auxdev)
                if (!pfs_start)
                        pfs_start = res_start;
 
-               pfs->pfs_header.cap_offset *= TPMI_CAP_OFFSET_UNIT;
-
-               pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset;
+               pfs->vsec_offset = pfs_start + pfs->pfs_header.cap_offset * TPMI_CAP_OFFSET_UNIT;
 
                /*
                 * Process TPMI_INFO to get PCI device to CPU package ID.
index 187018f..ad46041 100644 (file)
@@ -315,17 +315,12 @@ struct ibm_init_struct {
 /* DMI Quirks */
 struct quirk_entry {
        bool btusb_bug;
-       u32 s2idle_bug_mmio;
 };
 
 static struct quirk_entry quirk_btusb_bug = {
        .btusb_bug = true,
 };
 
-static struct quirk_entry quirk_s2idle_bug = {
-       .s2idle_bug_mmio = 0xfed80380,
-};
-
 static struct {
        u32 bluetooth:1;
        u32 hotkey:1;
@@ -4422,136 +4417,9 @@ static const struct dmi_system_id fwbug_list[] __initconst = {
                        DMI_MATCH(DMI_BOARD_NAME, "20MV"),
                },
        },
-       {
-               .ident = "L14 Gen2 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20X5"),
-               }
-       },
-       {
-               .ident = "T14s Gen2 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20XF"),
-               }
-       },
-       {
-               .ident = "X13 Gen2 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20XH"),
-               }
-       },
-       {
-               .ident = "T14 Gen2 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20XK"),
-               }
-       },
-       {
-               .ident = "T14 Gen1 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20UD"),
-               }
-       },
-       {
-               .ident = "T14 Gen1 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20UE"),
-               }
-       },
-       {
-               .ident = "T14s Gen1 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20UH"),
-               }
-       },
-       {
-               .ident = "T14s Gen1 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20UJ"),
-               }
-       },
-       {
-               .ident = "P14s Gen1 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "20Y1"),
-               }
-       },
-       {
-               .ident = "P14s Gen2 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "21A0"),
-               }
-       },
-       {
-               .ident = "P14s Gen2 AMD",
-               .driver_data = &quirk_s2idle_bug,
-               .matches = {
-                       DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
-                       DMI_MATCH(DMI_PRODUCT_NAME, "21A1"),
-               }
-       },
        {}
 };
 
-#ifdef CONFIG_SUSPEND
-/*
- * Lenovo laptops from a variety of generations run a SMI handler during the D3->D0
- * transition that occurs specifically when exiting suspend to idle which can cause
- * large delays during resume when the IOMMU translation layer is enabled (the default
- * behavior) for NVME devices:
- *
- * To avoid this firmware problem, skip the SMI handler on these machines before the
- * D0 transition occurs.
- */
-static void thinkpad_acpi_amd_s2idle_restore(void)
-{
-       struct resource *res;
-       void __iomem *addr;
-       u8 val;
-
-       res = request_mem_region_muxed(tp_features.quirks->s2idle_bug_mmio, 1,
-                                       "thinkpad_acpi_pm80");
-       if (!res)
-               return;
-
-       addr = ioremap(tp_features.quirks->s2idle_bug_mmio, 1);
-       if (!addr)
-               goto cleanup_resource;
-
-       val = ioread8(addr);
-       iowrite8(val & ~BIT(0), addr);
-
-       iounmap(addr);
-cleanup_resource:
-       release_resource(res);
-       kfree(res);
-}
-
-static struct acpi_s2idle_dev_ops thinkpad_acpi_s2idle_dev_ops = {
-       .restore = thinkpad_acpi_amd_s2idle_restore,
-};
-#endif
-
 static const struct pci_device_id fwbug_cards_ids[] __initconst = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x24FD) },
@@ -11668,10 +11536,6 @@ static void thinkpad_acpi_module_exit(void)
 
        tpacpi_lifecycle = TPACPI_LIFE_EXITING;
 
-#ifdef CONFIG_SUSPEND
-       if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio)
-               acpi_unregister_lps0_dev(&thinkpad_acpi_s2idle_dev_ops);
-#endif
        if (tpacpi_hwmon)
                hwmon_device_unregister(tpacpi_hwmon);
        if (tp_features.sensors_pdrv_registered)
@@ -11861,13 +11725,6 @@ static int __init thinkpad_acpi_module_init(void)
                tp_features.input_device_registered = 1;
        }
 
-#ifdef CONFIG_SUSPEND
-       if (tp_features.quirks && tp_features.quirks->s2idle_bug_mmio) {
-               if (!acpi_register_lps0_dev(&thinkpad_acpi_s2idle_dev_ops))
-                       pr_info("Using s2idle quirk to avoid %s platform firmware bug\n",
-                               (dmi_id && dmi_id->ident) ? dmi_id->ident : "");
-       }
-#endif
        return 0;
 }
 
index 68e66b6..a5b687e 100644 (file)
@@ -26,6 +26,21 @@ 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_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-archos-101-cesium-educ.fw"),
+       { }
+};
+
+static const struct ts_dmi_data archos_101_cesium_educ_data = {
+       .acpi_name      = "MSSL1680:00",
+       .properties     = archos_101_cesium_educ_props,
+};
+
 static const struct property_entry chuwi_hi8_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-size-x", 1665),
        PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
@@ -1048,6 +1063,13 @@ static const struct ts_dmi_data vinga_twizzle_j116_data = {
 /* NOTE: Please keep this table sorted alphabetically */
 const struct dmi_system_id touchscreen_dmi_table[] = {
        {
+               /* Archos 101 Cesium Educ */
+               .driver_data = (void *)&archos_101_cesium_educ_data,
+               .matches = {
+                       DMI_MATCH(DMI_PRODUCT_NAME, "ARCHOS 101 Cesium Educ"),
+               },
+       },
+       {
                /* Chuwi Hi8 */
                .driver_data = (void *)&chuwi_hi8_data,
                .matches = {
index 5b95d7a..a78ddd8 100644 (file)
@@ -136,6 +136,16 @@ static acpi_status find_guid(const char *guid_string, struct wmi_block **out)
        return AE_NOT_FOUND;
 }
 
+static bool guid_parse_and_compare(const char *string, const guid_t *guid)
+{
+       guid_t guid_input;
+
+       if (guid_parse(string, &guid_input))
+               return false;
+
+       return guid_equal(&guid_input, guid);
+}
+
 static const void *find_guid_context(struct wmi_block *wblock,
                                     struct wmi_driver *wdriver)
 {
@@ -146,11 +156,7 @@ static const void *find_guid_context(struct wmi_block *wblock,
                return NULL;
 
        while (*id->guid_string) {
-               guid_t guid_input;
-
-               if (guid_parse(id->guid_string, &guid_input))
-                       continue;
-               if (guid_equal(&wblock->gblock.guid, &guid_input))
+               if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))
                        return id->context;
                id++;
        }
@@ -895,11 +901,7 @@ static int wmi_dev_match(struct device *dev, struct device_driver *driver)
                return 0;
 
        while (*id->guid_string) {
-               guid_t driver_guid;
-
-               if (WARN_ON(guid_parse(id->guid_string, &driver_guid)))
-                       continue;
-               if (guid_equal(&driver_guid, &wblock->gblock.guid))
+               if (guid_parse_and_compare(id->guid_string, &wblock->gblock.guid))
                        return 1;
 
                id++;
@@ -1239,11 +1241,7 @@ static bool guid_already_parsed_for_legacy(struct acpi_device *device, const gui
        list_for_each_entry(wblock, &wmi_block_list, list) {
                /* skip warning and register if we know the driver will use struct wmi_driver */
                for (int i = 0; allow_duplicates[i] != NULL; i++) {
-                       guid_t tmp;
-
-                       if (guid_parse(allow_duplicates[i], &tmp))
-                               continue;
-                       if (guid_equal(&tmp, guid))
+                       if (guid_parse_and_compare(allow_duplicates[i], guid))
                                return false;
                }
                if (guid_equal(&wblock->gblock.guid, guid)) {
index 9b5fccd..6df7f37 100644 (file)
@@ -36,7 +36,7 @@ static const struct smcd_ops ism_ops;
 static struct ism_client *clients[MAX_CLIENTS];        /* use an array rather than */
                                                /* a list for fast mapping  */
 static u8 max_client;
-static DEFINE_SPINLOCK(clients_lock);
+static DEFINE_MUTEX(clients_lock);
 struct ism_dev_list {
        struct list_head list;
        struct mutex mutex; /* protects ism device list */
@@ -47,14 +47,22 @@ static struct ism_dev_list ism_dev_list = {
        .mutex = __MUTEX_INITIALIZER(ism_dev_list.mutex),
 };
 
+static void ism_setup_forwarding(struct ism_client *client, struct ism_dev *ism)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ism->lock, flags);
+       ism->subs[client->id] = client;
+       spin_unlock_irqrestore(&ism->lock, flags);
+}
+
 int ism_register_client(struct ism_client *client)
 {
        struct ism_dev *ism;
-       unsigned long flags;
        int i, rc = -ENOSPC;
 
        mutex_lock(&ism_dev_list.mutex);
-       spin_lock_irqsave(&clients_lock, flags);
+       mutex_lock(&clients_lock);
        for (i = 0; i < MAX_CLIENTS; ++i) {
                if (!clients[i]) {
                        clients[i] = client;
@@ -65,12 +73,14 @@ int ism_register_client(struct ism_client *client)
                        break;
                }
        }
-       spin_unlock_irqrestore(&clients_lock, flags);
+       mutex_unlock(&clients_lock);
+
        if (i < MAX_CLIENTS) {
                /* initialize with all devices that we got so far */
                list_for_each_entry(ism, &ism_dev_list.list, list) {
                        ism->priv[i] = NULL;
                        client->add(ism);
+                       ism_setup_forwarding(client, ism);
                }
        }
        mutex_unlock(&ism_dev_list.mutex);
@@ -86,25 +96,32 @@ int ism_unregister_client(struct ism_client *client)
        int rc = 0;
 
        mutex_lock(&ism_dev_list.mutex);
-       spin_lock_irqsave(&clients_lock, flags);
-       clients[client->id] = NULL;
-       if (client->id + 1 == max_client)
-               max_client--;
-       spin_unlock_irqrestore(&clients_lock, flags);
        list_for_each_entry(ism, &ism_dev_list.list, list) {
+               spin_lock_irqsave(&ism->lock, flags);
+               /* Stop forwarding IRQs and events */
+               ism->subs[client->id] = NULL;
                for (int i = 0; i < ISM_NR_DMBS; ++i) {
                        if (ism->sba_client_arr[i] == client->id) {
-                               pr_err("%s: attempt to unregister client '%s'"
-                                      "with registered dmb(s)\n", __func__,
-                                      client->name);
+                               WARN(1, "%s: attempt to unregister '%s' with registered dmb(s)\n",
+                                    __func__, client->name);
                                rc = -EBUSY;
-                               goto out;
+                               goto err_reg_dmb;
                        }
                }
+               spin_unlock_irqrestore(&ism->lock, flags);
        }
-out:
        mutex_unlock(&ism_dev_list.mutex);
 
+       mutex_lock(&clients_lock);
+       clients[client->id] = NULL;
+       if (client->id + 1 == max_client)
+               max_client--;
+       mutex_unlock(&clients_lock);
+       return rc;
+
+err_reg_dmb:
+       spin_unlock_irqrestore(&ism->lock, flags);
+       mutex_unlock(&ism_dev_list.mutex);
        return rc;
 }
 EXPORT_SYMBOL_GPL(ism_unregister_client);
@@ -328,6 +345,7 @@ int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb,
                     struct ism_client *client)
 {
        union ism_reg_dmb cmd;
+       unsigned long flags;
        int ret;
 
        ret = ism_alloc_dmb(ism, dmb);
@@ -351,7 +369,9 @@ int ism_register_dmb(struct ism_dev *ism, struct ism_dmb *dmb,
                goto out;
        }
        dmb->dmb_tok = cmd.response.dmb_tok;
+       spin_lock_irqsave(&ism->lock, flags);
        ism->sba_client_arr[dmb->sba_idx - ISM_DMB_BIT_OFFSET] = client->id;
+       spin_unlock_irqrestore(&ism->lock, flags);
 out:
        return ret;
 }
@@ -360,6 +380,7 @@ EXPORT_SYMBOL_GPL(ism_register_dmb);
 int ism_unregister_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
 {
        union ism_unreg_dmb cmd;
+       unsigned long flags;
        int ret;
 
        memset(&cmd, 0, sizeof(cmd));
@@ -368,7 +389,9 @@ int ism_unregister_dmb(struct ism_dev *ism, struct ism_dmb *dmb)
 
        cmd.request.dmb_tok = dmb->dmb_tok;
 
+       spin_lock_irqsave(&ism->lock, flags);
        ism->sba_client_arr[dmb->sba_idx - ISM_DMB_BIT_OFFSET] = NO_CLIENT;
+       spin_unlock_irqrestore(&ism->lock, flags);
 
        ret = ism_cmd(ism, &cmd);
        if (ret && ret != ISM_ERROR)
@@ -491,6 +514,7 @@ static u16 ism_get_chid(struct ism_dev *ism)
 static void ism_handle_event(struct ism_dev *ism)
 {
        struct ism_event *entry;
+       struct ism_client *clt;
        int i;
 
        while ((ism->ieq_idx + 1) != READ_ONCE(ism->ieq->header.idx)) {
@@ -499,21 +523,21 @@ static void ism_handle_event(struct ism_dev *ism)
 
                entry = &ism->ieq->entry[ism->ieq_idx];
                debug_event(ism_debug_info, 2, entry, sizeof(*entry));
-               spin_lock(&clients_lock);
-               for (i = 0; i < max_client; ++i)
-                       if (clients[i])
-                               clients[i]->handle_event(ism, entry);
-               spin_unlock(&clients_lock);
+               for (i = 0; i < max_client; ++i) {
+                       clt = ism->subs[i];
+                       if (clt)
+                               clt->handle_event(ism, entry);
+               }
        }
 }
 
 static irqreturn_t ism_handle_irq(int irq, void *data)
 {
        struct ism_dev *ism = data;
-       struct ism_client *clt;
        unsigned long bit, end;
        unsigned long *bv;
        u16 dmbemask;
+       u8 client_id;
 
        bv = (void *) &ism->sba->dmb_bits[ISM_DMB_WORD_OFFSET];
        end = sizeof(ism->sba->dmb_bits) * BITS_PER_BYTE - ISM_DMB_BIT_OFFSET;
@@ -530,8 +554,10 @@ static irqreturn_t ism_handle_irq(int irq, void *data)
                dmbemask = ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET];
                ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0;
                barrier();
-               clt = clients[ism->sba_client_arr[bit]];
-               clt->handle_irq(ism, bit + ISM_DMB_BIT_OFFSET, dmbemask);
+               client_id = ism->sba_client_arr[bit];
+               if (unlikely(client_id == NO_CLIENT || !ism->subs[client_id]))
+                       continue;
+               ism->subs[client_id]->handle_irq(ism, bit + ISM_DMB_BIT_OFFSET, dmbemask);
        }
 
        if (ism->sba->e) {
@@ -548,20 +574,9 @@ static u64 ism_get_local_gid(struct ism_dev *ism)
        return ism->local_gid;
 }
 
-static void ism_dev_add_work_func(struct work_struct *work)
-{
-       struct ism_client *client = container_of(work, struct ism_client,
-                                                add_work);
-
-       client->add(client->tgt_ism);
-       atomic_dec(&client->tgt_ism->add_dev_cnt);
-       wake_up(&client->tgt_ism->waitq);
-}
-
 static int ism_dev_init(struct ism_dev *ism)
 {
        struct pci_dev *pdev = ism->pdev;
-       unsigned long flags;
        int i, ret;
 
        ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI);
@@ -594,25 +609,16 @@ static int ism_dev_init(struct ism_dev *ism)
                /* hardware is V2 capable */
                ism_create_system_eid();
 
-       init_waitqueue_head(&ism->waitq);
-       atomic_set(&ism->free_clients_cnt, 0);
-       atomic_set(&ism->add_dev_cnt, 0);
-
-       wait_event(ism->waitq, !atomic_read(&ism->add_dev_cnt));
-       spin_lock_irqsave(&clients_lock, flags);
-       for (i = 0; i < max_client; ++i)
+       mutex_lock(&ism_dev_list.mutex);
+       mutex_lock(&clients_lock);
+       for (i = 0; i < max_client; ++i) {
                if (clients[i]) {
-                       INIT_WORK(&clients[i]->add_work,
-                                 ism_dev_add_work_func);
-                       clients[i]->tgt_ism = ism;
-                       atomic_inc(&ism->add_dev_cnt);
-                       schedule_work(&clients[i]->add_work);
+                       clients[i]->add(ism);
+                       ism_setup_forwarding(clients[i], ism);
                }
-       spin_unlock_irqrestore(&clients_lock, flags);
-
-       wait_event(ism->waitq, !atomic_read(&ism->add_dev_cnt));
+       }
+       mutex_unlock(&clients_lock);
 
-       mutex_lock(&ism_dev_list.mutex);
        list_add(&ism->list, &ism_dev_list.list);
        mutex_unlock(&ism_dev_list.mutex);
 
@@ -687,36 +693,24 @@ err_dev:
        return ret;
 }
 
-static void ism_dev_remove_work_func(struct work_struct *work)
-{
-       struct ism_client *client = container_of(work, struct ism_client,
-                                                remove_work);
-
-       client->remove(client->tgt_ism);
-       atomic_dec(&client->tgt_ism->free_clients_cnt);
-       wake_up(&client->tgt_ism->waitq);
-}
-
-/* Callers must hold ism_dev_list.mutex */
 static void ism_dev_exit(struct ism_dev *ism)
 {
        struct pci_dev *pdev = ism->pdev;
        unsigned long flags;
        int i;
 
-       wait_event(ism->waitq, !atomic_read(&ism->free_clients_cnt));
-       spin_lock_irqsave(&clients_lock, flags);
+       spin_lock_irqsave(&ism->lock, flags);
        for (i = 0; i < max_client; ++i)
-               if (clients[i]) {
-                       INIT_WORK(&clients[i]->remove_work,
-                                 ism_dev_remove_work_func);
-                       clients[i]->tgt_ism = ism;
-                       atomic_inc(&ism->free_clients_cnt);
-                       schedule_work(&clients[i]->remove_work);
-               }
-       spin_unlock_irqrestore(&clients_lock, flags);
+               ism->subs[i] = NULL;
+       spin_unlock_irqrestore(&ism->lock, flags);
 
-       wait_event(ism->waitq, !atomic_read(&ism->free_clients_cnt));
+       mutex_lock(&ism_dev_list.mutex);
+       mutex_lock(&clients_lock);
+       for (i = 0; i < max_client; ++i) {
+               if (clients[i])
+                       clients[i]->remove(ism);
+       }
+       mutex_unlock(&clients_lock);
 
        if (SYSTEM_EID.serial_number[0] != '0' ||
            SYSTEM_EID.type[0] != '0')
@@ -727,15 +721,14 @@ static void ism_dev_exit(struct ism_dev *ism)
        kfree(ism->sba_client_arr);
        pci_free_irq_vectors(pdev);
        list_del_init(&ism->list);
+       mutex_unlock(&ism_dev_list.mutex);
 }
 
 static void ism_remove(struct pci_dev *pdev)
 {
        struct ism_dev *ism = dev_get_drvdata(&pdev->dev);
 
-       mutex_lock(&ism_dev_list.mutex);
        ism_dev_exit(ism);
-       mutex_unlock(&ism_dev_list.mutex);
 
        pci_release_mem_regions(pdev);
        pci_disable_device(pdev);
index 7c6efde..73b6ac0 100644 (file)
@@ -2618,7 +2618,7 @@ struct aac_hba_info {
 struct aac_aifcmd {
        __le32 command;         /* Tell host what type of notify this is */
        __le32 seqnum;          /* To allow ordering of reports (if necessary) */
-       u8 data[1];             /* Undefined length (from kernel viewpoint) */
+       u8 data[];              /* Undefined length (from kernel viewpoint) */
 };
 
 /**
index f3c3a26..be0d7c5 100644 (file)
@@ -465,7 +465,7 @@ int fnic_trace_buf_init(void)
        fnic_max_trace_entries = (trace_max_pages * PAGE_SIZE)/
                                          FNIC_ENTRY_SIZE_BYTES;
 
-       fnic_trace_buf_p = (unsigned long)vzalloc(trace_max_pages * PAGE_SIZE);
+       fnic_trace_buf_p = (unsigned long)vcalloc(trace_max_pages, PAGE_SIZE);
        if (!fnic_trace_buf_p) {
                printk(KERN_ERR PFX "Failed to allocate memory "
                                  "for fnic_trace_buf_p\n");
index 499849b..fdd7f69 100644 (file)
@@ -6944,7 +6944,9 @@ lpfc_unregister_fcf_rescan(struct lpfc_hba *phba)
        if (rc)
                return;
        /* Reset HBA FCF states after successful unregister FCF */
+       spin_lock_irq(&phba->hbalock);
        phba->fcf.fcf_flag = 0;
+       spin_unlock_irq(&phba->hbalock);
        phba->fcf.current_rec.flag = 0;
 
        /*
index d44c4d3..4ae3830 100644 (file)
@@ -4462,7 +4462,6 @@ struct qla_hw_data {
 
        /* n2n */
        struct fc_els_flogi plogi_els_payld;
-#define LOGIN_TEMPLATE_SIZE (sizeof(struct fc_els_flogi) - 4)
 
        void            *swl;
 
index c3dd8dd..367fba2 100644 (file)
@@ -8434,7 +8434,7 @@ qla24xx_load_risc_flash(scsi_qla_host_t *vha, uint32_t *srisc_addr,
                ql_dbg(ql_dbg_init, vha, 0x0163,
                    "-> fwdt%u template allocate template %#x words...\n",
                    j, risc_size);
-               fwdt->template = vmalloc(risc_size * sizeof(*dcode));
+               fwdt->template = vmalloc_array(risc_size, sizeof(*dcode));
                if (!fwdt->template) {
                        ql_log(ql_log_warn, vha, 0x0164,
                            "-> fwdt%u failed allocate template.\n", j);
@@ -8689,7 +8689,7 @@ qla24xx_load_risc_blob(scsi_qla_host_t *vha, uint32_t *srisc_addr)
                ql_dbg(ql_dbg_init, vha, 0x0173,
                    "-> fwdt%u template allocate template %#x words...\n",
                    j, risc_size);
-               fwdt->template = vmalloc(risc_size * sizeof(*dcode));
+               fwdt->template = vmalloc_array(risc_size, sizeof(*dcode));
                if (!fwdt->template) {
                        ql_log(ql_log_warn, vha, 0x0174,
                            "-> fwdt%u failed allocate template.\n", j);
index a1675f0..730d860 100644 (file)
@@ -3073,7 +3073,8 @@ qla24xx_els_dcmd2_iocb(scsi_qla_host_t *vha, int els_opcode,
        memset(ptr, 0, sizeof(struct els_plogi_payload));
        memset(resp_ptr, 0, sizeof(struct els_plogi_payload));
        memcpy(elsio->u.els_plogi.els_plogi_pyld->data,
-           &ha->plogi_els_payld.fl_csp, LOGIN_TEMPLATE_SIZE);
+              (void *)&ha->plogi_els_payld + offsetof(struct fc_els_flogi, fl_csp),
+              sizeof(ha->plogi_els_payld) - offsetof(struct fc_els_flogi, fl_csp));
 
        elsio->u.els_plogi.els_cmd = els_opcode;
        elsio->u.els_plogi.els_plogi_pyld->opcode = els_opcode;
@@ -3911,7 +3912,7 @@ qla2x00_start_sp(srb_t *sp)
 
        pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
        if (!pkt) {
-               rval = EAGAIN;
+               rval = -EAGAIN;
                ql_log(ql_log_warn, vha, 0x700c,
                    "qla2x00_alloc_iocbs failed.\n");
                goto done;
index 8c58128..9c0af50 100644 (file)
@@ -841,11 +841,6 @@ static int sdeb_zbc_nr_conv = DEF_ZBC_NR_CONV_ZONES;
 static int submit_queues = DEF_SUBMIT_QUEUES;  /* > 1 for multi-queue (mq) */
 static int poll_queues; /* iouring iopoll interface.*/
 
-static DEFINE_RWLOCK(atomic_rw);
-static DEFINE_RWLOCK(atomic_rw2);
-
-static rwlock_t *ramdisk_lck_a[2];
-
 static char sdebug_proc_name[] = MY_NAME;
 static const char *my_name = MY_NAME;
 
@@ -6818,9 +6813,6 @@ static int __init scsi_debug_init(void)
        int k, ret, hosts_to_add;
        int idx = -1;
 
-       ramdisk_lck_a[0] = &atomic_rw;
-       ramdisk_lck_a[1] = &atomic_rw2;
-
        if (sdebug_ndelay >= 1000 * 1000 * 1000) {
                pr_warn("ndelay must be less than 1 second, ignored\n");
                sdebug_ndelay = 0;
index abbd089..a252155 100644 (file)
@@ -831,7 +831,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
        struct request_queue *q = disk->queue;
        u32 zone_blocks = sdkp->early_zone_info.zone_blocks;
        unsigned int nr_zones = sdkp->early_zone_info.nr_zones;
-       u32 max_append;
        int ret = 0;
        unsigned int flags;
 
@@ -876,6 +875,11 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
                goto unlock;
        }
 
+       blk_queue_chunk_sectors(q,
+                       logical_to_sectors(sdkp->device, zone_blocks));
+       blk_queue_max_zone_append_sectors(q,
+                       q->limits.max_segments << PAGE_SECTORS_SHIFT);
+
        ret = blk_revalidate_disk_zones(disk, sd_zbc_revalidate_zones_cb);
 
        memalloc_noio_restore(flags);
@@ -888,12 +892,6 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
                goto unlock;
        }
 
-       max_append = min_t(u32, logical_to_sectors(sdkp->device, zone_blocks),
-                          q->limits.max_segments << PAGE_SECTORS_SHIFT);
-       max_append = min_t(u32, max_append, queue_max_hw_sectors(q));
-
-       blk_queue_max_zone_append_sectors(q, max_append);
-
        sd_zbc_print_zones(sdkp);
 
 unlock:
index 659196a..7f12d93 100644 (file)
@@ -318,6 +318,7 @@ enum storvsc_request_type {
 #define SRB_STATUS_INVALID_REQUEST     0x06
 #define SRB_STATUS_DATA_OVERRUN                0x12
 #define SRB_STATUS_INVALID_LUN         0x20
+#define SRB_STATUS_INTERNAL_ERROR      0x30
 
 #define SRB_STATUS(status) \
        (status & ~(SRB_STATUS_AUTOSENSE_VALID | SRB_STATUS_QUEUE_FROZEN))
@@ -978,6 +979,7 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb,
        case SRB_STATUS_ERROR:
        case SRB_STATUS_ABORTED:
        case SRB_STATUS_INVALID_REQUEST:
+       case SRB_STATUS_INTERNAL_ERROR:
                if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) {
                        /* Check for capacity change */
                        if ((asc == 0x2a) && (ascq == 0x9)) {
index 3b0f9fb..708eaad 100644 (file)
@@ -3,7 +3,6 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
-obj-$(CONFIG_ARCH_ACTIONS)     += actions/
 obj-y                          += apple/
 obj-y                          += aspeed/
 obj-$(CONFIG_ARCH_AT91)                += atmel/
@@ -29,7 +28,6 @@ obj-y                         += renesas/
 obj-y                          += rockchip/
 obj-$(CONFIG_SOC_SAMSUNG)      += samsung/
 obj-y                          += sifive/
-obj-$(CONFIG_SOC_STARFIVE)     += starfive/
 obj-y                          += sunxi/
 obj-$(CONFIG_ARCH_TEGRA)       += tegra/
 obj-y                          += ti/
diff --git a/drivers/soc/actions/Makefile b/drivers/soc/actions/Makefile
deleted file mode 100644 (file)
index 4db9e7b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-
-obj-$(CONFIG_OWL_PM_DOMAINS_HELPER) += owl-sps-helper.o
-obj-$(CONFIG_OWL_PM_DOMAINS) += owl-sps.o
index 7b8c5d3..c25f835 100644 (file)
@@ -2,7 +2,4 @@
 obj-$(CONFIG_MESON_CANVAS) += meson-canvas.o
 obj-$(CONFIG_MESON_CLK_MEASURE) += meson-clk-measure.o
 obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o
-obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
 obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
-obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o
-obj-$(CONFIG_MESON_SECURE_PM_DOMAINS) += meson-secure-pwrc.o
index e293770..b241e6a 100644 (file)
@@ -1,6 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_APPLE_PMGR_PWRSTATE)      += apple-pmgr-pwrstate.o
-
 obj-$(CONFIG_APPLE_RTKIT) += apple-rtkit.o
 apple-rtkit-y = rtkit.o rtkit-crashlog.o
 
index 24f92a6..f969067 100644 (file)
@@ -42,7 +42,27 @@ config SOC_BRCMSTB
 
          If unsure, say N.
 
-source "drivers/soc/bcm/bcm63xx/Kconfig"
+config BCM_PMB
+       bool "Broadcom PMB (Power Management Bus) driver"
+       depends on ARCH_BCMBCA || (COMPILE_TEST && OF)
+       default ARCH_BCMBCA
+       select PM_GENERIC_DOMAINS if PM
+       help
+         This enables support for the Broadcom's PMB (Power Management Bus) that
+         is used for disabling and enabling SoC devices.
+
+if SOC_BCM63XX
+
+config BCM63XX_POWER
+       bool "BCM63xx power domain driver"
+       depends on BMIPS_GENERIC || (COMPILE_TEST && OF)
+       select PM_GENERIC_DOMAINS if PM
+       help
+         This enables support for the BCM63xx power domains controller on
+         BCM6318, BCM6328, BCM6362 and BCM63268 SoCs.
+
+endif # SOC_BCM63XX
+
 source "drivers/soc/bcm/brcmstb/Kconfig"
 
 endmenu
index 0f0efa2..32424b1 100644 (file)
@@ -1,5 +1,2 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_BCM2835_POWER)    += bcm2835-power.o
-obj-$(CONFIG_RASPBERRYPI_POWER)        += raspberrypi-power.o
-obj-y                          += bcm63xx/
 obj-$(CONFIG_SOC_BRCMSTB)      += brcmstb/
diff --git a/drivers/soc/bcm/bcm63xx/Kconfig b/drivers/soc/bcm/bcm63xx/Kconfig
deleted file mode 100644 (file)
index 355c344..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-if SOC_BCM63XX
-
-config BCM63XX_POWER
-       bool "BCM63xx power domain driver"
-       depends on BMIPS_GENERIC || (COMPILE_TEST && OF)
-       select PM_GENERIC_DOMAINS if PM
-       help
-         This enables support for the BCM63xx power domains controller on
-         BCM6318, BCM6328, BCM6362 and BCM63268 SoCs.
-
-endif # SOC_BCM63XX
-
-config BCM_PMB
-       bool "Broadcom PMB (Power Management Bus) driver"
-       depends on ARCH_BCMBCA || (COMPILE_TEST && OF)
-       default ARCH_BCMBCA
-       select PM_GENERIC_DOMAINS if PM
-       help
-         This enables support for the Broadcom's PMB (Power Management Bus) that
-         is used for disabling and enabling SoC devices.
diff --git a/drivers/soc/bcm/bcm63xx/Makefile b/drivers/soc/bcm/bcm63xx/Makefile
deleted file mode 100644 (file)
index 557eed3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-obj-$(CONFIG_BCM63XX_POWER) += bcm63xx-power.o
-obj-$(CONFIG_BCM_PMB)          += bcm-pmb.o
index a28c44a..3ad321c 100644 (file)
@@ -2,10 +2,5 @@
 ifeq ($(CONFIG_ARM),y)
 obj-$(CONFIG_ARCH_MXC) += soc-imx.o
 endif
-obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
-obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
 obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
-obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8m-blk-ctrl.o
-obj-$(CONFIG_IMX8M_BLK_CTRL) += imx8mp-blk-ctrl.o
-obj-$(CONFIG_SOC_IMX9) += imx93-src.o imx93-pd.o
-obj-$(CONFIG_IMX9_BLK_CTRL) += imx93-blk-ctrl.o
+obj-$(CONFIG_SOC_IMX9) += imx93-src.o
index 8c0ddac..9d3ce78 100644 (file)
@@ -4,8 +4,6 @@ obj-$(CONFIG_MTK_DEVAPC) += mtk-devapc.o
 obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
 obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
 obj-$(CONFIG_MTK_REGULATOR_COUPLER) += mtk-regulator-coupler.o
-obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
-obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o
 obj-$(CONFIG_MTK_MMSYS) += mtk-mmsys.o
 obj-$(CONFIG_MTK_MMSYS) += mtk-mutex.o
 obj-$(CONFIG_MTK_SVS) += mtk-svs.o
index 99114c7..f548a71 100644 (file)
@@ -3,7 +3,6 @@ CFLAGS_rpmh-rsc.o := -I$(src)
 obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o
 obj-$(CONFIG_QCOM_GENI_SE) +=  qcom-geni-se.o
 obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o
-obj-$(CONFIG_QCOM_CPR)         += cpr.o
 obj-$(CONFIG_QCOM_GSBI)        +=      qcom_gsbi.o
 obj-$(CONFIG_QCOM_MDT_LOADER)  += mdt_loader.o
 obj-$(CONFIG_QCOM_OCMEM)       += ocmem.o
@@ -29,8 +28,6 @@ obj-$(CONFIG_QCOM_STATS)      += qcom_stats.o
 obj-$(CONFIG_QCOM_WCNSS_CTRL) += wcnss_ctrl.o
 obj-$(CONFIG_QCOM_APR) += apr.o
 obj-$(CONFIG_QCOM_LLCC) += llcc-qcom.o
-obj-$(CONFIG_QCOM_RPMHPD) += rpmhpd.o
-obj-$(CONFIG_QCOM_RPMPD) += rpmpd.o
 obj-$(CONFIG_QCOM_KRYO_L2_ACCESSORS) +=        kryo-l2-accessors.o
 obj-$(CONFIG_QCOM_ICC_BWMON)   += icc-bwmon.o
 qcom_ice-objs                  += ice.o
index 6e4e77b..734f8f8 100644 (file)
@@ -3,30 +3,6 @@
 obj-$(CONFIG_SOC_RENESAS)      += renesas-soc.o
 
 # SoC
-obj-$(CONFIG_SYSC_R8A7742)     += r8a7742-sysc.o
-obj-$(CONFIG_SYSC_R8A7743)     += r8a7743-sysc.o
-obj-$(CONFIG_SYSC_R8A7745)     += r8a7745-sysc.o
-obj-$(CONFIG_SYSC_R8A77470)    += r8a77470-sysc.o
-obj-$(CONFIG_SYSC_R8A774A1)    += r8a774a1-sysc.o
-obj-$(CONFIG_SYSC_R8A774B1)    += r8a774b1-sysc.o
-obj-$(CONFIG_SYSC_R8A774C0)    += r8a774c0-sysc.o
-obj-$(CONFIG_SYSC_R8A774E1)    += r8a774e1-sysc.o
-obj-$(CONFIG_SYSC_R8A7779)     += r8a7779-sysc.o
-obj-$(CONFIG_SYSC_R8A7790)     += r8a7790-sysc.o
-obj-$(CONFIG_SYSC_R8A7791)     += r8a7791-sysc.o
-obj-$(CONFIG_SYSC_R8A7792)     += r8a7792-sysc.o
-obj-$(CONFIG_SYSC_R8A7794)     += r8a7794-sysc.o
-obj-$(CONFIG_SYSC_R8A7795)     += r8a7795-sysc.o
-obj-$(CONFIG_SYSC_R8A77960)    += r8a7796-sysc.o
-obj-$(CONFIG_SYSC_R8A77961)    += r8a7796-sysc.o
-obj-$(CONFIG_SYSC_R8A77965)    += r8a77965-sysc.o
-obj-$(CONFIG_SYSC_R8A77970)    += r8a77970-sysc.o
-obj-$(CONFIG_SYSC_R8A77980)    += r8a77980-sysc.o
-obj-$(CONFIG_SYSC_R8A77990)    += r8a77990-sysc.o
-obj-$(CONFIG_SYSC_R8A77995)    += r8a77995-sysc.o
-obj-$(CONFIG_SYSC_R8A779A0)    += r8a779a0-sysc.o
-obj-$(CONFIG_SYSC_R8A779F0)    += r8a779f0-sysc.o
-obj-$(CONFIG_SYSC_R8A779G0)    += r8a779g0-sysc.o
 ifdef CONFIG_SMP
 obj-$(CONFIG_ARCH_R9A06G032)   += r9a06g032-smp.o
 endif
@@ -34,6 +10,3 @@ endif
 # Family
 obj-$(CONFIG_PWC_RZV2M)                += pwc-rzv2m.o
 obj-$(CONFIG_RST_RCAR)         += rcar-rst.o
-obj-$(CONFIG_SYSC_RCAR)                += rcar-sysc.o
-obj-$(CONFIG_SYSC_RCAR_GEN4)   += rcar-gen4-sysc.o
-obj-$(CONFIG_SYSC_RMOBILE)     += rmobile-sysc.o
index 05f31a4..23d4144 100644 (file)
@@ -4,5 +4,4 @@
 #
 obj-$(CONFIG_ROCKCHIP_GRF) += grf.o
 obj-$(CONFIG_ROCKCHIP_IODOMAIN) += io-domain.o
-obj-$(CONFIG_ROCKCHIP_PM_DOMAINS) += pm_domains.o
 obj-$(CONFIG_ROCKCHIP_DTPM) += dtpm.o
index d35270f..248a33d 100644 (file)
@@ -10,7 +10,6 @@ obj-$(CONFIG_EXYNOS_PMU)      += exynos-pmu.o
 
 obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS)   += exynos3250-pmu.o exynos4-pmu.o \
                                        exynos5250-pmu.o exynos5420-pmu.o
-obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
 obj-$(CONFIG_EXYNOS_REGULATOR_COUPLER) += exynos-regulator-coupler.o
 
 obj-$(CONFIG_SAMSUNG_PM_CHECK) += s3c-pm-check.o
diff --git a/drivers/soc/starfive/Makefile b/drivers/soc/starfive/Makefile
deleted file mode 100644 (file)
index 13b589d..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-obj-$(CONFIG_JH71XX_PMU)       += jh71xx_pmu.o
index 90ff2eb..5491595 100644 (file)
@@ -1,4 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0-only
 obj-$(CONFIG_SUNXI_MBUS) +=    sunxi_mbus.o
 obj-$(CONFIG_SUNXI_SRAM) +=    sunxi_sram.o
-obj-$(CONFIG_SUN20I_PPU) +=    sun20i-ppu.o
index d722f51..0105961 100644 (file)
@@ -5,7 +5,6 @@ obj-y += cbb/
 obj-y += common.o
 obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o
 obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o
-obj-$(CONFIG_SOC_TEGRA_POWERGATE_BPMP) += powergate-bpmp.o
 obj-$(CONFIG_SOC_TEGRA20_VOLTAGE_COUPLER) += regulators-tegra20.o
 obj-$(CONFIG_SOC_TEGRA30_VOLTAGE_COUPLER) += regulators-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_186_SOC) += ari-tegra186.o
index bd96204..84ab46c 100644 (file)
@@ -7,13 +7,9 @@
 #include <linux/cpufeature.h>
 #include <linux/debugfs.h>
 #include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/io.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <soc/tegra/fuse.h>
@@ -126,20 +122,16 @@ int tegra_cbb_get_irq(struct platform_device *pdev, unsigned int *nonsec_irq,
 
        if (num_intr == 2) {
                irq = platform_get_irq(pdev, index);
-               if (irq <= 0) {
-                       dev_err(&pdev->dev, "failed to get non-secure IRQ: %d\n", irq);
+               if (irq <= 0)
                        return -ENOENT;
-               }
 
                *nonsec_irq = irq;
                index++;
        }
 
        irq = platform_get_irq(pdev, index);
-       if (irq <= 0) {
-               dev_err(&pdev->dev, "failed to get secure IRQ: %d\n", irq);
+       if (irq <= 0)
                return -ENOENT;
-       }
 
        *sec_irq = irq;
 
index 54d7ce0..cf6886f 100644 (file)
 #include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
+#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/io.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <soc/tegra/fuse.h>
index 5d16161..5cf0e8c 100644 (file)
 #include <linux/debugfs.h>
 #include <linux/module.h>
 #include <linux/of.h>
-#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/device.h>
 #include <linux/io.h>
-#include <linux/of_irq.h>
-#include <linux/of_address.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <soc/tegra/fuse.h>
index d7a37f5..a2c28f4 100644 (file)
@@ -125,13 +125,10 @@ static int tegra_fuse_probe(struct platform_device *pdev)
                return err;
 
        /* take over the memory region from the early initialization */
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       fuse->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+       if (IS_ERR(fuse->base))
+               return PTR_ERR(fuse->base);
        fuse->phys = res->start;
-       fuse->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(fuse->base)) {
-               err = PTR_ERR(fuse->base);
-               return err;
-       }
 
        fuse->clk = devm_clk_get(&pdev->dev, "fuse");
        if (IS_ERR(fuse->clk)) {
index 12503f5..fdecf7b 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/kobject.h>
-#include <linux/of_device.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/random.h>
index c759fb7..e94d463 100644 (file)
@@ -10,8 +10,6 @@
 #include <linux/kernel.h>
 #include <linux/nvmem-consumer.h>
 #include <linux/nvmem-provider.h>
-#include <linux/of_device.h>
-#include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/random.h>
index eb0a1d9..da970f3 100644 (file)
@@ -4,13 +4,13 @@
  */
 
 #include <linux/export.h>
+#include <linux/io.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/io.h>
 
-#include <soc/tegra/fuse.h>
 #include <soc/tegra/common.h>
+#include <soc/tegra/fuse.h>
 
 #include "fuse.h"
 
index cc3c972..cb800a7 100644 (file)
@@ -6,9 +6,7 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS)   += knav_qmss.o
 knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
 obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA)   += knav_dma.o
 obj-$(CONFIG_AMX3_PM)                  += pm33xx.o
-obj-$(CONFIG_ARCH_OMAP2PLUS)           += omap_prm.o
 obj-$(CONFIG_WKUP_M3_IPC)              += wkup_m3_ipc.o
-obj-$(CONFIG_TI_SCI_PM_DOMAINS)                += ti_sci_pm_domains.o
 obj-$(CONFIG_TI_SCI_INTA_MSI_DOMAIN)   += ti_sci_inta_msi.o
 obj-$(CONFIG_TI_K3_RINGACC)            += k3-ringacc.o
 obj-$(CONFIG_TI_K3_SOCINFO)            += k3-socinfo.o
index 41e585b..33d9439 100644 (file)
@@ -1,4 +1,3 @@
 # SPDX-License-Identifier: GPL-2.0
 obj-$(CONFIG_ZYNQMP_POWER)     += zynqmp_power.o
-obj-$(CONFIG_ZYNQMP_PM_DOMAINS) += zynqmp_pm_domains.o
 obj-$(CONFIG_XLNX_EVENT_MANAGER)       += xlnx_event_manager.o
index f9d9b82..86a048a 100644 (file)
@@ -666,7 +666,7 @@ static int xlnx_event_manager_probe(struct platform_device *pdev)
        return ret;
 }
 
-static int xlnx_event_manager_remove(struct platform_device *pdev)
+static void xlnx_event_manager_remove(struct platform_device *pdev)
 {
        int i;
        struct registered_event_data *eve_data;
@@ -691,13 +691,11 @@ static int xlnx_event_manager_remove(struct platform_device *pdev)
        xlnx_event_cleanup_sgi(pdev);
 
        event_manager_availability = -EACCES;
-
-       return ret;
 }
 
 static struct platform_driver xlnx_event_manager_driver = {
        .probe = xlnx_event_manager_probe,
-       .remove = xlnx_event_manager_remove,
+       .remove_new = xlnx_event_manager_remove,
        .driver = {
                .name = "xlnx_event_manager",
        },
index 641dcc9..c2c8197 100644 (file)
@@ -11,6 +11,7 @@
 
 #include <linux/mailbox_client.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/reboot.h>
 #include <linux/suspend.h>
@@ -242,8 +243,8 @@ static int zynqmp_pm_probe(struct platform_device *pdev)
                }
        } else if (of_property_present(pdev->dev.of_node, "interrupts")) {
                irq = platform_get_irq(pdev, 0);
-               if (irq <= 0)
-                       return -ENXIO;
+               if (irq < 0)
+                       return irq;
 
                ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
                                                zynqmp_pm_isr,
index 9aecb77..07b5b71 100644 (file)
@@ -126,7 +126,7 @@ enum bcm63xx_regs_spi {
        SPI_MSG_DATA_SIZE,
 };
 
-#define BCM63XX_SPI_MAX_PREPEND                15
+#define BCM63XX_SPI_MAX_PREPEND                7
 
 #define BCM63XX_SPI_MAX_CS             8
 #define BCM63XX_SPI_BUS_NUM            0
index fd55697..b6c2659 100644 (file)
@@ -684,6 +684,8 @@ static int s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
        if ((sdd->cur_mode & SPI_LOOP) && sdd->port_conf->has_loopback)
                val |= S3C64XX_SPI_MODE_SELF_LOOPBACK;
+       else
+               val &= ~S3C64XX_SPI_MODE_SELF_LOOPBACK;
 
        writel(val, regs + S3C64XX_SPI_MODE_CFG);
 
index 983fae8..1294467 100644 (file)
@@ -8520,6 +8520,41 @@ out:
        return ret;
 }
 
+static void ufshcd_set_timestamp_attr(struct ufs_hba *hba)
+{
+       int err;
+       struct ufs_query_req *request = NULL;
+       struct ufs_query_res *response = NULL;
+       struct ufs_dev_info *dev_info = &hba->dev_info;
+       struct utp_upiu_query_v4_0 *upiu_data;
+
+       if (dev_info->wspecversion < 0x400)
+               return;
+
+       ufshcd_hold(hba);
+
+       mutex_lock(&hba->dev_cmd.lock);
+
+       ufshcd_init_query(hba, &request, &response,
+                         UPIU_QUERY_OPCODE_WRITE_ATTR,
+                         QUERY_ATTR_IDN_TIMESTAMP, 0, 0);
+
+       request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
+
+       upiu_data = (struct utp_upiu_query_v4_0 *)&request->upiu_req;
+
+       put_unaligned_be64(ktime_get_real_ns(), &upiu_data->osf3);
+
+       err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+
+       if (err)
+               dev_err(hba->dev, "%s: failed to set timestamp %d\n",
+                       __func__, err);
+
+       mutex_unlock(&hba->dev_cmd.lock);
+       ufshcd_release(hba);
+}
+
 /**
  * ufshcd_add_lus - probe and add UFS logical units
  * @hba: per-adapter instance
@@ -8708,6 +8743,8 @@ static int ufshcd_device_init(struct ufs_hba *hba, bool init_dev_params)
        ufshcd_set_ufs_dev_active(hba);
        ufshcd_force_reset_auto_bkops(hba);
 
+       ufshcd_set_timestamp_attr(hba);
+
        /* Gear up to HS gear if supported */
        if (hba->max_pwr_info.is_valid) {
                /*
@@ -9749,6 +9786,7 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                ret = ufshcd_set_dev_pwr_mode(hba, UFS_ACTIVE_PWR_MODE);
                if (ret)
                        goto set_old_link_state;
+               ufshcd_set_timestamp_attr(hba);
        }
 
        if (ufshcd_keep_autobkops_enabled_except_suspend(hba))
index 16624ba..580c8d0 100644 (file)
@@ -72,6 +72,7 @@ config SCSI_UFS_QCOM
 config SCSI_UFS_MEDIATEK
        tristate "Mediatek specific hooks to UFS controller platform driver"
        depends on SCSI_UFSHCD_PLATFORM && ARCH_MEDIATEK
+       depends on RESET_CONTROLLER
        select PHY_MTK_UFS
        select RESET_TI_SYSCON
        help
index 9784a77..76f6f26 100644 (file)
@@ -303,6 +303,8 @@ static struct device_node *xen_dt_get_node(struct device *dev)
                while (!pci_is_root_bus(bus))
                        bus = bus->parent;
 
+               if (!bus->bridge->parent)
+                       return NULL;
                return of_node_get(bus->bridge->parent->of_node);
        }
 
index 2a29943..cfad1ea 100644 (file)
@@ -148,7 +148,7 @@ static void *z_erofs_lz4_handle_overlap(struct z_erofs_lz4_decompress_ctx *ctx,
                *maptype = 0;
                return inpage;
        }
-       kunmap_atomic(inpage);
+       kunmap_local(inpage);
        might_sleep();
        src = erofs_vm_map_ram(rq->in, ctx->inpages);
        if (!src)
@@ -162,7 +162,7 @@ docopy:
        src = erofs_get_pcpubuf(ctx->inpages);
        if (!src) {
                DBG_BUGON(1);
-               kunmap_atomic(inpage);
+               kunmap_local(inpage);
                return ERR_PTR(-EFAULT);
        }
 
@@ -173,9 +173,9 @@ docopy:
                        min_t(unsigned int, total, PAGE_SIZE - *inputmargin);
 
                if (!inpage)
-                       inpage = kmap_atomic(*in);
+                       inpage = kmap_local_page(*in);
                memcpy(tmp, inpage + *inputmargin, page_copycnt);
-               kunmap_atomic(inpage);
+               kunmap_local(inpage);
                inpage = NULL;
                tmp += page_copycnt;
                total -= page_copycnt;
@@ -214,7 +214,7 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx,
        int ret, maptype;
 
        DBG_BUGON(*rq->in == NULL);
-       headpage = kmap_atomic(*rq->in);
+       headpage = kmap_local_page(*rq->in);
 
        /* LZ4 decompression inplace is only safe if zero_padding is enabled */
        if (erofs_sb_has_zero_padding(EROFS_SB(rq->sb))) {
@@ -223,7 +223,7 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx,
                                min_t(unsigned int, rq->inputsize,
                                      rq->sb->s_blocksize - rq->pageofs_in));
                if (ret) {
-                       kunmap_atomic(headpage);
+                       kunmap_local(headpage);
                        return ret;
                }
                may_inplace = !((rq->pageofs_in + rq->inputsize) &
@@ -261,7 +261,7 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx,
        }
 
        if (maptype == 0) {
-               kunmap_atomic(headpage);
+               kunmap_local(headpage);
        } else if (maptype == 1) {
                vm_unmap_ram(src, ctx->inpages);
        } else if (maptype == 2) {
@@ -289,7 +289,7 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
        /* one optimized fast path only for non bigpcluster cases yet */
        if (ctx.inpages == 1 && ctx.outpages == 1 && !rq->inplace_io) {
                DBG_BUGON(!*rq->out);
-               dst = kmap_atomic(*rq->out);
+               dst = kmap_local_page(*rq->out);
                dst_maptype = 0;
                goto dstmap_out;
        }
@@ -311,7 +311,7 @@ static int z_erofs_lz4_decompress(struct z_erofs_decompress_req *rq,
 dstmap_out:
        ret = z_erofs_lz4_decompress_mem(&ctx, dst + rq->pageofs_out);
        if (!dst_maptype)
-               kunmap_atomic(dst);
+               kunmap_local(dst);
        else if (dst_maptype == 2)
                vm_unmap_ram(dst, ctx.outpages);
        return ret;
@@ -328,7 +328,7 @@ static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
        const unsigned int lefthalf = rq->outputsize - righthalf;
        const unsigned int interlaced_offset =
                rq->alg == Z_EROFS_COMPRESSION_SHIFTED ? 0 : rq->pageofs_out;
-       unsigned char *src, *dst;
+       u8 *src;
 
        if (outpages > 2 && rq->alg == Z_EROFS_COMPRESSION_SHIFTED) {
                DBG_BUGON(1);
@@ -341,22 +341,19 @@ static int z_erofs_transform_plain(struct z_erofs_decompress_req *rq,
        }
 
        src = kmap_local_page(rq->in[inpages - 1]) + rq->pageofs_in;
-       if (rq->out[0]) {
-               dst = kmap_local_page(rq->out[0]);
-               memcpy(dst + rq->pageofs_out, src + interlaced_offset,
-                      righthalf);
-               kunmap_local(dst);
-       }
+       if (rq->out[0])
+               memcpy_to_page(rq->out[0], rq->pageofs_out,
+                              src + interlaced_offset, righthalf);
 
        if (outpages > inpages) {
                DBG_BUGON(!rq->out[outpages - 1]);
                if (rq->out[outpages - 1] != rq->in[inpages - 1]) {
-                       dst = kmap_local_page(rq->out[outpages - 1]);
-                       memcpy(dst, interlaced_offset ? src :
-                                       (src + righthalf), lefthalf);
-                       kunmap_local(dst);
+                       memcpy_to_page(rq->out[outpages - 1], 0, src +
+                                       (interlaced_offset ? 0 : righthalf),
+                                      lefthalf);
                } else if (!interlaced_offset) {
                        memmove(src, src + righthalf, lefthalf);
+                       flush_dcache_page(rq->in[inpages - 1]);
                }
        }
        kunmap_local(src);
index d70b12b..e125927 100644 (file)
@@ -183,7 +183,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,
 
        inode->i_flags &= ~S_DAX;
        if (test_opt(&sbi->opt, DAX_ALWAYS) && S_ISREG(inode->i_mode) &&
-           vi->datalayout == EROFS_INODE_FLAT_PLAIN)
+           (vi->datalayout == EROFS_INODE_FLAT_PLAIN ||
+            vi->datalayout == EROFS_INODE_CHUNK_BASED))
                inode->i_flags |= S_DAX;
 
        if (!nblks)
index 5f1890e..b69d89a 100644 (file)
@@ -1035,7 +1035,7 @@ hitted:
         */
        tight &= (fe->mode > Z_EROFS_PCLUSTER_FOLLOWED_NOINPLACE);
 
-       cur = end - min_t(unsigned int, offset + end - map->m_la, end);
+       cur = end - min_t(erofs_off_t, offset + end - map->m_la, end);
        if (!(map->m_flags & EROFS_MAP_MAPPED)) {
                zero_user_segment(page, cur, end);
                goto next_part;
@@ -1841,7 +1841,7 @@ static void z_erofs_pcluster_readmore(struct z_erofs_decompress_frontend *f,
        }
 
        cur = map->m_la + map->m_llen - 1;
-       while (cur >= end) {
+       while ((cur >= end) && (cur < i_size_read(inode))) {
                pgoff_t index = cur >> PAGE_SHIFT;
                struct page *page;
 
index b5808fe..e5eec6d 100644 (file)
@@ -532,7 +532,7 @@ struct smb_version_operations {
        /* Check for STATUS_IO_TIMEOUT */
        bool (*is_status_io_timeout)(char *buf);
        /* Check for STATUS_NETWORK_NAME_DELETED */
-       void (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
+       bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
 };
 
 struct smb_version_values {
index 19f7385..9dee267 100644 (file)
@@ -3184,7 +3184,7 @@ setAclRetry:
        param_offset = offsetof(struct smb_com_transaction2_spi_req,
                                InformationLevel) - 4;
        offset = param_offset + params;
-       parm_data = ((char *) &pSMB->hdr.Protocol) + offset;
+       parm_data = ((char *)pSMB) + sizeof(pSMB->hdr.smb_buf_length) + offset;
        pSMB->ParameterOffset = cpu_to_le16(param_offset);
 
        /* convert to on the wire format for POSIX ACL */
index 85dd1b3..9280e25 100644 (file)
@@ -60,7 +60,7 @@ extern bool disable_legacy_dialects;
 #define TLINK_IDLE_EXPIRE      (600 * HZ)
 
 /* Drop the connection to not overload the server */
-#define NUM_STATUS_IO_TIMEOUT   5
+#define MAX_STATUS_IO_TIMEOUT   5
 
 static int ip_connect(struct TCP_Server_Info *server);
 static int generic_ip_connect(struct TCP_Server_Info *server);
@@ -1117,6 +1117,7 @@ cifs_demultiplex_thread(void *p)
        struct mid_q_entry *mids[MAX_COMPOUND];
        char *bufs[MAX_COMPOUND];
        unsigned int noreclaim_flag, num_io_timeout = 0;
+       bool pending_reconnect = false;
 
        noreclaim_flag = memalloc_noreclaim_save();
        cifs_dbg(FYI, "Demultiplex PID: %d\n", task_pid_nr(current));
@@ -1156,6 +1157,8 @@ cifs_demultiplex_thread(void *p)
                cifs_dbg(FYI, "RFC1002 header 0x%x\n", pdu_length);
                if (!is_smb_response(server, buf[0]))
                        continue;
+
+               pending_reconnect = false;
 next_pdu:
                server->pdu_size = pdu_length;
 
@@ -1213,10 +1216,13 @@ next_pdu:
                if (server->ops->is_status_io_timeout &&
                    server->ops->is_status_io_timeout(buf)) {
                        num_io_timeout++;
-                       if (num_io_timeout > NUM_STATUS_IO_TIMEOUT) {
-                               cifs_reconnect(server, false);
+                       if (num_io_timeout > MAX_STATUS_IO_TIMEOUT) {
+                               cifs_server_dbg(VFS,
+                                               "Number of request timeouts exceeded %d. Reconnecting",
+                                               MAX_STATUS_IO_TIMEOUT);
+
+                               pending_reconnect = true;
                                num_io_timeout = 0;
-                               continue;
                        }
                }
 
@@ -1226,9 +1232,14 @@ next_pdu:
                        if (mids[i] != NULL) {
                                mids[i]->resp_buf_size = server->pdu_size;
 
-                               if (bufs[i] && server->ops->is_network_name_deleted)
-                                       server->ops->is_network_name_deleted(bufs[i],
-                                                                       server);
+                               if (bufs[i] != NULL) {
+                                       if (server->ops->is_network_name_deleted &&
+                                           server->ops->is_network_name_deleted(bufs[i],
+                                                                                server)) {
+                                               cifs_server_dbg(FYI,
+                                                               "Share deleted. Reconnect needed");
+                                       }
+                               }
 
                                if (!mids[i]->multiRsp || mids[i]->multiEnd)
                                        mids[i]->callback(mids[i]);
@@ -1263,6 +1274,11 @@ next_pdu:
                        buf = server->smallbuf;
                        goto next_pdu;
                }
+
+               /* do this reconnect at the very end after processing all MIDs */
+               if (pending_reconnect)
+                       cifs_reconnect(server, true);
+
        } /* end while !EXITING */
 
        /* buffer usually freed in free_mid - need to free it here on exit */
index 1403a2d..df3fd3b 100644 (file)
@@ -66,6 +66,12 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
        return rc;
 }
 
+/*
+ * Track individual DFS referral servers used by new DFS mount.
+ *
+ * On success, their lifetime will be shared by final tcon (dfs_ses_list).
+ * Otherwise, they will be put by dfs_put_root_smb_sessions() in cifs_mount().
+ */
 static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
 {
        struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
@@ -80,11 +86,12 @@ static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
                INIT_LIST_HEAD(&root_ses->list);
 
                spin_lock(&cifs_tcp_ses_lock);
-               ses->ses_count++;
+               cifs_smb_ses_inc_refcount(ses);
                spin_unlock(&cifs_tcp_ses_lock);
                root_ses->ses = ses;
                list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list);
        }
+       /* Select new DFS referral server so that new referrals go through it */
        ctx->dfs_root_ses = ses;
        return 0;
 }
@@ -242,7 +249,6 @@ out:
 int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
 {
        struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
-       struct cifs_ses *ses;
        bool nodfs = ctx->nodfs;
        int rc;
 
@@ -276,20 +282,8 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
        }
 
        *isdfs = true;
-       /*
-        * Prevent DFS root session of being put in the first call to
-        * cifs_mount_put_conns().  If another DFS root server was not found
-        * while chasing the referrals (@ctx->dfs_root_ses == @ses), then we
-        * can safely put extra refcount of @ses.
-        */
-       ses = mnt_ctx->ses;
-       mnt_ctx->ses = NULL;
-       mnt_ctx->server = NULL;
-       rc = __dfs_mount_share(mnt_ctx);
-       if (ses == ctx->dfs_root_ses)
-               cifs_put_smb_ses(ses);
-
-       return rc;
+       add_root_smb_session(mnt_ctx);
+       return __dfs_mount_share(mnt_ctx);
 }
 
 /* Update dfs referral path of superblock */
index 879bc8e..fc5acc9 100644 (file)
@@ -1080,8 +1080,8 @@ int cifs_close(struct inode *inode, struct file *file)
                cfile = file->private_data;
                file->private_data = NULL;
                dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
-               if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
-                   cinode->lease_granted &&
+               if ((cifs_sb->ctx->closetimeo && cinode->oplock == CIFS_CACHE_RHW_FLG)
+                   && cinode->lease_granted &&
                    !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) &&
                    dclose) {
                        if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) {
index 87abce0..0f62bc3 100644 (file)
@@ -2395,7 +2395,7 @@ smb2_is_status_io_timeout(char *buf)
                return false;
 }
 
-static void
+static bool
 smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
 {
        struct smb2_hdr *shdr = (struct smb2_hdr *)buf;
@@ -2404,7 +2404,7 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
        struct cifs_tcon *tcon;
 
        if (shdr->Status != STATUS_NETWORK_NAME_DELETED)
-               return;
+               return false;
 
        /* If server is a channel, select the primary channel */
        pserver = CIFS_SERVER_IS_CHAN(server) ? server->primary_server : server;
@@ -2419,11 +2419,13 @@ smb2_is_network_name_deleted(char *buf, struct TCP_Server_Info *server)
                                spin_unlock(&cifs_tcp_ses_lock);
                                pr_warn_once("Server share %s deleted.\n",
                                             tcon->tree_name);
-                               return;
+                               return true;
                        }
                }
        }
        spin_unlock(&cifs_tcp_ses_lock);
+
+       return false;
 }
 
 static int
index c6db898..7676091 100644 (file)
@@ -160,7 +160,7 @@ smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
                        spin_unlock(&ses->ses_lock);
                        continue;
                }
-               ++ses->ses_count;
+               cifs_smb_ses_inc_refcount(ses);
                spin_unlock(&ses->ses_lock);
                return ses;
        }
index 0587354..9c59409 100644 (file)
                *(.text.unlikely .text.unlikely.*)                      \
                *(.text.unknown .text.unknown.*)                        \
                NOINSTR_TEXT                                            \
-               *(.text..refcount)                                      \
                *(.ref.text)                                            \
                *(.text.asan.* .text.tsan.*)                            \
        MEM_KEEP(init.text*)                                            \
index e95b483..f9544d9 100644 (file)
@@ -583,15 +583,14 @@ void drm_sched_entity_set_priority(struct drm_sched_entity *entity,
 bool drm_sched_entity_is_ready(struct drm_sched_entity *entity);
 int drm_sched_entity_error(struct drm_sched_entity *entity);
 
-void drm_sched_fence_set_parent(struct drm_sched_fence *s_fence,
-                               struct dma_fence *fence);
 struct drm_sched_fence *drm_sched_fence_alloc(
        struct drm_sched_entity *s_entity, void *owner);
 void drm_sched_fence_init(struct drm_sched_fence *fence,
                          struct drm_sched_entity *entity);
 void drm_sched_fence_free(struct drm_sched_fence *fence);
 
-void drm_sched_fence_scheduled(struct drm_sched_fence *fence);
+void drm_sched_fence_scheduled(struct drm_sched_fence *fence,
+                              struct dma_fence *parent);
 void drm_sched_fence_finished(struct drm_sched_fence *fence, int result);
 
 unsigned long drm_sched_suspend_timeout(struct drm_gpu_scheduler *sched);
index e6802b6..90ab33c 100644 (file)
@@ -111,6 +111,7 @@ struct blk_crypto_profile {
         * keyslots while ensuring that they can't be changed concurrently.
         */
        struct rw_semaphore lock;
+       struct lock_class_key lockdep_key;
 
        /* List of idle slots, with least recently used slot at front */
        wait_queue_head_t idle_slots_wait_queue;
index 2b7fb8e..b96e004 100644 (file)
@@ -158,13 +158,13 @@ struct request {
 
        /*
         * The rb_node is only used inside the io scheduler, requests
-        * are pruned when moved to the dispatch queue. So let the
-        * completion_data share space with the rb_node.
+        * are pruned when moved to the dispatch queue. special_vec must
+        * only be used if RQF_SPECIAL_PAYLOAD is set, and those cannot be
+        * insert into an IO scheduler.
         */
        union {
                struct rb_node rb_node; /* sort/lookup */
                struct bio_vec special_vec;
-               void *completion_data;
        };
 
        /*
index d54b595..0d678e9 100644 (file)
@@ -606,7 +606,7 @@ static inline signed long dma_fence_wait(struct dma_fence *fence, bool intr)
 void dma_fence_set_deadline(struct dma_fence *fence, ktime_t deadline);
 
 struct dma_fence *dma_fence_get_stub(void);
-struct dma_fence *dma_fence_allocate_private_stub(void);
+struct dma_fence *dma_fence_allocate_private_stub(ktime_t timestamp);
 u64 dma_fence_context_alloc(unsigned num);
 
 extern const struct dma_fence_ops dma_fence_array_ops;
index 8e59bd9..ce156c7 100644 (file)
@@ -41,6 +41,15 @@ struct ftrace_ops;
 struct ftrace_regs;
 struct dyn_ftrace;
 
+char *arch_ftrace_match_adjust(char *str, const char *search);
+
+#ifdef CONFIG_HAVE_FUNCTION_GRAPH_RETVAL
+struct fgraph_ret_regs;
+unsigned long ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs);
+#else
+unsigned long ftrace_return_to_handler(unsigned long frame_pointer);
+#endif
+
 #ifdef CONFIG_FUNCTION_TRACER
 /*
  * If the arch's mcount caller does not support all of ftrace's
index ea2bcda..9a4c204 100644 (file)
@@ -44,9 +44,7 @@ struct ism_dev {
        u64 local_gid;
        int ieq_idx;
 
-       atomic_t free_clients_cnt;
-       atomic_t add_dev_cnt;
-       wait_queue_head_t waitq;
+       struct ism_client *subs[MAX_CLIENTS];
 };
 
 struct ism_event {
@@ -68,9 +66,6 @@ struct ism_client {
         */
        void (*handle_irq)(struct ism_dev *dev, unsigned int bit, u16 dmbemask);
        /* Private area - don't touch! */
-       struct work_struct remove_work;
-       struct work_struct add_work;
-       struct ism_dev *tgt_ism;
        u8 id;
 };
 
index 182b6d6..26dd3f8 100644 (file)
@@ -473,7 +473,7 @@ struct nvme_id_ns_nvm {
 };
 
 enum {
-       NVME_ID_NS_NVM_STS_MASK         = 0x3f,
+       NVME_ID_NS_NVM_STS_MASK         = 0x7f,
        NVME_ID_NS_NVM_GUARD_SHIFT      = 7,
        NVME_ID_NS_NVM_GUARD_MASK       = 0x3,
 };
index ab26200..e074587 100644 (file)
@@ -23,8 +23,9 @@ void psi_memstall_enter(unsigned long *flags);
 void psi_memstall_leave(unsigned long *flags);
 
 int psi_show(struct seq_file *s, struct psi_group *group, enum psi_res res);
-struct psi_trigger *psi_trigger_create(struct psi_group *group,
-                       char *buf, enum psi_res res, struct file *file);
+struct psi_trigger *psi_trigger_create(struct psi_group *group, char *buf,
+                                      enum psi_res res, struct file *file,
+                                      struct kernfs_open_file *of);
 void psi_trigger_destroy(struct psi_trigger *t);
 
 __poll_t psi_trigger_poll(void **trigger_ptr, struct file *file,
index 040c089..f1fd3a8 100644 (file)
@@ -137,6 +137,9 @@ struct psi_trigger {
        /* Wait queue for polling */
        wait_queue_head_t event_wait;
 
+       /* Kernfs file for cgroup triggers */
+       struct kernfs_open_file *of;
+
        /* Pending event flag */
        int event;
 
index fdf26cd..26b6f3c 100644 (file)
@@ -59,6 +59,7 @@ struct rethook_node {
 };
 
 struct rethook *rethook_alloc(void *data, rethook_handler_t handler);
+void rethook_stop(struct rethook *rh);
 void rethook_free(struct rethook *rh);
 void rethook_add_node(struct rethook *rh, struct rethook_node *node);
 struct rethook_node *rethook_try_get(struct rethook *rh);
index 9334371..f7dd950 100644 (file)
@@ -67,6 +67,9 @@ struct nf_conntrack_tuple {
                /* The protocol. */
                u_int8_t protonum;
 
+               /* The direction must be ignored for the tuplehash */
+               struct { } __nfct_hash_offsetend;
+
                /* The direction (for tuplehash) */
                u_int8_t dir;
        } dst;
index 84f2fd8..640441a 100644 (file)
@@ -1211,6 +1211,29 @@ int __nft_release_basechain(struct nft_ctx *ctx);
 
 unsigned int nft_do_chain(struct nft_pktinfo *pkt, void *priv);
 
+static inline bool nft_use_inc(u32 *use)
+{
+       if (*use == UINT_MAX)
+               return false;
+
+       (*use)++;
+
+       return true;
+}
+
+static inline void nft_use_dec(u32 *use)
+{
+       WARN_ON_ONCE((*use)-- == 0);
+}
+
+/* For error and abort path: restore use counter to previous state. */
+static inline void nft_use_inc_restore(u32 *use)
+{
+       WARN_ON_ONCE(!nft_use_inc(use));
+}
+
+#define nft_use_dec_restore    nft_use_dec
+
 /**
  *     struct nft_table - nf_tables table
  *
@@ -1296,8 +1319,8 @@ struct nft_object {
        struct list_head                list;
        struct rhlist_head              rhlhead;
        struct nft_object_hash_key      key;
-       u32                             genmask:2,
-                                       use:30;
+       u32                             genmask:2;
+       u32                             use;
        u64                             handle;
        u16                             udlen;
        u8                              *udata;
@@ -1399,8 +1422,8 @@ struct nft_flowtable {
        char                            *name;
        int                             hooknum;
        int                             ops_len;
-       u32                             genmask:2,
-                                       use:30;
+       u32                             genmask:2;
+       u32                             use;
        u64                             handle;
        /* runtime data below here */
        struct list_head                hook_list ____cacheline_aligned;
index e98aac9..1596056 100644 (file)
@@ -134,7 +134,7 @@ extern const struct nla_policy rtm_tca_policy[TCA_MAX + 1];
  */
 static inline unsigned int psched_mtu(const struct net_device *dev)
 {
-       return dev->mtu + dev->hard_header_len;
+       return READ_ONCE(dev->mtu) + dev->hard_header_len;
 }
 
 static inline struct net *qdisc_net(struct Qdisc *q)
index 22aae50..a8c2817 100644 (file)
@@ -663,6 +663,7 @@ struct ocelot_ops {
                              struct flow_stats *stats);
        void (*cut_through_fwd)(struct ocelot *ocelot);
        void (*tas_clock_adjust)(struct ocelot *ocelot);
+       void (*tas_guard_bands_update)(struct ocelot *ocelot, int port);
        void (*update_stats)(struct ocelot *ocelot);
 };
 
@@ -863,12 +864,12 @@ struct ocelot {
        struct mutex                    stat_view_lock;
        /* Lock for serializing access to the MAC table */
        struct mutex                    mact_lock;
-       /* Lock for serializing forwarding domain changes */
+       /* Lock for serializing forwarding domain changes, including the
+        * configuration of the Time-Aware Shaper, MAC Merge layer and
+        * cut-through forwarding, on which it depends
+        */
        struct mutex                    fwd_domain_lock;
 
-       /* Lock for serializing Time-Aware Shaper changes */
-       struct mutex                    tas_lock;
-
        struct workqueue_struct         *owq;
 
        u8                              ptp:1;
index 2801b65..fd3f9e5 100644 (file)
@@ -71,6 +71,31 @@ struct utp_upiu_query {
 };
 
 /**
+ * struct utp_upiu_query_v4_0 - upiu request buffer structure for
+ * query request >= UFS 4.0 spec.
+ * @opcode: command to perform B-0
+ * @idn: a value that indicates the particular type of data B-1
+ * @index: Index to further identify data B-2
+ * @selector: Index to further identify data B-3
+ * @osf4: spec field B-5
+ * @osf5: spec field B 6,7
+ * @osf6: spec field DW 8,9
+ * @osf7: spec field DW 10,11
+ */
+struct utp_upiu_query_v4_0 {
+       __u8 opcode;
+       __u8 idn;
+       __u8 index;
+       __u8 selector;
+       __u8 osf3;
+       __u8 osf4;
+       __be16 osf5;
+       __be32 osf6;
+       __be32 osf7;
+       __be32 reserved;
+};
+
+/**
  * struct utp_upiu_cmd - Command UPIU structure
  * @data_transfer_len: Data Transfer Length DW-3
  * @cdb: Command Descriptor Block CDB DW-4 to DW-7
index 4e8d624..198cb39 100644 (file)
@@ -170,6 +170,7 @@ enum attr_idn {
        QUERY_ATTR_IDN_WB_BUFF_LIFE_TIME_EST    = 0x1E,
        QUERY_ATTR_IDN_CURR_WB_BUFF_SIZE        = 0x1F,
        QUERY_ATTR_IDN_EXT_IID_EN               = 0x2A,
+       QUERY_ATTR_IDN_TIMESTAMP                = 0x30
 };
 
 /* Descriptor idn for Query requests */
index e8096d5..7505de2 100644 (file)
@@ -2489,6 +2489,8 @@ int io_run_task_work_sig(struct io_ring_ctx *ctx)
 static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
                                          struct io_wait_queue *iowq)
 {
+       int token, ret;
+
        if (unlikely(READ_ONCE(ctx->check_cq)))
                return 1;
        if (unlikely(!llist_empty(&ctx->work_llist)))
@@ -2499,11 +2501,20 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
                return -EINTR;
        if (unlikely(io_should_wake(iowq)))
                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.
+        */
+       token = io_schedule_prepare();
+       ret = 0;
        if (iowq->timeout == KTIME_MAX)
                schedule();
        else if (!schedule_hrtimeout(&iowq->timeout, HRTIMER_MODE_ABS))
-               return -ETIME;
-       return 0;
+               ret = -ETIME;
+       io_schedule_finish(token);
+       return ret;
 }
 
 /*
index 8a33e87..6ae02be 100644 (file)
@@ -122,22 +122,6 @@ static void get_cpu_map_entry(struct bpf_cpu_map_entry *rcpu)
        atomic_inc(&rcpu->refcnt);
 }
 
-/* called from workqueue, to workaround syscall using preempt_disable */
-static void cpu_map_kthread_stop(struct work_struct *work)
-{
-       struct bpf_cpu_map_entry *rcpu;
-
-       rcpu = container_of(work, struct bpf_cpu_map_entry, kthread_stop_wq);
-
-       /* Wait for flush in __cpu_map_entry_free(), via full RCU barrier,
-        * as it waits until all in-flight call_rcu() callbacks complete.
-        */
-       rcu_barrier();
-
-       /* kthread_stop will wake_up_process and wait for it to complete */
-       kthread_stop(rcpu->kthread);
-}
-
 static void __cpu_map_ring_cleanup(struct ptr_ring *ring)
 {
        /* The tear-down procedure should have made sure that queue is
@@ -165,6 +149,30 @@ static void put_cpu_map_entry(struct bpf_cpu_map_entry *rcpu)
        }
 }
 
+/* called from workqueue, to workaround syscall using preempt_disable */
+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);
+
+       /* Wait for flush in __cpu_map_entry_free(), via full RCU barrier,
+        * as it waits until all in-flight call_rcu() callbacks complete.
+        */
+       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);
+       }
+}
+
 static void cpu_map_bpf_prog_run_skb(struct bpf_cpu_map_entry *rcpu,
                                     struct list_head *listp,
                                     struct xdp_cpumap_stats *stats)
index 11e54dd..930b555 100644 (file)
@@ -5642,8 +5642,9 @@ continue_func:
                                verbose(env, "verifier bug. subprog has tail_call and async cb\n");
                                return -EFAULT;
                        }
-                        /* async callbacks don't increase bpf prog stack size */
-                       continue;
+                       /* async callbacks don't increase bpf prog stack size unless called directly */
+                       if (!bpf_pseudo_call(insn + i))
+                               continue;
                }
                i = next_insn;
 
index bfe3cd8..f55a40d 100644 (file)
@@ -3730,7 +3730,7 @@ static ssize_t pressure_write(struct kernfs_open_file *of, char *buf,
        }
 
        psi = cgroup_psi(cgrp);
-       new = psi_trigger_create(psi, buf, res, of->file);
+       new = psi_trigger_create(psi, buf, res, of->file, of);
        if (IS_ERR(new)) {
                cgroup_put(cgrp);
                return PTR_ERR(new);
index 7982cc9..016d997 100644 (file)
@@ -174,11 +174,10 @@ static bool cleanup_symbol_name(char *s)
         * LLVM appends various suffixes for local functions and variables that
         * must be promoted to global scope as part of LTO.  This can break
         * hooking of static functions with kprobes. '.' is not a valid
-        * character in an identifier in C. Suffixes observed:
+        * character in an identifier in C. Suffixes only in LLVM LTO observed:
         * - foo.llvm.[0-9a-f]+
-        * - foo.[0-9a-f]+
         */
-       res = strchr(s, '.');
+       res = strstr(s, ".llvm.");
        if (res) {
                *res = '\0';
                return true;
index ce13f1a..1fc6095 100644 (file)
@@ -1072,7 +1072,7 @@ static int kprobe_ftrace_enabled;
 static int __arm_kprobe_ftrace(struct kprobe *p, struct ftrace_ops *ops,
                               int *cnt)
 {
-       int ret = 0;
+       int ret;
 
        lockdep_assert_held(&kprobe_mutex);
 
@@ -1110,7 +1110,7 @@ static int arm_kprobe_ftrace(struct kprobe *p)
 static int __disarm_kprobe_ftrace(struct kprobe *p, struct ftrace_ops *ops,
                                  int *cnt)
 {
-       int ret = 0;
+       int ret;
 
        lockdep_assert_held(&kprobe_mutex);
 
@@ -2007,9 +2007,9 @@ void __weak arch_kretprobe_fixup_return(struct pt_regs *regs,
 unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
                                             void *frame_pointer)
 {
-       kprobe_opcode_t *correct_ret_addr = NULL;
        struct kretprobe_instance *ri = NULL;
        struct llist_node *first, *node = NULL;
+       kprobe_opcode_t *correct_ret_addr;
        struct kretprobe *rp;
 
        /* Find correct address and all nodes for this frame. */
@@ -2693,7 +2693,7 @@ void kprobe_free_init_mem(void)
 
 static int __init init_kprobes(void)
 {
-       int i, err = 0;
+       int i, err;
 
        /* FIXME allocate the probe table, currently defined statically */
        /* initialize all list heads */
index f62e89d..e1b4bfa 100644 (file)
@@ -1179,6 +1179,7 @@ static ssize_t resume_store(struct kobject *kobj, struct kobj_attribute *attr,
                unsigned maj, min, offset;
                char *p, dummy;
 
+               error = 0;
                if (sscanf(name, "%u:%u%c", &maj, &min, &dummy) == 2 ||
                    sscanf(name, "%u:%u:%u:%c", &maj, &min, &offset,
                                &dummy) == 3) {
index af51ed6..782d3b4 100644 (file)
@@ -426,6 +426,11 @@ late_initcall(cpu_latency_qos_init);
 
 /* Definitions related to the frequency QoS below. */
 
+static inline bool freq_qos_value_invalid(s32 value)
+{
+       return value < 0 && value != PM_QOS_DEFAULT_VALUE;
+}
+
 /**
  * freq_constraints_init - Initialize frequency QoS constraints.
  * @qos: Frequency QoS constraints to initialize.
@@ -531,7 +536,7 @@ int freq_qos_add_request(struct freq_constraints *qos,
 {
        int ret;
 
-       if (IS_ERR_OR_NULL(qos) || !req || value < 0)
+       if (IS_ERR_OR_NULL(qos) || !req || freq_qos_value_invalid(value))
                return -EINVAL;
 
        if (WARN(freq_qos_request_active(req),
@@ -563,7 +568,7 @@ EXPORT_SYMBOL_GPL(freq_qos_add_request);
  */
 int freq_qos_update_request(struct freq_qos_request *req, s32 new_value)
 {
-       if (!req || new_value < 0)
+       if (!req || freq_qos_value_invalid(new_value))
                return -EINVAL;
 
        if (WARN(!freq_qos_request_active(req),
index a80a739..b3e25be 100644 (file)
@@ -7174,7 +7174,7 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)
            recent_used_cpu != target &&
            cpus_share_cache(recent_used_cpu, target) &&
            (available_idle_cpu(recent_used_cpu) || sched_idle_cpu(recent_used_cpu)) &&
-           cpumask_test_cpu(p->recent_used_cpu, p->cpus_ptr) &&
+           cpumask_test_cpu(recent_used_cpu, p->cpus_ptr) &&
            asym_fits_cpu(task_util, util_min, util_max, recent_used_cpu)) {
                return recent_used_cpu;
        }
index 81fca77..9bb3f2b 100644 (file)
@@ -493,8 +493,12 @@ static u64 update_triggers(struct psi_group *group, u64 now, bool *update_total,
                        continue;
 
                /* Generate an event */
-               if (cmpxchg(&t->event, 0, 1) == 0)
-                       wake_up_interruptible(&t->event_wait);
+               if (cmpxchg(&t->event, 0, 1) == 0) {
+                       if (t->of)
+                               kernfs_notify(t->of->kn);
+                       else
+                               wake_up_interruptible(&t->event_wait);
+               }
                t->last_event_time = now;
                /* Reset threshold breach flag once event got generated */
                t->pending_event = false;
@@ -1271,8 +1275,9 @@ int psi_show(struct seq_file *m, struct psi_group *group, enum psi_res res)
        return 0;
 }
 
-struct psi_trigger *psi_trigger_create(struct psi_group *group,
-                       char *buf, enum psi_res res, struct file *file)
+struct psi_trigger *psi_trigger_create(struct psi_group *group, char *buf,
+                                      enum psi_res res, struct file *file,
+                                      struct kernfs_open_file *of)
 {
        struct psi_trigger *t;
        enum psi_states state;
@@ -1331,7 +1336,9 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group,
 
        t->event = 0;
        t->last_event_time = 0;
-       init_waitqueue_head(&t->event_wait);
+       t->of = of;
+       if (!of)
+               init_waitqueue_head(&t->event_wait);
        t->pending_event = false;
        t->aggregator = privileged ? PSI_POLL : PSI_AVGS;
 
@@ -1388,7 +1395,10 @@ void psi_trigger_destroy(struct psi_trigger *t)
         * being accessed later. Can happen if cgroup is deleted from under a
         * polling process.
         */
-       wake_up_pollfree(&t->event_wait);
+       if (t->of)
+               kernfs_notify(t->of->kn);
+       else
+               wake_up_interruptible(&t->event_wait);
 
        if (t->aggregator == PSI_AVGS) {
                mutex_lock(&group->avgs_lock);
@@ -1465,7 +1475,10 @@ __poll_t psi_trigger_poll(void **trigger_ptr,
        if (!t)
                return DEFAULT_POLLMASK | EPOLLERR | EPOLLPRI;
 
-       poll_wait(file, &t->event_wait, wait);
+       if (t->of)
+               kernfs_generic_poll(t->of, wait);
+       else
+               poll_wait(file, &t->event_wait, wait);
 
        if (cmpxchg(&t->event, 1, 0) == 1)
                ret |= EPOLLPRI;
@@ -1535,7 +1548,7 @@ static ssize_t psi_write(struct file *file, const char __user *user_buf,
                return -EBUSY;
        }
 
-       new = psi_trigger_create(&psi_system, buf, res, file);
+       new = psi_trigger_create(&psi_system, buf, res, file, NULL);
        if (IS_ERR(new)) {
                mutex_unlock(&seq->lock);
                return PTR_ERR(new);
index cd2c35b..c83c005 100644 (file)
@@ -15,6 +15,7 @@
 #include <trace/events/sched.h>
 
 #include "ftrace_internal.h"
+#include "trace.h"
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 #define ASSIGN_OPS_HASH(opsname, val) \
index e4704ec..3b21f40 100644 (file)
@@ -100,14 +100,22 @@ static void fprobe_kprobe_handler(unsigned long ip, unsigned long parent_ip,
                return;
        }
 
+       /*
+        * This user handler is shared with other kprobes and is not expected to be
+        * called recursively. So if any other kprobe handler is running, this will
+        * exit as kprobe does. See the section 'Share the callbacks with kprobes'
+        * in Documentation/trace/fprobe.rst for more information.
+        */
        if (unlikely(kprobe_running())) {
                fp->nmissed++;
-               return;
+               goto recursion_unlock;
        }
 
        kprobe_busy_begin();
        __fprobe_handler(ip, parent_ip, ops, fregs);
        kprobe_busy_end();
+
+recursion_unlock:
        ftrace_test_recursion_unlock(bit);
 }
 
@@ -371,19 +379,16 @@ int unregister_fprobe(struct fprobe *fp)
        if (!fprobe_is_registered(fp))
                return -EINVAL;
 
-       /*
-        * rethook_free() starts disabling the rethook, but the rethook handlers
-        * may be running on other processors at this point. To make sure that all
-        * current running handlers are finished, call unregister_ftrace_function()
-        * after this.
-        */
        if (fp->rethook)
-               rethook_free(fp->rethook);
+               rethook_stop(fp->rethook);
 
        ret = unregister_ftrace_function(&fp->ops);
        if (ret < 0)
                return ret;
 
+       if (fp->rethook)
+               rethook_free(fp->rethook);
+
        ftrace_free_filter(&fp->ops);
 
        return ret;
index 3740aca..05c0024 100644 (file)
@@ -3305,6 +3305,22 @@ static int ftrace_allocate_records(struct ftrace_page *pg, int count)
        return cnt;
 }
 
+static void ftrace_free_pages(struct ftrace_page *pages)
+{
+       struct ftrace_page *pg = pages;
+
+       while (pg) {
+               if (pg->records) {
+                       free_pages((unsigned long)pg->records, pg->order);
+                       ftrace_number_of_pages -= 1 << pg->order;
+               }
+               pages = pg->next;
+               kfree(pg);
+               pg = pages;
+               ftrace_number_of_groups--;
+       }
+}
+
 static struct ftrace_page *
 ftrace_allocate_pages(unsigned long num_to_init)
 {
@@ -3343,17 +3359,7 @@ ftrace_allocate_pages(unsigned long num_to_init)
        return start_pg;
 
  free_pages:
-       pg = start_pg;
-       while (pg) {
-               if (pg->records) {
-                       free_pages((unsigned long)pg->records, pg->order);
-                       ftrace_number_of_pages -= 1 << pg->order;
-               }
-               start_pg = pg->next;
-               kfree(pg);
-               pg = start_pg;
-               ftrace_number_of_groups--;
-       }
+       ftrace_free_pages(start_pg);
        pr_info("ftrace: FAILED to allocate memory for functions\n");
        return NULL;
 }
@@ -6471,9 +6477,11 @@ static int ftrace_process_locs(struct module *mod,
                               unsigned long *start,
                               unsigned long *end)
 {
+       struct ftrace_page *pg_unuse = NULL;
        struct ftrace_page *start_pg;
        struct ftrace_page *pg;
        struct dyn_ftrace *rec;
+       unsigned long skipped = 0;
        unsigned long count;
        unsigned long *p;
        unsigned long addr;
@@ -6536,8 +6544,10 @@ static int ftrace_process_locs(struct module *mod,
                 * object files to satisfy alignments.
                 * Skip any NULL pointers.
                 */
-               if (!addr)
+               if (!addr) {
+                       skipped++;
                        continue;
+               }
 
                end_offset = (pg->index+1) * sizeof(pg->records[0]);
                if (end_offset > PAGE_SIZE << pg->order) {
@@ -6551,8 +6561,10 @@ static int ftrace_process_locs(struct module *mod,
                rec->ip = addr;
        }
 
-       /* We should have used all pages */
-       WARN_ON(pg->next);
+       if (pg->next) {
+               pg_unuse = pg->next;
+               pg->next = NULL;
+       }
 
        /* Assign the last page to ftrace_pages */
        ftrace_pages = pg;
@@ -6574,6 +6586,11 @@ static int ftrace_process_locs(struct module *mod,
  out:
        mutex_unlock(&ftrace_lock);
 
+       /* We should have used all pages unless we skipped some */
+       if (pg_unuse) {
+               WARN_ON(!skipped);
+               ftrace_free_pages(pg_unuse);
+       }
        return ret;
 }
 
index 382775e..5012c04 100644 (file)
@@ -2,6 +2,9 @@
 #ifndef _LINUX_KERNEL_FTRACE_INTERNAL_H
 #define  _LINUX_KERNEL_FTRACE_INTERNAL_H
 
+int __register_ftrace_function(struct ftrace_ops *ops);
+int __unregister_ftrace_function(struct ftrace_ops *ops);
+
 #ifdef CONFIG_FUNCTION_TRACER
 
 extern struct mutex ftrace_lock;
@@ -15,8 +18,6 @@ int ftrace_ops_test(struct ftrace_ops *ops, unsigned long ip, void *regs);
 
 #else /* !CONFIG_DYNAMIC_FTRACE */
 
-int __register_ftrace_function(struct ftrace_ops *ops);
-int __unregister_ftrace_function(struct ftrace_ops *ops);
 /* Keep as macros so we do not need to define the commands */
 # define ftrace_startup(ops, command)                                  \
        ({                                                              \
index f32ee48..5eb9b59 100644 (file)
@@ -54,6 +54,19 @@ static void rethook_free_rcu(struct rcu_head *head)
 }
 
 /**
+ * rethook_stop() - Stop using a rethook.
+ * @rh: the struct rethook to stop.
+ *
+ * Stop using a rethook to prepare for freeing it. If you want to wait for
+ * all running rethook handler before calling rethook_free(), you need to
+ * call this first and wait RCU, and call rethook_free().
+ */
+void rethook_stop(struct rethook *rh)
+{
+       WRITE_ONCE(rh->handler, NULL);
+}
+
+/**
  * rethook_free() - Free struct rethook.
  * @rh: the struct rethook to be freed.
  *
index 834b361..14d8001 100644 (file)
@@ -5242,28 +5242,34 @@ unsigned long ring_buffer_size(struct trace_buffer *buffer, int cpu)
 }
 EXPORT_SYMBOL_GPL(ring_buffer_size);
 
+static void rb_clear_buffer_page(struct buffer_page *page)
+{
+       local_set(&page->write, 0);
+       local_set(&page->entries, 0);
+       rb_init_page(page->page);
+       page->read = 0;
+}
+
 static void
 rb_reset_cpu(struct ring_buffer_per_cpu *cpu_buffer)
 {
+       struct buffer_page *page;
+
        rb_head_page_deactivate(cpu_buffer);
 
        cpu_buffer->head_page
                = list_entry(cpu_buffer->pages, struct buffer_page, list);
-       local_set(&cpu_buffer->head_page->write, 0);
-       local_set(&cpu_buffer->head_page->entries, 0);
-       local_set(&cpu_buffer->head_page->page->commit, 0);
-
-       cpu_buffer->head_page->read = 0;
+       rb_clear_buffer_page(cpu_buffer->head_page);
+       list_for_each_entry(page, cpu_buffer->pages, list) {
+               rb_clear_buffer_page(page);
+       }
 
        cpu_buffer->tail_page = cpu_buffer->head_page;
        cpu_buffer->commit_page = cpu_buffer->head_page;
 
        INIT_LIST_HEAD(&cpu_buffer->reader_page->list);
        INIT_LIST_HEAD(&cpu_buffer->new_pages);
-       local_set(&cpu_buffer->reader_page->write, 0);
-       local_set(&cpu_buffer->reader_page->entries, 0);
-       local_set(&cpu_buffer->reader_page->page->commit, 0);
-       cpu_buffer->reader_page->read = 0;
+       rb_clear_buffer_page(cpu_buffer->reader_page);
 
        local_set(&cpu_buffer->entries_bytes, 0);
        local_set(&cpu_buffer->overrun, 0);
index 4529e26..be847d4 100644 (file)
@@ -3118,6 +3118,7 @@ static void __ftrace_trace_stack(struct trace_buffer *buffer,
        struct ftrace_stack *fstack;
        struct stack_entry *entry;
        int stackidx;
+       void *ptr;
 
        /*
         * Add one, for this function and the call to save_stack_trace()
@@ -3161,9 +3162,25 @@ static void __ftrace_trace_stack(struct trace_buffer *buffer,
                                    trace_ctx);
        if (!event)
                goto out;
-       entry = ring_buffer_event_data(event);
+       ptr = ring_buffer_event_data(event);
+       entry = ptr;
+
+       /*
+        * For backward compatibility reasons, the entry->caller is an
+        * array of 8 slots to store the stack. This is also exported
+        * to user space. The amount allocated on the ring buffer actually
+        * holds enough for the stack specified by nr_entries. This will
+        * go into the location of entry->caller. Due to string fortifiers
+        * checking the size of the destination of memcpy() it triggers
+        * when it detects that size is greater than 8. To hide this from
+        * the fortifiers, we use "ptr" and pointer arithmetic to assign caller.
+        *
+        * The below is really just:
+        *   memcpy(&entry->caller, fstack->calls, size);
+        */
+       ptr += offsetof(typeof(*entry), caller);
+       memcpy(ptr, fstack->calls, size);
 
-       memcpy(&entry->caller, fstack->calls, size);
        entry->size = nr_entries;
 
        if (!call_filter_check_discard(call, entry, buffer, event))
@@ -6764,6 +6781,7 @@ static int tracing_release_pipe(struct inode *inode, struct file *file)
 
        free_cpumask_var(iter->started);
        kfree(iter->fmt);
+       kfree(iter->temp);
        mutex_destroy(&iter->mutex);
        kfree(iter);
 
index ed7906b..e1edc21 100644 (file)
@@ -113,6 +113,8 @@ enum trace_type {
 #define MEM_FAIL(condition, fmt, ...)                                  \
        DO_ONCE_LITE_IF(condition, pr_err, "ERROR: " fmt, ##__VA_ARGS__)
 
+#define FAULT_STRING "(fault)"
+
 #define HIST_STACKTRACE_DEPTH  16
 #define HIST_STACKTRACE_SIZE   (HIST_STACKTRACE_DEPTH * sizeof(unsigned long))
 #define HIST_STACKTRACE_SKIP   5
index cb0077b..a0a704b 100644 (file)
@@ -644,6 +644,7 @@ static int enable_trace_eprobe(struct trace_event_call *call,
        struct trace_eprobe *ep;
        bool enabled;
        int ret = 0;
+       int cnt = 0;
 
        tp = trace_probe_primary_from_call(call);
        if (WARN_ON_ONCE(!tp))
@@ -667,12 +668,25 @@ static int enable_trace_eprobe(struct trace_event_call *call,
                if (ret)
                        break;
                enabled = true;
+               cnt++;
        }
 
        if (ret) {
                /* Failed to enable one of them. Roll back all */
-               if (enabled)
-                       disable_eprobe(ep, file->tr);
+               if (enabled) {
+                       /*
+                        * It's a bug if one failed for something other than memory
+                        * not being available but another eprobe succeeded.
+                        */
+                       WARN_ON_ONCE(ret != -ENOMEM);
+
+                       list_for_each_entry(pos, trace_probe_probe_list(tp), list) {
+                               ep = container_of(pos, struct trace_eprobe, tp);
+                               disable_eprobe(ep, file->tr);
+                               if (!--cnt)
+                                       break;
+                       }
+               }
                if (file)
                        trace_probe_remove_file(tp, file);
                else
index b97d3ad..c8c6138 100644 (file)
@@ -6663,13 +6663,15 @@ static int event_hist_trigger_parse(struct event_command *cmd_ops,
        if (get_named_trigger_data(trigger_data))
                goto enable;
 
-       if (has_hist_vars(hist_data))
-               save_hist_vars(hist_data);
-
        ret = create_actions(hist_data);
        if (ret)
                goto out_unreg;
 
+       if (has_hist_vars(hist_data) || hist_data->n_var_refs) {
+               if (save_hist_vars(hist_data))
+                       goto out_unreg;
+       }
+
        ret = tracing_map_init(hist_data->map);
        if (ret)
                goto out_unreg;
index 4f5e74b..33cb6af 100644 (file)
@@ -1317,6 +1317,9 @@ static int user_field_set_string(struct ftrace_event_field *field,
        pos += snprintf(buf + pos, LEN_OR_ZERO, " ");
        pos += snprintf(buf + pos, LEN_OR_ZERO, "%s", field->name);
 
+       if (str_has_prefix(field->type, "struct "))
+               pos += snprintf(buf + pos, LEN_OR_ZERO, " %d", field->size);
+
        if (colon)
                pos += snprintf(buf + pos, LEN_OR_ZERO, ";");
 
index 16548ee..3851cd1 100644 (file)
@@ -1,4 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
+
+#include "trace_kprobe_selftest.h"
+
 /*
  * Function used during the kprobe self test. This function is in a separate
  * compile unit so it can be compile with CC_FLAGS_FTRACE to ensure that it
index 7ba371d..b2b726b 100644 (file)
@@ -67,7 +67,7 @@ int PRINT_TYPE_FUNC_NAME(string)(struct trace_seq *s, void *data, void *ent)
        int len = *(u32 *)data >> 16;
 
        if (!len)
-               trace_seq_puts(s, "(fault)");
+               trace_seq_puts(s, FAULT_STRING);
        else
                trace_seq_printf(s, "\"%s\"",
                                 (const char *)get_loc_data(data, ent));
index c4e1d4c..bb723ee 100644 (file)
@@ -2,8 +2,6 @@
 #ifndef __TRACE_PROBE_KERNEL_H_
 #define __TRACE_PROBE_KERNEL_H_
 
-#define FAULT_STRING "(fault)"
-
 /*
  * This depends on trace_probe.h, but can not include it due to
  * the way trace_probe_tmpl.h is used by trace_kprobe.c and trace_eprobe.c.
@@ -15,16 +13,8 @@ static nokprobe_inline int
 fetch_store_strlen_user(unsigned long addr)
 {
        const void __user *uaddr =  (__force const void __user *)addr;
-       int ret;
 
-       ret = strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
-       /*
-        * strnlen_user_nofault returns zero on fault, insert the
-        * FAULT_STRING when that occurs.
-        */
-       if (ret <= 0)
-               return strlen(FAULT_STRING) + 1;
-       return ret;
+       return strnlen_user_nofault(uaddr, MAX_STRING_SIZE);
 }
 
 /* Return the length of string -- including null terminal byte */
@@ -44,18 +34,14 @@ fetch_store_strlen(unsigned long addr)
                len++;
        } while (c && ret == 0 && len < MAX_STRING_SIZE);
 
-       /* For faults, return enough to hold the FAULT_STRING */
-       return (ret < 0) ? strlen(FAULT_STRING) + 1 : len;
+       return (ret < 0) ? ret : len;
 }
 
-static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base, int len)
+static nokprobe_inline void set_data_loc(int ret, void *dest, void *__dest, void *base)
 {
-       if (ret >= 0) {
-               *(u32 *)dest = make_data_loc(ret, __dest - base);
-       } else {
-               strscpy(__dest, FAULT_STRING, len);
-               ret = strlen(__dest) + 1;
-       }
+       if (ret < 0)
+               ret = 0;
+       *(u32 *)dest = make_data_loc(ret, __dest - base);
 }
 
 /*
@@ -76,7 +62,7 @@ fetch_store_string_user(unsigned long addr, void *dest, void *base)
        __dest = get_loc_data(dest, base);
 
        ret = strncpy_from_user_nofault(__dest, uaddr, maxlen);
-       set_data_loc(ret, dest, __dest, base, maxlen);
+       set_data_loc(ret, dest, __dest, base);
 
        return ret;
 }
@@ -107,7 +93,7 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
         * probing.
         */
        ret = strncpy_from_kernel_nofault(__dest, (void *)addr, maxlen);
-       set_data_loc(ret, dest, __dest, base, maxlen);
+       set_data_loc(ret, dest, __dest, base);
 
        return ret;
 }
index 0070763..3935b34 100644 (file)
@@ -156,11 +156,11 @@ stage3:
                        code++;
                        goto array;
                case FETCH_OP_ST_USTRING:
-                       ret += fetch_store_strlen_user(val + code->offset);
+                       ret = fetch_store_strlen_user(val + code->offset);
                        code++;
                        goto array;
                case FETCH_OP_ST_SYMSTR:
-                       ret += fetch_store_symstrlen(val + code->offset);
+                       ret = fetch_store_symstrlen(val + code->offset);
                        code++;
                        goto array;
                default:
@@ -204,6 +204,8 @@ stage3:
 array:
        /* the last stage: Loop on array */
        if (code->op == FETCH_OP_LP_ARRAY) {
+               if (ret < 0)
+                       ret = 0;
                total += ret;
                if (++i < code->param) {
                        code = s3;
@@ -265,9 +267,7 @@ store_trace_args(void *data, struct trace_probe *tp, void *rec,
                if (unlikely(arg->dynamic))
                        *dl = make_data_loc(maxlen, dyndata - base);
                ret = process_fetch_insn(arg->code, rec, dl, base);
-               if (unlikely(ret < 0 && arg->dynamic)) {
-                       *dl = make_data_loc(0, dyndata - base);
-               } else {
+               if (arg->dynamic && likely(ret > 0)) {
                        dyndata += ret;
                        maxlen -= ret;
                }
index fa09b33..688bf57 100644 (file)
@@ -170,7 +170,8 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
                         */
                        ret++;
                *(u32 *)dest = make_data_loc(ret, (void *)dst - base);
-       }
+       } else
+               *(u32 *)dest = make_data_loc(0, (void *)dst - base);
 
        return ret;
 }
index b667b1e..e4dc809 100644 (file)
@@ -1349,7 +1349,7 @@ uaccess_end:
        return ret;
 }
 
-static int copy_iovec_from_user(struct iovec *iov,
+static __noclone int copy_iovec_from_user(struct iovec *iov,
                const struct iovec __user *uiov, unsigned long nr_segs)
 {
        int ret = -EFAULT;
index 1a888b8..1df1d29 100644 (file)
@@ -390,6 +390,8 @@ static int head_onwire_len(int ctrl_len, bool secure)
        int head_len;
        int rem_len;
 
+       BUG_ON(ctrl_len < 0 || ctrl_len > CEPH_MSG_MAX_CONTROL_LEN);
+
        if (secure) {
                head_len = CEPH_PREAMBLE_SECURE_LEN;
                if (ctrl_len > CEPH_PREAMBLE_INLINE_LEN) {
@@ -408,6 +410,10 @@ static int head_onwire_len(int ctrl_len, bool secure)
 static int __tail_onwire_len(int front_len, int middle_len, int data_len,
                             bool secure)
 {
+       BUG_ON(front_len < 0 || front_len > CEPH_MSG_MAX_FRONT_LEN ||
+              middle_len < 0 || middle_len > CEPH_MSG_MAX_MIDDLE_LEN ||
+              data_len < 0 || data_len > CEPH_MSG_MAX_DATA_LEN);
+
        if (!front_len && !middle_len && !data_len)
                return 0;
 
@@ -520,29 +526,34 @@ static int decode_preamble(void *p, struct ceph_frame_desc *desc)
                desc->fd_aligns[i] = ceph_decode_16(&p);
        }
 
-       /*
-        * This would fire for FRAME_TAG_WAIT (it has one empty
-        * segment), but we should never get it as client.
-        */
-       if (!desc->fd_lens[desc->fd_seg_cnt - 1]) {
-               pr_err("last segment empty\n");
+       if (desc->fd_lens[0] < 0 ||
+           desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) {
+               pr_err("bad control segment length %d\n", desc->fd_lens[0]);
                return -EINVAL;
        }
-
-       if (desc->fd_lens[0] > CEPH_MSG_MAX_CONTROL_LEN) {
-               pr_err("control segment too big %d\n", desc->fd_lens[0]);
+       if (desc->fd_lens[1] < 0 ||
+           desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) {
+               pr_err("bad front segment length %d\n", desc->fd_lens[1]);
                return -EINVAL;
        }
-       if (desc->fd_lens[1] > CEPH_MSG_MAX_FRONT_LEN) {
-               pr_err("front segment too big %d\n", desc->fd_lens[1]);
+       if (desc->fd_lens[2] < 0 ||
+           desc->fd_lens[2] > CEPH_MSG_MAX_MIDDLE_LEN) {
+               pr_err("bad middle segment length %d\n", desc->fd_lens[2]);
                return -EINVAL;
        }
-       if (desc->fd_lens[2] > CEPH_MSG_MAX_MIDDLE_LEN) {
-               pr_err("middle segment too big %d\n", desc->fd_lens[2]);
+       if (desc->fd_lens[3] < 0 ||
+           desc->fd_lens[3] > CEPH_MSG_MAX_DATA_LEN) {
+               pr_err("bad data segment length %d\n", desc->fd_lens[3]);
                return -EINVAL;
        }
-       if (desc->fd_lens[3] > CEPH_MSG_MAX_DATA_LEN) {
-               pr_err("data segment too big %d\n", desc->fd_lens[3]);
+
+       /*
+        * This would fire for FRAME_TAG_WAIT (it has one empty
+        * segment), but we should never get it as client.
+        */
+       if (!desc->fd_lens[desc->fd_seg_cnt - 1]) {
+               pr_err("last segment empty, segment count %d\n",
+                      desc->fd_seg_cnt);
                return -EINVAL;
        }
 
index 805b738..6aef976 100644 (file)
@@ -63,4 +63,6 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(napi_poll);
 EXPORT_TRACEPOINT_SYMBOL_GPL(tcp_send_reset);
 EXPORT_TRACEPOINT_SYMBOL_GPL(tcp_bad_csum);
 
+EXPORT_TRACEPOINT_SYMBOL_GPL(udp_fail_queue_rcv_skb);
+
 EXPORT_TRACEPOINT_SYMBOL_GPL(sk_data_ready);
index 6c5915e..a298992 100644 (file)
@@ -4261,6 +4261,11 @@ struct sk_buff *skb_segment_list(struct sk_buff *skb,
 
        skb_push(skb, -skb_network_offset(skb) + offset);
 
+       /* Ensure the head is writeable before touching the shared info */
+       err = skb_unclone(skb, GFP_ATOMIC);
+       if (err)
+               goto err_linearize;
+
        skb_shinfo(skb)->frag_list = NULL;
 
        while (list_skb) {
index 41e5ca8..8362130 100644 (file)
@@ -741,7 +741,7 @@ __bpf_kfunc int bpf_xdp_metadata_rx_hash(const struct xdp_md *ctx, u32 *hash,
 __diag_pop();
 
 BTF_SET8_START(xdp_metadata_kfunc_ids)
-#define XDP_METADATA_KFUNC(_, name) BTF_ID_FLAGS(func, name, 0)
+#define XDP_METADATA_KFUNC(_, name) BTF_ID_FLAGS(func, name, KF_TRUSTED_ARGS)
 XDP_METADATA_KFUNC_xxx
 #undef XDP_METADATA_KFUNC
 BTF_SET8_END(xdp_metadata_kfunc_ids)
index 5479da0..e5213e5 100644 (file)
@@ -318,9 +318,8 @@ static void addrconf_del_dad_work(struct inet6_ifaddr *ifp)
 static void addrconf_mod_rs_timer(struct inet6_dev *idev,
                                  unsigned long when)
 {
-       if (!timer_pending(&idev->rs_timer))
+       if (!mod_timer(&idev->rs_timer, jiffies + when))
                in6_dev_hold(idev);
-       mod_timer(&idev->rs_timer, jiffies + when);
 }
 
 static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
index 9edf1f4..65fa501 100644 (file)
@@ -424,7 +424,10 @@ static struct net_device *icmp6_dev(const struct sk_buff *skb)
        if (unlikely(dev->ifindex == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) {
                const struct rt6_info *rt6 = skb_rt6_info(skb);
 
-               if (rt6)
+               /* The destination could be an external IP in Ext Hdr (SRv6, RPL, etc.),
+                * and ip6_null_entry could be set to skb if no route is found.
+                */
+               if (rt6 && rt6->rt6i_idev)
                        dev = rt6->rt6i_idev->dev;
        }
 
index 317b01c..b7c972a 100644 (file)
@@ -45,6 +45,7 @@
 #include <net/tcp_states.h>
 #include <net/ip6_checksum.h>
 #include <net/ip6_tunnel.h>
+#include <trace/events/udp.h>
 #include <net/xfrm.h>
 #include <net/inet_hashtables.h>
 #include <net/inet6_hashtables.h>
@@ -90,7 +91,7 @@ static u32 udp6_ehashfn(const struct net *net,
        fhash = __ipv6_addr_jhash(faddr, udp_ipv6_hash_secret);
 
        return __inet6_ehashfn(lhash, lport, fhash, fport,
-                              udp_ipv6_hash_secret + net_hash_mix(net));
+                              udp6_ehash_secret + net_hash_mix(net));
 }
 
 int udp_v6_get_port(struct sock *sk, unsigned short snum)
@@ -680,6 +681,7 @@ static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
                }
                UDP6_INC_STATS(sock_net(sk), UDP_MIB_INERRORS, is_udplite);
                kfree_skb_reason(skb, drop_reason);
+               trace_udp_fail_queue_rcv_skb(rc, sk);
                return -1;
        }
 
index d119f1d..9923931 100644 (file)
@@ -211,24 +211,18 @@ static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple,
                              unsigned int zoneid,
                              const struct net *net)
 {
-       u64 a, b, c, d;
+       siphash_key_t key;
 
        get_random_once(&nf_conntrack_hash_rnd, sizeof(nf_conntrack_hash_rnd));
 
-       /* The direction must be ignored, handle usable tuplehash members manually */
-       a = (u64)tuple->src.u3.all[0] << 32 | tuple->src.u3.all[3];
-       b = (u64)tuple->dst.u3.all[0] << 32 | tuple->dst.u3.all[3];
+       key = nf_conntrack_hash_rnd;
 
-       c = (__force u64)tuple->src.u.all << 32 | (__force u64)tuple->dst.u.all << 16;
-       c |= tuple->dst.protonum;
+       key.key[0] ^= zoneid;
+       key.key[1] ^= net_hash_mix(net);
 
-       d = (u64)zoneid << 32 | net_hash_mix(net);
-
-       /* IPv4: u3.all[1,2,3] == 0 */
-       c ^= (u64)tuple->src.u3.all[1] << 32 | tuple->src.u3.all[2];
-       d += (u64)tuple->dst.u3.all[1] << 32 | tuple->dst.u3.all[2];
-
-       return (u32)siphash_4u64(a, b, c, d, &nf_conntrack_hash_rnd);
+       return siphash((void *)tuple,
+                       offsetofend(struct nf_conntrack_tuple, dst.__nfct_hash_offsetend),
+                       &key);
 }
 
 static u32 scale_hash(u32 hash)
index 0c4db2f..f22691f 100644 (file)
@@ -360,6 +360,9 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper *me)
        BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
        BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1);
 
+       if (!nf_ct_helper_hash)
+               return -ENOENT;
+
        if (me->expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
                return -EINVAL;
 
@@ -515,4 +518,5 @@ int nf_conntrack_helper_init(void)
 void nf_conntrack_helper_fini(void)
 {
        kvfree(nf_ct_helper_hash);
+       nf_ct_helper_hash = NULL;
 }
index ad6f0ca..af369e6 100644 (file)
@@ -205,6 +205,8 @@ int nf_conntrack_gre_packet(struct nf_conn *ct,
                            enum ip_conntrack_info ctinfo,
                            const struct nf_hook_state *state)
 {
+       unsigned long status;
+
        if (!nf_ct_is_confirmed(ct)) {
                unsigned int *timeouts = nf_ct_timeout_lookup(ct);
 
@@ -217,11 +219,17 @@ int nf_conntrack_gre_packet(struct nf_conn *ct,
                ct->proto.gre.timeout = timeouts[GRE_CT_UNREPLIED];
        }
 
+       status = READ_ONCE(ct->status);
        /* If we've seen traffic both ways, this is a GRE connection.
         * Extend timeout. */
-       if (ct->status & IPS_SEEN_REPLY) {
+       if (status & IPS_SEEN_REPLY) {
                nf_ct_refresh_acct(ct, ctinfo, skb,
                                   ct->proto.gre.stream_timeout);
+
+               /* never set ASSURED for IPS_NAT_CLASH, they time out soon */
+               if (unlikely((status & IPS_NAT_CLASH)))
+                       return NF_ACCEPT;
+
                /* Also, more likely to be important, and not a probe. */
                if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
                        nf_conntrack_event_cache(IPCT_ASSURED, ct);
index 9573a8f..237f739 100644 (file)
@@ -253,8 +253,10 @@ int nf_tables_bind_chain(const struct nft_ctx *ctx, struct nft_chain *chain)
        if (chain->bound)
                return -EBUSY;
 
+       if (!nft_use_inc(&chain->use))
+               return -EMFILE;
+
        chain->bound = true;
-       chain->use++;
        nft_chain_trans_bind(ctx, chain);
 
        return 0;
@@ -437,7 +439,7 @@ static int nft_delchain(struct nft_ctx *ctx)
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       ctx->table->use--;
+       nft_use_dec(&ctx->table->use);
        nft_deactivate_next(ctx->net, ctx->chain);
 
        return 0;
@@ -476,7 +478,7 @@ nf_tables_delrule_deactivate(struct nft_ctx *ctx, struct nft_rule *rule)
        /* You cannot delete the same rule twice */
        if (nft_is_active_next(ctx->net, rule)) {
                nft_deactivate_next(ctx->net, rule);
-               ctx->chain->use--;
+               nft_use_dec(&ctx->chain->use);
                return 0;
        }
        return -ENOENT;
@@ -644,7 +646,7 @@ static int nft_delset(const struct nft_ctx *ctx, struct nft_set *set)
                nft_map_deactivate(ctx, set);
 
        nft_deactivate_next(ctx->net, set);
-       ctx->table->use--;
+       nft_use_dec(&ctx->table->use);
 
        return err;
 }
@@ -676,7 +678,7 @@ static int nft_delobj(struct nft_ctx *ctx, struct nft_object *obj)
                return err;
 
        nft_deactivate_next(ctx->net, obj);
-       ctx->table->use--;
+       nft_use_dec(&ctx->table->use);
 
        return err;
 }
@@ -711,7 +713,7 @@ static int nft_delflowtable(struct nft_ctx *ctx,
                return err;
 
        nft_deactivate_next(ctx->net, flowtable);
-       ctx->table->use--;
+       nft_use_dec(&ctx->table->use);
 
        return err;
 }
@@ -2396,9 +2398,6 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
        struct nft_chain *chain;
        int err;
 
-       if (table->use == UINT_MAX)
-               return -EOVERFLOW;
-
        if (nla[NFTA_CHAIN_HOOK]) {
                struct nft_stats __percpu *stats = NULL;
                struct nft_chain_hook hook = {};
@@ -2494,6 +2493,11 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
        if (err < 0)
                goto err_destroy_chain;
 
+       if (!nft_use_inc(&table->use)) {
+               err = -EMFILE;
+               goto err_use;
+       }
+
        trans = nft_trans_chain_add(ctx, NFT_MSG_NEWCHAIN);
        if (IS_ERR(trans)) {
                err = PTR_ERR(trans);
@@ -2510,10 +2514,11 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 genmask,
                goto err_unregister_hook;
        }
 
-       table->use++;
-
        return 0;
+
 err_unregister_hook:
+       nft_use_dec_restore(&table->use);
+err_use:
        nf_tables_unregister_hook(net, table, chain);
 err_destroy_chain:
        nf_tables_chain_destroy(ctx);
@@ -2694,7 +2699,7 @@ err_hooks:
 
 static struct nft_chain *nft_chain_lookup_byid(const struct net *net,
                                               const struct nft_table *table,
-                                              const struct nlattr *nla)
+                                              const struct nlattr *nla, u8 genmask)
 {
        struct nftables_pernet *nft_net = nft_pernet(net);
        u32 id = ntohl(nla_get_be32(nla));
@@ -2705,7 +2710,8 @@ static struct nft_chain *nft_chain_lookup_byid(const struct net *net,
 
                if (trans->msg_type == NFT_MSG_NEWCHAIN &&
                    chain->table == table &&
-                   id == nft_trans_chain_id(trans))
+                   id == nft_trans_chain_id(trans) &&
+                   nft_active_genmask(chain, genmask))
                        return chain;
        }
        return ERR_PTR(-ENOENT);
@@ -3809,7 +3815,8 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
                        return -EOPNOTSUPP;
 
        } else if (nla[NFTA_RULE_CHAIN_ID]) {
-               chain = nft_chain_lookup_byid(net, table, nla[NFTA_RULE_CHAIN_ID]);
+               chain = nft_chain_lookup_byid(net, table, nla[NFTA_RULE_CHAIN_ID],
+                                             genmask);
                if (IS_ERR(chain)) {
                        NL_SET_BAD_ATTR(extack, nla[NFTA_RULE_CHAIN_ID]);
                        return PTR_ERR(chain);
@@ -3840,9 +3847,6 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
                        return -EINVAL;
                handle = nf_tables_alloc_handle(table);
 
-               if (chain->use == UINT_MAX)
-                       return -EOVERFLOW;
-
                if (nla[NFTA_RULE_POSITION]) {
                        pos_handle = be64_to_cpu(nla_get_be64(nla[NFTA_RULE_POSITION]));
                        old_rule = __nft_rule_lookup(chain, pos_handle);
@@ -3936,6 +3940,11 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
                }
        }
 
+       if (!nft_use_inc(&chain->use)) {
+               err = -EMFILE;
+               goto err_release_rule;
+       }
+
        if (info->nlh->nlmsg_flags & NLM_F_REPLACE) {
                err = nft_delrule(&ctx, old_rule);
                if (err < 0)
@@ -3967,7 +3976,6 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
                }
        }
        kvfree(expr_info);
-       chain->use++;
 
        if (flow)
                nft_trans_flow_rule(trans) = flow;
@@ -3978,6 +3986,7 @@ static int nf_tables_newrule(struct sk_buff *skb, const struct nfnl_info *info,
        return 0;
 
 err_destroy_flow_rule:
+       nft_use_dec_restore(&chain->use);
        if (flow)
                nft_flow_rule_destroy(flow);
 err_release_rule:
@@ -5014,9 +5023,15 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
        alloc_size = sizeof(*set) + size + udlen;
        if (alloc_size < size || alloc_size > INT_MAX)
                return -ENOMEM;
+
+       if (!nft_use_inc(&table->use))
+               return -EMFILE;
+
        set = kvzalloc(alloc_size, GFP_KERNEL_ACCOUNT);
-       if (!set)
-               return -ENOMEM;
+       if (!set) {
+               err = -ENOMEM;
+               goto err_alloc;
+       }
 
        name = nla_strdup(nla[NFTA_SET_NAME], GFP_KERNEL_ACCOUNT);
        if (!name) {
@@ -5074,7 +5089,7 @@ static int nf_tables_newset(struct sk_buff *skb, const struct nfnl_info *info,
                goto err_set_expr_alloc;
 
        list_add_tail_rcu(&set->list, &table->sets);
-       table->use++;
+
        return 0;
 
 err_set_expr_alloc:
@@ -5086,6 +5101,9 @@ err_set_init:
        kfree(set->name);
 err_set_name:
        kvfree(set);
+err_alloc:
+       nft_use_dec_restore(&table->use);
+
        return err;
 }
 
@@ -5224,9 +5242,6 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
        struct nft_set_binding *i;
        struct nft_set_iter iter;
 
-       if (set->use == UINT_MAX)
-               return -EOVERFLOW;
-
        if (!list_empty(&set->bindings) && nft_set_is_anonymous(set))
                return -EBUSY;
 
@@ -5254,10 +5269,12 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
                        return iter.err;
        }
 bind:
+       if (!nft_use_inc(&set->use))
+               return -EMFILE;
+
        binding->chain = ctx->chain;
        list_add_tail_rcu(&binding->list, &set->bindings);
        nft_set_trans_bind(ctx, set);
-       set->use++;
 
        return 0;
 }
@@ -5331,7 +5348,7 @@ void nf_tables_activate_set(const struct nft_ctx *ctx, struct nft_set *set)
                nft_clear(ctx->net, set);
        }
 
-       set->use++;
+       nft_use_inc_restore(&set->use);
 }
 EXPORT_SYMBOL_GPL(nf_tables_activate_set);
 
@@ -5347,7 +5364,7 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
                else
                        list_del_rcu(&binding->list);
 
-               set->use--;
+               nft_use_dec(&set->use);
                break;
        case NFT_TRANS_PREPARE:
                if (nft_set_is_anonymous(set)) {
@@ -5356,7 +5373,7 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
 
                        nft_deactivate_next(ctx->net, set);
                }
-               set->use--;
+               nft_use_dec(&set->use);
                return;
        case NFT_TRANS_ABORT:
        case NFT_TRANS_RELEASE:
@@ -5364,7 +5381,7 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
                    set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
                        nft_map_deactivate(ctx, set);
 
-               set->use--;
+               nft_use_dec(&set->use);
                fallthrough;
        default:
                nf_tables_unbind_set(ctx, set, binding,
@@ -6155,7 +6172,7 @@ void nft_set_elem_destroy(const struct nft_set *set, void *elem,
                nft_set_elem_expr_destroy(&ctx, nft_set_ext_expr(ext));
 
        if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
-               (*nft_set_ext_obj(ext))->use--;
+               nft_use_dec(&(*nft_set_ext_obj(ext))->use);
        kfree(elem);
 }
 EXPORT_SYMBOL_GPL(nft_set_elem_destroy);
@@ -6657,8 +6674,16 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
                                     set->objtype, genmask);
                if (IS_ERR(obj)) {
                        err = PTR_ERR(obj);
+                       obj = NULL;
+                       goto err_parse_key_end;
+               }
+
+               if (!nft_use_inc(&obj->use)) {
+                       err = -EMFILE;
+                       obj = NULL;
                        goto err_parse_key_end;
                }
+
                err = nft_set_ext_add(&tmpl, NFT_SET_EXT_OBJREF);
                if (err < 0)
                        goto err_parse_key_end;
@@ -6727,10 +6752,9 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
        if (flags)
                *nft_set_ext_flags(ext) = flags;
 
-       if (obj) {
+       if (obj)
                *nft_set_ext_obj(ext) = obj;
-               obj->use++;
-       }
+
        if (ulen > 0) {
                if (nft_set_ext_check(&tmpl, NFT_SET_EXT_USERDATA, ulen) < 0) {
                        err = -EINVAL;
@@ -6798,12 +6822,13 @@ err_element_clash:
        kfree(trans);
 err_elem_free:
        nf_tables_set_elem_destroy(ctx, set, elem.priv);
-       if (obj)
-               obj->use--;
 err_parse_data:
        if (nla[NFTA_SET_ELEM_DATA] != NULL)
                nft_data_release(&elem.data.val, desc.type);
 err_parse_key_end:
+       if (obj)
+               nft_use_dec_restore(&obj->use);
+
        nft_data_release(&elem.key_end.val, NFT_DATA_VALUE);
 err_parse_key:
        nft_data_release(&elem.key.val, NFT_DATA_VALUE);
@@ -6883,7 +6908,7 @@ void nft_data_hold(const struct nft_data *data, enum nft_data_types type)
                case NFT_JUMP:
                case NFT_GOTO:
                        chain = data->verdict.chain;
-                       chain->use++;
+                       nft_use_inc_restore(&chain->use);
                        break;
                }
        }
@@ -6898,7 +6923,7 @@ static void nft_setelem_data_activate(const struct net *net,
        if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
                nft_data_hold(nft_set_ext_data(ext), set->dtype);
        if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
-               (*nft_set_ext_obj(ext))->use++;
+               nft_use_inc_restore(&(*nft_set_ext_obj(ext))->use);
 }
 
 static void nft_setelem_data_deactivate(const struct net *net,
@@ -6910,7 +6935,7 @@ static void nft_setelem_data_deactivate(const struct net *net,
        if (nft_set_ext_exists(ext, NFT_SET_EXT_DATA))
                nft_data_release(nft_set_ext_data(ext), set->dtype);
        if (nft_set_ext_exists(ext, NFT_SET_EXT_OBJREF))
-               (*nft_set_ext_obj(ext))->use--;
+               nft_use_dec(&(*nft_set_ext_obj(ext))->use);
 }
 
 static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set,
@@ -7453,9 +7478,14 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
 
        nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
 
+       if (!nft_use_inc(&table->use))
+               return -EMFILE;
+
        type = nft_obj_type_get(net, objtype);
-       if (IS_ERR(type))
-               return PTR_ERR(type);
+       if (IS_ERR(type)) {
+               err = PTR_ERR(type);
+               goto err_type;
+       }
 
        obj = nft_obj_init(&ctx, type, nla[NFTA_OBJ_DATA]);
        if (IS_ERR(obj)) {
@@ -7489,7 +7519,7 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,
                goto err_obj_ht;
 
        list_add_tail_rcu(&obj->list, &table->objects);
-       table->use++;
+
        return 0;
 err_obj_ht:
        /* queued in transaction log */
@@ -7505,6 +7535,9 @@ err_strdup:
        kfree(obj);
 err_init:
        module_put(type->owner);
+err_type:
+       nft_use_dec_restore(&table->use);
+
        return err;
 }
 
@@ -7906,7 +7939,7 @@ void nf_tables_deactivate_flowtable(const struct nft_ctx *ctx,
        case NFT_TRANS_PREPARE:
        case NFT_TRANS_ABORT:
        case NFT_TRANS_RELEASE:
-               flowtable->use--;
+               nft_use_dec(&flowtable->use);
                fallthrough;
        default:
                return;
@@ -8260,9 +8293,14 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
 
        nft_ctx_init(&ctx, net, skb, info->nlh, family, table, NULL, nla);
 
+       if (!nft_use_inc(&table->use))
+               return -EMFILE;
+
        flowtable = kzalloc(sizeof(*flowtable), GFP_KERNEL_ACCOUNT);
-       if (!flowtable)
-               return -ENOMEM;
+       if (!flowtable) {
+               err = -ENOMEM;
+               goto flowtable_alloc;
+       }
 
        flowtable->table = table;
        flowtable->handle = nf_tables_alloc_handle(table);
@@ -8317,7 +8355,6 @@ static int nf_tables_newflowtable(struct sk_buff *skb,
                goto err5;
 
        list_add_tail_rcu(&flowtable->list, &table->flowtables);
-       table->use++;
 
        return 0;
 err5:
@@ -8334,6 +8371,9 @@ err2:
        kfree(flowtable->name);
 err1:
        kfree(flowtable);
+flowtable_alloc:
+       nft_use_dec_restore(&table->use);
+
        return err;
 }
 
@@ -9713,7 +9753,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                                 */
                                if (nft_set_is_anonymous(nft_trans_set(trans)) &&
                                    !list_empty(&nft_trans_set(trans)->bindings))
-                                       trans->ctx.table->use--;
+                                       nft_use_dec(&trans->ctx.table->use);
                        }
                        nf_tables_set_notify(&trans->ctx, nft_trans_set(trans),
                                             NFT_MSG_NEWSET, GFP_KERNEL);
@@ -9943,7 +9983,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                                        nft_trans_destroy(trans);
                                        break;
                                }
-                               trans->ctx.table->use--;
+                               nft_use_dec_restore(&trans->ctx.table->use);
                                nft_chain_del(trans->ctx.chain);
                                nf_tables_unregister_hook(trans->ctx.net,
                                                          trans->ctx.table,
@@ -9956,7 +9996,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                                list_splice(&nft_trans_chain_hooks(trans),
                                            &nft_trans_basechain(trans)->hook_list);
                        } else {
-                               trans->ctx.table->use++;
+                               nft_use_inc_restore(&trans->ctx.table->use);
                                nft_clear(trans->ctx.net, trans->ctx.chain);
                        }
                        nft_trans_destroy(trans);
@@ -9966,7 +10006,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                                nft_trans_destroy(trans);
                                break;
                        }
-                       trans->ctx.chain->use--;
+                       nft_use_dec_restore(&trans->ctx.chain->use);
                        list_del_rcu(&nft_trans_rule(trans)->list);
                        nft_rule_expr_deactivate(&trans->ctx,
                                                 nft_trans_rule(trans),
@@ -9976,7 +10016,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                        break;
                case NFT_MSG_DELRULE:
                case NFT_MSG_DESTROYRULE:
-                       trans->ctx.chain->use++;
+                       nft_use_inc_restore(&trans->ctx.chain->use);
                        nft_clear(trans->ctx.net, nft_trans_rule(trans));
                        nft_rule_expr_activate(&trans->ctx, nft_trans_rule(trans));
                        if (trans->ctx.chain->flags & NFT_CHAIN_HW_OFFLOAD)
@@ -9989,7 +10029,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                                nft_trans_destroy(trans);
                                break;
                        }
-                       trans->ctx.table->use--;
+                       nft_use_dec_restore(&trans->ctx.table->use);
                        if (nft_trans_set_bound(trans)) {
                                nft_trans_destroy(trans);
                                break;
@@ -9998,7 +10038,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                        break;
                case NFT_MSG_DELSET:
                case NFT_MSG_DESTROYSET:
-                       trans->ctx.table->use++;
+                       nft_use_inc_restore(&trans->ctx.table->use);
                        nft_clear(trans->ctx.net, nft_trans_set(trans));
                        if (nft_trans_set(trans)->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
                                nft_map_activate(&trans->ctx, nft_trans_set(trans));
@@ -10042,13 +10082,13 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                                nft_obj_destroy(&trans->ctx, nft_trans_obj_newobj(trans));
                                nft_trans_destroy(trans);
                        } else {
-                               trans->ctx.table->use--;
+                               nft_use_dec_restore(&trans->ctx.table->use);
                                nft_obj_del(nft_trans_obj(trans));
                        }
                        break;
                case NFT_MSG_DELOBJ:
                case NFT_MSG_DESTROYOBJ:
-                       trans->ctx.table->use++;
+                       nft_use_inc_restore(&trans->ctx.table->use);
                        nft_clear(trans->ctx.net, nft_trans_obj(trans));
                        nft_trans_destroy(trans);
                        break;
@@ -10057,7 +10097,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                                nft_unregister_flowtable_net_hooks(net,
                                                &nft_trans_flowtable_hooks(trans));
                        } else {
-                               trans->ctx.table->use--;
+                               nft_use_dec_restore(&trans->ctx.table->use);
                                list_del_rcu(&nft_trans_flowtable(trans)->list);
                                nft_unregister_flowtable_net_hooks(net,
                                                &nft_trans_flowtable(trans)->hook_list);
@@ -10069,7 +10109,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
                                list_splice(&nft_trans_flowtable_hooks(trans),
                                            &nft_trans_flowtable(trans)->hook_list);
                        } else {
-                               trans->ctx.table->use++;
+                               nft_use_inc_restore(&trans->ctx.table->use);
                                nft_clear(trans->ctx.net, nft_trans_flowtable(trans));
                        }
                        nft_trans_destroy(trans);
@@ -10502,7 +10542,8 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
                                                 genmask);
                } else if (tb[NFTA_VERDICT_CHAIN_ID]) {
                        chain = nft_chain_lookup_byid(ctx->net, ctx->table,
-                                                     tb[NFTA_VERDICT_CHAIN_ID]);
+                                                     tb[NFTA_VERDICT_CHAIN_ID],
+                                                     genmask);
                        if (IS_ERR(chain))
                                return PTR_ERR(chain);
                } else {
@@ -10518,8 +10559,9 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data,
                if (desc->flags & NFT_DATA_DESC_SETELEM &&
                    chain->flags & NFT_CHAIN_BINDING)
                        return -EINVAL;
+               if (!nft_use_inc(&chain->use))
+                       return -EMFILE;
 
-               chain->use++;
                data->verdict.chain = chain;
                break;
        }
@@ -10537,7 +10579,7 @@ static void nft_verdict_uninit(const struct nft_data *data)
        case NFT_JUMP:
        case NFT_GOTO:
                chain = data->verdict.chain;
-               chain->use--;
+               nft_use_dec(&chain->use);
                break;
        }
 }
@@ -10706,11 +10748,11 @@ int __nft_release_basechain(struct nft_ctx *ctx)
        nf_tables_unregister_hook(ctx->net, ctx->chain->table, ctx->chain);
        list_for_each_entry_safe(rule, nr, &ctx->chain->rules, list) {
                list_del(&rule->list);
-               ctx->chain->use--;
+               nft_use_dec(&ctx->chain->use);
                nf_tables_rule_release(ctx, rule);
        }
        nft_chain_del(ctx->chain);
-       ctx->table->use--;
+       nft_use_dec(&ctx->table->use);
        nf_tables_chain_destroy(ctx);
 
        return 0;
@@ -10760,18 +10802,18 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
                ctx.chain = chain;
                list_for_each_entry_safe(rule, nr, &chain->rules, list) {
                        list_del(&rule->list);
-                       chain->use--;
+                       nft_use_dec(&chain->use);
                        nf_tables_rule_release(&ctx, rule);
                }
        }
        list_for_each_entry_safe(flowtable, nf, &table->flowtables, list) {
                list_del(&flowtable->list);
-               table->use--;
+               nft_use_dec(&table->use);
                nf_tables_flowtable_destroy(flowtable);
        }
        list_for_each_entry_safe(set, ns, &table->sets, list) {
                list_del(&set->list);
-               table->use--;
+               nft_use_dec(&table->use);
                if (set->flags & (NFT_SET_MAP | NFT_SET_OBJECT))
                        nft_map_deactivate(&ctx, set);
 
@@ -10779,13 +10821,13 @@ static void __nft_release_table(struct net *net, struct nft_table *table)
        }
        list_for_each_entry_safe(obj, ne, &table->objects, list) {
                nft_obj_del(obj);
-               table->use--;
+               nft_use_dec(&table->use);
                nft_obj_destroy(&ctx, obj);
        }
        list_for_each_entry_safe(chain, nc, &table->chains, list) {
                ctx.chain = chain;
                nft_chain_del(chain);
-               table->use--;
+               nft_use_dec(&table->use);
                nf_tables_chain_destroy(&ctx);
        }
        nf_tables_table_destroy(&ctx);
index 9a85e79..e596d1a 100644 (file)
@@ -30,11 +30,11 @@ void nft_byteorder_eval(const struct nft_expr *expr,
        const struct nft_byteorder *priv = nft_expr_priv(expr);
        u32 *src = &regs->data[priv->sreg];
        u32 *dst = &regs->data[priv->dreg];
-       union { u32 u32; u16 u16; } *s, *d;
+       u16 *s16, *d16;
        unsigned int i;
 
-       s = (void *)src;
-       d = (void *)dst;
+       s16 = (void *)src;
+       d16 = (void *)dst;
 
        switch (priv->size) {
        case 8: {
@@ -62,11 +62,11 @@ void nft_byteorder_eval(const struct nft_expr *expr,
                switch (priv->op) {
                case NFT_BYTEORDER_NTOH:
                        for (i = 0; i < priv->len / 4; i++)
-                               d[i].u32 = ntohl((__force __be32)s[i].u32);
+                               dst[i] = ntohl((__force __be32)src[i]);
                        break;
                case NFT_BYTEORDER_HTON:
                        for (i = 0; i < priv->len / 4; i++)
-                               d[i].u32 = (__force __u32)htonl(s[i].u32);
+                               dst[i] = (__force __u32)htonl(src[i]);
                        break;
                }
                break;
@@ -74,11 +74,11 @@ void nft_byteorder_eval(const struct nft_expr *expr,
                switch (priv->op) {
                case NFT_BYTEORDER_NTOH:
                        for (i = 0; i < priv->len / 2; i++)
-                               d[i].u16 = ntohs((__force __be16)s[i].u16);
+                               d16[i] = ntohs((__force __be16)s16[i]);
                        break;
                case NFT_BYTEORDER_HTON:
                        for (i = 0; i < priv->len / 2; i++)
-                               d[i].u16 = (__force __u16)htons(s[i].u16);
+                               d16[i] = (__force __u16)htons(s16[i]);
                        break;
                }
                break;
index 5ef9146..ab3362c 100644 (file)
@@ -408,8 +408,10 @@ static int nft_flow_offload_init(const struct nft_ctx *ctx,
        if (IS_ERR(flowtable))
                return PTR_ERR(flowtable);
 
+       if (!nft_use_inc(&flowtable->use))
+               return -EMFILE;
+
        priv->flowtable = flowtable;
-       flowtable->use++;
 
        return nf_ct_netns_get(ctx->net, ctx->family);
 }
@@ -428,7 +430,7 @@ static void nft_flow_offload_activate(const struct nft_ctx *ctx,
 {
        struct nft_flow_offload *priv = nft_expr_priv(expr);
 
-       priv->flowtable->use++;
+       nft_use_inc_restore(&priv->flowtable->use);
 }
 
 static void nft_flow_offload_destroy(const struct nft_ctx *ctx,
index 3d76ebf..407d719 100644 (file)
@@ -159,7 +159,7 @@ static void nft_immediate_deactivate(const struct nft_ctx *ctx,
                        default:
                                nft_chain_del(chain);
                                chain->bound = false;
-                               chain->table->use--;
+                               nft_use_dec(&chain->table->use);
                                break;
                        }
                        break;
@@ -198,7 +198,7 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
                 * let the transaction records release this chain and its rules.
                 */
                if (chain->bound) {
-                       chain->use--;
+                       nft_use_dec(&chain->use);
                        break;
                }
 
@@ -206,9 +206,9 @@ static void nft_immediate_destroy(const struct nft_ctx *ctx,
                chain_ctx = *ctx;
                chain_ctx.chain = chain;
 
-               chain->use--;
+               nft_use_dec(&chain->use);
                list_for_each_entry_safe(rule, n, &chain->rules, list) {
-                       chain->use--;
+                       nft_use_dec(&chain->use);
                        list_del(&rule->list);
                        nf_tables_rule_destroy(&chain_ctx, rule);
                }
index a48dd5b..509011b 100644 (file)
@@ -41,8 +41,10 @@ static int nft_objref_init(const struct nft_ctx *ctx,
        if (IS_ERR(obj))
                return -ENOENT;
 
+       if (!nft_use_inc(&obj->use))
+               return -EMFILE;
+
        nft_objref_priv(expr) = obj;
-       obj->use++;
 
        return 0;
 }
@@ -72,7 +74,7 @@ static void nft_objref_deactivate(const struct nft_ctx *ctx,
        if (phase == NFT_TRANS_COMMIT)
                return;
 
-       obj->use--;
+       nft_use_dec(&obj->use);
 }
 
 static void nft_objref_activate(const struct nft_ctx *ctx,
@@ -80,7 +82,7 @@ static void nft_objref_activate(const struct nft_ctx *ctx,
 {
        struct nft_object *obj = nft_objref_priv(expr);
 
-       obj->use++;
+       nft_use_inc_restore(&obj->use);
 }
 
 static const struct nft_expr_ops nft_objref_ops = {
index f7887f4..9d3f26b 100644 (file)
@@ -1320,7 +1320,7 @@ struct tc_action_ops *tc_action_load_ops(struct nlattr *nla, bool police,
                        return ERR_PTR(err);
                }
        } else {
-               if (strlcpy(act_name, "police", IFNAMSIZ) >= IFNAMSIZ) {
+               if (strscpy(act_name, "police", IFNAMSIZ) < 0) {
                        NL_SET_ERR_MSG(extack, "TC action name too long");
                        return ERR_PTR(-EINVAL);
                }
index 56065cc..f2b0bc4 100644 (file)
@@ -812,6 +812,16 @@ static int fl_set_key_port_range(struct nlattr **tb, struct fl_flow_key *key,
                       TCA_FLOWER_KEY_PORT_SRC_MAX, &mask->tp_range.tp_max.src,
                       TCA_FLOWER_UNSPEC, sizeof(key->tp_range.tp_max.src));
 
+       if (mask->tp_range.tp_min.dst != mask->tp_range.tp_max.dst) {
+               NL_SET_ERR_MSG(extack,
+                              "Both min and max destination ports must be specified");
+               return -EINVAL;
+       }
+       if (mask->tp_range.tp_min.src != mask->tp_range.tp_max.src) {
+               NL_SET_ERR_MSG(extack,
+                              "Both min and max source ports must be specified");
+               return -EINVAL;
+       }
        if (mask->tp_range.tp_min.dst && mask->tp_range.tp_max.dst &&
            ntohs(key->tp_range.tp_max.dst) <=
            ntohs(key->tp_range.tp_min.dst)) {
index ae9439a..8641f80 100644 (file)
@@ -212,11 +212,6 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp,
        if (err < 0)
                return err;
 
-       if (tb[TCA_FW_CLASSID]) {
-               f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
-               tcf_bind_filter(tp, &f->res, base);
-       }
-
        if (tb[TCA_FW_INDEV]) {
                int ret;
                ret = tcf_change_indev(net, tb[TCA_FW_INDEV], extack);
@@ -233,6 +228,11 @@ static int fw_set_parms(struct net *net, struct tcf_proto *tp,
        } else if (head->mask != 0xFFFFFFFF)
                return err;
 
+       if (tb[TCA_FW_CLASSID]) {
+               f->res.classid = nla_get_u32(tb[TCA_FW_CLASSID]);
+               tcf_bind_filter(tp, &f->res, base);
+       }
+
        return 0;
 }
 
index dfd9a99..befaf74 100644 (file)
@@ -381,8 +381,13 @@ static int qfq_change_agg(struct Qdisc *sch, struct qfq_class *cl, u32 weight,
                           u32 lmax)
 {
        struct qfq_sched *q = qdisc_priv(sch);
-       struct qfq_aggregate *new_agg = qfq_find_agg(q, lmax, weight);
+       struct qfq_aggregate *new_agg;
 
+       /* 'lmax' can range from [QFQ_MIN_LMAX, pktlen + stab overhead] */
+       if (lmax > QFQ_MAX_LMAX)
+               return -EINVAL;
+
+       new_agg = qfq_find_agg(q, lmax, weight);
        if (new_agg == NULL) { /* create new aggregate */
                new_agg = kzalloc(sizeof(*new_agg), GFP_ATOMIC);
                if (new_agg == NULL)
@@ -423,10 +428,17 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid,
        else
                weight = 1;
 
-       if (tb[TCA_QFQ_LMAX])
+       if (tb[TCA_QFQ_LMAX]) {
                lmax = nla_get_u32(tb[TCA_QFQ_LMAX]);
-       else
+       } else {
+               /* MTU size is user controlled */
                lmax = psched_mtu(qdisc_dev(sch));
+               if (lmax < QFQ_MIN_LMAX || lmax > QFQ_MAX_LMAX) {
+                       NL_SET_ERR_MSG_MOD(extack,
+                                          "MTU size out of bounds for qfq");
+                       return -EINVAL;
+               }
+       }
 
        inv_w = ONE_FP / weight;
        weight = ONE_FP / inv_w;
index 89c9ad6..1783ab9 100644 (file)
@@ -580,6 +580,8 @@ int ieee80211_strip_8023_mesh_hdr(struct sk_buff *skb)
                hdrlen += ETH_ALEN + 2;
        else if (!pskb_may_pull(skb, hdrlen))
                return -EINVAL;
+       else
+               payload.eth.h_proto = htons(skb->len - hdrlen);
 
        mesh_addr = skb->data + sizeof(payload.eth) + ETH_ALEN;
        switch (payload.flags & MESH_FLAGS_AE) {
index 06d8891..e5ed080 100644 (file)
@@ -2,7 +2,9 @@
 #include <linux/module.h>
 #include <linux/kthread.h>
 #include <linux/ftrace.h>
+#ifndef CONFIG_ARM64
 #include <asm/asm-offsets.h>
+#endif
 
 extern void my_direct_func1(void);
 extern void my_direct_func2(void);
@@ -96,6 +98,38 @@ asm (
 
 #endif /* CONFIG_S390 */
 
+#ifdef CONFIG_ARM64
+
+asm (
+"      .pushsection    .text, \"ax\", @progbits\n"
+"      .type           my_tramp1, @function\n"
+"      .globl          my_tramp1\n"
+"   my_tramp1:"
+"      bti     c\n"
+"      sub     sp, sp, #16\n"
+"      stp     x9, x30, [sp]\n"
+"      bl      my_direct_func1\n"
+"      ldp     x30, x9, [sp]\n"
+"      add     sp, sp, #16\n"
+"      ret     x9\n"
+"      .size           my_tramp1, .-my_tramp1\n"
+
+"      .type           my_tramp2, @function\n"
+"      .globl          my_tramp2\n"
+"   my_tramp2:"
+"      bti     c\n"
+"      sub     sp, sp, #16\n"
+"      stp     x9, x30, [sp]\n"
+"      bl      my_direct_func2\n"
+"      ldp     x30, x9, [sp]\n"
+"      add     sp, sp, #16\n"
+"      ret     x9\n"
+"      .size           my_tramp2, .-my_tramp2\n"
+"      .popsection\n"
+);
+
+#endif /* CONFIG_ARM64 */
+
 #ifdef CONFIG_LOONGARCH
 
 asm (
index 62f6b68..292cff2 100644 (file)
@@ -2,7 +2,9 @@
 #include <linux/module.h>
 #include <linux/kthread.h>
 #include <linux/ftrace.h>
+#ifndef CONFIG_ARM64
 #include <asm/asm-offsets.h>
+#endif
 
 extern void my_direct_func1(unsigned long ip);
 extern void my_direct_func2(unsigned long ip);
@@ -103,6 +105,44 @@ asm (
 
 #endif /* CONFIG_S390 */
 
+#ifdef CONFIG_ARM64
+
+asm (
+"      .pushsection    .text, \"ax\", @progbits\n"
+"      .type           my_tramp1, @function\n"
+"      .globl          my_tramp1\n"
+"   my_tramp1:"
+"      bti     c\n"
+"      sub     sp, sp, #32\n"
+"      stp     x9, x30, [sp]\n"
+"      str     x0, [sp, #16]\n"
+"      mov     x0, x30\n"
+"      bl      my_direct_func1\n"
+"      ldp     x30, x9, [sp]\n"
+"      ldr     x0, [sp, #16]\n"
+"      add     sp, sp, #32\n"
+"      ret     x9\n"
+"      .size           my_tramp1, .-my_tramp1\n"
+
+"      .type           my_tramp2, @function\n"
+"      .globl          my_tramp2\n"
+"   my_tramp2:"
+"      bti     c\n"
+"      sub     sp, sp, #32\n"
+"      stp     x9, x30, [sp]\n"
+"      str     x0, [sp, #16]\n"
+"      mov     x0, x30\n"
+"      bl      my_direct_func2\n"
+"      ldp     x30, x9, [sp]\n"
+"      ldr     x0, [sp, #16]\n"
+"      add     sp, sp, #32\n"
+"      ret     x9\n"
+"      .size           my_tramp2, .-my_tramp2\n"
+"      .popsection\n"
+);
+
+#endif /* CONFIG_ARM64 */
+
 #ifdef CONFIG_LOONGARCH
 #include <asm/asm.h>
 
index 5482cf6..b4391e0 100644 (file)
@@ -4,7 +4,9 @@
 #include <linux/mm.h> /* for handle_mm_fault() */
 #include <linux/ftrace.h>
 #include <linux/sched/stat.h>
+#ifndef CONFIG_ARM64
 #include <asm/asm-offsets.h>
+#endif
 
 extern void my_direct_func(unsigned long ip);
 
@@ -66,6 +68,29 @@ asm (
 
 #endif /* CONFIG_S390 */
 
+#ifdef CONFIG_ARM64
+
+asm (
+"      .pushsection    .text, \"ax\", @progbits\n"
+"      .type           my_tramp, @function\n"
+"      .globl          my_tramp\n"
+"   my_tramp:"
+"      bti     c\n"
+"      sub     sp, sp, #32\n"
+"      stp     x9, x30, [sp]\n"
+"      str     x0, [sp, #16]\n"
+"      mov     x0, x30\n"
+"      bl      my_direct_func\n"
+"      ldp     x30, x9, [sp]\n"
+"      ldr     x0, [sp, #16]\n"
+"      add     sp, sp, #32\n"
+"      ret     x9\n"
+"      .size           my_tramp, .-my_tramp\n"
+"      .popsection\n"
+);
+
+#endif /* CONFIG_ARM64 */
+
 #ifdef CONFIG_LOONGARCH
 
 #include <asm/asm.h>
index a05bc2c..e9804c5 100644 (file)
@@ -3,16 +3,18 @@
 
 #include <linux/mm.h> /* for handle_mm_fault() */
 #include <linux/ftrace.h>
+#ifndef CONFIG_ARM64
 #include <asm/asm-offsets.h>
+#endif
 
-extern void my_direct_func(struct vm_area_struct *vma,
-                          unsigned long address, unsigned int flags);
+extern void my_direct_func(struct vm_area_struct *vma, unsigned long address,
+                          unsigned int flags, struct pt_regs *regs);
 
-void my_direct_func(struct vm_area_struct *vma,
-                       unsigned long address, unsigned int flags)
+void my_direct_func(struct vm_area_struct *vma, unsigned long address,
+                   unsigned int flags, struct pt_regs *regs)
 {
-       trace_printk("handle mm fault vma=%p address=%lx flags=%x\n",
-                    vma, address, flags);
+       trace_printk("handle mm fault vma=%p address=%lx flags=%x regs=%p\n",
+                    vma, address, flags, regs);
 }
 
 extern void my_tramp(void *);
@@ -34,7 +36,9 @@ asm (
 "      pushq %rdi\n"
 "      pushq %rsi\n"
 "      pushq %rdx\n"
+"      pushq %rcx\n"
 "      call my_direct_func\n"
+"      popq %rcx\n"
 "      popq %rdx\n"
 "      popq %rsi\n"
 "      popq %rdi\n"
@@ -70,6 +74,30 @@ asm (
 
 #endif /* CONFIG_S390 */
 
+#ifdef CONFIG_ARM64
+
+asm (
+"      .pushsection    .text, \"ax\", @progbits\n"
+"      .type           my_tramp, @function\n"
+"      .globl          my_tramp\n"
+"   my_tramp:"
+"      bti     c\n"
+"      sub     sp, sp, #48\n"
+"      stp     x9, x30, [sp]\n"
+"      stp     x0, x1, [sp, #16]\n"
+"      stp     x2, x3, [sp, #32]\n"
+"      bl      my_direct_func\n"
+"      ldp     x30, x9, [sp]\n"
+"      ldp     x0, x1, [sp, #16]\n"
+"      ldp     x2, x3, [sp, #32]\n"
+"      add     sp, sp, #48\n"
+"      ret     x9\n"
+"      .size           my_tramp, .-my_tramp\n"
+"      .popsection\n"
+);
+
+#endif /* CONFIG_ARM64 */
+
 #ifdef CONFIG_LOONGARCH
 
 asm (
index 06879bb..20f4a7c 100644 (file)
@@ -3,7 +3,9 @@
 
 #include <linux/sched.h> /* for wake_up_process() */
 #include <linux/ftrace.h>
+#ifndef CONFIG_ARM64
 #include <asm/asm-offsets.h>
+#endif
 
 extern void my_direct_func(struct task_struct *p);
 
@@ -63,6 +65,28 @@ asm (
 
 #endif /* CONFIG_S390 */
 
+#ifdef CONFIG_ARM64
+
+asm (
+"      .pushsection    .text, \"ax\", @progbits\n"
+"      .type           my_tramp, @function\n"
+"      .globl          my_tramp\n"
+"   my_tramp:"
+"      bti     c\n"
+"      sub     sp, sp, #32\n"
+"      stp     x9, x30, [sp]\n"
+"      str     x0, [sp, #16]\n"
+"      bl      my_direct_func\n"
+"      ldp     x30, x9, [sp]\n"
+"      ldr     x0, [sp, #16]\n"
+"      add     sp, sp, #32\n"
+"      ret     x9\n"
+"      .size           my_tramp, .-my_tramp\n"
+"      .popsection\n"
+);
+
+#endif /* CONFIG_ARM64 */
+
 #ifdef CONFIG_LOONGARCH
 
 asm (
index d387c93..16c8793 100644 (file)
@@ -349,10 +349,10 @@ static void cleanup_symbol_name(char *s)
         * ASCII[_]   = 5f
         * ASCII[a-z] = 61,7a
         *
-        * As above, replacing '.' with '\0' does not affect the main sorting,
-        * but it helps us with subsorting.
+        * As above, replacing the first '.' in ".llvm." with '\0' does not
+        * affect the main sorting, but it helps us with subsorting.
         */
-       p = strchr(s, '.');
+       p = strstr(s, ".llvm.");
        if (p)
                *p = '\0';
 }
index d420b5d..081befa 100644 (file)
@@ -1005,7 +1005,7 @@ struct elf *elf_open_read(const char *name, int flags)
                perror("malloc");
                return NULL;
        }
-       memset(elf, 0, offsetof(struct elf, sections));
+       memset(elf, 0, sizeof(*elf));
 
        INIT_LIST_HEAD(&elf->sections);
 
diff --git a/tools/testing/selftests/bpf/prog_tests/async_stack_depth.c b/tools/testing/selftests/bpf/prog_tests/async_stack_depth.c
new file mode 100644 (file)
index 0000000..118abc2
--- /dev/null
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_progs.h>
+
+#include "async_stack_depth.skel.h"
+
+void test_async_stack_depth(void)
+{
+       RUN_TESTS(async_stack_depth);
+}
diff --git a/tools/testing/selftests/bpf/progs/async_stack_depth.c b/tools/testing/selftests/bpf/progs/async_stack_depth.c
new file mode 100644 (file)
index 0000000..477ba95
--- /dev/null
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <vmlinux.h>
+#include <bpf/bpf_helpers.h>
+
+#include "bpf_misc.h"
+
+struct hmap_elem {
+       struct bpf_timer timer;
+};
+
+struct {
+       __uint(type, BPF_MAP_TYPE_HASH);
+       __uint(max_entries, 64);
+       __type(key, int);
+       __type(value, struct hmap_elem);
+} hmap SEC(".maps");
+
+__attribute__((noinline))
+static int timer_cb(void *map, int *key, struct bpf_timer *timer)
+{
+       volatile char buf[256] = {};
+       return buf[69];
+}
+
+SEC("tc")
+__failure __msg("combined stack size of 2 calls")
+int prog(struct __sk_buff *ctx)
+{
+       struct hmap_elem *elem;
+       volatile char buf[256] = {};
+
+       elem = bpf_map_lookup_elem(&hmap, &(int){0});
+       if (!elem)
+               return 0;
+
+       timer_cb(NULL, NULL, NULL);
+       return bpf_timer_set_callback(&elem->timer, timer_cb) + buf[0];
+}
+
+char _license[] SEC("license") = "GPL";
index 681b906..4da48bf 100755 (executable)
@@ -79,6 +79,7 @@ recompile_kernel()
        cd "${kernel_checkout}"
 
        ${make_command} olddefconfig
+       ${make_command} headers
        ${make_command}
 }
 
index 147899a..976dffd 100644 (file)
             "$TC qdisc del dev $DUMMY handle 1: root",
             "$IP link del dev $DUMMY type dummy"
         ]
+    },
+    {
+        "id": "85ee",
+        "name": "QFQ with big MTU",
+        "category": [
+            "qdisc",
+            "qfq"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$IP link add dev $DUMMY type dummy || /bin/true",
+            "$IP link set dev $DUMMY mtu 2147483647 || /bin/true",
+            "$TC qdisc add dev $DUMMY handle 1: root qfq"
+        ],
+        "cmdUnderTest": "$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 100",
+        "expExitCode": "2",
+        "verifyCmd": "$TC class show dev $DUMMY",
+        "matchPattern": "class qfq 1:",
+        "matchCount": "0",
+        "teardown": [
+            "$IP link del dev $DUMMY type dummy"
+        ]
+    },
+    {
+        "id": "ddfa",
+        "name": "QFQ with small MTU",
+        "category": [
+            "qdisc",
+            "qfq"
+        ],
+        "plugins": {
+            "requires": "nsPlugin"
+        },
+        "setup": [
+            "$IP link add dev $DUMMY type dummy || /bin/true",
+            "$IP link set dev $DUMMY mtu 256 || /bin/true",
+            "$TC qdisc add dev $DUMMY handle 1: root qfq"
+        ],
+        "cmdUnderTest": "$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 100",
+        "expExitCode": "2",
+        "verifyCmd": "$TC class show dev $DUMMY",
+        "matchPattern": "class qfq 1:",
+        "matchCount": "0",
+        "teardown": [
+            "$IP link del dev $DUMMY type dummy"
+        ]
+    },
+    {
+        "id": "5993",
+        "name": "QFQ with stab overhead greater than max packet len",
+        "category": [
+            "qdisc",
+            "qfq",
+            "scapy"
+        ],
+        "plugins": {
+            "requires": [
+                "nsPlugin",
+                "scapyPlugin"
+            ]
+        },
+        "setup": [
+            "$IP link add dev $DUMMY type dummy || /bin/true",
+            "$IP link set dev $DUMMY up || /bin/true",
+            "$TC qdisc add dev $DUMMY handle 1: stab mtu 2048 tsize 512 mpu 0 overhead 999999999 linklayer ethernet root qfq",
+            "$TC class add dev $DUMMY parent 1: classid 1:1 qfq weight 100",
+            "$TC qdisc add dev $DEV1 clsact",
+            "$TC filter add dev $DEV1 ingress protocol ip flower dst_ip 1.3.3.7/32 action mirred egress mirror dev $DUMMY"
+        ],
+        "cmdUnderTest": "$TC filter add dev $DUMMY parent 1: matchall classid 1:1",
+        "scapy": [
+            {
+                "iface": "$DEV0",
+                "count": 22,
+                "packet": "Ether(type=0x800)/IP(src='10.0.0.10',dst='1.3.3.7')/TCP(sport=5000,dport=10)"
+            }
+        ],
+        "expExitCode": "0",
+        "verifyCmd": "$TC -s qdisc ls dev $DUMMY",
+        "matchPattern": "dropped 22",
+        "matchCount": "1",
+        "teardown": [
+            "$TC qdisc del dev $DUMMY handle 1: root qfq"
+        ]
     }
 ]
index d6979a4..91a4444 100644 (file)
@@ -217,6 +217,18 @@ TEST_F(user, matching) {
        /* Types don't match */
        TEST_NMATCH("__test_event u64 a; u64 b",
                    "__test_event u32 a; u32 b");
+
+       /* Struct name and size matches */
+       TEST_MATCH("__test_event struct my_struct a 20",
+                  "__test_event struct my_struct a 20");
+
+       /* Struct name don't match */
+       TEST_NMATCH("__test_event struct my_struct a 20",
+                   "__test_event struct my_struct b 20");
+
+       /* Struct size don't match */
+       TEST_NMATCH("__test_event struct my_struct a 20",
+                   "__test_event struct my_struct a 21");
 }
 
 int main(int argc, char **argv)