]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
Merge tag 'kvmarm-5.14' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmar...
authorPaolo Bonzini <pbonzini@redhat.com>
Fri, 25 Jun 2021 15:24:24 +0000 (11:24 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 25 Jun 2021 15:24:24 +0000 (11:24 -0400)
KVM/arm64 updates for v5.14.

- Add MTE support in guests, complete with tag save/restore interface
- Reduce the impact of CMOs by moving them in the page-table code
- Allow device block mappings at stage-2
- Reduce the footprint of the vmemmap in protected mode
- Support the vGIC on dumb systems such as the Apple M1
- Add selftest infrastructure to support multiple configuration
  and apply that to PMU/non-PMU setups
- Add selftests for the debug architecture
- The usual crop of PMU fixes

816 files changed:
Documentation/admin-guide/sysctl/kernel.rst
Documentation/devicetree/bindings/clock/idt,versaclock5.yaml
Documentation/devicetree/bindings/i2c/i2c-mpc.yaml
Documentation/devicetree/bindings/iio/adc/st,stm32-dfsdm-adc.yaml
Documentation/devicetree/bindings/input/input.yaml
Documentation/devicetree/bindings/interconnect/qcom,rpmh.yaml
Documentation/devicetree/bindings/leds/leds-bcm6328.txt
Documentation/devicetree/bindings/leds/leds-bcm6358.txt
Documentation/devicetree/bindings/media/renesas,drif.yaml
Documentation/devicetree/bindings/net/qcom,ipa.yaml
Documentation/devicetree/bindings/net/renesas,ether.yaml
Documentation/devicetree/bindings/nvmem/mtk-efuse.txt
Documentation/devicetree/bindings/phy/phy-cadence-torrent.yaml
Documentation/devicetree/bindings/power/supply/sc2731-charger.yaml
Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml
Documentation/devicetree/bindings/spi/spi-mux.yaml
Documentation/driver-api/usb/usb.rst
Documentation/powerpc/syscall64-abi.rst
Documentation/userspace-api/seccomp_filter.rst
Documentation/virt/kvm/api.rst
MAINTAINERS
Makefile
arch/alpha/kernel/syscalls/syscall.tbl
arch/arm/mach-npcm/Kconfig
arch/arm/mach-pxa/pxa_cplds_irqs.c
arch/arm/tools/syscall.tbl
arch/arm64/Kbuild
arch/arm64/boot/dts/renesas/hihope-rzg2-ex-aistarvision-mipi-adapter-2.1.dtsi
arch/arm64/boot/dts/renesas/r8a774a1.dtsi
arch/arm64/boot/dts/renesas/r8a774b1.dtsi
arch/arm64/boot/dts/renesas/r8a774c0-ek874-mipi-2.1.dts
arch/arm64/boot/dts/renesas/r8a774c0.dtsi
arch/arm64/boot/dts/renesas/r8a774e1.dtsi
arch/arm64/boot/dts/renesas/r8a77950.dtsi
arch/arm64/boot/dts/renesas/r8a77951.dtsi
arch/arm64/boot/dts/renesas/r8a77960.dtsi
arch/arm64/boot/dts/renesas/r8a77961.dtsi
arch/arm64/boot/dts/renesas/r8a77965.dtsi
arch/arm64/boot/dts/renesas/r8a77970.dtsi
arch/arm64/boot/dts/renesas/r8a77980.dtsi
arch/arm64/boot/dts/renesas/r8a77990-ebisu.dts
arch/arm64/boot/dts/renesas/r8a77990.dtsi
arch/arm64/boot/dts/renesas/salvator-common.dtsi
arch/arm64/include/asm/alternative-macros.h
arch/arm64/include/asm/arch_gicv3.h
arch/arm64/include/asm/assembler.h
arch/arm64/include/asm/barrier.h
arch/arm64/include/asm/cacheflush.h
arch/arm64/include/asm/efi.h
arch/arm64/include/asm/kvm_arm.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/kvm_mmu.h
arch/arm64/include/asm/kvm_mte.h [new file with mode: 0644]
arch/arm64/include/asm/kvm_pgtable.h
arch/arm64/include/asm/mte-def.h
arch/arm64/include/asm/mte.h
arch/arm64/include/asm/pgtable.h
arch/arm64/include/asm/sysreg.h
arch/arm64/include/asm/unistd32.h
arch/arm64/include/uapi/asm/kvm.h
arch/arm64/kernel/alternative.c
arch/arm64/kernel/asm-offsets.c
arch/arm64/kernel/efi-entry.S
arch/arm64/kernel/head.S
arch/arm64/kernel/hibernate-asm.S
arch/arm64/kernel/hibernate.c
arch/arm64/kernel/idreg-override.c
arch/arm64/kernel/image-vars.h
arch/arm64/kernel/insn.c
arch/arm64/kernel/kaslr.c
arch/arm64/kernel/machine_kexec.c
arch/arm64/kernel/mte.c
arch/arm64/kernel/probes/uprobes.c
arch/arm64/kernel/smp.c
arch/arm64/kernel/smp_spin_table.c
arch/arm64/kernel/sys_compat.c
arch/arm64/kvm/arch_timer.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/guest.c
arch/arm64/kvm/hyp/entry.S
arch/arm64/kvm/hyp/exception.c
arch/arm64/kvm/hyp/hyp-entry.S
arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
arch/arm64/kvm/hyp/include/nvhe/gfp.h
arch/arm64/kvm/hyp/include/nvhe/mem_protect.h
arch/arm64/kvm/hyp/include/nvhe/memory.h
arch/arm64/kvm/hyp/include/nvhe/mm.h
arch/arm64/kvm/hyp/nvhe/cache.S
arch/arm64/kvm/hyp/nvhe/mem_protect.c
arch/arm64/kvm/hyp/nvhe/page_alloc.c
arch/arm64/kvm/hyp/nvhe/setup.c
arch/arm64/kvm/hyp/nvhe/tlb.c
arch/arm64/kvm/hyp/pgtable.c
arch/arm64/kvm/hyp/reserved_mem.c
arch/arm64/kvm/mmu.c
arch/arm64/kvm/pmu-emul.c
arch/arm64/kvm/reset.c
arch/arm64/kvm/sys_regs.c
arch/arm64/kvm/vgic/vgic-init.c
arch/arm64/kvm/vgic/vgic-v2.c
arch/arm64/kvm/vgic/vgic-v3.c
arch/arm64/kvm/vgic/vgic.c
arch/arm64/lib/uaccess_flushcache.c
arch/arm64/mm/cache.S
arch/arm64/mm/flush.c
arch/arm64/mm/mmu.c
arch/ia64/kernel/syscalls/syscall.tbl
arch/m68k/kernel/signal.c
arch/m68k/kernel/syscalls/syscall.tbl
arch/microblaze/kernel/syscalls/syscall.tbl
arch/mips/alchemy/board-xxs1500.c
arch/mips/include/asm/mips-boards/launch.h
arch/mips/kernel/syscalls/syscall_n32.tbl
arch/mips/kernel/syscalls/syscall_n64.tbl
arch/mips/kernel/syscalls/syscall_o32.tbl
arch/mips/lib/mips-atomic.c
arch/mips/ralink/of.c
arch/openrisc/include/asm/barrier.h [new file with mode: 0644]
arch/openrisc/kernel/setup.c
arch/openrisc/mm/init.c
arch/parisc/kernel/syscalls/syscall.tbl
arch/powerpc/boot/dts/fsl/p1010si-post.dtsi
arch/powerpc/boot/dts/fsl/p2041si-post.dtsi
arch/powerpc/include/asm/ptrace.h
arch/powerpc/include/asm/syscall.h
arch/powerpc/kernel/setup_64.c
arch/powerpc/kernel/syscalls/syscall.tbl
arch/riscv/Kconfig
arch/riscv/include/asm/kexec.h
arch/riscv/kernel/machine_kexec.c
arch/riscv/kernel/probes/kprobes.c
arch/riscv/kernel/stacktrace.c
arch/s390/kernel/syscalls/syscall.tbl
arch/sh/kernel/syscalls/syscall.tbl
arch/sparc/kernel/syscalls/syscall.tbl
arch/x86/Makefile
arch/x86/entry/syscalls/syscall_32.tbl
arch/x86/entry/syscalls/syscall_64.tbl
arch/x86/events/core.c
arch/x86/events/intel/core.c
arch/x86/events/intel/lbr.c
arch/x86/events/perf_event.h
arch/x86/kernel/sev-shared.c
arch/x86/kernel/sev.c
arch/x86/kernel/signal_compat.c
arch/x86/xen/enlighten_pv.c
arch/xtensa/kernel/syscalls/syscall.tbl
block/genhd.c
drivers/acpi/acpi_apd.c
drivers/acpi/internal.h
drivers/acpi/power.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/android/binder.c
drivers/base/core.c
drivers/cdrom/gdrom.c
drivers/char/hpet.c
drivers/crypto/cavium/nitrox/nitrox_main.c
drivers/dma-buf/dma-buf.c
drivers/dma/qcom/hidma_mgmt.c
drivers/firmware/arm_scmi/notify.h
drivers/firmware/arm_scpi.c
drivers/gpio/gpio-cadence.c
drivers/gpio/gpio-tegra186.c
drivers/gpio/gpio-xilinx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v10_3.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
drivers/gpu/drm/amd/display/dc/core/dc_link.c
drivers/gpu/drm/amd/display/dc/dcn30/dcn30_resource.c
drivers/gpu/drm/amd/display/dc/dcn301/dcn301_resource.c
drivers/gpu/drm/amd/display/dc/dcn302/dcn302_resource.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/exynos/exynos5433_drm_decon.c
drivers/gpu/drm/exynos/exynos_drm_dsi.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/i915/Kconfig
drivers/gpu/drm/i915/display/intel_dp_link_training.c
drivers/gpu/drm/i915/gem/i915_gem_pages.c
drivers/gpu/drm/i915/gt/gen7_renderclear.c
drivers/gpu/drm/i915/gvt/gvt.c
drivers/gpu/drm/i915/gvt/gvt.h
drivers/gpu/drm/i915/gvt/hypercall.h
drivers/gpu/drm/i915/gvt/kvmgt.c
drivers/gpu/drm/i915/gvt/mpt.h
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_mm.c
drivers/gpu/drm/meson/meson_drv.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/ttm/ttm_device.c
drivers/hwmon/lm80.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-ali1563.c
drivers/i2c/busses/i2c-cadence.c
drivers/i2c/busses/i2c-designware-master.c
drivers/i2c/busses/i2c-eg20t.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-icy.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mt65xx.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/busses/i2c-qcom-geni.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sh_mobile.c
drivers/i2c/busses/i2c-st.c
drivers/i2c/busses/i2c-stm32f4.c
drivers/i2c/muxes/i2c-arb-gpio-challenge.c
drivers/iio/adc/ad7124.c
drivers/iio/adc/ad7192.c
drivers/iio/adc/ad7768-1.c
drivers/iio/adc/ad7793.c
drivers/iio/adc/ad7923.c
drivers/iio/dac/ad5770r.c
drivers/iio/gyro/fxas21002c_core.c
drivers/infiniband/core/cma.c
drivers/infiniband/core/uverbs_std_types_device.c
drivers/infiniband/hw/mlx5/devx.c
drivers/infiniband/hw/mlx5/dm.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/mr.c
drivers/infiniband/sw/rxe/rxe_comp.c
drivers/infiniband/sw/rxe/rxe_qp.c
drivers/infiniband/sw/siw/siw_verbs.c
drivers/interconnect/qcom/bcm-voter.c
drivers/iommu/amd/iommu.c
drivers/iommu/intel/dmar.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/pasid.c
drivers/iommu/virtio-iommu.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-apple-aic.c
drivers/irqchip/irq-gic-common.c
drivers/irqchip/irq-gic-common.h
drivers/irqchip/irq-gic-v3.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-mvebu-icu.c
drivers/irqchip/irq-mvebu-sei.c
drivers/irqchip/irq-stm32-exti.c
drivers/isdn/hardware/mISDN/hfcsusb.c
drivers/isdn/hardware/mISDN/mISDNinfineon.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/leds/leds-lp5523.c
drivers/md/dm-integrity.c
drivers/md/dm-snap.c
drivers/md/dm-verity-verify-sig.c
drivers/md/raid5.c
drivers/media/dvb-frontends/sp8870.c
drivers/media/platform/rcar_drif.c
drivers/media/usb/gspca/cpia1.c
drivers/media/usb/gspca/m5602/m5602_mt9m111.c
drivers/media/usb/gspca/m5602/m5602_po1030.c
drivers/misc/eeprom/at24.c
drivers/misc/habanalabs/common/command_submission.c
drivers/misc/habanalabs/common/firmware_if.c
drivers/misc/habanalabs/common/habanalabs.h
drivers/misc/habanalabs/common/habanalabs_drv.c
drivers/misc/habanalabs/common/sysfs.c
drivers/misc/habanalabs/gaudi/gaudi.c
drivers/misc/habanalabs/gaudi/gaudi_hwmgr.c
drivers/misc/habanalabs/goya/goya.c
drivers/misc/habanalabs/goya/goya_hwmgr.c
drivers/misc/ics932s401.c
drivers/misc/kgdbts.c
drivers/misc/lis3lv02d/lis3lv02d.h
drivers/misc/mei/interrupt.c
drivers/mmc/host/meson-gx-mmc.c
drivers/mmc/host/sdhci-pci-gli.c
drivers/mtd/nand/raw/cs553x_nand.c
drivers/mtd/nand/raw/fsmc_nand.c
drivers/mtd/nand/raw/lpc32xx_slc.c
drivers/mtd/nand/raw/ndfc.c
drivers/mtd/nand/raw/sharpsl.c
drivers/mtd/nand/raw/tmio_nand.c
drivers/mtd/nand/raw/txx9ndfmc.c
drivers/mtd/parsers/ofpart_core.c
drivers/net/appletalk/cops.c
drivers/net/bonding/bond_main.c
drivers/net/caif/caif_serial.c
drivers/net/dsa/bcm_sf2.c
drivers/net/dsa/microchip/ksz9477.c
drivers/net/dsa/mt7530.c
drivers/net/dsa/ocelot/felix_vsc9959.c
drivers/net/dsa/sja1105/sja1105_dynamic_config.c
drivers/net/dsa/sja1105/sja1105_main.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sriov.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/cadence/macb_main.c
drivers/net/ethernet/cavium/liquidio/lio_main.c
drivers/net/ethernet/cavium/liquidio/lio_vf_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c
drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.h
drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_io.c
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/fujitsu/fmvj18x_cs.c
drivers/net/ethernet/google/gve/gve_main.c
drivers/net/ethernet/google/gve/gve_tx.c
drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3_ethtool.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c
drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
drivers/net/ethernet/korina.c
drivers/net/ethernet/lantiq_xrx200.c
drivers/net/ethernet/marvell/mvpp2/mvpp2.h
drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mediatek/mtk_eth_soc.h
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/port.c
drivers/net/ethernet/mellanox/mlx5/core/en/rep/bond.c
drivers/net/ethernet/mellanox/mlx5/core/en/rep/tc.c
drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads_termtbl.c
drivers/net/ethernet/mellanox/mlx5/core/lag_mp.c
drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c
drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.h
drivers/net/ethernet/mellanox/mlx5/core/main.c
drivers/net/ethernet/mellanox/mlx5/core/pci_irq.c
drivers/net/ethernet/mellanox/mlx5/core/sf/devlink.c
drivers/net/ethernet/microchip/encx24j600.c
drivers/net/ethernet/microchip/encx24j600_hw.h
drivers/net/ethernet/pensando/Kconfig
drivers/net/ethernet/qlogic/qla3xxx.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/sun/niu.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ipa/ipa.h
drivers/net/ipa/ipa_mem.c
drivers/net/mdio/mdio-octeon.c
drivers/net/mdio/mdio-thunder.c
drivers/net/phy/mdio_bus.c
drivers/net/usb/cdc_eem.c
drivers/net/usb/hso.c
drivers/net/usb/lan78xx.c
drivers/net/usb/r8152.c
drivers/net/usb/smsc75xx.c
drivers/net/wireless/ath/ath10k/htt.h
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/rx_desc.h
drivers/net/wireless/ath/ath11k/dp_rx.c
drivers/net/wireless/ath/ath11k/dp_rx.h
drivers/net/wireless/ath/ath11k/mac.c
drivers/net/wireless/ath/ath6kl/debug.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.h
drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
drivers/net/wireless/marvell/libertas/mesh.c
drivers/net/wireless/realtek/rtlwifi/base.c
drivers/nfc/nfcmrvl/fw_dnld.h
drivers/nfc/nfcmrvl/i2c.c
drivers/nfc/nfcmrvl/nfcmrvl.h
drivers/nfc/nfcmrvl/spi.c
drivers/nfc/nfcmrvl/uart.c
drivers/nfc/nfcmrvl/usb.c
drivers/nvme/host/Kconfig
drivers/nvme/host/core.c
drivers/nvme/host/fabrics.c
drivers/nvme/host/fc.c
drivers/nvme/host/tcp.c
drivers/nvme/target/core.c
drivers/nvme/target/loop.c
drivers/nvme/target/nvmet.h
drivers/nvme/target/tcp.c
drivers/platform/mellanox/mlxbf-tmfifo.c
drivers/platform/surface/aggregator/controller.c
drivers/platform/surface/surface_dtx.c
drivers/platform/x86/Kconfig
drivers/platform/x86/dell/dell-smbios-wmi.c
drivers/platform/x86/gigabyte-wmi.c
drivers/platform/x86/hp-wireless.c
drivers/platform/x86/hp_accel.c
drivers/platform/x86/ideapad-laptop.c
drivers/platform/x86/intel_int0002_vgpio.c
drivers/platform/x86/intel_punit_ipc.c
drivers/platform/x86/touchscreen_dmi.c
drivers/ptp/ptp_ocp.c
drivers/rapidio/rio_cm.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_int.h
drivers/s390/cio/vfio_ccw_cp.c
drivers/s390/cio/vfio_ccw_drv.c
drivers/s390/cio/vfio_ccw_fsm.c
drivers/s390/cio/vfio_ccw_ops.c
drivers/scsi/BusLogic.c
drivers/scsi/BusLogic.h
drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
drivers/scsi/aic7xxx/aicasm/aicasm_symbol.h
drivers/scsi/aic7xxx/scsi_message.h
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
drivers/scsi/libsas/sas_port.c
drivers/scsi/pm8001/pm8001_hwi.c
drivers/scsi/pm8001/pm8001_init.c
drivers/scsi/pm8001/pm8001_sas.c
drivers/scsi/pm8001/pm80xx_hwi.c
drivers/scsi/qedf/qedf_main.c
drivers/scsi/qla2xxx/qla_nx.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/ufs/ufs-hisi.c
drivers/scsi/ufs/ufs-mediatek.c
drivers/scsi/ufs/ufshcd.c
drivers/scsi/vmw_pvscsi.c
drivers/soundwire/qcom.c
drivers/spi/Kconfig
drivers/spi/spi-fsl-dspi.c
drivers/spi/spi-sc18is602.c
drivers/spi/spi-sprd.c
drivers/spi/spi-zynq-qspi.c
drivers/spi/spi.c
drivers/staging/emxx_udc/emxx_udc.c
drivers/staging/iio/cdc/ad7746.c
drivers/target/target_core_iblock.c
drivers/target/target_core_transport.c
drivers/target/target_core_user.c
drivers/tee/amdtee/amdtee_private.h
drivers/tee/amdtee/call.c
drivers/tee/amdtee/core.c
drivers/thermal/intel/int340x_thermal/int340x_thermal_zone.c
drivers/thermal/intel/x86_pkg_temp_thermal.c
drivers/thermal/qcom/qcom-spmi-adc-tm5.c
drivers/thermal/ti-soc-thermal/ti-bandgap.c
drivers/thunderbolt/dma_port.c
drivers/thunderbolt/usb4.c
drivers/tty/serial/8250/8250.h
drivers/tty/serial/8250/8250_aspeed_vuart.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/max310x.c
drivers/tty/serial/mvebu-uart.c
drivers/tty/serial/rp2.c
drivers/tty/serial/serial-tegra.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sh-sci.c
drivers/uio/uio_hv_generic.c
drivers/uio/uio_pci_generic.c
drivers/usb/cdns3/cdns3-gadget.c
drivers/usb/cdns3/cdnsp-gadget.c
drivers/usb/chipidea/udc.c
drivers/usb/core/devio.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/udc/renesas_usb3.c
drivers/usb/host/xhci-ring.c
drivers/usb/misc/trancevibrator.c
drivers/usb/misc/uss720.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/pl2303.h
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/typec/mux.c
drivers/usb/typec/tcpm/tcpm.c
drivers/usb/typec/ucsi/ucsi.c
drivers/vdpa/mlx5/net/mlx5_vnet.c
drivers/video/fbdev/hgafb.c
drivers/video/fbdev/imsttfb.c
drivers/xen/xen-pciback/vpci.c
drivers/xen/xen-pciback/xenbus.c
fs/afs/cmservice.c
fs/afs/dir.c
fs/afs/fsclient.c
fs/afs/vlclient.c
fs/block_dev.c
fs/btrfs/compression.c
fs/btrfs/extent_io.c
fs/btrfs/inode.c
fs/btrfs/reflink.c
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/zoned.c
fs/btrfs/zoned.h
fs/cifs/cifs_ioctl.h
fs/cifs/cifsfs.c
fs/cifs/cifsglob.h
fs/cifs/cifspdu.h
fs/cifs/file.c
fs/cifs/fs_context.c
fs/cifs/ioctl.c
fs/cifs/misc.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/trace.h
fs/debugfs/inode.c
fs/ecryptfs/crypto.c
fs/hugetlbfs/inode.c
fs/io-wq.c
fs/io-wq.h
fs/io_uring.c
fs/namespace.c
fs/netfs/Kconfig
fs/netfs/read_helper.c
fs/nfs/filelayout/filelayout.c
fs/nfs/namespace.c
fs/nfs/nfs4file.c
fs/nfs/nfs4proc.c
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/super.c
fs/proc/base.c
fs/quota/dquot.c
fs/signalfd.c
fs/xfs/libxfs/xfs_ag_resv.c
fs/xfs/libxfs/xfs_bmap.c
fs/xfs/libxfs/xfs_fs.h
fs/xfs/libxfs/xfs_inode_buf.c
fs/xfs/libxfs/xfs_trans_inode.c
fs/xfs/scrub/common.c
fs/xfs/xfs_bmap_util.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_message.h
include/kvm/arm_vgic.h
include/linux/bits.h
include/linux/cgroup-defs.h
include/linux/cgroup.h
include/linux/compat.h
include/linux/const.h
include/linux/device.h
include/linux/dynamic_debug.h
include/linux/genhd.h
include/linux/init.h
include/linux/irqchip/arm-gic-common.h
include/linux/irqchip/arm-vgic-info.h [new file with mode: 0644]
include/linux/minmax.h
include/linux/mlx5/driver.h
include/linux/mlx5/mpfs.h [new file with mode: 0644]
include/linux/phy.h
include/linux/sched/signal.h
include/linux/signal.h
include/linux/spi/spi.h
include/linux/sunrpc/xprt.h
include/linux/surface_aggregator/device.h
include/net/cfg80211.h
include/net/netfilter/nf_flow_table.h
include/net/nfc/nci_core.h
include/net/pkt_cls.h
include/net/pkt_sched.h
include/net/sch_generic.h
include/net/sock.h
include/sound/soc-dai.h
include/uapi/asm-generic/siginfo.h
include/uapi/linux/kvm.h
include/uapi/linux/perf_event.h
include/uapi/linux/signalfd.h
include/uapi/misc/habanalabs.h
init/Kconfig
ipc/mqueue.c
ipc/msg.c
ipc/sem.c
kernel/bpf/Kconfig [new file with mode: 0644]
kernel/bpf/bpf_lsm.c
kernel/bpf/btf.c
kernel/bpf/helpers.c
kernel/bpf/ringbuf.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/cgroup/cgroup-v1.c
kernel/cgroup/cgroup.c
kernel/cgroup/cpuset.c
kernel/cgroup/rdma.c
kernel/cgroup/rstat.c
kernel/events/core.c
kernel/kcsan/debugfs.c
kernel/locking/lockdep.c
kernel/locking/mutex-debug.c
kernel/locking/mutex-debug.h
kernel/locking/mutex.c
kernel/locking/mutex.h
kernel/module.c
kernel/seccomp.c
kernel/signal.c
kernel/sysctl.c
kernel/watchdog.c
kernel/workqueue.c
lib/Makefile
lib/dynamic_debug.c
lib/percpu-refcount.c
mm/gup.c
mm/internal.h
mm/shuffle.h
mm/slub.c
mm/userfaultfd.c
net/Kconfig
net/can/isotp.c
net/core/dev.c
net/core/filter.c
net/core/sock.c
net/dsa/master.c
net/dsa/slave.c
net/ethtool/stats.c
net/hsr/hsr_device.c
net/hsr/hsr_forward.c
net/hsr/hsr_forward.h
net/hsr/hsr_main.h
net/hsr/hsr_slave.c
net/ipv4/bpf_tcp_ca.c
net/ipv6/mcast.c
net/ipv6/reassembly.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/wpa.c
net/mptcp/options.c
net/mptcp/pm_netlink.c
net/mptcp/protocol.c
net/mptcp/protocol.h
net/mptcp/sockopt.c
net/mptcp/subflow.c
net/netfilter/nf_flow_table_core.c
net/netfilter/nf_flow_table_offload.c
net/netfilter/nft_set_pipapo.c
net/netfilter/nft_set_pipapo.h
net/netfilter/nft_set_pipapo_avx2.c
net/netlink/af_netlink.c
net/nfc/nci/core.c
net/nfc/nci/hci.c
net/nfc/rawsock.c
net/openvswitch/meter.c
net/packet/af_packet.c
net/rds/connection.c
net/rds/tcp.c
net/rds/tcp.h
net/rds/tcp_listen.c
net/sched/cls_api.c
net/sched/sch_dsmark.c
net/sched/sch_fq_pie.c
net/sched/sch_generic.c
net/sctp/socket.c
net/sctp/sysctl.c
net/smc/smc_ism.c
net/sunrpc/clnt.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/rpc_rdma.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/sunrpc/xprtsock.c
net/tipc/core.c
net/tipc/core.h
net/tipc/discover.c
net/tipc/link.c
net/tipc/link.h
net/tipc/msg.c
net/tipc/net.c
net/tipc/node.c
net/tipc/socket.c
net/tipc/udp_media.c
net/tls/tls_sw.c
net/wireless/util.c
samples/bpf/xdpsock_user.c
scripts/dummy-tools/gcc
scripts/jobserver-exec
sound/firewire/Kconfig
sound/firewire/amdtp-stream-trace.h
sound/firewire/amdtp-stream.c
sound/firewire/bebob/bebob.c
sound/firewire/dice/dice-alesis.c
sound/firewire/dice/dice-pcm.c
sound/firewire/dice/dice-stream.c
sound/firewire/dice/dice-tcelectronic.c
sound/firewire/dice/dice.c
sound/firewire/dice/dice.h
sound/firewire/oxfw/oxfw.c
sound/isa/gus/gus_main.c
sound/isa/sb/sb16_main.c
sound/isa/sb/sb8.c
sound/pci/hda/patch_realtek.c
sound/pci/intel8x0.c
sound/soc/amd/raven/acp3x-pcm-dma.c
sound/soc/amd/raven/acp3x.h
sound/soc/amd/raven/pci-acp3x.c
sound/soc/codecs/ak5558.c
sound/soc/codecs/cs35l32.c
sound/soc/codecs/cs35l33.c
sound/soc/codecs/cs35l34.c
sound/soc/codecs/cs42l42.c
sound/soc/codecs/cs42l56.c
sound/soc/codecs/cs42l73.c
sound/soc/codecs/cs43130.c
sound/soc/codecs/cs53l30.c
sound/soc/codecs/da7219.c
sound/soc/codecs/lpass-rx-macro.c
sound/soc/codecs/lpass-tx-macro.c
sound/soc/codecs/max98088.c
sound/soc/codecs/rt5645.c
sound/soc/codecs/rt711-sdca.c
sound/soc/codecs/sti-sas.c
sound/soc/fsl/Kconfig
sound/soc/generic/audio-graph-card.c
sound/soc/generic/simple-card.c
sound/soc/intel/boards/bytcr_rt5640.c
sound/soc/qcom/lpass-cpu.c
sound/soc/sof/intel/hda-dai.c
sound/soc/stm/stm32_sai_sub.c
sound/usb/format.c
sound/usb/line6/driver.c
sound/usb/line6/pod.c
sound/usb/line6/variax.c
sound/usb/midi.c
sound/usb/mixer_quirks.c
sound/usb/mixer_scarlett_gen2.c
sound/usb/mixer_scarlett_gen2.h
tools/arch/x86/include/uapi/asm/kvm.h
tools/bpf/bpftool/Documentation/bpftool-cgroup.rst
tools/bpf/bpftool/Documentation/bpftool-prog.rst
tools/bpf/bpftool/bash-completion/bpftool
tools/bpf/bpftool/cgroup.c
tools/bpf/bpftool/prog.c
tools/build/Makefile.build
tools/include/linux/bits.h
tools/include/linux/const.h
tools/include/uapi/linux/fs.h
tools/include/uapi/linux/perf_event.h
tools/lib/bpf/libbpf.c
tools/lib/bpf/libbpf_internal.h
tools/perf/Documentation/perf-intel-pt.txt
tools/perf/Documentation/perf-script.txt
tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
tools/perf/arch/s390/entry/syscalls/syscall.tbl
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
tools/perf/builtin-buildid-list.c
tools/perf/builtin-stat.c
tools/perf/perf.c
tools/perf/pmu-events/arch/powerpc/power10/cache.json
tools/perf/pmu-events/arch/powerpc/power10/floating_point.json
tools/perf/pmu-events/arch/powerpc/power10/frontend.json
tools/perf/pmu-events/arch/powerpc/power10/locks.json
tools/perf/pmu-events/arch/powerpc/power10/marked.json
tools/perf/pmu-events/arch/powerpc/power10/memory.json
tools/perf/pmu-events/arch/powerpc/power10/others.json
tools/perf/pmu-events/arch/powerpc/power10/pipeline.json
tools/perf/pmu-events/arch/powerpc/power10/pmc.json
tools/perf/pmu-events/arch/powerpc/power10/translation.json
tools/perf/pmu-events/jevents.c
tools/perf/scripts/python/exported-sql-viewer.py
tools/perf/tests/pfm.c
tools/perf/util/bpf_counter.c
tools/perf/util/event.h
tools/perf/util/evlist.c
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
tools/perf/util/intel-pt.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.l
tools/perf/util/pfm.c
tools/scripts/Makefile.include
tools/testing/selftests/bpf/network_helpers.c
tools/testing/selftests/bpf/network_helpers.h
tools/testing/selftests/bpf/prog_tests/ringbuf.c
tools/testing/selftests/bpf/prog_tests/tc_redirect.c [new file with mode: 0644]
tools/testing/selftests/bpf/progs/test_tc_neigh.c
tools/testing/selftests/bpf/progs/test_tc_neigh_fib.c
tools/testing/selftests/bpf/progs/test_tc_peer.c
tools/testing/selftests/bpf/test_tc_redirect.sh [deleted file]
tools/testing/selftests/bpf/verifier/stack_ptr.c
tools/testing/selftests/bpf/verifier/value_ptr_arith.c
tools/testing/selftests/exec/Makefile
tools/testing/selftests/kvm/.gitignore
tools/testing/selftests/kvm/Makefile
tools/testing/selftests/kvm/aarch64/debug-exceptions.c [new file with mode: 0644]
tools/testing/selftests/kvm/aarch64/get-reg-list-sve.c [deleted file]
tools/testing/selftests/kvm/aarch64/get-reg-list.c
tools/testing/selftests/kvm/include/aarch64/processor.h
tools/testing/selftests/kvm/include/kvm_util.h
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/lib/aarch64/handlers.S [new file with mode: 0644]
tools/testing/selftests/kvm/lib/aarch64/processor.c
tools/testing/selftests/kvm/lib/x86_64/processor.c
tools/testing/selftests/kvm/x86_64/evmcs_test.c
tools/testing/selftests/kvm/x86_64/kvm_pv_test.c
tools/testing/selftests/kvm/x86_64/sync_regs_test.c
tools/testing/selftests/kvm/x86_64/tsc_msrs_test.c
tools/testing/selftests/kvm/x86_64/userspace_msr_exit_test.c
tools/testing/selftests/kvm/x86_64/xapic_ipi_test.c
tools/testing/selftests/nci/.gitignore [new file with mode: 0644]
tools/testing/selftests/perf_events/sigtrap_threads.c
tools/testing/selftests/seccomp/seccomp_bpf.c
tools/testing/selftests/tc-testing/tc-tests/qdiscs/fq_pie.json

index 7ca8df5451d45052e1230e68db130701317c63ee..68b21395a743f0a0f355d8de09d1b0edefee42d5 100644 (file)
@@ -1458,11 +1458,22 @@ unprivileged_bpf_disabled
 =========================
 
 Writing 1 to this entry will disable unprivileged calls to ``bpf()``;
-once disabled, calling ``bpf()`` without ``CAP_SYS_ADMIN`` will return
-``-EPERM``.
+once disabled, calling ``bpf()`` without ``CAP_SYS_ADMIN`` or ``CAP_BPF``
+will return ``-EPERM``. Once set to 1, this can't be cleared from the
+running kernel anymore.
 
-Once set, this can't be cleared.
+Writing 2 to this entry will also disable unprivileged calls to ``bpf()``,
+however, an admin can still change this setting later on, if needed, by
+writing 0 or 1 to this entry.
 
+If ``BPF_UNPRIV_DEFAULT_OFF`` is enabled in the kernel config, then this
+entry will default to 2 instead of 0.
+
+= =============================================================
+0 Unprivileged calls to ``bpf()`` are enabled
+1 Unprivileged calls to ``bpf()`` are disabled without recovery
+2 Unprivileged calls to ``bpf()`` are disabled
+= =============================================================
 
 watchdog
 ========
index c268debe5b8d58cd04530e7c8cde17a638ad149d..28675b0b80f1ba53022550c85dfa43af7a394817 100644 (file)
@@ -60,7 +60,6 @@ properties:
     maxItems: 2
 
   idt,xtal-load-femtofarads:
-    $ref: /schemas/types.yaml#/definitions/uint32
     minimum: 9000
     maximum: 22760
     description: Optional load capacitor for XTAL1 and XTAL2
@@ -84,7 +83,6 @@ patternProperties:
         enum: [ 1800000, 2500000, 3300000 ]
       idt,slew-percent:
         description: The Slew rate control for CMOS single-ended.
-        $ref: /schemas/types.yaml#/definitions/uint32
         enum: [ 80, 85, 90, 100 ]
 
 required:
index 7b553d559c832c4b262b249ad71d497ec3c714f3..98c6fcf7bf26560e671cd7c8b58a395d12db47cc 100644 (file)
@@ -46,6 +46,13 @@ properties:
     description: |
       I2C bus timeout in microseconds
 
+  fsl,i2c-erratum-a004447:
+    $ref: /schemas/types.yaml#/definitions/flag
+    description: |
+      Indicates the presence of QorIQ erratum A-004447, which
+      says that the standard i2c recovery scheme mechanism does
+      not work and an alternate implementation is needed.
+
 required:
   - compatible
   - reg
index 6f2398cdc82ddd9669d42278bc00fee2baa3f9df..1e7894e524f9b9e8ab4c16b145ec26745cb2783b 100644 (file)
@@ -102,7 +102,6 @@ patternProperties:
 
       st,adc-channel-names:
         description: List of single-ended channel names.
-        $ref: /schemas/types.yaml#/definitions/string-array
 
       st,filter-order:
         description: |
index 74244d21d2b3f3bb04702f50956c4d1c9e4ff243..d41d8743aad4ed2a0f5cf66dce97ef2b569a09c5 100644 (file)
@@ -38,6 +38,5 @@ properties:
       Duration in seconds which the key should be kept pressed for device to
       reset automatically. Device with key pressed reset feature can specify
       this property.
-    $ref: /schemas/types.yaml#/definitions/uint32
 
 additionalProperties: true
index cb6498108b78a67832fc44a8c13530d066ed2f39..36c955965d90261a5be5e58afc97da695fb5dce6 100644 (file)
@@ -92,7 +92,6 @@ properties:
       this interconnect to send RPMh commands.
 
   qcom,bcm-voter-names:
-    $ref: /schemas/types.yaml#/definitions/string-array
     description: |
       Names for each of the qcom,bcm-voters specified.
 
index ccebce597f372b656adf76ab0f1eccb6e85c6a30..a555d94084b7f590cf8bade67fa7ab233d46db38 100644 (file)
@@ -4,8 +4,8 @@ This controller is present on BCM6318, BCM6328, BCM6362 and BCM63268.
 In these SoCs it's possible to control LEDs both as GPIOs or by hardware.
 However, on some devices there are Serial LEDs (LEDs connected to a 74x164
 controller), which can either be controlled by software (exporting the 74x164
-as spi-gpio. See Documentation/devicetree/bindings/gpio/gpio-74x164.txt), or
-by hardware using this driver.
+as spi-gpio. See Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml),
+or by hardware using this driver.
 Some of these Serial LEDs are hardware controlled (e.g. ethernet LEDs) and
 exporting the 74x164 as spi-gpio prevents those LEDs to be hardware
 controlled, so the only chance to keep them working is by using this driver.
index da5708e7b43b93ba83a0f759d39452c44be8223d..6e51c6b91ee54cd51c781d2e9942c1b75b652bd1 100644 (file)
@@ -3,7 +3,7 @@ LEDs connected to Broadcom BCM6358 controller
 This controller is present on BCM6358 and BCM6368.
 In these SoCs there are Serial LEDs (LEDs connected to a 74x164 controller),
 which can either be controlled by software (exporting the 74x164 as spi-gpio.
-See Documentation/devicetree/bindings/gpio/gpio-74x164.txt), or
+See Documentation/devicetree/bindings/gpio/fairchild,74hc595.yaml), or
 by hardware using this driver.
 
 Required properties:
index f1bdaeab40538f130c720cd17073e53aa74a8d6c..ce505a7c006aac60a0b48726f55c6a433e63e887 100644 (file)
@@ -99,32 +99,26 @@ properties:
       Indicates that the channel acts as primary among the bonded channels.
 
   port:
-    type: object
+    $ref: /schemas/graph.yaml#/properties/port
+    unevaluatedProperties: false
     description:
-      Child port node corresponding to the data input, in accordance with the
-      video interface bindings defined in
-      Documentation/devicetree/bindings/media/video-interfaces.txt.
-      The port node must contain at least one endpoint.
+      Child port node corresponding to the data input. The port node must
+      contain at least one endpoint.
 
     properties:
       endpoint:
-        type: object
+        $ref: /schemas/graph.yaml#/$defs/endpoint-base
+        unevaluatedProperties: false
 
         properties:
-          remote-endpoint:
-            description:
-              A phandle to the remote tuner endpoint subnode in remote node
-              port.
-
           sync-active:
+            $ref: /schemas/types.yaml#/definitions/uint32
             enum: [0, 1]
             description:
               Indicates sync signal polarity, 0/1 for low/high respectively.
               This property maps to SYNCAC bit in the hardware manual. The
               default is 1 (active high).
 
-        additionalProperties: false
-
 required:
   - compatible
   - reg
index 7443490d4cc6d6a0a51d2c72e8c45da045beea7f..5fe6d3dceb082817f4d468e7b6838aeee9a72194 100644 (file)
@@ -105,7 +105,6 @@ properties:
       - description: Whether the IPA clock is enabled (if valid)
 
   qcom,smem-state-names:
-    $ref: /schemas/types.yaml#/definitions/string-array
     description: The names of the state bits used for SMP2P output
     items:
       - const: ipa-clock-enabled-valid
index 8ce5ed8a58dd76e6af8c6bdf1ffb2fda6c986be1..c101a1ec846ea8e95052eb066c3e6bf42a2c3ba5 100644 (file)
@@ -10,7 +10,7 @@ allOf:
   - $ref: ethernet-controller.yaml#
 
 maintainers:
-  - Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
+  - Sergei Shtylyov <sergei.shtylyov@gmail.com>
 
 properties:
   compatible:
index d479ad977e24fb6b7ee1bdc1c818e3af24080e2d..b6791702bcfc916971847eae61e2a15d03456272 100644 (file)
@@ -9,7 +9,6 @@ Required properties:
              "mediatek,mt8173-efuse" or "mediatek,efuse": for MT8173
              "mediatek,mt8192-efuse", "mediatek,efuse": for MT8192
              "mediatek,mt8516-efuse", "mediatek,efuse": for MT8516
-             "mediatek,mt8192-efuse", "mediatek,efuse": for MT8192
 - reg: Should contain registers location and length
 
 = Data cells =
index 01dcd14e7b2ad21248efdd588efcaf279d1fa54e..320a232c7208c9c4315d93b64069c606bee5185e 100644 (file)
@@ -118,7 +118,7 @@ patternProperties:
         description:
           Specifies the Spread Spectrum Clocking mode used. It can be NO_SSC,
           EXTERNAL_SSC or INTERNAL_SSC.
-          Refer include/dt-bindings/phy/phy-cadence-torrent.h for the constants to be used.
+          Refer include/dt-bindings/phy/phy-cadence.h for the constants to be used.
         $ref: /schemas/types.yaml#/definitions/uint32
         enum: [0, 1, 2]
         default: 0
index db1aa238cda53fcdb2a95467127495d9c3f5f950..b62c2431f94e75c041b78383a43ef1506f9ecb5a 100644 (file)
@@ -20,7 +20,7 @@ properties:
     maxItems: 1
 
   phys:
-    $ref: /schemas/types.yaml#/definitions/phandle
+    maxItems: 1
     description: phandle to the USB phy
 
   monitored-battery:
index b4c190bddd84c87fb925ce1620a39445b7c73bd3..61802a11baf4e4ebfbf78c21c90399bf5f8f57e7 100644 (file)
@@ -49,7 +49,7 @@ properties:
     maxItems: 1
 
   memory-region:
-    $ref: /schemas/types.yaml#/definitions/phandle
+    maxItems: 1
     description:
       phandle to a node describing reserved memory (System RAM memory)
       The M core can't access all the DDR memory space on some platform,
index d09c6355e22dcecffcbf874cd78fe32432cb3583..51c7622dc20b41675d1138c77aa1c3297e3f7a9d 100644 (file)
@@ -72,7 +72,7 @@ examples:
 
             mux-controls = <&mux>;
 
-            spi-flash@0 {
+            flash@0 {
                 compatible = "jedec,spi-nor";
                 reg = <0>;
                 spi-max-frequency = <40000000>;
index 820e867af45ab32a9d9e32d44dc6b33cfa1874f9..2c94ff2f438573625e6db043698df1edbb2bb42d 100644 (file)
@@ -123,6 +123,8 @@ are in ``drivers/usb/common/common.c``.
 In addition, some functions useful for creating debugging output are
 defined in ``drivers/usb/common/debug.c``.
 
+.. _usb_header:
+
 Host-Side Data Types and Macros
 ===============================
 
index dabee3729e5a5b1a12ed4c4274c2616e48660602..56490c4c0c07a33e9e38c4ab840342001d612fc5 100644 (file)
@@ -109,6 +109,16 @@ auxiliary vector.
 
 scv 0 syscalls will always behave as PPC_FEATURE2_HTM_NOSC.
 
+ptrace
+------
+When ptracing system calls (PTRACE_SYSCALL), the pt_regs.trap value contains
+the system call type that can be used to distinguish between sc and scv 0
+system calls, and the different register conventions can be accounted for.
+
+If the value of (pt_regs.trap & 0xfff0) is 0xc00 then the system call was
+performed with the sc instruction, if it is 0x3000 then the system call was
+performed with the scv 0 instruction.
+
 vsyscall
 ========
 
index bd9165241b6c8970754c5ab7b84087b4eb251ba5..6efb41cc807255a7ae1b61879062c55c16a32389 100644 (file)
@@ -250,14 +250,14 @@ Users can read via ``ioctl(SECCOMP_IOCTL_NOTIF_RECV)``  (or ``poll()``) on a
 seccomp notification fd to receive a ``struct seccomp_notif``, which contains
 five members: the input length of the structure, a unique-per-filter ``id``,
 the ``pid`` of the task which triggered this request (which may be 0 if the
-task is in a pid ns not visible from the listener's pid namespace), a ``flags``
-member which for now only has ``SECCOMP_NOTIF_FLAG_SIGNALED``, representing
-whether or not the notification is a result of a non-fatal signal, and the
-``data`` passed to seccomp. Userspace can then make a decision based on this
-information about what to do, and ``ioctl(SECCOMP_IOCTL_NOTIF_SEND)`` a
-response, indicating what should be returned to userspace. The ``id`` member of
-``struct seccomp_notif_resp`` should be the same ``id`` as in ``struct
-seccomp_notif``.
+task is in a pid ns not visible from the listener's pid namespace). The
+notification also contains the ``data`` passed to seccomp, and a filters flag.
+The structure should be zeroed out prior to calling the ioctl.
+
+Userspace can then make a decision based on this information about what to do,
+and ``ioctl(SECCOMP_IOCTL_NOTIF_SEND)`` a response, indicating what should be
+returned to userspace. The ``id`` member of ``struct seccomp_notif_resp`` should
+be the same ``id`` as in ``struct seccomp_notif``.
 
 It is worth noting that ``struct seccomp_data`` contains the values of register
 arguments to the syscall, but does not contain pointers to memory. The task's
index 3b6e3b1628b4f2e2259f5e6c3973d7463ef62d77..b9ddce5638f5fc167f8ad52d4d843baf39a98438 100644 (file)
@@ -5039,6 +5039,42 @@ see KVM_XEN_VCPU_SET_ATTR above.
 The KVM_XEN_VCPU_ATTR_TYPE_RUNSTATE_ADJUST type may not be used
 with the KVM_XEN_VCPU_GET_ATTR ioctl.
 
+4.130 KVM_ARM_MTE_COPY_TAGS
+---------------------------
+
+:Capability: KVM_CAP_ARM_MTE
+:Architectures: arm64
+:Type: vm ioctl
+:Parameters: struct kvm_arm_copy_mte_tags
+:Returns: number of bytes copied, < 0 on error (-EINVAL for incorrect
+          arguments, -EFAULT if memory cannot be accessed).
+
+::
+
+  struct kvm_arm_copy_mte_tags {
+       __u64 guest_ipa;
+       __u64 length;
+       void __user *addr;
+       __u64 flags;
+       __u64 reserved[2];
+  };
+
+Copies Memory Tagging Extension (MTE) tags to/from guest tag memory. The
+``guest_ipa`` and ``length`` fields must be ``PAGE_SIZE`` aligned. The ``addr``
+field must point to a buffer which the tags will be copied to or from.
+
+``flags`` specifies the direction of copy, either ``KVM_ARM_TAGS_TO_GUEST`` or
+``KVM_ARM_TAGS_FROM_GUEST``.
+
+The size of the buffer to store the tags is ``(length / 16)`` bytes
+(granules in MTE are 16 bytes long). Each byte contains a single tag
+value. This matches the format of ``PTRACE_PEEKMTETAGS`` and
+``PTRACE_POKEMTETAGS``.
+
+If an error occurs before any data is copied then a negative error code is
+returned. If some tags have been copied before an error occurs then the number
+of bytes successfully copied is returned. If the call completes successfully
+then ``length`` is returned.
 
 4.131 KVM_GET_SREGS2
 ------------------
@@ -6622,6 +6658,29 @@ that are valid (ie: if KVM_INTERNAL_ERROR_EMULATION_FLAG_INSTRUCTION_BYTES is
 set in the 'flags' field then both 'insn_size' and 'insn_bytes' have valid data
 in them.)
 
+7.28 KVM_CAP_ARM_MTE
+--------------------
+
+:Architectures: arm64
+:Parameters: none
+
+This capability indicates that KVM (and the hardware) supports exposing the
+Memory Tagging Extensions (MTE) to the guest. It must also be enabled by the
+VMM before creating any VCPUs to allow the guest access. Note that MTE is only
+available to a guest running in AArch64 mode and enabling this capability will
+cause attempts to create AArch32 VCPUs to fail.
+
+When enabled the guest is able to access tags associated with any memory given
+to the guest. KVM will ensure that the tags are maintained during swap or
+hibernation of the host; however the VMM needs to manually save/restore the
+tags as appropriate if the VM is migrated.
+
+When this capability is enabled all memory in memslots must be mapped as
+not-shareable (no MAP_SHARED), attempts to create a memslot with a
+MAP_SHARED mmap will result in an -EINVAL return.
+
+When enabled the VMM may make use of the ``KVM_ARM_MTE_COPY_TAGS`` ioctl to
+perform a bulk copy of tags to/from the guest.
 
 8. Other capabilities.
 ======================
index 008fcad7ac00814a5156e1623dcf6790296ad260..b9d5999253c45ae6eda5d18a9bfc43633e6c7740 100644 (file)
@@ -1618,8 +1618,8 @@ F:        Documentation/devicetree/bindings/sound/amlogic*
 F:     sound/soc/meson/
 
 ARM/Amlogic Meson SoC support
+M:     Neil Armstrong <narmstrong@baylibre.com>
 M:     Kevin Hilman <khilman@baylibre.com>
-R:     Neil Armstrong <narmstrong@baylibre.com>
 R:     Jerome Brunet <jbrunet@baylibre.com>
 R:     Martin Blumenstingl <martin.blumenstingl@googlemail.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -4138,6 +4138,14 @@ S:       Odd Fixes
 F:     Documentation/devicetree/bindings/arm/cavium-thunder2.txt
 F:     arch/arm64/boot/dts/cavium/thunder2-99xx*
 
+CBS/ETF/TAPRIO QDISCS
+M:     Vinicius Costa Gomes <vinicius.gomes@intel.com>
+S:     Maintained
+L:     netdev@vger.kernel.org
+F:     net/sched/sch_cbs.c
+F:     net/sched/sch_etf.c
+F:     net/sched/sch_taprio.c
+
 CC2520 IEEE-802.15.4 RADIO DRIVER
 M:     Varka Bhadram <varkabhadram@gmail.com>
 L:     linux-wpan@vger.kernel.org
@@ -5569,7 +5577,6 @@ F:        drivers/soc/fsl/dpio
 
 DPAA2 ETHERNET DRIVER
 M:     Ioana Ciornei <ioana.ciornei@nxp.com>
-M:     Ioana Radulescu <ruxandra.radulescu@nxp.com>
 L:     netdev@vger.kernel.org
 S:     Maintained
 F:     Documentation/networking/device_drivers/ethernet/freescale/dpaa2/ethernet-driver.rst
@@ -9986,6 +9993,8 @@ F:        arch/arm64/include/asm/kvm*
 F:     arch/arm64/include/uapi/asm/kvm*
 F:     arch/arm64/kvm/
 F:     include/kvm/arm_*
+F:     tools/testing/selftests/kvm/*/aarch64/
+F:     tools/testing/selftests/kvm/aarch64/
 
 KERNEL VIRTUAL MACHINE FOR MIPS (KVM/mips)
 M:     Huacai Chen <chenhuacai@kernel.org>
@@ -12180,6 +12189,7 @@ F:      drivers/platform/surface/surfacepro3_button.c
 
 MICROSOFT SURFACE SYSTEM AGGREGATOR SUBSYSTEM
 M:     Maximilian Luz <luzmaximilian@gmail.com>
+L:     platform-driver-x86@vger.kernel.org
 S:     Maintained
 W:     https://github.com/linux-surface/surface-aggregator-module
 C:     irc://chat.freenode.net/##linux-surface
@@ -12680,9 +12690,9 @@ F:      drivers/rtc/rtc-ntxec.c
 F:     include/linux/mfd/ntxec.h
 
 NETRONOME ETHERNET DRIVERS
-M:     Simon Horman <simon.horman@netronome.com>
+M:     Simon Horman <simon.horman@corigine.com>
 R:     Jakub Kicinski <kuba@kernel.org>
-L:     oss-drivers@netronome.com
+L:     oss-drivers@corigine.com
 S:     Maintained
 F:     drivers/net/ethernet/netronome/
 
@@ -12709,7 +12719,6 @@ M:      "David S. Miller" <davem@davemloft.net>
 M:     Jakub Kicinski <kuba@kernel.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-W:     http://www.linuxfoundation.org/en/Net
 Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git
@@ -12754,7 +12763,6 @@ M:      "David S. Miller" <davem@davemloft.net>
 M:     Jakub Kicinski <kuba@kernel.org>
 L:     netdev@vger.kernel.org
 S:     Maintained
-W:     http://www.linuxfoundation.org/en/Net
 Q:     https://patchwork.kernel.org/project/netdevbpf/list/
 B:     mailto:netdev@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git
@@ -12896,8 +12904,10 @@ F:     include/uapi/linux/nexthop.h
 F:     net/ipv4/nexthop.c
 
 NFC SUBSYSTEM
+M:     Krzysztof Kozlowski <krzysztof.kozlowski@canonical.com>
+L:     linux-nfc@lists.01.org (moderated for non-subscribers)
 L:     netdev@vger.kernel.org
-S:     Orphan
+S:     Maintained
 F:     Documentation/devicetree/bindings/net/nfc/
 F:     drivers/nfc/
 F:     include/linux/platform_data/nfcmrvl.h
@@ -13205,7 +13215,6 @@ F:      Documentation/devicetree/bindings/sound/tfa9879.txt
 F:     sound/soc/codecs/tfa9879*
 
 NXP-NCI NFC DRIVER
-M:     Clément Perrochaud <clement.perrochaud@effinnov.com>
 R:     Charles Gorand <charles.gorand@effinnov.com>
 L:     linux-nfc@lists.01.org (moderated for non-subscribers)
 S:     Supported
@@ -14317,10 +14326,12 @@ PER-CPU MEMORY ALLOCATOR
 M:     Dennis Zhou <dennis@kernel.org>
 M:     Tejun Heo <tj@kernel.org>
 M:     Christoph Lameter <cl@linux.com>
+L:     linux-mm@kvack.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/dennis/percpu.git
 F:     arch/*/include/asm/percpu.h
 F:     include/linux/percpu*.h
+F:     lib/percpu*.c
 F:     mm/percpu*.c
 
 PER-TASK DELAY ACCOUNTING
@@ -14734,7 +14745,6 @@ W:      https://wireless.wiki.kernel.org/en/users/Drivers/p54
 F:     drivers/net/wireless/intersil/prism54/
 
 PROC FILESYSTEM
-R:     Alexey Dobriyan <adobriyan@gmail.com>
 L:     linux-kernel@vger.kernel.org
 L:     linux-fsdevel@vger.kernel.org
 S:     Maintained
@@ -15945,6 +15955,7 @@ S390 IUCV NETWORK LAYER
 M:     Julian Wiedmann <jwi@linux.ibm.com>
 M:     Karsten Graul <kgraul@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
+L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
 F:     drivers/s390/net/*iucv*
@@ -15955,6 +15966,7 @@ S390 NETWORK DRIVERS
 M:     Julian Wiedmann <jwi@linux.ibm.com>
 M:     Karsten Graul <kgraul@linux.ibm.com>
 L:     linux-s390@vger.kernel.org
+L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.ibm.com/developerworks/linux/linux390/
 F:     drivers/s390/net/
@@ -17304,6 +17316,12 @@ L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/busses/i2c-stm32*
 
+ST STM32 SPI DRIVER
+M:     Alain Volmat <alain.volmat@foss.st.com>
+L:     linux-spi@vger.kernel.org
+S:     Maintained
+F:     drivers/spi/spi-stm32.c
+
 ST STPDDC60 DRIVER
 M:     Daniel Nilsson <daniel.nilsson@flex.com>
 L:     linux-hwmon@vger.kernel.org
@@ -17662,7 +17680,6 @@ R:      Mika Westerberg <mika.westerberg@linux.intel.com>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/busses/i2c-designware-*
-F:     include/linux/platform_data/i2c-designware.h
 
 SYNOPSYS DESIGNWARE MMC/SD/SDIO DRIVER
 M:     Jaehoon Chung <jh80.chung@samsung.com>
@@ -19998,6 +20015,7 @@ F:      arch/x86/xen/*swiotlb*
 F:     drivers/xen/*swiotlb*
 
 XFS FILESYSTEM
+C:     irc://irc.oftc.net/xfs
 M:     Darrick J. Wong <djwong@kernel.org>
 M:     linux-xfs@vger.kernel.org
 L:     linux-xfs@vger.kernel.org
index 0ed7e061c8e9eb8ded46538de1fbcb161f6785ca..b79e0e8acbe3385028eda1781c528d7f666c3131 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 13
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc4
 NAME = Frozen Wasteland
 
 # *DOCUMENTATION*
@@ -928,6 +928,11 @@ CC_FLAGS_LTO       += -fvisibility=hidden
 
 # Limit inlining across translation units to reduce binary size
 KBUILD_LDFLAGS += -mllvm -import-instr-limit=5
+
+# Check for frame size exceeding threshold during prolog/epilog insertion.
+ifneq ($(CONFIG_FRAME_WARN),0)
+KBUILD_LDFLAGS += -plugin-opt=-warn-stack-size=$(CONFIG_FRAME_WARN)
+endif
 endif
 
 ifdef CONFIG_LTO
index 5622578742fdde44e9c6a28955923438795f1b4e..3000a2e8ee21734d1759f2f4b208f5e68e63d4a3 100644 (file)
 550    common  process_madvise                 sys_process_madvise
 551    common  epoll_pwait2                    sys_epoll_pwait2
 552    common  mount_setattr                   sys_mount_setattr
-553    common  quotactl_path                   sys_quotactl_path
+# 553 reserved for quotactl_path
 554    common  landlock_create_ruleset         sys_landlock_create_ruleset
 555    common  landlock_add_rule               sys_landlock_add_rule
 556    common  landlock_restrict_self          sys_landlock_restrict_self
index 658c8efb4ca1445891c370aad48ff924658537d5..a71cf1d189ae5b740246be8477d7e2a8b18e82e9 100644 (file)
@@ -10,6 +10,7 @@ config ARCH_WPCM450
        bool "Support for WPCM450 BMC (Hermon)"
        depends on ARCH_MULTI_V5
        select CPU_ARM926T
+       select WPCM450_AIC
        select NPCM7XX_TIMER
        help
          General support for WPCM450 BMC (Hermon).
index ec0d9b094744db67ae99bb80faababa817c3845e..bddfc7cd5d40f5e921ca8ef0fd6db332ddd632e2 100644 (file)
@@ -121,8 +121,13 @@ static int cplds_probe(struct platform_device *pdev)
                return fpga->irq;
 
        base_irq = platform_get_irq(pdev, 1);
-       if (base_irq < 0)
+       if (base_irq < 0) {
                base_irq = 0;
+       } else {
+               ret = devm_irq_alloc_descs(&pdev->dev, base_irq, base_irq, CPLDS_NB_IRQ, 0);
+               if (ret < 0)
+                       return ret;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        fpga->base = devm_ioremap_resource(&pdev->dev, res);
index c7679d7db98b0cf689b9d549569effb71ca72128..28e03b5fec0044da777eaf5fa8efc5f3a6e87df4 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index d6465823b28102eb6510bb2367ebc2da9975722b..7b393cfec071617ceadc2bcf5d6ea17049605f6e 100644 (file)
@@ -1,6 +1,5 @@
 # SPDX-License-Identifier: GPL-2.0-only
-obj-y                  += kernel/ mm/
-obj-$(CONFIG_NET)      += net/
+obj-y                  += kernel/ mm/ net/
 obj-$(CONFIG_KVM)      += kvm/
 obj-$(CONFIG_XEN)      += xen/
 obj-$(CONFIG_CRYPTO)   += crypto/
index c62ddb9b2ba565e9270d2acd72417ae73b7a81ba..3771144a2ce49a452a69c96bb8abb6b1135d8bc0 100644 (file)
@@ -14,7 +14,6 @@
 
        ports {
                port@0 {
-                       reg = <0>;
                        csi20_in: endpoint {
                                clock-lanes = <0>;
                                data-lanes = <1 2>;
@@ -29,7 +28,6 @@
 
        ports {
                port@0 {
-                       reg = <0>;
                        csi40_in: endpoint {
                                clock-lanes = <0>;
                                data-lanes = <1 2>;
index d64fb8b1b86c37318a8b63abdd4630b0b954f9fc..46f8dbf6890482d93fe8f279f0198d8b0ad93f72 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index 5b05474dc272788414fba848d01bb0f559260dc5..d16a4be5ef77a21bd64284ada40132d3cf105874 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index e7b4a929bb17484002b98d349254bc7c9ccdae24..2e3d1981cac4814478c1d3e7d573e172d378a995 100644 (file)
@@ -33,7 +33,7 @@
        status = "okay";
 
        ports {
-               port {
+               port@0 {
                        csi40_in: endpoint {
                                clock-lanes = <0>;
                                data-lanes = <1 2>;
index 20fa3caa050e5d5ec0eaae8904e3b1c632fdeebc..1aef34447abd1b3d30d623593dcb558b85ad3f02 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index 8eb006cbd9af4c98f4dc28b5b12c049da83f20dc..1f51237ab0a648fa9c9d5a188d6013fb39d7e27a 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index 25b87da32eebb6dc2f9abf0f671cfa7410722274..b643d3079db1e7aa0a72761f535a76da86e75316 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <0>;
 
+                       port@0 {
+                               reg = <0>;
+                       };
+
                        port@1 {
                                #address-cells = <1>;
                                #size-cells = <0>;
index 5c39152e45707441d3c5f31bb50fcfe11c883b4d..85d66d15465ab2b6ca66c39634f429120ca70d20 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index 25d947a81b294a8138ed8a928cd4c787187866d7..12476e354d746d0eb867c7e2d97a355ce1a76660 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index ab081f14af9aa0fbf92e7323b0b8cdc5f702f4fd..d9804768425a76037d716ea818be100cab045d35 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index 657b20d3533bd398c6d323ccd61372c167a3a53e..dcb9df861d749692798bfd8afc0ad07815da47e7 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index 5a5d5649332a8b1dec168ebe2d81d0ee2442edf3..e8f6352c3665f44c6503a53e0ee832a17d328407 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index 1ffa4a995a7ab8ae8fe8fa25d347ef04fd7a5fa4..7b51d464de0eac8bdeea65f63fb79c331056463e 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index 295d34f1d216d963e22e38e60b6f72613e21ba7f..4715e4a4abe064cdf70b577c27c84428c06d0886 100644 (file)
 
        ports {
                port@0 {
-                       reg = <0>;
-
                        csi40_in: endpoint {
                                clock-lanes = <0>;
                                data-lanes = <1 2>;
index 5010f23fafcc7f98e1b1d7f7c9de7741f636471e..0eaea58f4210d89a9f3417b74e09d0a7e270f276 100644 (file)
                                #address-cells = <1>;
                                #size-cells = <0>;
 
+                               port@0 {
+                                       reg = <0>;
+                               };
+
                                port@1 {
                                        #address-cells = <1>;
                                        #size-cells = <0>;
index e18747df219f8118ae2f75bbbe3290207d44647e..453ffcef24fae1be1dec0923258322182461c98a 100644 (file)
 
        ports {
                port@0 {
-                       reg = <0>;
                        csi20_in: endpoint {
                                clock-lanes = <0>;
                                data-lanes = <1>;
 
        ports {
                port@0 {
-                       reg = <0>;
-
                        csi40_in: endpoint {
                                clock-lanes = <0>;
                                data-lanes = <1 2 3 4>;
index 8a078fc662ac5df176785caa5f04746b55f50063..477703578caa40625eb3d9e33419c33e31a44f51 100644 (file)
@@ -197,11 +197,6 @@ alternative_endif
 #define _ALTERNATIVE_CFG(insn1, insn2, cap, cfg, ...)  \
        alternative_insn insn1, insn2, cap, IS_ENABLED(cfg)
 
-.macro user_alt, label, oldinstr, newinstr, cond
-9999:  alternative_insn "\oldinstr", "\newinstr", \cond
-       _asm_extable 9999b, \label
-.endm
-
 #endif  /*  __ASSEMBLY__  */
 
 /*
index 934b9be582d21deb1f7d7d98d036918642e80180..4ad22c3135dbb916b6e427f517f1ae2038c7da44 100644 (file)
@@ -124,7 +124,8 @@ static inline u32 gic_read_rpr(void)
 #define gic_read_lpir(c)               readq_relaxed(c)
 #define gic_write_lpir(v, c)           writeq_relaxed(v, c)
 
-#define gic_flush_dcache_to_poc(a,l)   __flush_dcache_area((a), (l))
+#define gic_flush_dcache_to_poc(a,l)   \
+       dcache_clean_inval_poc((unsigned long)(a), (unsigned long)(a)+(l))
 
 #define gits_read_baser(c)             readq_relaxed(c)
 #define gits_write_baser(v, c)         writeq_relaxed(v, c)
index 8418c1bd8f044e0bb27bd21f3ae6fd01bd51bff4..c4cecf85dccf50954bfaa18523599b1561041e47 100644 (file)
@@ -130,15 +130,27 @@ alternative_endif
        .endm
 
 /*
- * Emit an entry into the exception table
+ * Create an exception table entry for `insn`, which will branch to `fixup`
+ * when an unhandled fault is taken.
  */
-       .macro          _asm_extable, from, to
+       .macro          _asm_extable, insn, fixup
        .pushsection    __ex_table, "a"
        .align          3
-       .long           (\from - .), (\to - .)
+       .long           (\insn - .), (\fixup - .)
        .popsection
        .endm
 
+/*
+ * Create an exception table entry for `insn` if `fixup` is provided. Otherwise
+ * do nothing.
+ */
+       .macro          _cond_extable, insn, fixup
+       .ifnc           \fixup,
+       _asm_extable    \insn, \fixup
+       .endif
+       .endm
+
+
 #define USER(l, x...)                          \
 9999:  x;                                      \
        _asm_extable    9999b, l
@@ -375,51 +387,53 @@ alternative_cb_end
        bfi     \tcr, \tmp0, \pos, #3
        .endm
 
+       .macro __dcache_op_workaround_clean_cache, op, addr
+alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
+       dc      \op, \addr
+alternative_else
+       dc      civac, \addr
+alternative_endif
+       .endm
+
 /*
  * Macro to perform a data cache maintenance for the interval
- * [kaddr, kaddr + size)
+ * [start, end)
  *
  *     op:             operation passed to dc instruction
  *     domain:         domain used in dsb instruciton
- *     kaddr:          starting virtual address of the region
- *     size:           size of the region
- *     Corrupts:       kaddr, size, tmp1, tmp2
+ *     start:          starting virtual address of the region
+ *     end:            end virtual address of the region
+ *     fixup:          optional label to branch to on user fault
+ *     Corrupts:       start, end, tmp1, tmp2
  */
-       .macro __dcache_op_workaround_clean_cache, op, kaddr
-alternative_if_not ARM64_WORKAROUND_CLEAN_CACHE
-       dc      \op, \kaddr
-alternative_else
-       dc      civac, \kaddr
-alternative_endif
-       .endm
-
-       .macro dcache_by_line_op op, domain, kaddr, size, tmp1, tmp2
+       .macro dcache_by_line_op op, domain, start, end, tmp1, tmp2, fixup
        dcache_line_size \tmp1, \tmp2
-       add     \size, \kaddr, \size
        sub     \tmp2, \tmp1, #1
-       bic     \kaddr, \kaddr, \tmp2
-9998:
+       bic     \start, \start, \tmp2
+.Ldcache_op\@:
        .ifc    \op, cvau
-       __dcache_op_workaround_clean_cache \op, \kaddr
+       __dcache_op_workaround_clean_cache \op, \start
        .else
        .ifc    \op, cvac
-       __dcache_op_workaround_clean_cache \op, \kaddr
+       __dcache_op_workaround_clean_cache \op, \start
        .else
        .ifc    \op, cvap
-       sys     3, c7, c12, 1, \kaddr   // dc cvap
+       sys     3, c7, c12, 1, \start   // dc cvap
        .else
        .ifc    \op, cvadp
-       sys     3, c7, c13, 1, \kaddr   // dc cvadp
+       sys     3, c7, c13, 1, \start   // dc cvadp
        .else
-       dc      \op, \kaddr
+       dc      \op, \start
        .endif
        .endif
        .endif
        .endif
-       add     \kaddr, \kaddr, \tmp1
-       cmp     \kaddr, \size
-       b.lo    9998b
+       add     \start, \start, \tmp1
+       cmp     \start, \end
+       b.lo    .Ldcache_op\@
        dsb     \domain
+
+       _cond_extable .Ldcache_op\@, \fixup
        .endm
 
 /*
@@ -427,20 +441,22 @@ alternative_endif
  * [start, end)
  *
  *     start, end:     virtual addresses describing the region
- *     label:          A label to branch to on user fault.
+ *     fixup:          optional label to branch to on user fault
  *     Corrupts:       tmp1, tmp2
  */
-       .macro invalidate_icache_by_line start, end, tmp1, tmp2, label
+       .macro invalidate_icache_by_line start, end, tmp1, tmp2, fixup
        icache_line_size \tmp1, \tmp2
        sub     \tmp2, \tmp1, #1
        bic     \tmp2, \start, \tmp2
-9997:
-USER(\label, ic        ivau, \tmp2)                    // invalidate I line PoU
+.Licache_op\@:
+       ic      ivau, \tmp2                     // invalidate I line PoU
        add     \tmp2, \tmp2, \tmp1
        cmp     \tmp2, \end
-       b.lo    9997b
+       b.lo    .Licache_op\@
        dsb     ish
        isb
+
+       _cond_extable .Licache_op\@, \fixup
        .endm
 
 /*
index 2175ec0004edb38fbb2de0a8c9e691e3536c7f62..451e11e5fd23b768af35a4587fe568db7cdbee7f 100644 (file)
@@ -74,7 +74,7 @@ static inline unsigned long array_index_mask_nospec(unsigned long idx,
  * This insanity brought to you by speculative system register reads,
  * out-of-order memory accesses, sequence locks and Thomas Gleixner.
  *
- * http://lists.infradead.org/pipermail/linux-arm-kernel/2019-February/631195.html
+ * https://lore.kernel.org/r/alpine.DEB.2.21.1902081950260.1662@nanos.tec.linutronix.de/
  */
 #define arch_counter_enforce_ordering(val) do {                                \
        u64 tmp, _val = (val);                                          \
index 52e5c162322401d38a5942905e7ca5dae150578b..543c997eb3b7d7508b44800581e8b82288b80e97 100644 (file)
  *     the implementation assumes non-aliasing VIPT D-cache and (aliasing)
  *     VIPT I-cache.
  *
- *     flush_icache_range(start, end)
+ *     All functions below apply to the interval [start, end)
+ *             - start  - virtual start address (inclusive)
+ *             - end    - virtual end address (exclusive)
  *
- *             Ensure coherency between the I-cache and the D-cache in the
- *             region described by start, end.
- *             - start  - virtual start address
- *             - end    - virtual end address
+ *     caches_clean_inval_pou(start, end)
  *
- *     invalidate_icache_range(start, end)
+ *             Ensure coherency between the I-cache and the D-cache region to
+ *             the Point of Unification.
  *
- *             Invalidate the I-cache in the region described by start, end.
- *             - start  - virtual start address
- *             - end    - virtual end address
+ *     caches_clean_inval_user_pou(start, end)
  *
- *     __flush_cache_user_range(start, end)
+ *             Ensure coherency between the I-cache and the D-cache region to
+ *             the Point of Unification.
+ *             Use only if the region might access user memory.
  *
- *             Ensure coherency between the I-cache and the D-cache in the
- *             region described by start, end.
- *             - start  - virtual start address
- *             - end    - virtual end address
+ *     icache_inval_pou(start, end)
  *
- *     __flush_dcache_area(kaddr, size)
+ *             Invalidate I-cache region to the Point of Unification.
  *
- *             Ensure that the data held in page is written back.
- *             - kaddr  - page address
- *             - size   - region size
+ *     dcache_clean_inval_poc(start, end)
+ *
+ *             Clean and invalidate D-cache region to the Point of Coherency.
+ *
+ *     dcache_inval_poc(start, end)
+ *
+ *             Invalidate D-cache region to the Point of Coherency.
+ *
+ *     dcache_clean_poc(start, end)
+ *
+ *             Clean D-cache region to the Point of Coherency.
+ *
+ *     dcache_clean_pop(start, end)
+ *
+ *             Clean D-cache region to the Point of Persistence.
+ *
+ *     dcache_clean_pou(start, end)
+ *
+ *             Clean D-cache region to the Point of Unification.
  */
-extern void __flush_icache_range(unsigned long start, unsigned long end);
-extern int  invalidate_icache_range(unsigned long start, unsigned long end);
-extern void __flush_dcache_area(void *addr, size_t len);
-extern void __inval_dcache_area(void *addr, size_t len);
-extern void __clean_dcache_area_poc(void *addr, size_t len);
-extern void __clean_dcache_area_pop(void *addr, size_t len);
-extern void __clean_dcache_area_pou(void *addr, size_t len);
-extern long __flush_cache_user_range(unsigned long start, unsigned long end);
-extern void sync_icache_aliases(void *kaddr, unsigned long len);
+extern void caches_clean_inval_pou(unsigned long start, unsigned long end);
+extern void icache_inval_pou(unsigned long start, unsigned long end);
+extern void dcache_clean_inval_poc(unsigned long start, unsigned long end);
+extern void dcache_inval_poc(unsigned long start, unsigned long end);
+extern void dcache_clean_poc(unsigned long start, unsigned long end);
+extern void dcache_clean_pop(unsigned long start, unsigned long end);
+extern void dcache_clean_pou(unsigned long start, unsigned long end);
+extern long caches_clean_inval_user_pou(unsigned long start, unsigned long end);
+extern void sync_icache_aliases(unsigned long start, unsigned long end);
 
 static inline void flush_icache_range(unsigned long start, unsigned long end)
 {
-       __flush_icache_range(start, end);
+       caches_clean_inval_pou(start, end);
 
        /*
         * IPI all online CPUs so that they undergo a context synchronization
@@ -122,7 +135,7 @@ extern void copy_to_user_page(struct vm_area_struct *, struct page *,
 #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
 extern void flush_dcache_page(struct page *);
 
-static __always_inline void __flush_icache_all(void)
+static __always_inline void icache_inval_all_pou(void)
 {
        if (cpus_have_const_cap(ARM64_HAS_CACHE_DIC))
                return;
index 3578aba9c60805ad538ad99a352a09bc1ea2b340..1bed37eb013a1624046eea8a855f368204045ed4 100644 (file)
@@ -137,7 +137,7 @@ void efi_virtmap_unload(void);
 
 static inline void efi_capsule_flush_cache_range(void *addr, int size)
 {
-       __flush_dcache_area(addr, size);
+       dcache_clean_inval_poc((unsigned long)addr, (unsigned long)addr + size);
 }
 
 #endif /* _ASM_EFI_H */
index 692c9049befab069cf5c146a9275e68a2ba3f693..d436831dd70681a4e402852ba557b2ee6bded925 100644 (file)
@@ -12,7 +12,8 @@
 #include <asm/types.h>
 
 /* Hyp Configuration Register (HCR) bits */
-#define HCR_ATA                (UL(1) << 56)
+#define HCR_ATA_SHIFT  56
+#define HCR_ATA                (UL(1) << HCR_ATA_SHIFT)
 #define HCR_FWB                (UL(1) << 46)
 #define HCR_API                (UL(1) << 41)
 #define HCR_APK                (UL(1) << 40)
index 01b9857757f2a0c4992bfa99f75f74f0321beda5..fd418955e31e68c2d2d7ec2d477d724f3dd34bcc 100644 (file)
@@ -84,6 +84,9 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
        if (cpus_have_const_cap(ARM64_MISMATCHED_CACHE_TYPE) ||
            vcpu_el1_is_32bit(vcpu))
                vcpu->arch.hcr_el2 |= HCR_TID2;
+
+       if (kvm_has_mte(vcpu->kvm))
+               vcpu->arch.hcr_el2 |= HCR_ATA;
 }
 
 static inline unsigned long *vcpu_hcr(struct kvm_vcpu *vcpu)
index 5a2c82f63baaa5d18d4984f7f69d7104d0b5c1a7..41911585ae0cfa3db73e6c67b78e88e0e781a118 100644 (file)
@@ -46,6 +46,7 @@
 #define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
 #define KVM_REQ_RECORD_STEAL   KVM_ARCH_REQ(3)
 #define KVM_REQ_RELOAD_GICv4   KVM_ARCH_REQ(4)
+#define KVM_REQ_RELOAD_PMU     KVM_ARCH_REQ(5)
 
 #define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
                                     KVM_DIRTY_LOG_INITIALLY_SET)
@@ -132,6 +133,9 @@ struct kvm_arch {
 
        u8 pfr0_csv2;
        u8 pfr0_csv3;
+
+       /* Memory Tagging Extension enabled for the guest */
+       bool mte_enabled;
 };
 
 struct kvm_vcpu_fault_info {
@@ -206,6 +210,12 @@ enum vcpu_sysreg {
        CNTP_CVAL_EL0,
        CNTP_CTL_EL0,
 
+       /* Memory Tagging Extension registers */
+       RGSR_EL1,       /* Random Allocation Tag Seed Register */
+       GCR_EL1,        /* Tag Control Register */
+       TFSR_EL1,       /* Tag Fault Status Register (EL1) */
+       TFSRE0_EL1,     /* Tag Fault Status Register (EL0) */
+
        /* 32bit specific registers. Keep them at the end of the range */
        DACR32_EL2,     /* Domain Access Control Register */
        IFSR32_EL2,     /* Instruction Fault Status Register */
@@ -716,6 +726,9 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu,
 int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
                               struct kvm_device_attr *attr);
 
+long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
+                               struct kvm_arm_copy_mte_tags *copy_tags);
+
 /* Guest/host FPSIMD coordination helpers */
 int kvm_arch_vcpu_run_map_fp(struct kvm_vcpu *vcpu);
 void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu);
@@ -764,6 +777,7 @@ bool kvm_arm_vcpu_is_finalized(struct kvm_vcpu *vcpu);
 #define kvm_arm_vcpu_sve_finalized(vcpu) \
        ((vcpu)->arch.flags & KVM_ARM64_VCPU_SVE_FINALIZED)
 
+#define kvm_has_mte(kvm) (system_supports_mte() && (kvm)->arch.mte_enabled)
 #define kvm_vcpu_has_pmu(vcpu)                                 \
        (test_bit(KVM_ARM_VCPU_PMU_V3, (vcpu)->arch.features))
 
index 25ed956f9af1530bf57c3343107d6f7ad54b3574..b52c5c4b9a3dde602a5f734eca60c800f6d3927f 100644 (file)
@@ -180,17 +180,16 @@ static inline void *__kvm_vector_slot2addr(void *base,
 
 struct kvm;
 
-#define kvm_flush_dcache_to_poc(a,l)   __flush_dcache_area((a), (l))
+#define kvm_flush_dcache_to_poc(a,l)   \
+       dcache_clean_inval_poc((unsigned long)(a), (unsigned long)(a)+(l))
 
 static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
 {
        return (vcpu_read_sys_reg(vcpu, SCTLR_EL1) & 0b101) == 0b101;
 }
 
-static inline void __clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
+static inline void __clean_dcache_guest_page(void *va, size_t size)
 {
-       void *va = page_address(pfn_to_page(pfn));
-
        /*
         * With FWB, we ensure that the guest always accesses memory using
         * cacheable attributes, and we don't have to clean to PoC when
@@ -203,18 +202,14 @@ static inline void __clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
        kvm_flush_dcache_to_poc(va, size);
 }
 
-static inline void __invalidate_icache_guest_page(kvm_pfn_t pfn,
-                                                 unsigned long size)
+static inline void __invalidate_icache_guest_page(void *va, size_t size)
 {
        if (icache_is_aliasing()) {
                /* any kind of VIPT cache */
-               __flush_icache_all();
+               icache_inval_all_pou();
        } else if (is_kernel_in_hyp_mode() || !icache_is_vpipt()) {
                /* PIPT or VPIPT at EL2 (see comment in __kvm_tlb_flush_vmid_ipa) */
-               void *va = page_address(pfn_to_page(pfn));
-
-               invalidate_icache_range((unsigned long)va,
-                                       (unsigned long)va + size);
+               icache_inval_pou((unsigned long)va, (unsigned long)va + size);
        }
 }
 
diff --git a/arch/arm64/include/asm/kvm_mte.h b/arch/arm64/include/asm/kvm_mte.h
new file mode 100644 (file)
index 0000000..de00263
--- /dev/null
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2021 ARM Ltd.
+ */
+#ifndef __ASM_KVM_MTE_H
+#define __ASM_KVM_MTE_H
+
+#ifdef __ASSEMBLY__
+
+#include <asm/sysreg.h>
+
+#ifdef CONFIG_ARM64_MTE
+
+.macro mte_switch_to_guest g_ctxt, h_ctxt, reg1
+alternative_if_not ARM64_MTE
+       b       .L__skip_switch\@
+alternative_else_nop_endif
+       mrs     \reg1, hcr_el2
+       tbz     \reg1, #(HCR_ATA_SHIFT), .L__skip_switch\@
+
+       mrs_s   \reg1, SYS_RGSR_EL1
+       str     \reg1, [\h_ctxt, #CPU_RGSR_EL1]
+       mrs_s   \reg1, SYS_GCR_EL1
+       str     \reg1, [\h_ctxt, #CPU_GCR_EL1]
+
+       ldr     \reg1, [\g_ctxt, #CPU_RGSR_EL1]
+       msr_s   SYS_RGSR_EL1, \reg1
+       ldr     \reg1, [\g_ctxt, #CPU_GCR_EL1]
+       msr_s   SYS_GCR_EL1, \reg1
+
+.L__skip_switch\@:
+.endm
+
+.macro mte_switch_to_hyp g_ctxt, h_ctxt, reg1
+alternative_if_not ARM64_MTE
+       b       .L__skip_switch\@
+alternative_else_nop_endif
+       mrs     \reg1, hcr_el2
+       tbz     \reg1, #(HCR_ATA_SHIFT), .L__skip_switch\@
+
+       mrs_s   \reg1, SYS_RGSR_EL1
+       str     \reg1, [\g_ctxt, #CPU_RGSR_EL1]
+       mrs_s   \reg1, SYS_GCR_EL1
+       str     \reg1, [\g_ctxt, #CPU_GCR_EL1]
+
+       ldr     \reg1, [\h_ctxt, #CPU_RGSR_EL1]
+       msr_s   SYS_RGSR_EL1, \reg1
+       ldr     \reg1, [\h_ctxt, #CPU_GCR_EL1]
+       msr_s   SYS_GCR_EL1, \reg1
+
+       isb
+
+.L__skip_switch\@:
+.endm
+
+#else /* !CONFIG_ARM64_MTE */
+
+.macro mte_switch_to_guest g_ctxt, h_ctxt, reg1
+.endm
+
+.macro mte_switch_to_hyp g_ctxt, h_ctxt, reg1
+.endm
+
+#endif /* CONFIG_ARM64_MTE */
+#endif /* __ASSEMBLY__ */
+#endif /* __ASM_KVM_MTE_H */
index c3674c47d48c6fbd7de55ad3003f720bab0e9bd1..f004c0115d89db1cfd9441382a73e19fbac11613 100644 (file)
@@ -27,23 +27,29 @@ typedef u64 kvm_pte_t;
 
 /**
  * struct kvm_pgtable_mm_ops - Memory management callbacks.
- * @zalloc_page:       Allocate a single zeroed memory page. The @arg parameter
- *                     can be used by the walker to pass a memcache. The
- *                     initial refcount of the page is 1.
- * @zalloc_pages_exact:        Allocate an exact number of zeroed memory pages. The
- *                     @size parameter is in bytes, and is rounded-up to the
- *                     next page boundary. The resulting allocation is
- *                     physically contiguous.
- * @free_pages_exact:  Free an exact number of memory pages previously
- *                     allocated by zalloc_pages_exact.
- * @get_page:          Increment the refcount on a page.
- * @put_page:          Decrement the refcount on a page. When the refcount
- *                     reaches 0 the page is automatically freed.
- * @page_count:                Return the refcount of a page.
- * @phys_to_virt:      Convert a physical address into a virtual address mapped
- *                     in the current context.
- * @virt_to_phys:      Convert a virtual address mapped in the current context
- *                     into a physical address.
+ * @zalloc_page:               Allocate a single zeroed memory page.
+ *                             The @arg parameter can be used by the walker
+ *                             to pass a memcache. The initial refcount of
+ *                             the page is 1.
+ * @zalloc_pages_exact:                Allocate an exact number of zeroed memory pages.
+ *                             The @size parameter is in bytes, and is rounded
+ *                             up to the next page boundary. The resulting
+ *                             allocation is physically contiguous.
+ * @free_pages_exact:          Free an exact number of memory pages previously
+ *                             allocated by zalloc_pages_exact.
+ * @get_page:                  Increment the refcount on a page.
+ * @put_page:                  Decrement the refcount on a page. When the
+ *                             refcount reaches 0 the page is automatically
+ *                             freed.
+ * @page_count:                        Return the refcount of a page.
+ * @phys_to_virt:              Convert a physical address into a virtual
+ *                             address mapped in the current context.
+ * @virt_to_phys:              Convert a virtual address mapped in the current
+ *                             context into a physical address.
+ * @dcache_clean_inval_poc:    Clean and invalidate the data cache to the PoC
+ *                             for the specified memory address range.
+ * @icache_inval_pou:          Invalidate the instruction cache to the PoU
+ *                             for the specified memory address range.
  */
 struct kvm_pgtable_mm_ops {
        void*           (*zalloc_page)(void *arg);
@@ -54,6 +60,8 @@ struct kvm_pgtable_mm_ops {
        int             (*page_count)(void *addr);
        void*           (*phys_to_virt)(phys_addr_t phys);
        phys_addr_t     (*virt_to_phys)(void *addr);
+       void            (*dcache_clean_inval_poc)(void *addr, size_t size);
+       void            (*icache_inval_pou)(void *addr, size_t size);
 };
 
 /**
index cf241b0f0a425a4e4a76a7d0a74edb604188ae61..626d359b396e58e8f1d8ee4fcb149d6a16c77868 100644 (file)
@@ -7,6 +7,7 @@
 
 #define MTE_GRANULE_SIZE       UL(16)
 #define MTE_GRANULE_MASK       (~(MTE_GRANULE_SIZE - 1))
+#define MTE_GRANULES_PER_PAGE  (PAGE_SIZE / MTE_GRANULE_SIZE)
 #define MTE_TAG_SHIFT          56
 #define MTE_TAG_SIZE           4
 #define MTE_TAG_MASK           GENMASK((MTE_TAG_SHIFT + (MTE_TAG_SIZE - 1)), MTE_TAG_SHIFT)
index bc88a1ced0d7e588070437f1ac34ba9fa01aec02..347ef38a35f79a307766dd35495bbfc8910a8d03 100644 (file)
@@ -37,7 +37,7 @@ void mte_free_tag_storage(char *storage);
 /* track which pages have valid allocation tags */
 #define PG_mte_tagged  PG_arch_2
 
-void mte_sync_tags(pte_t *ptep, pte_t pte);
+void mte_sync_tags(pte_t old_pte, pte_t pte);
 void mte_copy_page_tags(void *kto, const void *kfrom);
 void mte_thread_init_user(void);
 void mte_thread_switch(struct task_struct *next);
@@ -53,7 +53,7 @@ int mte_ptrace_copy_tags(struct task_struct *child, long request,
 /* unused if !CONFIG_ARM64_MTE, silence the compiler */
 #define PG_mte_tagged  0
 
-static inline void mte_sync_tags(pte_t *ptep, pte_t pte)
+static inline void mte_sync_tags(pte_t old_pte, pte_t pte)
 {
 }
 static inline void mte_copy_page_tags(void *kto, const void *kfrom)
index 0b10204e72fcbca2586d0106a610833e9f6b194c..db5402168841c2437a0cc32fb0fdee0e25c500c9 100644 (file)
@@ -314,9 +314,25 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
        if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
                __sync_icache_dcache(pte);
 
-       if (system_supports_mte() &&
-           pte_present(pte) && pte_tagged(pte) && !pte_special(pte))
-               mte_sync_tags(ptep, pte);
+       /*
+        * If the PTE would provide user space access to the tags associated
+        * with it then ensure that the MTE tags are synchronised.  Although
+        * pte_access_permitted() returns false for exec only mappings, they
+        * don't expose tags (instruction fetches don't check tags).
+        */
+       if (system_supports_mte() && pte_access_permitted(pte, false) &&
+           !pte_special(pte)) {
+               pte_t old_pte = READ_ONCE(*ptep);
+               /*
+                * We only need to synchronise if the new PTE has tags enabled
+                * or if swapping in (in which case another mapping may have
+                * set tags in the past even if this PTE isn't tagged).
+                * (!pte_none() && !pte_present()) is an open coded version of
+                * is_swap_pte()
+                */
+               if (pte_tagged(pte) || (!pte_none(old_pte) && !pte_present(old_pte)))
+                       mte_sync_tags(old_pte, pte);
+       }
 
        __check_racy_pte_update(mm, ptep, pte);
 
index 65d15700a16853b73d694b830918e51f95588aa2..347ccac2341ee34cee4a1ff3bf0245d6cc958196 100644 (file)
 
 #define INIT_SCTLR_EL2_MMU_ON                                          \
        (SCTLR_ELx_M  | SCTLR_ELx_C | SCTLR_ELx_SA | SCTLR_ELx_I |      \
-        SCTLR_ELx_IESB | SCTLR_ELx_WXN | ENDIAN_SET_EL2 | SCTLR_EL2_RES1)
+        SCTLR_ELx_IESB | SCTLR_ELx_WXN | ENDIAN_SET_EL2 |              \
+        SCTLR_ELx_ITFSB | SCTLR_EL2_RES1)
 
 #define INIT_SCTLR_EL2_MMU_OFF \
        (SCTLR_EL2_RES1 | ENDIAN_SET_EL2)
index 7859749d6628a5d0bf4ed758d03b25e5d3c0ac19..5dab69d2c22bf2074acee8be2df2e25c9521ab39 100644 (file)
@@ -893,8 +893,7 @@ __SYSCALL(__NR_process_madvise, sys_process_madvise)
 __SYSCALL(__NR_epoll_pwait2, compat_sys_epoll_pwait2)
 #define __NR_mount_setattr 442
 __SYSCALL(__NR_mount_setattr, sys_mount_setattr)
-#define __NR_quotactl_path 443
-__SYSCALL(__NR_quotactl_path, sys_quotactl_path)
+/* 443 is reserved for quotactl_path */
 #define __NR_landlock_create_ruleset 444
 __SYSCALL(__NR_landlock_create_ruleset, sys_landlock_create_ruleset)
 #define __NR_landlock_add_rule 445
index 24223adae150ca5a912c5a44800159860ae0627b..b3edde68bc3e013c66d3272e8848a090800362d3 100644 (file)
@@ -184,6 +184,17 @@ struct kvm_vcpu_events {
        __u32 reserved[12];
 };
 
+struct kvm_arm_copy_mte_tags {
+       __u64 guest_ipa;
+       __u64 length;
+       void __user *addr;
+       __u64 flags;
+       __u64 reserved[2];
+};
+
+#define KVM_ARM_TAGS_TO_GUEST          0
+#define KVM_ARM_TAGS_FROM_GUEST                1
+
 /* If you need to interpret the index values, here is the key: */
 #define KVM_REG_ARM_COPROC_MASK                0x000000000FFF0000
 #define KVM_REG_ARM_COPROC_SHIFT       16
index c906d20c7b529ca80af17d94a245ae3d0df9eaa9..3fb79b76e9d96adae5de2f08f3974a4a40ff898e 100644 (file)
@@ -181,7 +181,7 @@ static void __nocfi __apply_alternatives(struct alt_region *region, bool is_modu
         */
        if (!is_module) {
                dsb(ish);
-               __flush_icache_all();
+               icache_inval_all_pou();
                isb();
 
                /* Ignore ARM64_CB bit from feature mask */
index 0cb34ccb6e7330757118d727a230d934ce050d36..6f0044cb233e7ab3e3538bcf2579d2db57a744bd 100644 (file)
@@ -111,6 +111,8 @@ int main(void)
   DEFINE(VCPU_WORKAROUND_FLAGS,        offsetof(struct kvm_vcpu, arch.workaround_flags));
   DEFINE(VCPU_HCR_EL2,         offsetof(struct kvm_vcpu, arch.hcr_el2));
   DEFINE(CPU_USER_PT_REGS,     offsetof(struct kvm_cpu_context, regs));
+  DEFINE(CPU_RGSR_EL1,         offsetof(struct kvm_cpu_context, sys_regs[RGSR_EL1]));
+  DEFINE(CPU_GCR_EL1,          offsetof(struct kvm_cpu_context, sys_regs[GCR_EL1]));
   DEFINE(CPU_APIAKEYLO_EL1,    offsetof(struct kvm_cpu_context, sys_regs[APIAKEYLO_EL1]));
   DEFINE(CPU_APIBKEYLO_EL1,    offsetof(struct kvm_cpu_context, sys_regs[APIBKEYLO_EL1]));
   DEFINE(CPU_APDAKEYLO_EL1,    offsetof(struct kvm_cpu_context, sys_regs[APDAKEYLO_EL1]));
index 0073b24b5d25e8f6d77f938c9299262da0d32d25..61a87fa1c3055e26252c2b5e029359aceb4d0574 100644 (file)
@@ -28,7 +28,8 @@ SYM_CODE_START(efi_enter_kernel)
         * stale icache entries from before relocation.
         */
        ldr     w1, =kernel_size
-       bl      __clean_dcache_area_poc
+       add     x1, x0, x1
+       bl      dcache_clean_poc
        ic      ialluis
 
        /*
@@ -36,8 +37,8 @@ SYM_CODE_START(efi_enter_kernel)
         * so that we can safely disable the MMU and caches.
         */
        adr     x0, 0f
-       ldr     w1, 3f
-       bl      __clean_dcache_area_poc
+       adr     x1, 3f
+       bl      dcache_clean_poc
 0:
        /* Turn off Dcache and MMU */
        mrs     x0, CurrentEL
@@ -64,5 +65,5 @@ SYM_CODE_START(efi_enter_kernel)
        mov     x2, xzr
        mov     x3, xzr
        br      x19
+3:
 SYM_CODE_END(efi_enter_kernel)
-3:     .long   . - 0b
index 96873dfa67fd5214dca48d68a98483b6b1bf9d2c..6928cb67d3a033f5000495f2cc484530e67733de 100644 (file)
@@ -117,8 +117,8 @@ SYM_CODE_START_LOCAL(preserve_boot_args)
        dmb     sy                              // needed before dc ivac with
                                                // MMU off
 
-       mov     x1, #0x20                       // 4 x 8 bytes
-       b       __inval_dcache_area             // tail call
+       add     x1, x0, #0x20                   // 4 x 8 bytes
+       b       dcache_inval_poc                // tail call
 SYM_CODE_END(preserve_boot_args)
 
 /*
@@ -268,8 +268,7 @@ SYM_FUNC_START_LOCAL(__create_page_tables)
         */
        adrp    x0, init_pg_dir
        adrp    x1, init_pg_end
-       sub     x1, x1, x0
-       bl      __inval_dcache_area
+       bl      dcache_inval_poc
 
        /*
         * Clear the init page tables.
@@ -382,13 +381,11 @@ SYM_FUNC_START_LOCAL(__create_page_tables)
 
        adrp    x0, idmap_pg_dir
        adrp    x1, idmap_pg_end
-       sub     x1, x1, x0
-       bl      __inval_dcache_area
+       bl      dcache_inval_poc
 
        adrp    x0, init_pg_dir
        adrp    x1, init_pg_end
-       sub     x1, x1, x0
-       bl      __inval_dcache_area
+       bl      dcache_inval_poc
 
        ret     x28
 SYM_FUNC_END(__create_page_tables)
index 8ccca660034e4859bfb821f3053f49946fb258d4..81c0186a5e322a8d2b2cf4b6be94b75d752bc90b 100644 (file)
@@ -45,7 +45,7 @@
  * Because this code has to be copied to a 'safe' page, it can't call out to
  * other functions by PC-relative address. Also remember that it may be
  * mid-way through over-writing other functions. For this reason it contains
- * code from flush_icache_range() and uses the copy_page() macro.
+ * code from caches_clean_inval_pou() and uses the copy_page() macro.
  *
  * This 'safe' page is mapped via ttbr0, and executed from there. This function
  * switches to a copy of the linear map in ttbr1, performs the restore, then
@@ -87,11 +87,12 @@ SYM_CODE_START(swsusp_arch_suspend_exit)
        copy_page       x0, x1, x2, x3, x4, x5, x6, x7, x8, x9
 
        add     x1, x10, #PAGE_SIZE
-       /* Clean the copied page to PoU - based on flush_icache_range() */
+       /* Clean the copied page to PoU - based on caches_clean_inval_pou() */
        raw_dcache_line_size x2, x3
        sub     x3, x2, #1
        bic     x4, x10, x3
-2:     dc      cvau, x4        /* clean D line / unified line */
+2:     /* clean D line / unified line */
+alternative_insn "dc cvau, x4",  "dc civac, x4",  ARM64_WORKAROUND_CLEAN_CACHE
        add     x4, x4, x2
        cmp     x4, x1
        b.lo    2b
index b1cef371df2b211ced3f07f84e0dac92220c4097..46a0b4d6e2519768eaa86bc141f75f2efa698550 100644 (file)
@@ -210,7 +210,7 @@ static int create_safe_exec_page(void *src_start, size_t length,
                return -ENOMEM;
 
        memcpy(page, src_start, length);
-       __flush_icache_range((unsigned long)page, (unsigned long)page + length);
+       caches_clean_inval_pou((unsigned long)page, (unsigned long)page + length);
        rc = trans_pgd_idmap_page(&trans_info, &trans_ttbr0, &t0sz, page);
        if (rc)
                return rc;
@@ -240,8 +240,6 @@ static int create_safe_exec_page(void *src_start, size_t length,
        return 0;
 }
 
-#define dcache_clean_range(start, end) __flush_dcache_area(start, (end - start))
-
 #ifdef CONFIG_ARM64_MTE
 
 static DEFINE_XARRAY(mte_pages);
@@ -383,13 +381,18 @@ int swsusp_arch_suspend(void)
                ret = swsusp_save();
        } else {
                /* Clean kernel core startup/idle code to PoC*/
-               dcache_clean_range(__mmuoff_data_start, __mmuoff_data_end);
-               dcache_clean_range(__idmap_text_start, __idmap_text_end);
+               dcache_clean_inval_poc((unsigned long)__mmuoff_data_start,
+                                   (unsigned long)__mmuoff_data_end);
+               dcache_clean_inval_poc((unsigned long)__idmap_text_start,
+                                   (unsigned long)__idmap_text_end);
 
                /* Clean kvm setup code to PoC? */
                if (el2_reset_needed()) {
-                       dcache_clean_range(__hyp_idmap_text_start, __hyp_idmap_text_end);
-                       dcache_clean_range(__hyp_text_start, __hyp_text_end);
+                       dcache_clean_inval_poc(
+                               (unsigned long)__hyp_idmap_text_start,
+                               (unsigned long)__hyp_idmap_text_end);
+                       dcache_clean_inval_poc((unsigned long)__hyp_text_start,
+                                           (unsigned long)__hyp_text_end);
                }
 
                swsusp_mte_restore_tags();
@@ -474,7 +477,8 @@ int swsusp_arch_resume(void)
         * The hibernate exit text contains a set of el2 vectors, that will
         * be executed at el2 with the mmu off in order to reload hyp-stub.
         */
-       __flush_dcache_area(hibernate_exit, exit_size);
+       dcache_clean_inval_poc((unsigned long)hibernate_exit,
+                           (unsigned long)hibernate_exit + exit_size);
 
        /*
         * KASLR will cause the el2 vectors to be in a different location in
index e628c8ce1ffe2f6976fd20233f75632d73ce42c4..53a381a7f65dd48b23ddd82246be7a59453d635b 100644 (file)
@@ -237,7 +237,8 @@ asmlinkage void __init init_feature_override(void)
 
        for (i = 0; i < ARRAY_SIZE(regs); i++) {
                if (regs[i]->override)
-                       __flush_dcache_area(regs[i]->override,
+                       dcache_clean_inval_poc((unsigned long)regs[i]->override,
+                                           (unsigned long)regs[i]->override +
                                            sizeof(*regs[i]->override));
        }
 }
index bcf3c27553708ddc97a96b00f8312581b78d3738..c96a9a0043bf4a6d73d90f3d435f2c80b5bbce85 100644 (file)
@@ -35,7 +35,7 @@ __efistub_strnlen             = __pi_strnlen;
 __efistub_strcmp               = __pi_strcmp;
 __efistub_strncmp              = __pi_strncmp;
 __efistub_strrchr              = __pi_strrchr;
-__efistub___clean_dcache_area_poc = __pi___clean_dcache_area_poc;
+__efistub_dcache_clean_poc = __pi_dcache_clean_poc;
 
 #if defined(CONFIG_KASAN_GENERIC) || defined(CONFIG_KASAN_SW_TAGS)
 __efistub___memcpy             = __pi_memcpy;
index 6c0de2f60ea96a19fc15aa098604b833cae0a2a6..51cb8dc98d008268e151bfd6bd85925a541184de 100644 (file)
@@ -198,7 +198,7 @@ int __kprobes aarch64_insn_patch_text_nosync(void *addr, u32 insn)
 
        ret = aarch64_insn_write(tp, insn);
        if (ret == 0)
-               __flush_icache_range((uintptr_t)tp,
+               caches_clean_inval_pou((uintptr_t)tp,
                                     (uintptr_t)tp + AARCH64_INSN_SIZE);
 
        return ret;
index 341342b207f63286db6db7c48b72fe7629c12b9e..cfa2cfde3019d678e32241acd21416891dd74c0e 100644 (file)
@@ -72,7 +72,9 @@ u64 __init kaslr_early_init(void)
         * we end up running with module randomization disabled.
         */
        module_alloc_base = (u64)_etext - MODULES_VSIZE;
-       __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
+       dcache_clean_inval_poc((unsigned long)&module_alloc_base,
+                           (unsigned long)&module_alloc_base +
+                                   sizeof(module_alloc_base));
 
        /*
         * Try to map the FDT early. If this fails, we simply bail,
@@ -170,8 +172,12 @@ u64 __init kaslr_early_init(void)
        module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21;
        module_alloc_base &= PAGE_MASK;
 
-       __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
-       __flush_dcache_area(&memstart_offset_seed, sizeof(memstart_offset_seed));
+       dcache_clean_inval_poc((unsigned long)&module_alloc_base,
+                           (unsigned long)&module_alloc_base +
+                                   sizeof(module_alloc_base));
+       dcache_clean_inval_poc((unsigned long)&memstart_offset_seed,
+                           (unsigned long)&memstart_offset_seed +
+                                   sizeof(memstart_offset_seed));
 
        return offset;
 }
index 90a335c744425d0849844b2d89d5081f7145a361..03ceabe4d912c0ac79985e20bdb313b41cf2096a 100644 (file)
@@ -68,10 +68,16 @@ int machine_kexec_post_load(struct kimage *kimage)
        kimage->arch.kern_reloc = __pa(reloc_code);
        kexec_image_info(kimage);
 
-       /* Flush the reloc_code in preparation for its execution. */
-       __flush_dcache_area(reloc_code, arm64_relocate_new_kernel_size);
-       flush_icache_range((uintptr_t)reloc_code, (uintptr_t)reloc_code +
-                          arm64_relocate_new_kernel_size);
+       /*
+        * For execution with the MMU off, reloc_code needs to be cleaned to the
+        * PoC and invalidated from the I-cache.
+        */
+       dcache_clean_inval_poc((unsigned long)reloc_code,
+                           (unsigned long)reloc_code +
+                                   arm64_relocate_new_kernel_size);
+       icache_inval_pou((uintptr_t)reloc_code,
+                               (uintptr_t)reloc_code +
+                                       arm64_relocate_new_kernel_size);
 
        return 0;
 }
@@ -102,16 +108,18 @@ static void kexec_list_flush(struct kimage *kimage)
 
        for (entry = &kimage->head; ; entry++) {
                unsigned int flag;
-               void *addr;
+               unsigned long addr;
 
                /* flush the list entries. */
-               __flush_dcache_area(entry, sizeof(kimage_entry_t));
+               dcache_clean_inval_poc((unsigned long)entry,
+                                   (unsigned long)entry +
+                                           sizeof(kimage_entry_t));
 
                flag = *entry & IND_FLAGS;
                if (flag == IND_DONE)
                        break;
 
-               addr = phys_to_virt(*entry & PAGE_MASK);
+               addr = (unsigned long)phys_to_virt(*entry & PAGE_MASK);
 
                switch (flag) {
                case IND_INDIRECTION:
@@ -120,7 +128,7 @@ static void kexec_list_flush(struct kimage *kimage)
                        break;
                case IND_SOURCE:
                        /* flush the source pages. */
-                       __flush_dcache_area(addr, PAGE_SIZE);
+                       dcache_clean_inval_poc(addr, addr + PAGE_SIZE);
                        break;
                case IND_DESTINATION:
                        break;
@@ -147,8 +155,10 @@ static void kexec_segment_flush(const struct kimage *kimage)
                        kimage->segment[i].memsz,
                        kimage->segment[i].memsz /  PAGE_SIZE);
 
-               __flush_dcache_area(phys_to_virt(kimage->segment[i].mem),
-                       kimage->segment[i].memsz);
+               dcache_clean_inval_poc(
+                       (unsigned long)phys_to_virt(kimage->segment[i].mem),
+                       (unsigned long)phys_to_virt(kimage->segment[i].mem) +
+                               kimage->segment[i].memsz);
        }
 }
 
index 125a10e413e9f2967b7cbc56fb355924020d66e0..69b3fde8759e400e442ce3409bd578f705ecce79 100644 (file)
@@ -32,10 +32,9 @@ DEFINE_STATIC_KEY_FALSE(mte_async_mode);
 EXPORT_SYMBOL_GPL(mte_async_mode);
 #endif
 
-static void mte_sync_page_tags(struct page *page, pte_t *ptep, bool check_swap)
+static void mte_sync_page_tags(struct page *page, pte_t old_pte,
+                              bool check_swap, bool pte_is_tagged)
 {
-       pte_t old_pte = READ_ONCE(*ptep);
-
        if (check_swap && is_swap_pte(old_pte)) {
                swp_entry_t entry = pte_to_swp_entry(old_pte);
 
@@ -43,6 +42,9 @@ static void mte_sync_page_tags(struct page *page, pte_t *ptep, bool check_swap)
                        return;
        }
 
+       if (!pte_is_tagged)
+               return;
+
        page_kasan_tag_reset(page);
        /*
         * We need smp_wmb() in between setting the flags and clearing the
@@ -55,16 +57,22 @@ static void mte_sync_page_tags(struct page *page, pte_t *ptep, bool check_swap)
        mte_clear_page_tags(page_address(page));
 }
 
-void mte_sync_tags(pte_t *ptep, pte_t pte)
+void mte_sync_tags(pte_t old_pte, pte_t pte)
 {
        struct page *page = pte_page(pte);
        long i, nr_pages = compound_nr(page);
        bool check_swap = nr_pages == 1;
+       bool pte_is_tagged = pte_tagged(pte);
+
+       /* Early out if there's nothing to do */
+       if (!check_swap && !pte_is_tagged)
+               return;
 
        /* if PG_mte_tagged is set, tags have already been initialised */
        for (i = 0; i < nr_pages; i++, page++) {
                if (!test_and_set_bit(PG_mte_tagged, &page->flags))
-                       mte_sync_page_tags(page, ptep, check_swap);
+                       mte_sync_page_tags(page, old_pte, check_swap,
+                                          pte_is_tagged);
        }
 }
 
index 2c247634552b196b59e32e096381ce4dcdb827f0..9be668f3f03417455ec179b3211cd0f3550ec980 100644 (file)
@@ -21,7 +21,7 @@ void arch_uprobe_copy_ixol(struct page *page, unsigned long vaddr,
        memcpy(dst, src, len);
 
        /* flush caches (dcache/icache) */
-       sync_icache_aliases(dst, len);
+       sync_icache_aliases((unsigned long)dst, (unsigned long)dst + len);
 
        kunmap_atomic(xol_page_kaddr);
 }
index dcd7041b2b077f0ece865d5edfb4b1b67e04199c..9b4c1118194dac2d966e6f454098c3b7bd98b48c 100644 (file)
@@ -122,7 +122,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
        secondary_data.task = idle;
        secondary_data.stack = task_stack_page(idle) + THREAD_SIZE;
        update_cpu_boot_status(CPU_MMU_OFF);
-       __flush_dcache_area(&secondary_data, sizeof(secondary_data));
+       dcache_clean_inval_poc((unsigned long)&secondary_data,
+                           (unsigned long)&secondary_data +
+                                   sizeof(secondary_data));
 
        /* Now bring the CPU into our world */
        ret = boot_secondary(cpu, idle);
@@ -143,7 +145,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
        pr_crit("CPU%u: failed to come online\n", cpu);
        secondary_data.task = NULL;
        secondary_data.stack = NULL;
-       __flush_dcache_area(&secondary_data, sizeof(secondary_data));
+       dcache_clean_inval_poc((unsigned long)&secondary_data,
+                           (unsigned long)&secondary_data +
+                                   sizeof(secondary_data));
        status = READ_ONCE(secondary_data.status);
        if (status == CPU_MMU_OFF)
                status = READ_ONCE(__early_cpu_boot_status);
index c45a835128057ac6f904e9770138005c08efdfbb..7e1624ecab3c80ea6b34437d91672630e434a52a 100644 (file)
@@ -36,7 +36,7 @@ static void write_pen_release(u64 val)
        unsigned long size = sizeof(secondary_holding_pen_release);
 
        secondary_holding_pen_release = val;
-       __flush_dcache_area(start, size);
+       dcache_clean_inval_poc((unsigned long)start, (unsigned long)start + size);
 }
 
 
@@ -90,8 +90,9 @@ static int smp_spin_table_cpu_prepare(unsigned int cpu)
         * the boot protocol.
         */
        writeq_relaxed(pa_holding_pen, release_addr);
-       __flush_dcache_area((__force void *)release_addr,
-                           sizeof(*release_addr));
+       dcache_clean_inval_poc((__force unsigned long)release_addr,
+                           (__force unsigned long)release_addr +
+                                   sizeof(*release_addr));
 
        /*
         * Send an event to wake up the secondary CPU.
index 265fe3eb10699b71033d350b004b0549af6dfd58..db5159a3055fc3d9863210db32a75e8b95e845ca 100644 (file)
@@ -41,7 +41,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
                        dsb(ish);
                }
 
-               ret = __flush_cache_user_range(start, start + chunk);
+               ret = caches_clean_inval_user_pou(start, start + chunk);
                if (ret)
                        return ret;
 
index 74e0699661e90cee74094136c6a052c965cd5073..3df67c127489813b8c2e5cb7e1c5285fec5388fb 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/uaccess.h>
 
 #include <clocksource/arm_arch_timer.h>
@@ -973,36 +974,154 @@ static int kvm_timer_dying_cpu(unsigned int cpu)
        return 0;
 }
 
-int kvm_timer_hyp_init(bool has_gic)
+static int timer_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
 {
-       struct arch_timer_kvm_info *info;
-       int err;
+       if (vcpu)
+               irqd_set_forwarded_to_vcpu(d);
+       else
+               irqd_clr_forwarded_to_vcpu(d);
 
-       info = arch_timer_get_kvm_info();
-       timecounter = &info->timecounter;
+       return 0;
+}
 
-       if (!timecounter->cc) {
-               kvm_err("kvm_arch_timer: uninitialized timecounter\n");
-               return -ENODEV;
+static int timer_irq_set_irqchip_state(struct irq_data *d,
+                                      enum irqchip_irq_state which, bool val)
+{
+       if (which != IRQCHIP_STATE_ACTIVE || !irqd_is_forwarded_to_vcpu(d))
+               return irq_chip_set_parent_state(d, which, val);
+
+       if (val)
+               irq_chip_mask_parent(d);
+       else
+               irq_chip_unmask_parent(d);
+
+       return 0;
+}
+
+static void timer_irq_eoi(struct irq_data *d)
+{
+       if (!irqd_is_forwarded_to_vcpu(d))
+               irq_chip_eoi_parent(d);
+}
+
+static void timer_irq_ack(struct irq_data *d)
+{
+       d = d->parent_data;
+       if (d->chip->irq_ack)
+               d->chip->irq_ack(d);
+}
+
+static struct irq_chip timer_chip = {
+       .name                   = "KVM",
+       .irq_ack                = timer_irq_ack,
+       .irq_mask               = irq_chip_mask_parent,
+       .irq_unmask             = irq_chip_unmask_parent,
+       .irq_eoi                = timer_irq_eoi,
+       .irq_set_type           = irq_chip_set_type_parent,
+       .irq_set_vcpu_affinity  = timer_irq_set_vcpu_affinity,
+       .irq_set_irqchip_state  = timer_irq_set_irqchip_state,
+};
+
+static int timer_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
+                                 unsigned int nr_irqs, void *arg)
+{
+       irq_hw_number_t hwirq = (uintptr_t)arg;
+
+       return irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+                                            &timer_chip, NULL);
+}
+
+static void timer_irq_domain_free(struct irq_domain *domain, unsigned int virq,
+                                 unsigned int nr_irqs)
+{
+}
+
+static const struct irq_domain_ops timer_domain_ops = {
+       .alloc  = timer_irq_domain_alloc,
+       .free   = timer_irq_domain_free,
+};
+
+static struct irq_ops arch_timer_irq_ops = {
+       .get_input_level = kvm_arch_timer_get_input_level,
+};
+
+static void kvm_irq_fixup_flags(unsigned int virq, u32 *flags)
+{
+       *flags = irq_get_trigger_type(virq);
+       if (*flags != IRQF_TRIGGER_HIGH && *flags != IRQF_TRIGGER_LOW) {
+               kvm_err("Invalid trigger for timer IRQ%d, assuming level low\n",
+                       virq);
+               *flags = IRQF_TRIGGER_LOW;
        }
+}
 
-       /* First, do the virtual EL1 timer irq */
+static int kvm_irq_init(struct arch_timer_kvm_info *info)
+{
+       struct irq_domain *domain = NULL;
 
        if (info->virtual_irq <= 0) {
                kvm_err("kvm_arch_timer: invalid virtual timer IRQ: %d\n",
                        info->virtual_irq);
                return -ENODEV;
        }
+
        host_vtimer_irq = info->virtual_irq;
+       kvm_irq_fixup_flags(host_vtimer_irq, &host_vtimer_irq_flags);
+
+       if (kvm_vgic_global_state.no_hw_deactivation) {
+               struct fwnode_handle *fwnode;
+               struct irq_data *data;
+
+               fwnode = irq_domain_alloc_named_fwnode("kvm-timer");
+               if (!fwnode)
+                       return -ENOMEM;
+
+               /* Assume both vtimer and ptimer in the same parent */
+               data = irq_get_irq_data(host_vtimer_irq);
+               domain = irq_domain_create_hierarchy(data->domain, 0,
+                                                    NR_KVM_TIMERS, fwnode,
+                                                    &timer_domain_ops, NULL);
+               if (!domain) {
+                       irq_domain_free_fwnode(fwnode);
+                       return -ENOMEM;
+               }
+
+               arch_timer_irq_ops.flags |= VGIC_IRQ_SW_RESAMPLE;
+               WARN_ON(irq_domain_push_irq(domain, host_vtimer_irq,
+                                           (void *)TIMER_VTIMER));
+       }
 
-       host_vtimer_irq_flags = irq_get_trigger_type(host_vtimer_irq);
-       if (host_vtimer_irq_flags != IRQF_TRIGGER_HIGH &&
-           host_vtimer_irq_flags != IRQF_TRIGGER_LOW) {
-               kvm_err("Invalid trigger for vtimer IRQ%d, assuming level low\n",
-                       host_vtimer_irq);
-               host_vtimer_irq_flags = IRQF_TRIGGER_LOW;
+       if (info->physical_irq > 0) {
+               host_ptimer_irq = info->physical_irq;
+               kvm_irq_fixup_flags(host_ptimer_irq, &host_ptimer_irq_flags);
+
+               if (domain)
+                       WARN_ON(irq_domain_push_irq(domain, host_ptimer_irq,
+                                                   (void *)TIMER_PTIMER));
        }
 
+       return 0;
+}
+
+int kvm_timer_hyp_init(bool has_gic)
+{
+       struct arch_timer_kvm_info *info;
+       int err;
+
+       info = arch_timer_get_kvm_info();
+       timecounter = &info->timecounter;
+
+       if (!timecounter->cc) {
+               kvm_err("kvm_arch_timer: uninitialized timecounter\n");
+               return -ENODEV;
+       }
+
+       err = kvm_irq_init(info);
+       if (err)
+               return err;
+
+       /* First, do the virtual EL1 timer irq */
+
        err = request_percpu_irq(host_vtimer_irq, kvm_arch_timer_handler,
                                 "kvm guest vtimer", kvm_get_running_vcpus());
        if (err) {
@@ -1027,15 +1146,6 @@ int kvm_timer_hyp_init(bool has_gic)
        /* Now let's do the physical EL1 timer irq */
 
        if (info->physical_irq > 0) {
-               host_ptimer_irq = info->physical_irq;
-               host_ptimer_irq_flags = irq_get_trigger_type(host_ptimer_irq);
-               if (host_ptimer_irq_flags != IRQF_TRIGGER_HIGH &&
-                   host_ptimer_irq_flags != IRQF_TRIGGER_LOW) {
-                       kvm_err("Invalid trigger for ptimer IRQ%d, assuming level low\n",
-                               host_ptimer_irq);
-                       host_ptimer_irq_flags = IRQF_TRIGGER_LOW;
-               }
-
                err = request_percpu_irq(host_ptimer_irq, kvm_arch_timer_handler,
                                         "kvm guest ptimer", kvm_get_running_vcpus());
                if (err) {
@@ -1143,7 +1253,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
        ret = kvm_vgic_map_phys_irq(vcpu,
                                    map.direct_vtimer->host_timer_irq,
                                    map.direct_vtimer->irq.irq,
-                                   kvm_arch_timer_get_input_level);
+                                   &arch_timer_irq_ops);
        if (ret)
                return ret;
 
@@ -1151,7 +1261,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
                ret = kvm_vgic_map_phys_irq(vcpu,
                                            map.direct_ptimer->host_timer_irq,
                                            map.direct_ptimer->irq.irq,
-                                           kvm_arch_timer_get_input_level);
+                                           &arch_timer_irq_ops);
        }
 
        if (ret)
index e720148232a06c887c3035f3a4f790d235ec6744..e0b81870ff2a45ee26b81e1fffc8b86544d85bf4 100644 (file)
@@ -93,6 +93,12 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,
                r = 0;
                kvm->arch.return_nisv_io_abort_to_user = true;
                break;
+       case KVM_CAP_ARM_MTE:
+               if (!system_supports_mte() || kvm->created_vcpus)
+                       return -EINVAL;
+               r = 0;
+               kvm->arch.mte_enabled = true;
+               break;
        default:
                r = -EINVAL;
                break;
@@ -237,6 +243,9 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                 */
                r = 1;
                break;
+       case KVM_CAP_ARM_MTE:
+               r = system_supports_mte();
+               break;
        case KVM_CAP_STEAL_TIME:
                r = kvm_arm_pvtime_supported();
                break;
@@ -689,6 +698,10 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
                        vgic_v4_load(vcpu);
                        preempt_enable();
                }
+
+               if (kvm_check_request(KVM_REQ_RELOAD_PMU, vcpu))
+                       kvm_pmu_handle_pmcr(vcpu,
+                                           __vcpu_sys_reg(vcpu, PMCR_EL0));
        }
 }
 
@@ -1078,7 +1091,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
                if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
                        stage2_unmap_vm(vcpu->kvm);
                else
-                       __flush_icache_all();
+                       icache_inval_all_pou();
        }
 
        vcpu_reset_hcr(vcpu);
@@ -1350,6 +1363,13 @@ long kvm_arch_vm_ioctl(struct file *filp,
 
                return 0;
        }
+       case KVM_ARM_MTE_COPY_TAGS: {
+               struct kvm_arm_copy_mte_tags copy_tags;
+
+               if (copy_from_user(&copy_tags, argp, sizeof(copy_tags)))
+                       return -EFAULT;
+               return kvm_vm_ioctl_mte_copy_tags(kvm, &copy_tags);
+       }
        default:
                return -EINVAL;
        }
index 1512a8007a786389807fffd66ccc5066041a9583..1dfb83578277091f539cc986852405a1178983b7 100644 (file)
@@ -1015,3 +1015,89 @@ int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu,
 
        return ret;
 }
+
+long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
+                               struct kvm_arm_copy_mte_tags *copy_tags)
+{
+       gpa_t guest_ipa = copy_tags->guest_ipa;
+       size_t length = copy_tags->length;
+       void __user *tags = copy_tags->addr;
+       gpa_t gfn;
+       bool write = !(copy_tags->flags & KVM_ARM_TAGS_FROM_GUEST);
+       int ret = 0;
+
+       if (!kvm_has_mte(kvm))
+               return -EINVAL;
+
+       if (copy_tags->reserved[0] || copy_tags->reserved[1])
+               return -EINVAL;
+
+       if (copy_tags->flags & ~KVM_ARM_TAGS_FROM_GUEST)
+               return -EINVAL;
+
+       if (length & ~PAGE_MASK || guest_ipa & ~PAGE_MASK)
+               return -EINVAL;
+
+       gfn = gpa_to_gfn(guest_ipa);
+
+       mutex_lock(&kvm->slots_lock);
+
+       while (length > 0) {
+               kvm_pfn_t pfn = gfn_to_pfn_prot(kvm, gfn, write, NULL);
+               void *maddr;
+               unsigned long num_tags;
+               struct page *page;
+
+               if (is_error_noslot_pfn(pfn)) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               page = pfn_to_online_page(pfn);
+               if (!page) {
+                       /* Reject ZONE_DEVICE memory */
+                       ret = -EFAULT;
+                       goto out;
+               }
+               maddr = page_address(page);
+
+               if (!write) {
+                       if (test_bit(PG_mte_tagged, &page->flags))
+                               num_tags = mte_copy_tags_to_user(tags, maddr,
+                                                       MTE_GRANULES_PER_PAGE);
+                       else
+                               /* No tags in memory, so write zeros */
+                               num_tags = MTE_GRANULES_PER_PAGE -
+                                       clear_user(tags, MTE_GRANULES_PER_PAGE);
+                       kvm_release_pfn_clean(pfn);
+               } else {
+                       num_tags = mte_copy_tags_from_user(maddr, tags,
+                                                       MTE_GRANULES_PER_PAGE);
+
+                       /*
+                        * Set the flag after checking the write
+                        * completed fully
+                        */
+                       if (num_tags == MTE_GRANULES_PER_PAGE)
+                               set_bit(PG_mte_tagged, &page->flags);
+
+                       kvm_release_pfn_dirty(pfn);
+               }
+
+               if (num_tags != MTE_GRANULES_PER_PAGE) {
+                       ret = -EFAULT;
+                       goto out;
+               }
+
+               gfn++;
+               tags += num_tags;
+               length -= PAGE_SIZE;
+       }
+
+out:
+       mutex_unlock(&kvm->slots_lock);
+       /* If some data has been copied report the number of bytes copied */
+       if (length != copy_tags->length)
+               return copy_tags->length - length;
+       return ret;
+}
index e831d3dfd50d7cee211d915a7e39f9468ceff154..435346ea1504e158f7877499514118d39400f247 100644 (file)
@@ -13,6 +13,7 @@
 #include <asm/kvm_arm.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmu.h>
+#include <asm/kvm_mte.h>
 #include <asm/kvm_ptrauth.h>
 
        .text
@@ -51,6 +52,9 @@ alternative_else_nop_endif
 
        add     x29, x0, #VCPU_CONTEXT
 
+       // mte_switch_to_guest(g_ctxt, h_ctxt, tmp1)
+       mte_switch_to_guest x29, x1, x2
+
        // Macro ptrauth_switch_to_guest format:
        //      ptrauth_switch_to_guest(guest cxt, tmp1, tmp2, tmp3)
        // The below macro to restore guest keys is not implemented in C code
@@ -142,6 +146,9 @@ SYM_INNER_LABEL(__guest_exit, SYM_L_GLOBAL)
        // when this feature is enabled for kernel code.
        ptrauth_switch_to_hyp x1, x2, x3, x4, x5
 
+       // mte_switch_to_hyp(g_ctxt, h_ctxt, reg1)
+       mte_switch_to_hyp x1, x2, x3
+
        // Restore hyp's sp_el0
        restore_sp_el0 x2, x3
 
index 11541b94b328f8e1d110fa0be3fd37ec07f1ae59..0418399e0a2016738c632ef286ec985febc24cdb 100644 (file)
@@ -112,7 +112,8 @@ static void enter_exception64(struct kvm_vcpu *vcpu, unsigned long target_mode,
        new |= (old & PSR_C_BIT);
        new |= (old & PSR_V_BIT);
 
-       // TODO: TCO (if/when ARMv8.5-MemTag is exposed to guests)
+       if (kvm_has_mte(vcpu->kvm))
+               new |= PSR_TCO_BIT;
 
        new |= (old & PSR_DIT_BIT);
 
index 5f49df4ffdd8651d4277b42d74c514166a21cba0..9aa9b73475c95d59b9c1d99a7ec9426625c7bf76 100644 (file)
@@ -76,6 +76,7 @@ el1_trap:
        b       __guest_exit
 
 el1_irq:
+el1_fiq:
        get_vcpu_ptr    x1, x0
        mov     x0, #ARM_EXCEPTION_IRQ
        b       __guest_exit
@@ -131,7 +132,6 @@ SYM_CODE_END(\label)
        invalid_vector  el2t_error_invalid
        invalid_vector  el2h_irq_invalid
        invalid_vector  el2h_fiq_invalid
-       invalid_vector  el1_fiq_invalid
 
        .ltorg
 
@@ -179,12 +179,12 @@ SYM_CODE_START(__kvm_hyp_vector)
 
        valid_vect      el1_sync                // Synchronous 64-bit EL1
        valid_vect      el1_irq                 // IRQ 64-bit EL1
-       invalid_vect    el1_fiq_invalid         // FIQ 64-bit EL1
+       valid_vect      el1_fiq                 // FIQ 64-bit EL1
        valid_vect      el1_error               // Error 64-bit EL1
 
        valid_vect      el1_sync                // Synchronous 32-bit EL1
        valid_vect      el1_irq                 // IRQ 32-bit EL1
-       invalid_vect    el1_fiq_invalid         // FIQ 32-bit EL1
+       valid_vect      el1_fiq                 // FIQ 32-bit EL1
        valid_vect      el1_error               // Error 32-bit EL1
 SYM_CODE_END(__kvm_hyp_vector)
 
index cce43bfe158fa3a887fa35c725ff61e569c659ee..de7e14c862e6c9b5415df6a7daf815142a302a16 100644 (file)
@@ -14,6 +14,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
+#include <asm/kvm_mmu.h>
 
 static inline void __sysreg_save_common_state(struct kvm_cpu_context *ctxt)
 {
@@ -26,6 +27,16 @@ static inline void __sysreg_save_user_state(struct kvm_cpu_context *ctxt)
        ctxt_sys_reg(ctxt, TPIDRRO_EL0) = read_sysreg(tpidrro_el0);
 }
 
+static inline bool ctxt_has_mte(struct kvm_cpu_context *ctxt)
+{
+       struct kvm_vcpu *vcpu = ctxt->__hyp_running_vcpu;
+
+       if (!vcpu)
+               vcpu = container_of(ctxt, struct kvm_vcpu, arch.ctxt);
+
+       return kvm_has_mte(kern_hyp_va(vcpu->kvm));
+}
+
 static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
 {
        ctxt_sys_reg(ctxt, CSSELR_EL1)  = read_sysreg(csselr_el1);
@@ -46,6 +57,11 @@ static inline void __sysreg_save_el1_state(struct kvm_cpu_context *ctxt)
        ctxt_sys_reg(ctxt, PAR_EL1)     = read_sysreg_par();
        ctxt_sys_reg(ctxt, TPIDR_EL1)   = read_sysreg(tpidr_el1);
 
+       if (ctxt_has_mte(ctxt)) {
+               ctxt_sys_reg(ctxt, TFSR_EL1) = read_sysreg_el1(SYS_TFSR);
+               ctxt_sys_reg(ctxt, TFSRE0_EL1) = read_sysreg_s(SYS_TFSRE0_EL1);
+       }
+
        ctxt_sys_reg(ctxt, SP_EL1)      = read_sysreg(sp_el1);
        ctxt_sys_reg(ctxt, ELR_EL1)     = read_sysreg_el1(SYS_ELR);
        ctxt_sys_reg(ctxt, SPSR_EL1)    = read_sysreg_el1(SYS_SPSR);
@@ -107,6 +123,11 @@ static inline void __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt)
        write_sysreg(ctxt_sys_reg(ctxt, PAR_EL1),       par_el1);
        write_sysreg(ctxt_sys_reg(ctxt, TPIDR_EL1),     tpidr_el1);
 
+       if (ctxt_has_mte(ctxt)) {
+               write_sysreg_el1(ctxt_sys_reg(ctxt, TFSR_EL1), SYS_TFSR);
+               write_sysreg_s(ctxt_sys_reg(ctxt, TFSRE0_EL1), SYS_TFSRE0_EL1);
+       }
+
        if (!has_vhe() &&
            cpus_have_final_cap(ARM64_WORKAROUND_SPECULATIVE_AT) &&
            ctxt->__hyp_running_vcpu) {
index 18a4494337bdd7ee784aa309f88f34cb61fb3fd1..fb0f523d14921c6c79b246e63111f4c1cbbf0767 100644 (file)
@@ -7,7 +7,7 @@
 #include <nvhe/memory.h>
 #include <nvhe/spinlock.h>
 
-#define HYP_NO_ORDER   UINT_MAX
+#define HYP_NO_ORDER   USHRT_MAX
 
 struct hyp_pool {
        /*
@@ -19,48 +19,13 @@ struct hyp_pool {
        struct list_head free_area[MAX_ORDER];
        phys_addr_t range_start;
        phys_addr_t range_end;
-       unsigned int max_order;
+       unsigned short max_order;
 };
 
-static inline void hyp_page_ref_inc(struct hyp_page *p)
-{
-       struct hyp_pool *pool = hyp_page_to_pool(p);
-
-       hyp_spin_lock(&pool->lock);
-       p->refcount++;
-       hyp_spin_unlock(&pool->lock);
-}
-
-static inline int hyp_page_ref_dec_and_test(struct hyp_page *p)
-{
-       struct hyp_pool *pool = hyp_page_to_pool(p);
-       int ret;
-
-       hyp_spin_lock(&pool->lock);
-       p->refcount--;
-       ret = (p->refcount == 0);
-       hyp_spin_unlock(&pool->lock);
-
-       return ret;
-}
-
-static inline void hyp_set_page_refcounted(struct hyp_page *p)
-{
-       struct hyp_pool *pool = hyp_page_to_pool(p);
-
-       hyp_spin_lock(&pool->lock);
-       if (p->refcount) {
-               hyp_spin_unlock(&pool->lock);
-               BUG();
-       }
-       p->refcount = 1;
-       hyp_spin_unlock(&pool->lock);
-}
-
 /* Allocation */
-void *hyp_alloc_pages(struct hyp_pool *pool, unsigned int order);
-void hyp_get_page(void *addr);
-void hyp_put_page(void *addr);
+void *hyp_alloc_pages(struct hyp_pool *pool, unsigned short order);
+void hyp_get_page(struct hyp_pool *pool, void *addr);
+void hyp_put_page(struct hyp_pool *pool, void *addr);
 
 /* Used pages cannot be freed */
 int hyp_pool_init(struct hyp_pool *pool, u64 pfn, unsigned int nr_pages,
index 42d81ec739facdb9ef683779a74c1a1f2732d365..9c227d87c36d3c23a04d3ab19c9ed0a66c7fcf74 100644 (file)
@@ -23,7 +23,7 @@ extern struct host_kvm host_kvm;
 int __pkvm_prot_finalize(void);
 int __pkvm_mark_hyp(phys_addr_t start, phys_addr_t end);
 
-int kvm_host_prepare_stage2(void *mem_pgt_pool, void *dev_pgt_pool);
+int kvm_host_prepare_stage2(void *pgt_pool_base);
 void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt);
 
 static __always_inline void __load_host_stage2(void)
index fd78bde939ee7ce10ffde9f1bb0a2bc4ada21143..592b7edb3edb4cdcb3a43855b3edf3a53c37e346 100644 (file)
@@ -7,12 +7,9 @@
 
 #include <linux/types.h>
 
-struct hyp_pool;
 struct hyp_page {
-       unsigned int refcount;
-       unsigned int order;
-       struct hyp_pool *pool;
-       struct list_head node;
+       unsigned short refcount;
+       unsigned short order;
 };
 
 extern u64 __hyp_vmemmap;
index 0095f62897429ece1ae2d4221a8e898c0e30b98c..8ec3a5a7744b8815bd3f5452b05107c8ff384536 100644 (file)
@@ -78,19 +78,20 @@ static inline unsigned long hyp_s1_pgtable_pages(void)
        return res;
 }
 
-static inline unsigned long host_s2_mem_pgtable_pages(void)
+static inline unsigned long host_s2_pgtable_pages(void)
 {
+       unsigned long res;
+
        /*
         * Include an extra 16 pages to safely upper-bound the worst case of
         * concatenated pgds.
         */
-       return __hyp_pgtable_total_pages() + 16;
-}
+       res = __hyp_pgtable_total_pages() + 16;
 
-static inline unsigned long host_s2_dev_pgtable_pages(void)
-{
        /* Allow 1 GiB for MMIO mappings */
-       return __hyp_pgtable_max_pages(SZ_1G >> PAGE_SHIFT);
+       res += __hyp_pgtable_max_pages(SZ_1G >> PAGE_SHIFT);
+
+       return res;
 }
 
 #endif /* __KVM_HYP_MM_H */
index 36cef69154281cfd71d1c17fbe0538fbaa8c1a12..958734f4d6b0ed820ee7fc006d2fd38d2cf0a105 100644 (file)
@@ -7,7 +7,7 @@
 #include <asm/assembler.h>
 #include <asm/alternative.h>
 
-SYM_FUNC_START_PI(__flush_dcache_area)
+SYM_FUNC_START_PI(dcache_clean_inval_poc)
        dcache_by_line_op civac, sy, x0, x1, x2, x3
        ret
-SYM_FUNC_END_PI(__flush_dcache_area)
+SYM_FUNC_END_PI(dcache_clean_inval_poc)
index 4b60c0056c041521ffba9b9f0505ca605404aed2..d938ce95d3bdf255251cc0c69722c89275832749 100644 (file)
@@ -23,8 +23,7 @@
 extern unsigned long hyp_nr_cpus;
 struct host_kvm host_kvm;
 
-static struct hyp_pool host_s2_mem;
-static struct hyp_pool host_s2_dev;
+static struct hyp_pool host_s2_pool;
 
 /*
  * Copies of the host's CPU features registers holding sanitized values.
@@ -36,7 +35,7 @@ static const u8 pkvm_hyp_id = 1;
 
 static void *host_s2_zalloc_pages_exact(size_t size)
 {
-       return hyp_alloc_pages(&host_s2_mem, get_order(size));
+       return hyp_alloc_pages(&host_s2_pool, get_order(size));
 }
 
 static void *host_s2_zalloc_page(void *pool)
@@ -44,20 +43,24 @@ static void *host_s2_zalloc_page(void *pool)
        return hyp_alloc_pages(pool, 0);
 }
 
-static int prepare_s2_pools(void *mem_pgt_pool, void *dev_pgt_pool)
+static void host_s2_get_page(void *addr)
+{
+       hyp_get_page(&host_s2_pool, addr);
+}
+
+static void host_s2_put_page(void *addr)
+{
+       hyp_put_page(&host_s2_pool, addr);
+}
+
+static int prepare_s2_pool(void *pgt_pool_base)
 {
        unsigned long nr_pages, pfn;
        int ret;
 
-       pfn = hyp_virt_to_pfn(mem_pgt_pool);
-       nr_pages = host_s2_mem_pgtable_pages();
-       ret = hyp_pool_init(&host_s2_mem, pfn, nr_pages, 0);
-       if (ret)
-               return ret;
-
-       pfn = hyp_virt_to_pfn(dev_pgt_pool);
-       nr_pages = host_s2_dev_pgtable_pages();
-       ret = hyp_pool_init(&host_s2_dev, pfn, nr_pages, 0);
+       pfn = hyp_virt_to_pfn(pgt_pool_base);
+       nr_pages = host_s2_pgtable_pages();
+       ret = hyp_pool_init(&host_s2_pool, pfn, nr_pages, 0);
        if (ret)
                return ret;
 
@@ -67,8 +70,8 @@ static int prepare_s2_pools(void *mem_pgt_pool, void *dev_pgt_pool)
                .phys_to_virt = hyp_phys_to_virt,
                .virt_to_phys = hyp_virt_to_phys,
                .page_count = hyp_page_count,
-               .get_page = hyp_get_page,
-               .put_page = hyp_put_page,
+               .get_page = host_s2_get_page,
+               .put_page = host_s2_put_page,
        };
 
        return 0;
@@ -86,7 +89,7 @@ static void prepare_host_vtcr(void)
                                          id_aa64mmfr1_el1_sys_val, phys_shift);
 }
 
-int kvm_host_prepare_stage2(void *mem_pgt_pool, void *dev_pgt_pool)
+int kvm_host_prepare_stage2(void *pgt_pool_base)
 {
        struct kvm_s2_mmu *mmu = &host_kvm.arch.mmu;
        int ret;
@@ -94,7 +97,7 @@ int kvm_host_prepare_stage2(void *mem_pgt_pool, void *dev_pgt_pool)
        prepare_host_vtcr();
        hyp_spin_lock_init(&host_kvm.lock);
 
-       ret = prepare_s2_pools(mem_pgt_pool, dev_pgt_pool);
+       ret = prepare_s2_pool(pgt_pool_base);
        if (ret)
                return ret;
 
@@ -199,11 +202,10 @@ static bool range_is_memory(u64 start, u64 end)
 }
 
 static inline int __host_stage2_idmap(u64 start, u64 end,
-                                     enum kvm_pgtable_prot prot,
-                                     struct hyp_pool *pool)
+                                     enum kvm_pgtable_prot prot)
 {
        return kvm_pgtable_stage2_map(&host_kvm.pgt, start, end - start, start,
-                                     prot, pool);
+                                     prot, &host_s2_pool);
 }
 
 static int host_stage2_idmap(u64 addr)
@@ -211,7 +213,6 @@ static int host_stage2_idmap(u64 addr)
        enum kvm_pgtable_prot prot = KVM_PGTABLE_PROT_R | KVM_PGTABLE_PROT_W;
        struct kvm_mem_range range;
        bool is_memory = find_mem_range(addr, &range);
-       struct hyp_pool *pool = is_memory ? &host_s2_mem : &host_s2_dev;
        int ret;
 
        if (is_memory)
@@ -222,22 +223,21 @@ static int host_stage2_idmap(u64 addr)
        if (ret)
                goto unlock;
 
-       ret = __host_stage2_idmap(range.start, range.end, prot, pool);
-       if (is_memory || ret != -ENOMEM)
+       ret = __host_stage2_idmap(range.start, range.end, prot);
+       if (ret != -ENOMEM)
                goto unlock;
 
        /*
-        * host_s2_mem has been provided with enough pages to cover all of
-        * memory with page granularity, so we should never hit the ENOMEM case.
-        * However, it is difficult to know how much of the MMIO range we will
-        * need to cover upfront, so we may need to 'recycle' the pages if we
-        * run out.
+        * The pool has been provided with enough pages to cover all of memory
+        * with page granularity, but it is difficult to know how much of the
+        * MMIO range we will need to cover upfront, so we may need to 'recycle'
+        * the pages if we run out.
         */
        ret = host_stage2_unmap_dev_all();
        if (ret)
                goto unlock;
 
-       ret = __host_stage2_idmap(range.start, range.end, prot, pool);
+       ret = __host_stage2_idmap(range.start, range.end, prot);
 
 unlock:
        hyp_spin_unlock(&host_kvm.lock);
@@ -258,7 +258,7 @@ int __pkvm_mark_hyp(phys_addr_t start, phys_addr_t end)
 
        hyp_spin_lock(&host_kvm.lock);
        ret = kvm_pgtable_stage2_set_owner(&host_kvm.pgt, start, end - start,
-                                          &host_s2_mem, pkvm_hyp_id);
+                                          &host_s2_pool, pkvm_hyp_id);
        hyp_spin_unlock(&host_kvm.lock);
 
        return ret != -EAGAIN ? ret : 0;
index 237e03bf0cb110161b44a47c62d84486e623886c..41fc25bdfb34660f470ef9dda78fe0a8a7aee989 100644 (file)
@@ -32,7 +32,7 @@ u64 __hyp_vmemmap;
  */
 static struct hyp_page *__find_buddy_nocheck(struct hyp_pool *pool,
                                             struct hyp_page *p,
-                                            unsigned int order)
+                                            unsigned short order)
 {
        phys_addr_t addr = hyp_page_to_phys(p);
 
@@ -51,21 +51,49 @@ static struct hyp_page *__find_buddy_nocheck(struct hyp_pool *pool,
 /* Find a buddy page currently available for allocation */
 static struct hyp_page *__find_buddy_avail(struct hyp_pool *pool,
                                           struct hyp_page *p,
-                                          unsigned int order)
+                                          unsigned short order)
 {
        struct hyp_page *buddy = __find_buddy_nocheck(pool, p, order);
 
-       if (!buddy || buddy->order != order || list_empty(&buddy->node))
+       if (!buddy || buddy->order != order || buddy->refcount)
                return NULL;
 
        return buddy;
 
 }
 
+/*
+ * Pages that are available for allocation are tracked in free-lists, so we use
+ * the pages themselves to store the list nodes to avoid wasting space. As the
+ * allocator always returns zeroed pages (which are zeroed on the hyp_put_page()
+ * path to optimize allocation speed), we also need to clean-up the list node in
+ * each page when we take it out of the list.
+ */
+static inline void page_remove_from_list(struct hyp_page *p)
+{
+       struct list_head *node = hyp_page_to_virt(p);
+
+       __list_del_entry(node);
+       memset(node, 0, sizeof(*node));
+}
+
+static inline void page_add_to_list(struct hyp_page *p, struct list_head *head)
+{
+       struct list_head *node = hyp_page_to_virt(p);
+
+       INIT_LIST_HEAD(node);
+       list_add_tail(node, head);
+}
+
+static inline struct hyp_page *node_to_page(struct list_head *node)
+{
+       return hyp_virt_to_page(node);
+}
+
 static void __hyp_attach_page(struct hyp_pool *pool,
                              struct hyp_page *p)
 {
-       unsigned int order = p->order;
+       unsigned short order = p->order;
        struct hyp_page *buddy;
 
        memset(hyp_page_to_virt(p), 0, PAGE_SIZE << p->order);
@@ -83,32 +111,23 @@ static void __hyp_attach_page(struct hyp_pool *pool,
                        break;
 
                /* Take the buddy out of its list, and coallesce with @p */
-               list_del_init(&buddy->node);
+               page_remove_from_list(buddy);
                buddy->order = HYP_NO_ORDER;
                p = min(p, buddy);
        }
 
        /* Mark the new head, and insert it */
        p->order = order;
-       list_add_tail(&p->node, &pool->free_area[order]);
-}
-
-static void hyp_attach_page(struct hyp_page *p)
-{
-       struct hyp_pool *pool = hyp_page_to_pool(p);
-
-       hyp_spin_lock(&pool->lock);
-       __hyp_attach_page(pool, p);
-       hyp_spin_unlock(&pool->lock);
+       page_add_to_list(p, &pool->free_area[order]);
 }
 
 static struct hyp_page *__hyp_extract_page(struct hyp_pool *pool,
                                           struct hyp_page *p,
-                                          unsigned int order)
+                                          unsigned short order)
 {
        struct hyp_page *buddy;
 
-       list_del_init(&p->node);
+       page_remove_from_list(p);
        while (p->order > order) {
                /*
                 * The buddy of order n - 1 currently has HYP_NO_ORDER as it
@@ -119,30 +138,64 @@ static struct hyp_page *__hyp_extract_page(struct hyp_pool *pool,
                p->order--;
                buddy = __find_buddy_nocheck(pool, p, p->order);
                buddy->order = p->order;
-               list_add_tail(&buddy->node, &pool->free_area[buddy->order]);
+               page_add_to_list(buddy, &pool->free_area[buddy->order]);
        }
 
        return p;
 }
 
-void hyp_put_page(void *addr)
+static inline void hyp_page_ref_inc(struct hyp_page *p)
 {
-       struct hyp_page *p = hyp_virt_to_page(addr);
+       BUG_ON(p->refcount == USHRT_MAX);
+       p->refcount++;
+}
 
+static inline int hyp_page_ref_dec_and_test(struct hyp_page *p)
+{
+       p->refcount--;
+       return (p->refcount == 0);
+}
+
+static inline void hyp_set_page_refcounted(struct hyp_page *p)
+{
+       BUG_ON(p->refcount);
+       p->refcount = 1;
+}
+
+static void __hyp_put_page(struct hyp_pool *pool, struct hyp_page *p)
+{
        if (hyp_page_ref_dec_and_test(p))
-               hyp_attach_page(p);
+               __hyp_attach_page(pool, p);
+}
+
+/*
+ * Changes to the buddy tree and page refcounts must be done with the hyp_pool
+ * lock held. If a refcount change requires an update to the buddy tree (e.g.
+ * hyp_put_page()), both operations must be done within the same critical
+ * section to guarantee transient states (e.g. a page with null refcount but
+ * not yet attached to a free list) can't be observed by well-behaved readers.
+ */
+void hyp_put_page(struct hyp_pool *pool, void *addr)
+{
+       struct hyp_page *p = hyp_virt_to_page(addr);
+
+       hyp_spin_lock(&pool->lock);
+       __hyp_put_page(pool, p);
+       hyp_spin_unlock(&pool->lock);
 }
 
-void hyp_get_page(void *addr)
+void hyp_get_page(struct hyp_pool *pool, void *addr)
 {
        struct hyp_page *p = hyp_virt_to_page(addr);
 
+       hyp_spin_lock(&pool->lock);
        hyp_page_ref_inc(p);
+       hyp_spin_unlock(&pool->lock);
 }
 
-void *hyp_alloc_pages(struct hyp_pool *pool, unsigned int order)
+void *hyp_alloc_pages(struct hyp_pool *pool, unsigned short order)
 {
-       unsigned int i = order;
+       unsigned short i = order;
        struct hyp_page *p;
 
        hyp_spin_lock(&pool->lock);
@@ -156,11 +209,11 @@ void *hyp_alloc_pages(struct hyp_pool *pool, unsigned int order)
        }
 
        /* Extract it from the tree at the right order */
-       p = list_first_entry(&pool->free_area[i], struct hyp_page, node);
+       p = node_to_page(pool->free_area[i].next);
        p = __hyp_extract_page(pool, p, order);
 
-       hyp_spin_unlock(&pool->lock);
        hyp_set_page_refcounted(p);
+       hyp_spin_unlock(&pool->lock);
 
        return hyp_page_to_virt(p);
 }
@@ -181,15 +234,14 @@ int hyp_pool_init(struct hyp_pool *pool, u64 pfn, unsigned int nr_pages,
 
        /* Init the vmemmap portion */
        p = hyp_phys_to_page(phys);
-       memset(p, 0, sizeof(*p) * nr_pages);
        for (i = 0; i < nr_pages; i++) {
-               p[i].pool = pool;
-               INIT_LIST_HEAD(&p[i].node);
+               p[i].order = 0;
+               hyp_set_page_refcounted(&p[i]);
        }
 
        /* Attach the unused pages to the buddy tree */
        for (i = reserved_pages; i < nr_pages; i++)
-               __hyp_attach_page(pool, &p[i]);
+               __hyp_put_page(pool, &p[i]);
 
        return 0;
 }
index a3d3a275344e906f8b539abf910c0410845eafba..0b574d106519cfd1364a1a1237294b7d9dab62cb 100644 (file)
@@ -24,8 +24,7 @@ unsigned long hyp_nr_cpus;
 
 static void *vmemmap_base;
 static void *hyp_pgt_base;
-static void *host_s2_mem_pgt_base;
-static void *host_s2_dev_pgt_base;
+static void *host_s2_pgt_base;
 static struct kvm_pgtable_mm_ops pkvm_pgtable_mm_ops;
 
 static int divide_memory_pool(void *virt, unsigned long size)
@@ -45,14 +44,9 @@ static int divide_memory_pool(void *virt, unsigned long size)
        if (!hyp_pgt_base)
                return -ENOMEM;
 
-       nr_pages = host_s2_mem_pgtable_pages();
-       host_s2_mem_pgt_base = hyp_early_alloc_contig(nr_pages);
-       if (!host_s2_mem_pgt_base)
-               return -ENOMEM;
-
-       nr_pages = host_s2_dev_pgtable_pages();
-       host_s2_dev_pgt_base = hyp_early_alloc_contig(nr_pages);
-       if (!host_s2_dev_pgt_base)
+       nr_pages = host_s2_pgtable_pages();
+       host_s2_pgt_base = hyp_early_alloc_contig(nr_pages);
+       if (!host_s2_pgt_base)
                return -ENOMEM;
 
        return 0;
@@ -134,7 +128,8 @@ static void update_nvhe_init_params(void)
        for (i = 0; i < hyp_nr_cpus; i++) {
                params = per_cpu_ptr(&kvm_init_params, i);
                params->pgd_pa = __hyp_pa(pkvm_pgtable.pgd);
-               __flush_dcache_area(params, sizeof(*params));
+               dcache_clean_inval_poc((unsigned long)params,
+                                   (unsigned long)params + sizeof(*params));
        }
 }
 
@@ -143,6 +138,16 @@ static void *hyp_zalloc_hyp_page(void *arg)
        return hyp_alloc_pages(&hpool, 0);
 }
 
+static void hpool_get_page(void *addr)
+{
+       hyp_get_page(&hpool, addr);
+}
+
+static void hpool_put_page(void *addr)
+{
+       hyp_put_page(&hpool, addr);
+}
+
 void __noreturn __pkvm_init_finalise(void)
 {
        struct kvm_host_data *host_data = this_cpu_ptr(&kvm_host_data);
@@ -158,7 +163,7 @@ void __noreturn __pkvm_init_finalise(void)
        if (ret)
                goto out;
 
-       ret = kvm_host_prepare_stage2(host_s2_mem_pgt_base, host_s2_dev_pgt_base);
+       ret = kvm_host_prepare_stage2(host_s2_pgt_base);
        if (ret)
                goto out;
 
@@ -166,8 +171,8 @@ void __noreturn __pkvm_init_finalise(void)
                .zalloc_page = hyp_zalloc_hyp_page,
                .phys_to_virt = hyp_phys_to_virt,
                .virt_to_phys = hyp_virt_to_phys,
-               .get_page = hyp_get_page,
-               .put_page = hyp_put_page,
+               .get_page = hpool_get_page,
+               .put_page = hpool_put_page,
        };
        pkvm_pgtable.mm_ops = &pkvm_pgtable_mm_ops;
 
index 83dc3b271bc5b82bd77b0abe786b5eefefbb857e..38ed0f6f27032d297dfbf5466d45cbd65441f469 100644 (file)
@@ -104,7 +104,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
         * you should be running with VHE enabled.
         */
        if (icache_is_vpipt())
-               __flush_icache_all();
+               icache_inval_all_pou();
 
        __tlb_switch_to_host(&cxt);
 }
index c37c1dc4feafa6c9c50d87b8dc857fea4abae3bd..05321f4165e34643a8cf8b963d918bbff8713324 100644 (file)
@@ -577,12 +577,24 @@ static void stage2_put_pte(kvm_pte_t *ptep, struct kvm_s2_mmu *mmu, u64 addr,
        mm_ops->put_page(ptep);
 }
 
+static bool stage2_pte_cacheable(struct kvm_pgtable *pgt, kvm_pte_t pte)
+{
+       u64 memattr = pte & KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR;
+       return memattr == KVM_S2_MEMATTR(pgt, NORMAL);
+}
+
+static bool stage2_pte_executable(kvm_pte_t pte)
+{
+       return !(pte & KVM_PTE_LEAF_ATTR_HI_S2_XN);
+}
+
 static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
                                      kvm_pte_t *ptep,
                                      struct stage2_map_data *data)
 {
        kvm_pte_t new, old = *ptep;
        u64 granule = kvm_granule_size(level), phys = data->phys;
+       struct kvm_pgtable *pgt = data->mmu->pgt;
        struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
 
        if (!kvm_block_mapping_supported(addr, end, phys, level))
@@ -606,6 +618,14 @@ static int stage2_map_walker_try_leaf(u64 addr, u64 end, u32 level,
                stage2_put_pte(ptep, data->mmu, addr, level, mm_ops);
        }
 
+       /* Perform CMOs before installation of the guest stage-2 PTE */
+       if (mm_ops->dcache_clean_inval_poc && stage2_pte_cacheable(pgt, new))
+               mm_ops->dcache_clean_inval_poc(kvm_pte_follow(new, mm_ops),
+                                               granule);
+
+       if (mm_ops->icache_inval_pou && stage2_pte_executable(new))
+               mm_ops->icache_inval_pou(kvm_pte_follow(new, mm_ops), granule);
+
        smp_store_release(ptep, new);
        if (stage2_pte_is_counted(new))
                mm_ops->get_page(ptep);
@@ -798,12 +818,6 @@ int kvm_pgtable_stage2_set_owner(struct kvm_pgtable *pgt, u64 addr, u64 size,
        return ret;
 }
 
-static bool stage2_pte_cacheable(struct kvm_pgtable *pgt, kvm_pte_t pte)
-{
-       u64 memattr = pte & KVM_PTE_LEAF_ATTR_LO_S2_MEMATTR;
-       return memattr == KVM_S2_MEMATTR(pgt, NORMAL);
-}
-
 static int stage2_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
                               enum kvm_pgtable_walk_flags flag,
                               void * const arg)
@@ -839,8 +853,11 @@ static int stage2_unmap_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
        stage2_put_pte(ptep, mmu, addr, level, mm_ops);
 
        if (need_flush) {
-               __flush_dcache_area(kvm_pte_follow(pte, mm_ops),
-                                   kvm_granule_size(level));
+               kvm_pte_t *pte_follow = kvm_pte_follow(pte, mm_ops);
+
+               dcache_clean_inval_poc((unsigned long)pte_follow,
+                                   (unsigned long)pte_follow +
+                                           kvm_granule_size(level));
        }
 
        if (childp)
@@ -861,10 +878,11 @@ int kvm_pgtable_stage2_unmap(struct kvm_pgtable *pgt, u64 addr, u64 size)
 }
 
 struct stage2_attr_data {
-       kvm_pte_t       attr_set;
-       kvm_pte_t       attr_clr;
-       kvm_pte_t       pte;
-       u32             level;
+       kvm_pte_t                       attr_set;
+       kvm_pte_t                       attr_clr;
+       kvm_pte_t                       pte;
+       u32                             level;
+       struct kvm_pgtable_mm_ops       *mm_ops;
 };
 
 static int stage2_attr_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
@@ -873,6 +891,7 @@ static int stage2_attr_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
 {
        kvm_pte_t pte = *ptep;
        struct stage2_attr_data *data = arg;
+       struct kvm_pgtable_mm_ops *mm_ops = data->mm_ops;
 
        if (!kvm_pte_valid(pte))
                return 0;
@@ -887,8 +906,17 @@ static int stage2_attr_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
         * but worst-case the access flag update gets lost and will be
         * set on the next access instead.
         */
-       if (data->pte != pte)
+       if (data->pte != pte) {
+               /*
+                * Invalidate instruction cache before updating the guest
+                * stage-2 PTE if we are going to add executable permission.
+                */
+               if (mm_ops->icache_inval_pou &&
+                   stage2_pte_executable(pte) && !stage2_pte_executable(*ptep))
+                       mm_ops->icache_inval_pou(kvm_pte_follow(pte, mm_ops),
+                                                 kvm_granule_size(level));
                WRITE_ONCE(*ptep, pte);
+       }
 
        return 0;
 }
@@ -903,6 +931,7 @@ static int stage2_update_leaf_attrs(struct kvm_pgtable *pgt, u64 addr,
        struct stage2_attr_data data = {
                .attr_set       = attr_set & attr_mask,
                .attr_clr       = attr_clr & attr_mask,
+               .mm_ops         = pgt->mm_ops,
        };
        struct kvm_pgtable_walker walker = {
                .cb             = stage2_attr_walker,
@@ -988,11 +1017,15 @@ static int stage2_flush_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
        struct kvm_pgtable *pgt = arg;
        struct kvm_pgtable_mm_ops *mm_ops = pgt->mm_ops;
        kvm_pte_t pte = *ptep;
+       kvm_pte_t *pte_follow;
 
        if (!kvm_pte_valid(pte) || !stage2_pte_cacheable(pgt, pte))
                return 0;
 
-       __flush_dcache_area(kvm_pte_follow(pte, mm_ops), kvm_granule_size(level));
+       pte_follow = kvm_pte_follow(pte, mm_ops);
+       dcache_clean_inval_poc((unsigned long)pte_follow,
+                           (unsigned long)pte_follow +
+                                   kvm_granule_size(level));
        return 0;
 }
 
index 83ca23ac259b146b9fae6a0699e0402d2b93541c..d654921dd09b5b19c07fa4b040de2d1c1845e1d7 100644 (file)
@@ -71,8 +71,7 @@ void __init kvm_hyp_reserve(void)
        }
 
        hyp_mem_pages += hyp_s1_pgtable_pages();
-       hyp_mem_pages += host_s2_mem_pgtable_pages();
-       hyp_mem_pages += host_s2_dev_pgtable_pages();
+       hyp_mem_pages += host_s2_pgtable_pages();
 
        /*
         * The hyp_vmemmap needs to be backed by pages, but these pages
index c10207fed2f36fe6a46970912e302e7528d4b196..57292dc5ce357a70d2db685ee9b4f12052c5412a 100644 (file)
@@ -126,6 +126,16 @@ static void *kvm_host_va(phys_addr_t phys)
        return __va(phys);
 }
 
+static void clean_dcache_guest_page(void *va, size_t size)
+{
+       __clean_dcache_guest_page(va, size);
+}
+
+static void invalidate_icache_guest_page(void *va, size_t size)
+{
+       __invalidate_icache_guest_page(va, size);
+}
+
 /*
  * Unmapping vs dcache management:
  *
@@ -432,6 +442,8 @@ static struct kvm_pgtable_mm_ops kvm_s2_mm_ops = {
        .page_count             = kvm_host_page_count,
        .phys_to_virt           = kvm_host_va,
        .virt_to_phys           = kvm_host_pa,
+       .dcache_clean_inval_poc = clean_dcache_guest_page,
+       .icache_inval_pou       = invalidate_icache_guest_page,
 };
 
 /**
@@ -693,16 +705,6 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
        kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask);
 }
 
-static void clean_dcache_guest_page(kvm_pfn_t pfn, unsigned long size)
-{
-       __clean_dcache_guest_page(pfn, size);
-}
-
-static void invalidate_icache_guest_page(kvm_pfn_t pfn, unsigned long size)
-{
-       __invalidate_icache_guest_page(pfn, size);
-}
-
 static void kvm_send_hwpoison_signal(unsigned long address, short lsb)
 {
        send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, current);
@@ -822,6 +824,74 @@ transparent_hugepage_adjust(struct kvm_memory_slot *memslot,
        return PAGE_SIZE;
 }
 
+static int get_vma_page_shift(struct vm_area_struct *vma, unsigned long hva)
+{
+       unsigned long pa;
+
+       if (is_vm_hugetlb_page(vma) && !(vma->vm_flags & VM_PFNMAP))
+               return huge_page_shift(hstate_vma(vma));
+
+       if (!(vma->vm_flags & VM_PFNMAP))
+               return PAGE_SHIFT;
+
+       VM_BUG_ON(is_vm_hugetlb_page(vma));
+
+       pa = (vma->vm_pgoff << PAGE_SHIFT) + (hva - vma->vm_start);
+
+#ifndef __PAGETABLE_PMD_FOLDED
+       if ((hva & (PUD_SIZE - 1)) == (pa & (PUD_SIZE - 1)) &&
+           ALIGN_DOWN(hva, PUD_SIZE) >= vma->vm_start &&
+           ALIGN(hva, PUD_SIZE) <= vma->vm_end)
+               return PUD_SHIFT;
+#endif
+
+       if ((hva & (PMD_SIZE - 1)) == (pa & (PMD_SIZE - 1)) &&
+           ALIGN_DOWN(hva, PMD_SIZE) >= vma->vm_start &&
+           ALIGN(hva, PMD_SIZE) <= vma->vm_end)
+               return PMD_SHIFT;
+
+       return PAGE_SHIFT;
+}
+
+/*
+ * The page will be mapped in stage 2 as Normal Cacheable, so the VM will be
+ * able to see the page's tags and therefore they must be initialised first. If
+ * PG_mte_tagged is set, tags have already been initialised.
+ *
+ * The race in the test/set of the PG_mte_tagged flag is handled by:
+ * - preventing VM_SHARED mappings in a memslot with MTE preventing two VMs
+ *   racing to santise the same page
+ * - mmap_lock protects between a VM faulting a page in and the VMM performing
+ *   an mprotect() to add VM_MTE
+ */
+static int sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,
+                            unsigned long size)
+{
+       unsigned long i, nr_pages = size >> PAGE_SHIFT;
+       struct page *page;
+
+       if (!kvm_has_mte(kvm))
+               return 0;
+
+       /*
+        * pfn_to_online_page() is used to reject ZONE_DEVICE pages
+        * that may not support tags.
+        */
+       page = pfn_to_online_page(pfn);
+
+       if (!page)
+               return -EFAULT;
+
+       for (i = 0; i < nr_pages; i++, page++) {
+               if (!test_bit(PG_mte_tagged, &page->flags)) {
+                       mte_clear_page_tags(page_address(page));
+                       set_bit(PG_mte_tagged, &page->flags);
+               }
+       }
+
+       return 0;
+}
+
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                          struct kvm_memory_slot *memslot, unsigned long hva,
                          unsigned long fault_status)
@@ -830,6 +900,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
        bool write_fault, writable, force_pte = false;
        bool exec_fault;
        bool device = false;
+       bool shared;
        unsigned long mmu_seq;
        struct kvm *kvm = vcpu->kvm;
        struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
@@ -853,7 +924,10 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                return -EFAULT;
        }
 
-       /* Let's check if we will get back a huge page backed by hugetlbfs */
+       /*
+        * Let's check if we will get back a huge page backed by hugetlbfs, or
+        * get block mapping for device MMIO region.
+        */
        mmap_read_lock(current->mm);
        vma = find_vma_intersection(current->mm, hva, hva + 1);
        if (unlikely(!vma)) {
@@ -862,17 +936,19 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                return -EFAULT;
        }
 
-       if (is_vm_hugetlb_page(vma))
-               vma_shift = huge_page_shift(hstate_vma(vma));
-       else
-               vma_shift = PAGE_SHIFT;
-
-       if (logging_active ||
-           (vma->vm_flags & VM_PFNMAP)) {
+       /*
+        * logging_active is guaranteed to never be true for VM_PFNMAP
+        * memslots.
+        */
+       if (logging_active) {
                force_pte = true;
                vma_shift = PAGE_SHIFT;
+       } else {
+               vma_shift = get_vma_page_shift(vma, hva);
        }
 
+       shared = (vma->vm_flags & VM_PFNMAP);
+
        switch (vma_shift) {
 #ifndef __PAGETABLE_PMD_FOLDED
        case PUD_SHIFT:
@@ -943,8 +1019,17 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
                return -EFAULT;
 
        if (kvm_is_device_pfn(pfn)) {
+               /*
+                * If the page was identified as device early by looking at
+                * the VMA flags, vma_pagesize is already representing the
+                * largest quantity we can map.  If instead it was mapped
+                * via gfn_to_pfn_prot(), vma_pagesize is set to PAGE_SIZE
+                * and must not be upgraded.
+                *
+                * In both cases, we don't let transparent_hugepage_adjust()
+                * change things at the last minute.
+                */
                device = true;
-               force_pte = true;
        } else if (logging_active && !write_fault) {
                /*
                 * Only actually map the page as writable if this was a write
@@ -965,19 +1050,25 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
         * If we are not forced to use page mapping, check if we are
         * backed by a THP and thus use block mapping if possible.
         */
-       if (vma_pagesize == PAGE_SIZE && !force_pte)
+       if (vma_pagesize == PAGE_SIZE && !(force_pte || device))
                vma_pagesize = transparent_hugepage_adjust(memslot, hva,
                                                           &pfn, &fault_ipa);
+
+       if (fault_status != FSC_PERM && !device && kvm_has_mte(kvm)) {
+               /* Check the VMM hasn't introduced a new VM_SHARED VMA */
+               if (!shared)
+                       ret = sanitise_mte_tags(kvm, pfn, vma_pagesize);
+               else
+                       ret = -EFAULT;
+               if (ret)
+                       goto out_unlock;
+       }
+
        if (writable)
                prot |= KVM_PGTABLE_PROT_W;
 
-       if (fault_status != FSC_PERM && !device)
-               clean_dcache_guest_page(pfn, vma_pagesize);
-
-       if (exec_fault) {
+       if (exec_fault)
                prot |= KVM_PGTABLE_PROT_X;
-               invalidate_icache_guest_page(pfn, vma_pagesize);
-       }
 
        if (device)
                prot |= KVM_PGTABLE_PROT_DEVICE;
@@ -1168,19 +1259,22 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
 bool kvm_set_spte_gfn(struct kvm *kvm, struct kvm_gfn_range *range)
 {
        kvm_pfn_t pfn = pte_pfn(range->pte);
+       int ret;
 
        if (!kvm->arch.mmu.pgt)
                return false;
 
        WARN_ON(range->end - range->start != 1);
 
-       /*
-        * We've moved a page around, probably through CoW, so let's treat it
-        * just like a translation fault and clean the cache to the PoC.
-        */
-       clean_dcache_guest_page(pfn, PAGE_SIZE);
+       ret = sanitise_mte_tags(kvm, pfn, PAGE_SIZE);
+       if (ret)
+               return false;
 
        /*
+        * We've moved a page around, probably through CoW, so let's treat
+        * it just like a translation fault and the map handler will clean
+        * the cache to the PoC.
+        *
         * The MMU notifiers will have unmapped a huge PMD before calling
         * ->change_pte() (which in turn calls kvm_set_spte_gfn()) and
         * therefore we never need to clear out a huge PMD through this
@@ -1346,7 +1440,6 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 {
        hva_t hva = mem->userspace_addr;
        hva_t reg_end = hva + mem->memory_size;
-       bool writable = !(mem->flags & KVM_MEM_READONLY);
        int ret = 0;
 
        if (change != KVM_MR_CREATE && change != KVM_MR_MOVE &&
@@ -1363,8 +1456,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
        mmap_read_lock(current->mm);
        /*
         * A memory region could potentially cover multiple VMAs, and any holes
-        * between them, so iterate over all of them to find out if we can map
-        * any of them right now.
+        * between them, so iterate over all of them.
         *
         *     +--------------------------------------------+
         * +---------------+----------------+   +----------------+
@@ -1375,51 +1467,29 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
         */
        do {
                struct vm_area_struct *vma;
-               hva_t vm_start, vm_end;
 
                vma = find_vma_intersection(current->mm, hva, reg_end);
                if (!vma)
                        break;
 
                /*
-                * Take the intersection of this VMA with the memory region
+                * VM_SHARED mappings are not allowed with MTE to avoid races
+                * when updating the PG_mte_tagged page flag, see
+                * sanitise_mte_tags for more details.
                 */
-               vm_start = max(hva, vma->vm_start);
-               vm_end = min(reg_end, vma->vm_end);
+               if (kvm_has_mte(kvm) && vma->vm_flags & VM_SHARED)
+                       return -EINVAL;
 
                if (vma->vm_flags & VM_PFNMAP) {
-                       gpa_t gpa = mem->guest_phys_addr +
-                                   (vm_start - mem->userspace_addr);
-                       phys_addr_t pa;
-
-                       pa = (phys_addr_t)vma->vm_pgoff << PAGE_SHIFT;
-                       pa += vm_start - vma->vm_start;
-
                        /* IO region dirty page logging not allowed */
                        if (memslot->flags & KVM_MEM_LOG_DIRTY_PAGES) {
                                ret = -EINVAL;
-                               goto out;
-                       }
-
-                       ret = kvm_phys_addr_ioremap(kvm, gpa, pa,
-                                                   vm_end - vm_start,
-                                                   writable);
-                       if (ret)
                                break;
+                       }
                }
-               hva = vm_end;
+               hva = min(reg_end, vma->vm_end);
        } while (hva < reg_end);
 
-       if (change == KVM_MR_FLAGS_ONLY)
-               goto out;
-
-       spin_lock(&kvm->mmu_lock);
-       if (ret)
-               unmap_stage2_range(&kvm->arch.mmu, mem->guest_phys_addr, mem->memory_size);
-       else if (!cpus_have_final_cap(ARM64_HAS_STAGE2_FWB))
-               stage2_flush_memslot(kvm, memslot);
-       spin_unlock(&kvm->mmu_lock);
-out:
        mmap_read_unlock(current->mm);
        return ret;
 }
index fd167d4f42157a80a4f45a2cb26617b18a393e1f..f33825c995cbbe215d603aa0e3ca659f8245c6ea 100644 (file)
@@ -578,6 +578,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val)
                kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0);
 
        if (val & ARMV8_PMU_PMCR_P) {
+               mask &= ~BIT(ARMV8_PMU_CYCLE_IDX);
                for_each_set_bit(i, &mask, 32)
                        kvm_pmu_set_counter_value(vcpu, i, 0);
        }
@@ -850,6 +851,9 @@ int kvm_arm_pmu_v3_enable(struct kvm_vcpu *vcpu)
                   return -EINVAL;
        }
 
+       /* One-off reload of the PMU on first run */
+       kvm_make_request(KVM_REQ_RELOAD_PMU, vcpu);
+
        return 0;
 }
 
index d37ebee085cfeb23671e7d58efcf6c753908e5b5..cba7872d69a857f27e2eedb6aa892f8bdaa19ac7 100644 (file)
@@ -176,6 +176,10 @@ static bool vcpu_allowed_register_width(struct kvm_vcpu *vcpu)
        if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1) && is32bit)
                return false;
 
+       /* MTE is incompatible with AArch32 */
+       if (kvm_has_mte(vcpu->kvm) && is32bit)
+               return false;
+
        /* Check that the vcpus are either all 32bit or all 64bit */
        kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
                if (vcpu_has_feature(tmp, KVM_ARM_VCPU_EL1_32BIT) != is32bit)
index 1a7968ad078c60a00f0d9e63577674c6b8fa13d9..f6f126eb6ac1326ccc7c277fc683e44af1ddc74d 100644 (file)
@@ -1047,6 +1047,13 @@ static u64 read_id_reg(const struct kvm_vcpu *vcpu,
                break;
        case SYS_ID_AA64PFR1_EL1:
                val &= ~FEATURE(ID_AA64PFR1_MTE);
+               if (kvm_has_mte(vcpu->kvm)) {
+                       u64 pfr, mte;
+
+                       pfr = read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1);
+                       mte = cpuid_feature_extract_unsigned_field(pfr, ID_AA64PFR1_MTE_SHIFT);
+                       val |= FIELD_PREP(FEATURE(ID_AA64PFR1_MTE), mte);
+               }
                break;
        case SYS_ID_AA64ISAR1_EL1:
                if (!vcpu_has_ptrauth(vcpu))
@@ -1302,6 +1309,23 @@ static bool access_ccsidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
        return true;
 }
 
+static unsigned int mte_visibility(const struct kvm_vcpu *vcpu,
+                                  const struct sys_reg_desc *rd)
+{
+       if (kvm_has_mte(vcpu->kvm))
+               return 0;
+
+       return REG_HIDDEN;
+}
+
+#define MTE_REG(name) {                                \
+       SYS_DESC(SYS_##name),                   \
+       .access = undef_access,                 \
+       .reset = reset_unknown,                 \
+       .reg = name,                            \
+       .visibility = mte_visibility,           \
+}
+
 /* sys_reg_desc initialiser for known cpufeature ID registers */
 #define ID_SANITISED(name) {                   \
        SYS_DESC(SYS_##name),                   \
@@ -1470,8 +1494,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_ACTLR_EL1), access_actlr, reset_actlr, ACTLR_EL1 },
        { SYS_DESC(SYS_CPACR_EL1), NULL, reset_val, CPACR_EL1, 0 },
 
-       { SYS_DESC(SYS_RGSR_EL1), undef_access },
-       { SYS_DESC(SYS_GCR_EL1), undef_access },
+       MTE_REG(RGSR_EL1),
+       MTE_REG(GCR_EL1),
 
        { SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility },
        { SYS_DESC(SYS_TRFCR_EL1), undef_access },
@@ -1498,8 +1522,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi },
        { SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi },
 
-       { SYS_DESC(SYS_TFSR_EL1), undef_access },
-       { SYS_DESC(SYS_TFSRE0_EL1), undef_access },
+       MTE_REG(TFSR_EL1),
+       MTE_REG(TFSRE0_EL1),
 
        { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 },
        { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 },
index 58cbda00e56d9044c97032c84e0027cb91e398b8..340c51d87677caf9165773a7e59869aa5da002c7 100644 (file)
@@ -482,6 +482,16 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
        return IRQ_HANDLED;
 }
 
+static struct gic_kvm_info *gic_kvm_info;
+
+void __init vgic_set_kvm_info(const struct gic_kvm_info *info)
+{
+       BUG_ON(gic_kvm_info != NULL);
+       gic_kvm_info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (gic_kvm_info)
+               *gic_kvm_info = *info;
+}
+
 /**
  * kvm_vgic_init_cpu_hardware - initialize the GIC VE hardware
  *
@@ -509,18 +519,29 @@ void kvm_vgic_init_cpu_hardware(void)
  */
 int kvm_vgic_hyp_init(void)
 {
-       const struct gic_kvm_info *gic_kvm_info;
+       bool has_mask;
        int ret;
 
-       gic_kvm_info = gic_get_kvm_info();
        if (!gic_kvm_info)
                return -ENODEV;
 
-       if (!gic_kvm_info->maint_irq) {
+       has_mask = !gic_kvm_info->no_maint_irq_mask;
+
+       if (has_mask && !gic_kvm_info->maint_irq) {
                kvm_err("No vgic maintenance irq\n");
                return -ENXIO;
        }
 
+       /*
+        * If we get one of these oddball non-GICs, taint the kernel,
+        * as we have no idea of how they *really* behave.
+        */
+       if (gic_kvm_info->no_hw_deactivation) {
+               kvm_info("Non-architectural vgic, tainting kernel\n");
+               add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
+               kvm_vgic_global_state.no_hw_deactivation = true;
+       }
+
        switch (gic_kvm_info->type) {
        case GIC_V2:
                ret = vgic_v2_probe(gic_kvm_info);
@@ -536,10 +557,17 @@ int kvm_vgic_hyp_init(void)
                ret = -ENODEV;
        }
 
+       kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
+
+       kfree(gic_kvm_info);
+       gic_kvm_info = NULL;
+
        if (ret)
                return ret;
 
-       kvm_vgic_global_state.maint_irq = gic_kvm_info->maint_irq;
+       if (!has_mask)
+               return 0;
+
        ret = request_percpu_irq(kvm_vgic_global_state.maint_irq,
                                 vgic_maintenance_handler,
                                 "vgic", kvm_get_running_vcpus());
index 11934c2af2f42711feddab663edb4e9fc2bdca02..2c580204f1dc9a344837683986b379387a77b793 100644 (file)
@@ -108,11 +108,22 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
                 * If this causes us to lower the level, we have to also clear
                 * the physical active state, since we will otherwise never be
                 * told when the interrupt becomes asserted again.
+                *
+                * Another case is when the interrupt requires a helping hand
+                * on deactivation (no HW deactivation, for example).
                 */
-               if (vgic_irq_is_mapped_level(irq) && (val & GICH_LR_PENDING_BIT)) {
-                       irq->line_level = vgic_get_phys_line_level(irq);
+               if (vgic_irq_is_mapped_level(irq)) {
+                       bool resample = false;
+
+                       if (val & GICH_LR_PENDING_BIT) {
+                               irq->line_level = vgic_get_phys_line_level(irq);
+                               resample = !irq->line_level;
+                       } else if (vgic_irq_needs_resampling(irq) &&
+                                  !(irq->active || irq->pending_latch)) {
+                               resample = true;
+                       }
 
-                       if (!irq->line_level)
+                       if (resample)
                                vgic_irq_set_phys_active(irq, false);
                }
 
@@ -152,7 +163,7 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (irq->group)
                val |= GICH_LR_GROUP1;
 
-       if (irq->hw) {
+       if (irq->hw && !vgic_irq_needs_resampling(irq)) {
                val |= GICH_LR_HW;
                val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
                /*
index 41ecf219c3334b9b0ef8ec899ca6380ae8c55ac3..66004f61cd83d49062f92fbdf17ed9ada98beace 100644 (file)
@@ -101,11 +101,22 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                 * If this causes us to lower the level, we have to also clear
                 * the physical active state, since we will otherwise never be
                 * told when the interrupt becomes asserted again.
+                *
+                * Another case is when the interrupt requires a helping hand
+                * on deactivation (no HW deactivation, for example).
                 */
-               if (vgic_irq_is_mapped_level(irq) && (val & ICH_LR_PENDING_BIT)) {
-                       irq->line_level = vgic_get_phys_line_level(irq);
+               if (vgic_irq_is_mapped_level(irq)) {
+                       bool resample = false;
+
+                       if (val & ICH_LR_PENDING_BIT) {
+                               irq->line_level = vgic_get_phys_line_level(irq);
+                               resample = !irq->line_level;
+                       } else if (vgic_irq_needs_resampling(irq) &&
+                                  !(irq->active || irq->pending_latch)) {
+                               resample = true;
+                       }
 
-                       if (!irq->line_level)
+                       if (resample)
                                vgic_irq_set_phys_active(irq, false);
                }
 
@@ -136,7 +147,7 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                }
        }
 
-       if (irq->hw) {
+       if (irq->hw && !vgic_irq_needs_resampling(irq)) {
                val |= ICH_LR_HW;
                val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
                /*
index 15b666200f0b4be8a70f10952f77ce6d1e1eff40..111bff47e4710f9349f626cda191552fe53c605a 100644 (file)
@@ -182,8 +182,8 @@ bool vgic_get_phys_line_level(struct vgic_irq *irq)
 
        BUG_ON(!irq->hw);
 
-       if (irq->get_input_level)
-               return irq->get_input_level(irq->intid);
+       if (irq->ops && irq->ops->get_input_level)
+               return irq->ops->get_input_level(irq->intid);
 
        WARN_ON(irq_get_irqchip_state(irq->host_irq,
                                      IRQCHIP_STATE_PENDING,
@@ -480,7 +480,7 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 /* @irq->irq_lock must be held */
 static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
                            unsigned int host_irq,
-                           bool (*get_input_level)(int vindid))
+                           struct irq_ops *ops)
 {
        struct irq_desc *desc;
        struct irq_data *data;
@@ -500,7 +500,7 @@ static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        irq->hw = true;
        irq->host_irq = host_irq;
        irq->hwintid = data->hwirq;
-       irq->get_input_level = get_input_level;
+       irq->ops = ops;
        return 0;
 }
 
@@ -509,11 +509,11 @@ static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq)
 {
        irq->hw = false;
        irq->hwintid = 0;
-       irq->get_input_level = NULL;
+       irq->ops = NULL;
 }
 
 int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
-                         u32 vintid, bool (*get_input_level)(int vindid))
+                         u32 vintid, struct irq_ops *ops)
 {
        struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
        unsigned long flags;
@@ -522,7 +522,7 @@ int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
        BUG_ON(!irq);
 
        raw_spin_lock_irqsave(&irq->irq_lock, flags);
-       ret = kvm_vgic_map_irq(vcpu, irq, host_irq, get_input_level);
+       ret = kvm_vgic_map_irq(vcpu, irq, host_irq, ops);
        raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
index c83bb5a4aad2c53ed2cc32029f34d50fdd97e1ed..baee22961bdba2eb63dc395e1c79ca069f70f8ff 100644 (file)
@@ -15,7 +15,7 @@ void memcpy_flushcache(void *dst, const void *src, size_t cnt)
         * barrier to order the cache maintenance against the memcpy.
         */
        memcpy(dst, src, cnt);
-       __clean_dcache_area_pop(dst, cnt);
+       dcache_clean_pop((unsigned long)dst, (unsigned long)dst + cnt);
 }
 EXPORT_SYMBOL_GPL(memcpy_flushcache);
 
@@ -33,6 +33,6 @@ unsigned long __copy_user_flushcache(void *to, const void __user *from,
        rc = raw_copy_from_user(to, from, n);
 
        /* See above */
-       __clean_dcache_area_pop(to, n - rc);
+       dcache_clean_pop((unsigned long)to, (unsigned long)to + n - rc);
        return rc;
 }
index 2d881f34dd9d54017c7565cc5749d88084ab4235..5051b3c1a4f1263fbd8b7619c88d5f76bed87867 100644 (file)
@@ -15,7 +15,7 @@
 #include <asm/asm-uaccess.h>
 
 /*
- *     flush_icache_range(start,end)
+ *     caches_clean_inval_pou_macro(start,end) [fixup]
  *
  *     Ensure that the I and D caches are coherent within specified region.
  *     This is typically used when code has been written to a memory region,
  *
  *     - start   - virtual start address of region
  *     - end     - virtual end address of region
+ *     - fixup   - optional label to branch to on user fault
  */
-SYM_FUNC_START(__flush_icache_range)
-       /* FALLTHROUGH */
+.macro caches_clean_inval_pou_macro, fixup
+alternative_if ARM64_HAS_CACHE_IDC
+       dsb     ishst
+       b       .Ldc_skip_\@
+alternative_else_nop_endif
+       mov     x2, x0
+       mov     x3, x1
+       dcache_by_line_op cvau, ish, x2, x3, x4, x5, \fixup
+.Ldc_skip_\@:
+alternative_if ARM64_HAS_CACHE_DIC
+       isb
+       b       .Lic_skip_\@
+alternative_else_nop_endif
+       invalidate_icache_by_line x0, x1, x2, x3, \fixup
+.Lic_skip_\@:
+.endm
 
 /*
- *     __flush_cache_user_range(start,end)
+ *     caches_clean_inval_pou(start,end)
  *
  *     Ensure that the I and D caches are coherent within specified region.
  *     This is typically used when code has been written to a memory region,
@@ -37,117 +52,103 @@ SYM_FUNC_START(__flush_icache_range)
  *     - start   - virtual start address of region
  *     - end     - virtual end address of region
  */
-SYM_FUNC_START(__flush_cache_user_range)
+SYM_FUNC_START(caches_clean_inval_pou)
+       caches_clean_inval_pou_macro
+       ret
+SYM_FUNC_END(caches_clean_inval_pou)
+
+/*
+ *     caches_clean_inval_user_pou(start,end)
+ *
+ *     Ensure that the I and D caches are coherent within specified region.
+ *     This is typically used when code has been written to a memory region,
+ *     and will be executed.
+ *
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
+ */
+SYM_FUNC_START(caches_clean_inval_user_pou)
        uaccess_ttbr0_enable x2, x3, x4
-alternative_if ARM64_HAS_CACHE_IDC
-       dsb     ishst
-       b       7f
-alternative_else_nop_endif
-       dcache_line_size x2, x3
-       sub     x3, x2, #1
-       bic     x4, x0, x3
-1:
-user_alt 9f, "dc cvau, x4",  "dc civac, x4",  ARM64_WORKAROUND_CLEAN_CACHE
-       add     x4, x4, x2
-       cmp     x4, x1
-       b.lo    1b
-       dsb     ish
 
-7:
-alternative_if ARM64_HAS_CACHE_DIC
-       isb
-       b       8f
-alternative_else_nop_endif
-       invalidate_icache_by_line x0, x1, x2, x3, 9f
-8:     mov     x0, #0
+       caches_clean_inval_pou_macro 2f
+       mov     x0, xzr
 1:
        uaccess_ttbr0_disable x1, x2
        ret
-9:
+2:
        mov     x0, #-EFAULT
        b       1b
-SYM_FUNC_END(__flush_icache_range)
-SYM_FUNC_END(__flush_cache_user_range)
+SYM_FUNC_END(caches_clean_inval_user_pou)
 
 /*
- *     invalidate_icache_range(start,end)
+ *     icache_inval_pou(start,end)
  *
  *     Ensure that the I cache is invalid within specified region.
  *
  *     - start   - virtual start address of region
  *     - end     - virtual end address of region
  */
-SYM_FUNC_START(invalidate_icache_range)
+SYM_FUNC_START(icache_inval_pou)
 alternative_if ARM64_HAS_CACHE_DIC
-       mov     x0, xzr
        isb
        ret
 alternative_else_nop_endif
 
-       uaccess_ttbr0_enable x2, x3, x4
-
-       invalidate_icache_by_line x0, x1, x2, x3, 2f
-       mov     x0, xzr
-1:
-       uaccess_ttbr0_disable x1, x2
+       invalidate_icache_by_line x0, x1, x2, x3
        ret
-2:
-       mov     x0, #-EFAULT
-       b       1b
-SYM_FUNC_END(invalidate_icache_range)
+SYM_FUNC_END(icache_inval_pou)
 
 /*
- *     __flush_dcache_area(kaddr, size)
+ *     dcache_clean_inval_poc(start, end)
  *
- *     Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
+ *     Ensure that any D-cache lines for the interval [start, end)
  *     are cleaned and invalidated to the PoC.
  *
- *     - kaddr   - kernel address
- *     - size    - size in question
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
  */
-SYM_FUNC_START_PI(__flush_dcache_area)
+SYM_FUNC_START_PI(dcache_clean_inval_poc)
        dcache_by_line_op civac, sy, x0, x1, x2, x3
        ret
-SYM_FUNC_END_PI(__flush_dcache_area)
+SYM_FUNC_END_PI(dcache_clean_inval_poc)
 
 /*
- *     __clean_dcache_area_pou(kaddr, size)
+ *     dcache_clean_pou(start, end)
  *
- *     Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
+ *     Ensure that any D-cache lines for the interval [start, end)
  *     are cleaned to the PoU.
  *
- *     - kaddr   - kernel address
- *     - size    - size in question
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
  */
-SYM_FUNC_START(__clean_dcache_area_pou)
+SYM_FUNC_START(dcache_clean_pou)
 alternative_if ARM64_HAS_CACHE_IDC
        dsb     ishst
        ret
 alternative_else_nop_endif
        dcache_by_line_op cvau, ish, x0, x1, x2, x3
        ret
-SYM_FUNC_END(__clean_dcache_area_pou)
+SYM_FUNC_END(dcache_clean_pou)
 
 /*
- *     __inval_dcache_area(kaddr, size)
+ *     dcache_inval_poc(start, end)
  *
- *     Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
+ *     Ensure that any D-cache lines for the interval [start, end)
  *     are invalidated. Any partial lines at the ends of the interval are
  *     also cleaned to PoC to prevent data loss.
  *
- *     - kaddr   - kernel address
- *     - size    - size in question
+ *     - start   - kernel start address of region
+ *     - end     - kernel end address of region
  */
 SYM_FUNC_START_LOCAL(__dma_inv_area)
-SYM_FUNC_START_PI(__inval_dcache_area)
+SYM_FUNC_START_PI(dcache_inval_poc)
        /* FALLTHROUGH */
 
 /*
- *     __dma_inv_area(start, size)
+ *     __dma_inv_area(start, end)
  *     - start   - virtual start address of region
- *     - size    - size in question
+ *     - end     - virtual end address of region
  */
-       add     x1, x1, x0
        dcache_line_size x2, x3
        sub     x3, x2, #1
        tst     x1, x3                          // end cache line aligned?
@@ -165,48 +166,48 @@ SYM_FUNC_START_PI(__inval_dcache_area)
        b.lo    2b
        dsb     sy
        ret
-SYM_FUNC_END_PI(__inval_dcache_area)
+SYM_FUNC_END_PI(dcache_inval_poc)
 SYM_FUNC_END(__dma_inv_area)
 
 /*
- *     __clean_dcache_area_poc(kaddr, size)
+ *     dcache_clean_poc(start, end)
  *
- *     Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
+ *     Ensure that any D-cache lines for the interval [start, end)
  *     are cleaned to the PoC.
  *
- *     - kaddr   - kernel address
- *     - size    - size in question
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
  */
 SYM_FUNC_START_LOCAL(__dma_clean_area)
-SYM_FUNC_START_PI(__clean_dcache_area_poc)
+SYM_FUNC_START_PI(dcache_clean_poc)
        /* FALLTHROUGH */
 
 /*
- *     __dma_clean_area(start, size)
+ *     __dma_clean_area(start, end)
  *     - start   - virtual start address of region
- *     - size    - size in question
+ *     - end     - virtual end address of region
  */
        dcache_by_line_op cvac, sy, x0, x1, x2, x3
        ret
-SYM_FUNC_END_PI(__clean_dcache_area_poc)
+SYM_FUNC_END_PI(dcache_clean_poc)
 SYM_FUNC_END(__dma_clean_area)
 
 /*
- *     __clean_dcache_area_pop(kaddr, size)
+ *     dcache_clean_pop(start, end)
  *
- *     Ensure that any D-cache lines for the interval [kaddr, kaddr+size)
+ *     Ensure that any D-cache lines for the interval [start, end)
  *     are cleaned to the PoP.
  *
- *     - kaddr   - kernel address
- *     - size    - size in question
+ *     - start   - virtual start address of region
+ *     - end     - virtual end address of region
  */
-SYM_FUNC_START_PI(__clean_dcache_area_pop)
+SYM_FUNC_START_PI(dcache_clean_pop)
        alternative_if_not ARM64_HAS_DCPOP
-       b       __clean_dcache_area_poc
+       b       dcache_clean_poc
        alternative_else_nop_endif
        dcache_by_line_op cvap, sy, x0, x1, x2, x3
        ret
-SYM_FUNC_END_PI(__clean_dcache_area_pop)
+SYM_FUNC_END_PI(dcache_clean_pop)
 
 /*
  *     __dma_flush_area(start, size)
@@ -217,6 +218,7 @@ SYM_FUNC_END_PI(__clean_dcache_area_pop)
  *     - size    - size in question
  */
 SYM_FUNC_START_PI(__dma_flush_area)
+       add     x1, x0, x1
        dcache_by_line_op civac, sy, x0, x1, x2, x3
        ret
 SYM_FUNC_END_PI(__dma_flush_area)
@@ -228,6 +230,7 @@ SYM_FUNC_END_PI(__dma_flush_area)
  *     - dir   - DMA direction
  */
 SYM_FUNC_START_PI(__dma_map_area)
+       add     x1, x0, x1
        cmp     w2, #DMA_FROM_DEVICE
        b.eq    __dma_inv_area
        b       __dma_clean_area
@@ -240,6 +243,7 @@ SYM_FUNC_END_PI(__dma_map_area)
  *     - dir   - DMA direction
  */
 SYM_FUNC_START_PI(__dma_unmap_area)
+       add     x1, x0, x1
        cmp     w2, #DMA_TO_DEVICE
        b.ne    __dma_inv_area
        ret
index 6d44c028d1c9e647394d08e67fde7b99efb4768a..2aaf950b906cbabac1f145555dcc1b37b0271631 100644 (file)
 #include <asm/cache.h>
 #include <asm/tlbflush.h>
 
-void sync_icache_aliases(void *kaddr, unsigned long len)
+void sync_icache_aliases(unsigned long start, unsigned long end)
 {
-       unsigned long addr = (unsigned long)kaddr;
-
        if (icache_is_aliasing()) {
-               __clean_dcache_area_pou(kaddr, len);
-               __flush_icache_all();
+               dcache_clean_pou(start, end);
+               icache_inval_all_pou();
        } else {
                /*
                 * Don't issue kick_all_cpus_sync() after I-cache invalidation
                 * for user mappings.
                 */
-               __flush_icache_range(addr, addr + len);
+               caches_clean_inval_pou(start, end);
        }
 }
 
-static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
-                               unsigned long uaddr, void *kaddr,
-                               unsigned long len)
+static void flush_ptrace_access(struct vm_area_struct *vma, unsigned long start,
+                               unsigned long end)
 {
        if (vma->vm_flags & VM_EXEC)
-               sync_icache_aliases(kaddr, len);
+               sync_icache_aliases(start, end);
 }
 
 /*
@@ -48,7 +45,7 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
                       unsigned long len)
 {
        memcpy(dst, src, len);
-       flush_ptrace_access(vma, page, uaddr, dst, len);
+       flush_ptrace_access(vma, (unsigned long)dst, (unsigned long)dst + len);
 }
 
 void __sync_icache_dcache(pte_t pte)
@@ -56,7 +53,9 @@ void __sync_icache_dcache(pte_t pte)
        struct page *page = pte_page(pte);
 
        if (!test_bit(PG_dcache_clean, &page->flags)) {
-               sync_icache_aliases(page_address(page), page_size(page));
+               sync_icache_aliases((unsigned long)page_address(page),
+                                   (unsigned long)page_address(page) +
+                                           page_size(page));
                set_bit(PG_dcache_clean, &page->flags);
        }
 }
@@ -77,20 +76,20 @@ EXPORT_SYMBOL(flush_dcache_page);
 /*
  * Additional functions defined in assembly.
  */
-EXPORT_SYMBOL(__flush_icache_range);
+EXPORT_SYMBOL(caches_clean_inval_pou);
 
 #ifdef CONFIG_ARCH_HAS_PMEM_API
 void arch_wb_cache_pmem(void *addr, size_t size)
 {
        /* Ensure order against any prior non-cacheable writes */
        dmb(osh);
-       __clean_dcache_area_pop(addr, size);
+       dcache_clean_pop((unsigned long)addr, (unsigned long)addr + size);
 }
 EXPORT_SYMBOL_GPL(arch_wb_cache_pmem);
 
 void arch_invalidate_pmem(void *addr, size_t size)
 {
-       __inval_dcache_area(addr, size);
+       dcache_inval_poc((unsigned long)addr, (unsigned long)addr + size);
 }
 EXPORT_SYMBOL_GPL(arch_invalidate_pmem);
 #endif
index 6dd9369e3ea0e12db81a1d667343ad2b172182e6..89b66ef43a0ff9baca0c534875564e696fafbbae 100644 (file)
@@ -515,7 +515,8 @@ static void __init map_mem(pgd_t *pgdp)
         */
        BUILD_BUG_ON(pgd_index(direct_map_end - 1) == pgd_index(direct_map_end));
 
-       if (rodata_full || crash_mem_map || debug_pagealloc_enabled())
+       if (rodata_full || crash_mem_map || debug_pagealloc_enabled() ||
+           IS_ENABLED(CONFIG_KFENCE))
                flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
 
        /*
index 1ee8e736a48e37d73c5137e17154741777292a61..bb11fe4c875af9c4b03362bc8e15310bab2da3d5 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index a4b7ee1df211936ca569b673b9efe693f2ebd0af..8f215e79e70e61c1a69b949aac19a6ff8b5a43d9 100644 (file)
@@ -623,7 +623,8 @@ static inline void siginfo_build_tests(void)
        BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x12);
 
        /* _sigfault._perf */
-       BUILD_BUG_ON(offsetof(siginfo_t, si_perf) != 0x10);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_perf_data) != 0x10);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_perf_type) != 0x14);
 
        /* _sigpoll */
        BUILD_BUG_ON(offsetof(siginfo_t, si_band)   != 0x0c);
index 0dd019dc21362d18360269261f4f69977aa1cf3b..79c2d24c89ddade58fc6161c1d917edc0df11768 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index 2ac716984ca2869112ad4847c56eda8803dc83f7..b11395a20c203769a55bc32b97e84d5c389206d1 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index b184baa4e56a65b3da2edd8b225a2c2d62095459..f175bce2987faebdf91bf9789f4217976580a712 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/reboot.h>
 #include <asm/setup.h>
 #include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/gpio-au1000.h>
 #include <prom.h>
 
 const char *get_system_type(void)
index f93aa5ee2e2e36b864b7722f1be0bad022276382..3481ed4c117bd000a9e8b44afc5a25ba87c330e8 100644 (file)
@@ -3,6 +3,9 @@
  *
  */
 
+#ifndef _ASM_MIPS_BOARDS_LAUNCH_H
+#define _ASM_MIPS_BOARDS_LAUNCH_H
+
 #ifndef _ASSEMBLER_
 
 struct cpulaunch {
@@ -34,3 +37,5 @@ struct cpulaunch {
 
 /* Polling period in count cycles for secondary CPU's */
 #define LAUNCHPERIOD   10000
+
+#endif /* _ASM_MIPS_BOARDS_LAUNCH_H */
index 5e009665725104d960b1c0a1d066a4470f324abc..9220909526f9b2246951e69f447abc6f2c4df04d 100644 (file)
 440    n32     process_madvise                 sys_process_madvise
 441    n32     epoll_pwait2                    compat_sys_epoll_pwait2
 442    n32     mount_setattr                   sys_mount_setattr
-443    n32     quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    n32     landlock_create_ruleset         sys_landlock_create_ruleset
 445    n32     landlock_add_rule               sys_landlock_add_rule
 446    n32     landlock_restrict_self          sys_landlock_restrict_self
index 9974f5f8e49bce05819434ff65479b98caf85b91..9cd1c34f31b5040434060a7b242be5946bd5c988 100644 (file)
 440    n64     process_madvise                 sys_process_madvise
 441    n64     epoll_pwait2                    sys_epoll_pwait2
 442    n64     mount_setattr                   sys_mount_setattr
-443    n64     quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    n64     landlock_create_ruleset         sys_landlock_create_ruleset
 445    n64     landlock_add_rule               sys_landlock_add_rule
 446    n64     landlock_restrict_self          sys_landlock_restrict_self
index 39d6e71e57b608866fda81de210974076d0ca8cb..d560c467a8c697b8e01bc4d66910d2a15bb27d37 100644 (file)
 440    o32     process_madvise                 sys_process_madvise
 441    o32     epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
 442    o32     mount_setattr                   sys_mount_setattr
-443    o32     quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    o32     landlock_create_ruleset         sys_landlock_create_ruleset
 445    o32     landlock_add_rule               sys_landlock_add_rule
 446    o32     landlock_restrict_self          sys_landlock_restrict_self
index de03838b343b8bc33d869156ecefaa6326f3ed48..a9b72eacfc0b36e7fec5652dc3c2445fb449b5b4 100644 (file)
@@ -37,7 +37,7 @@
  */
 notrace void arch_local_irq_disable(void)
 {
-       preempt_disable();
+       preempt_disable_notrace();
 
        __asm__ __volatile__(
        "       .set    push                                            \n"
@@ -53,7 +53,7 @@ notrace void arch_local_irq_disable(void)
        : /* no inputs */
        : "memory");
 
-       preempt_enable();
+       preempt_enable_notrace();
 }
 EXPORT_SYMBOL(arch_local_irq_disable);
 
@@ -61,7 +61,7 @@ notrace unsigned long arch_local_irq_save(void)
 {
        unsigned long flags;
 
-       preempt_disable();
+       preempt_disable_notrace();
 
        __asm__ __volatile__(
        "       .set    push                                            \n"
@@ -78,7 +78,7 @@ notrace unsigned long arch_local_irq_save(void)
        : /* no inputs */
        : "memory");
 
-       preempt_enable();
+       preempt_enable_notrace();
 
        return flags;
 }
@@ -88,7 +88,7 @@ notrace void arch_local_irq_restore(unsigned long flags)
 {
        unsigned long __tmp1;
 
-       preempt_disable();
+       preempt_disable_notrace();
 
        __asm__ __volatile__(
        "       .set    push                                            \n"
@@ -106,7 +106,7 @@ notrace void arch_local_irq_restore(unsigned long flags)
        : "0" (flags)
        : "memory");
 
-       preempt_enable();
+       preempt_enable_notrace();
 }
 EXPORT_SYMBOL(arch_local_irq_restore);
 
index 0c5de07da097ad5e9733aaffa100debb6699d0d3..0135376c5de5d0046579947bec45cc4a9af9d3c2 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/sizes.h>
 #include <linux/of_fdt.h>
@@ -25,6 +26,7 @@
 
 __iomem void *rt_sysc_membase;
 __iomem void *rt_memc_membase;
+EXPORT_SYMBOL_GPL(rt_sysc_membase);
 
 __iomem void *plat_of_remap_node(const char *node)
 {
diff --git a/arch/openrisc/include/asm/barrier.h b/arch/openrisc/include/asm/barrier.h
new file mode 100644 (file)
index 0000000..7538294
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_BARRIER_H
+#define __ASM_BARRIER_H
+
+#define mb() asm volatile ("l.msync" ::: "memory")
+
+#include <asm-generic/barrier.h>
+
+#endif /* __ASM_BARRIER_H */
index 2416a9f9153306c37a2800f9396798e02510e6fa..c6f9e7b9f7cb23f165e127b153a45595ca582baf 100644 (file)
@@ -278,6 +278,8 @@ void calibrate_delay(void)
        pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
                loops_per_jiffy / (500000 / HZ),
                (loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy);
+
+       of_node_put(cpu);
 }
 
 void __init setup_arch(char **cmdline_p)
index d5641198b90ce7b10c8fa1c7bc8d30e90a6b930c..cfef61a7b6c2a83c150eae8e775011c3305a5514 100644 (file)
@@ -75,7 +75,6 @@ static void __init map_ram(void)
        /* These mark extents of read-only kernel pages...
         * ...from vmlinux.lds.S
         */
-       struct memblock_region *region;
 
        v = PAGE_OFFSET;
 
@@ -121,7 +120,7 @@ static void __init map_ram(void)
                }
 
                printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
-                      region->base, region->base + region->size);
+                      start, end);
        }
 }
 
@@ -129,7 +128,6 @@ void __init paging_init(void)
 {
        extern void tlb_init(void);
 
-       unsigned long end;
        int i;
 
        printk(KERN_INFO "Setting up paging and PTEs.\n");
@@ -145,8 +143,6 @@ void __init paging_init(void)
         */
        current_pgd[smp_processor_id()] = init_mm.pgd;
 
-       end = (unsigned long)__va(max_low_pfn * PAGE_SIZE);
-
        map_ram();
 
        zone_sizes_init();
index 5ac80b83d745e19020d37af6175b6da495a9a1ca..aabc37f8cae3a4248433cbbbb2af139badf75aa2 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index c2717f31925a20cce778340c6c10d8bd216ea633..ccda0a91abf003425bcff4f10e2092096856ac87 100644 (file)
        };
 
 /include/ "pq3-i2c-0.dtsi"
+       i2c@3000 {
+               fsl,i2c-erratum-a004447;
+       };
+
 /include/ "pq3-i2c-1.dtsi"
+       i2c@3100 {
+               fsl,i2c-erratum-a004447;
+       };
+
 /include/ "pq3-duart-0.dtsi"
 /include/ "pq3-espi-0.dtsi"
        spi0: spi@7000 {
index 872e4485dc3f033876ee7d69f59fa0add91a1783..ddc018d42252f9c49eb994705d0dde3774bbaabb 100644 (file)
        };
 
 /include/ "qoriq-i2c-0.dtsi"
+       i2c@118000 {
+               fsl,i2c-erratum-a004447;
+       };
+
+       i2c@118100 {
+               fsl,i2c-erratum-a004447;
+       };
+
 /include/ "qoriq-i2c-1.dtsi"
+       i2c@119000 {
+               fsl,i2c-erratum-a004447;
+       };
+
+       i2c@119100 {
+               fsl,i2c-erratum-a004447;
+       };
+
 /include/ "qoriq-duart-0.dtsi"
 /include/ "qoriq-duart-1.dtsi"
 /include/ "qoriq-gpio-0.dtsi"
index 9c9ab27461683bbfa904fbabc06d775a56078df0..b476a685f066ec77f080f923a1b25fdfcb8ca658 100644 (file)
@@ -19,6 +19,7 @@
 #ifndef _ASM_POWERPC_PTRACE_H
 #define _ASM_POWERPC_PTRACE_H
 
+#include <linux/err.h>
 #include <uapi/asm/ptrace.h>
 #include <asm/asm-const.h>
 
@@ -152,25 +153,6 @@ extern unsigned long profile_pc(struct pt_regs *regs);
 long do_syscall_trace_enter(struct pt_regs *regs);
 void do_syscall_trace_leave(struct pt_regs *regs);
 
-#define kernel_stack_pointer(regs) ((regs)->gpr[1])
-static inline int is_syscall_success(struct pt_regs *regs)
-{
-       return !(regs->ccr & 0x10000000);
-}
-
-static inline long regs_return_value(struct pt_regs *regs)
-{
-       if (is_syscall_success(regs))
-               return regs->gpr[3];
-       else
-               return -regs->gpr[3];
-}
-
-static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
-{
-       regs->gpr[3] = rc;
-}
-
 #ifdef __powerpc64__
 #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1)
 #else
@@ -235,6 +217,31 @@ static __always_inline void set_trap_norestart(struct pt_regs *regs)
        regs->trap |= 0x1;
 }
 
+#define kernel_stack_pointer(regs) ((regs)->gpr[1])
+static inline int is_syscall_success(struct pt_regs *regs)
+{
+       if (trap_is_scv(regs))
+               return !IS_ERR_VALUE((unsigned long)regs->gpr[3]);
+       else
+               return !(regs->ccr & 0x10000000);
+}
+
+static inline long regs_return_value(struct pt_regs *regs)
+{
+       if (trap_is_scv(regs))
+               return regs->gpr[3];
+
+       if (is_syscall_success(regs))
+               return regs->gpr[3];
+       else
+               return -regs->gpr[3];
+}
+
+static inline void regs_set_return_value(struct pt_regs *regs, unsigned long rc)
+{
+       regs->gpr[3] = rc;
+}
+
 #define arch_has_single_step() (1)
 #define arch_has_block_step()  (true)
 #define ARCH_HAS_USER_SINGLE_STEP_REPORT
index fd1b518eed17c2865010f7ed6ebb7a980261c271..ba0f88f3a30daea20e9c5e9efb322a627678a00c 100644 (file)
@@ -41,11 +41,17 @@ static inline void syscall_rollback(struct task_struct *task,
 static inline long syscall_get_error(struct task_struct *task,
                                     struct pt_regs *regs)
 {
-       /*
-        * If the system call failed,
-        * regs->gpr[3] contains a positive ERRORCODE.
-        */
-       return (regs->ccr & 0x10000000UL) ? -regs->gpr[3] : 0;
+       if (trap_is_scv(regs)) {
+               unsigned long error = regs->gpr[3];
+
+               return IS_ERR_VALUE(error) ? error : 0;
+       } else {
+               /*
+                * If the system call failed,
+                * regs->gpr[3] contains a positive ERRORCODE.
+                */
+               return (regs->ccr & 0x10000000UL) ? -regs->gpr[3] : 0;
+       }
 }
 
 static inline long syscall_get_return_value(struct task_struct *task,
@@ -58,18 +64,22 @@ static inline void syscall_set_return_value(struct task_struct *task,
                                            struct pt_regs *regs,
                                            int error, long val)
 {
-       /*
-        * In the general case it's not obvious that we must deal with CCR
-        * here, as the syscall exit path will also do that for us. However
-        * there are some places, eg. the signal code, which check ccr to
-        * decide if the value in r3 is actually an error.
-        */
-       if (error) {
-               regs->ccr |= 0x10000000L;
-               regs->gpr[3] = error;
+       if (trap_is_scv(regs)) {
+               regs->gpr[3] = (long) error ?: val;
        } else {
-               regs->ccr &= ~0x10000000L;
-               regs->gpr[3] = val;
+               /*
+                * In the general case it's not obvious that we must deal with
+                * CCR here, as the syscall exit path will also do that for us.
+                * However there are some places, eg. the signal code, which
+                * check ccr to decide if the value in r3 is actually an error.
+                */
+               if (error) {
+                       regs->ccr |= 0x10000000L;
+                       regs->gpr[3] = error;
+               } else {
+                       regs->ccr &= ~0x10000000L;
+                       regs->gpr[3] = val;
+               }
        }
 }
 
index b779d25761cf98f8b33ef22400f3708d665eb035..e42b85e4f1aa51a37dc2ef24fb6e1323f2c8d2c9 100644 (file)
@@ -369,11 +369,11 @@ void __init early_setup(unsigned long dt_ptr)
        apply_feature_fixups();
        setup_feature_keys();
 
-       early_ioremap_setup();
-
        /* Initialize the hash table or TLB handling */
        early_init_mmu();
 
+       early_ioremap_setup();
+
        /*
         * After firmware and early platform setup code has set things up,
         * we note the SPR values for configurable control/performance
index 2e68fbb57cc66de2e451c9e9721d425d9d76d9c1..8f052ff4058ce5534327ea64550af52bff5f5de2 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index a8ad8eb761206ab51d29f0351f6606048a867bb6..c5914e70a0fd74d6415ad4a3426dee7c1e81a0e0 100644 (file)
@@ -34,6 +34,7 @@ config RISCV
        select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
        select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
        select ARCH_SUPPORTS_HUGETLBFS if MMU
+       select ARCH_USE_MEMTEST
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
        select ARCH_WANT_FRAME_POINTERS
        select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
index 1e954101906ac7a24cdb81634be86720cfea45ee..e4e291d40759f003143c491e2baf3ee742e37bb2 100644 (file)
@@ -42,8 +42,8 @@ struct kimage_arch {
        unsigned long fdt_addr;
 };
 
-const extern unsigned char riscv_kexec_relocate[];
-const extern unsigned int riscv_kexec_relocate_size;
+extern const unsigned char riscv_kexec_relocate[];
+extern const unsigned int riscv_kexec_relocate_size;
 
 typedef void (*riscv_kexec_method)(unsigned long first_ind_entry,
                                   unsigned long jump_addr,
index cc048143fba55fe80d73e15a3f6e871edea172d4..9e99e1db156bc8ebd61b30f4ba006907b1b0e514 100644 (file)
@@ -14,8 +14,9 @@
 #include <asm/set_memory.h>    /* For set_memory_x() */
 #include <linux/compiler.h>    /* For unreachable() */
 #include <linux/cpu.h>         /* For cpu_down() */
+#include <linux/reboot.h>
 
-/**
+/*
  * kexec_image_info - Print received image details
  */
 static void
@@ -39,7 +40,7 @@ kexec_image_info(const struct kimage *image)
        }
 }
 
-/**
+/*
  * machine_kexec_prepare - Initialize kexec
  *
  * This function is called from do_kexec_load, when the user has
@@ -100,7 +101,7 @@ machine_kexec_prepare(struct kimage *image)
 }
 
 
-/**
+/*
  * machine_kexec_cleanup - Cleanup any leftovers from
  *                        machine_kexec_prepare
  *
@@ -135,7 +136,7 @@ void machine_shutdown(void)
 #endif
 }
 
-/**
+/*
  * machine_crash_shutdown - Prepare to kexec after a kernel crash
  *
  * This function is called by crash_kexec just before machine_kexec
@@ -151,7 +152,7 @@ machine_crash_shutdown(struct pt_regs *regs)
        pr_info("Starting crashdump kernel...\n");
 }
 
-/**
+/*
  * machine_kexec - Jump to the loaded kimage
  *
  * This function is called by kernel_kexec which is called by the
index 10b965c345366a4341ba9089033a2ee1ec3f8058..15cc65ac7ca6510668df49900af15d78aae86256 100644 (file)
@@ -84,6 +84,7 @@ int __kprobes arch_prepare_kprobe(struct kprobe *p)
        return 0;
 }
 
+#ifdef CONFIG_MMU
 void *alloc_insn_page(void)
 {
        return  __vmalloc_node_range(PAGE_SIZE, 1, VMALLOC_START, VMALLOC_END,
@@ -91,6 +92,7 @@ void *alloc_insn_page(void)
                                     VM_FLUSH_RESET_PERMS, NUMA_NO_NODE,
                                     __builtin_return_address(0));
 }
+#endif
 
 /* install breakpoint in text */
 void __kprobes arch_arm_kprobe(struct kprobe *p)
index 2b3e0cb90d789bec4bd0b84acadc0d91b4cb4cd2..bde85fc53357f8a0369fe20dc4f55b9926ac1175 100644 (file)
@@ -27,10 +27,10 @@ void notrace walk_stackframe(struct task_struct *task, struct pt_regs *regs,
                fp = frame_pointer(regs);
                sp = user_stack_pointer(regs);
                pc = instruction_pointer(regs);
-       } else if (task == NULL || task == current) {
-               fp = (unsigned long)__builtin_frame_address(0);
-               sp = sp_in_global;
-               pc = (unsigned long)walk_stackframe;
+       } else if (task == current) {
+               fp = (unsigned long)__builtin_frame_address(1);
+               sp = (unsigned long)__builtin_frame_address(0);
+               pc = (unsigned long)__builtin_return_address(0);
        } else {
                /* task blocked in __switch_to */
                fp = task->thread.s[0];
@@ -106,15 +106,15 @@ static bool print_trace_address(void *arg, unsigned long pc)
        return true;
 }
 
-void dump_backtrace(struct pt_regs *regs, struct task_struct *task,
+noinline void dump_backtrace(struct pt_regs *regs, struct task_struct *task,
                    const char *loglvl)
 {
-       pr_cont("%sCall Trace:\n", loglvl);
        walk_stackframe(task, regs, print_trace_address, (void *)loglvl);
 }
 
 void show_stack(struct task_struct *task, unsigned long *sp, const char *loglvl)
 {
+       pr_cont("%sCall Trace:\n", loglvl);
        dump_backtrace(NULL, task, loglvl);
 }
 
@@ -139,7 +139,7 @@ unsigned long get_wchan(struct task_struct *task)
 
 #ifdef CONFIG_STACKTRACE
 
-void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
+noinline void arch_stack_walk(stack_trace_consume_fn consume_entry, void *cookie,
                     struct task_struct *task, struct pt_regs *regs)
 {
        walk_stackframe(task, regs, consume_entry, cookie);
index 7e4a2aba366df088e153856f93f94cb0be0a2b4e..0690263df1dd0b58268941074441cb4e820744bc 100644 (file)
 440  common    process_madvise         sys_process_madvise             sys_process_madvise
 441  common    epoll_pwait2            sys_epoll_pwait2                compat_sys_epoll_pwait2
 442  common    mount_setattr           sys_mount_setattr               sys_mount_setattr
-443  common    quotactl_path           sys_quotactl_path               sys_quotactl_path
+# 443 reserved for quotactl_path
 444  common    landlock_create_ruleset sys_landlock_create_ruleset     sys_landlock_create_ruleset
 445  common    landlock_add_rule       sys_landlock_add_rule           sys_landlock_add_rule
 446  common    landlock_restrict_self  sys_landlock_restrict_self      sys_landlock_restrict_self
index f47a0dc5544551961efff6287c860ab347f90f05..0b91499ebdcfc2f67dfd597a66186cfea4d64280 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index b9e1c0e735b72b6ea50a862e401dd3afa39eb7f7..e34cc30ef22ced28c550699ab9973ac6b955a90e 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index c77c5d8a7b3eb181084daad2a2620eec1ffe16c9..307529417021a77bcb5d7f80d774967edf7f1b2c 100644 (file)
@@ -178,11 +178,6 @@ ifeq ($(ACCUMULATE_OUTGOING_ARGS), 1)
        KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args,)
 endif
 
-ifdef CONFIG_LTO_CLANG
-KBUILD_LDFLAGS += -plugin-opt=-code-model=kernel \
-                  -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8)
-endif
-
 # Workaround for a gcc prelease that unfortunately was shipped in a suse release
 KBUILD_CFLAGS += -Wno-sign-compare
 #
@@ -202,7 +197,12 @@ ifdef CONFIG_RETPOLINE
   endif
 endif
 
-KBUILD_LDFLAGS := -m elf_$(UTS_MACHINE)
+KBUILD_LDFLAGS += -m elf_$(UTS_MACHINE)
+
+ifdef CONFIG_LTO_CLANG
+KBUILD_LDFLAGS += -plugin-opt=-code-model=kernel \
+                  -plugin-opt=-stack-alignment=$(if $(CONFIG_X86_32),4,8)
+endif
 
 ifdef CONFIG_X86_NEED_RELOCS
 LDFLAGS_vmlinux := --emit-relocs --discard-none
index 28a1423ce32ee54e4e9b193d8f104b828acb5c96..4bbc267fb36bb9c8d07df4d4bd0b773f6bb1dc34 100644 (file)
 440    i386    process_madvise         sys_process_madvise
 441    i386    epoll_pwait2            sys_epoll_pwait2                compat_sys_epoll_pwait2
 442    i386    mount_setattr           sys_mount_setattr
-443    i386    quotactl_path           sys_quotactl_path
+# 443 reserved for quotactl_path
 444    i386    landlock_create_ruleset sys_landlock_create_ruleset
 445    i386    landlock_add_rule       sys_landlock_add_rule
 446    i386    landlock_restrict_self  sys_landlock_restrict_self
index ecd551b08d05256af7235764c72d711460b2d58a..ce18119ea0d0f0c6deaf54959a9a7de1ed2e89ef 100644 (file)
 440    common  process_madvise         sys_process_madvise
 441    common  epoll_pwait2            sys_epoll_pwait2
 442    common  mount_setattr           sys_mount_setattr
-443    common  quotactl_path           sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset sys_landlock_create_ruleset
 445    common  landlock_add_rule       sys_landlock_add_rule
 446    common  landlock_restrict_self  sys_landlock_restrict_self
index 8e509325c2c3d792792e76378898850c15111892..8f71dd72ef95fd6a583f1ee7d346fc15e3b5772b 100644 (file)
@@ -396,10 +396,12 @@ int x86_reserve_hardware(void)
        if (!atomic_inc_not_zero(&pmc_refcount)) {
                mutex_lock(&pmc_reserve_mutex);
                if (atomic_read(&pmc_refcount) == 0) {
-                       if (!reserve_pmc_hardware())
+                       if (!reserve_pmc_hardware()) {
                                err = -EBUSY;
-                       else
+                       } else {
                                reserve_ds_buffers();
+                               reserve_lbr_buffers();
+                       }
                }
                if (!err)
                        atomic_inc(&pmc_refcount);
index 2521d03de5e02e9f347e09edda033cbd0a6e9ede..e28892270c5803d421571aa207798e6740276ac8 100644 (file)
@@ -6253,7 +6253,7 @@ __init int intel_pmu_init(void)
         * Check all LBT MSR here.
         * Disable LBR access if any LBR MSRs can not be accessed.
         */
-       if (x86_pmu.lbr_nr && !check_msr(x86_pmu.lbr_tos, 0x3UL))
+       if (x86_pmu.lbr_tos && !check_msr(x86_pmu.lbr_tos, 0x3UL))
                x86_pmu.lbr_nr = 0;
        for (i = 0; i < x86_pmu.lbr_nr; i++) {
                if (!(check_msr(x86_pmu.lbr_from + i, 0xffffUL) &&
index 76dbab6ac9fbe3a82a1c6520eeea04354b2582ed..4409d2cccfda574fce38c8bef90ea97156313394 100644 (file)
@@ -658,7 +658,6 @@ static inline bool branch_user_callstack(unsigned br_sel)
 
 void intel_pmu_lbr_add(struct perf_event *event)
 {
-       struct kmem_cache *kmem_cache = event->pmu->task_ctx_cache;
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
 
        if (!x86_pmu.lbr_nr)
@@ -696,11 +695,6 @@ void intel_pmu_lbr_add(struct perf_event *event)
        perf_sched_cb_inc(event->ctx->pmu);
        if (!cpuc->lbr_users++ && !event->total_time_running)
                intel_pmu_lbr_reset();
-
-       if (static_cpu_has(X86_FEATURE_ARCH_LBR) &&
-           kmem_cache && !cpuc->lbr_xsave &&
-           (cpuc->lbr_users != cpuc->lbr_pebs_users))
-               cpuc->lbr_xsave = kmem_cache_alloc(kmem_cache, GFP_KERNEL);
 }
 
 void release_lbr_buffers(void)
@@ -722,6 +716,26 @@ void release_lbr_buffers(void)
        }
 }
 
+void reserve_lbr_buffers(void)
+{
+       struct kmem_cache *kmem_cache;
+       struct cpu_hw_events *cpuc;
+       int cpu;
+
+       if (!static_cpu_has(X86_FEATURE_ARCH_LBR))
+               return;
+
+       for_each_possible_cpu(cpu) {
+               cpuc = per_cpu_ptr(&cpu_hw_events, cpu);
+               kmem_cache = x86_get_pmu(cpu)->task_ctx_cache;
+               if (!kmem_cache || cpuc->lbr_xsave)
+                       continue;
+
+               cpuc->lbr_xsave = kmem_cache_alloc_node(kmem_cache, GFP_KERNEL,
+                                                       cpu_to_node(cpu));
+       }
+}
+
 void intel_pmu_lbr_del(struct perf_event *event)
 {
        struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
index 27fa85e7d4fda0a56ca34323f9f9c29bacf68ae4..ad87cb36f7c81c1ee67f82b108d91738cc17c806 100644 (file)
@@ -1244,6 +1244,8 @@ void reserve_ds_buffers(void);
 
 void release_lbr_buffers(void);
 
+void reserve_lbr_buffers(void);
+
 extern struct event_constraint bts_constraint;
 extern struct event_constraint vlbr_constraint;
 
@@ -1393,6 +1395,10 @@ static inline void release_lbr_buffers(void)
 {
 }
 
+static inline void reserve_lbr_buffers(void)
+{
+}
+
 static inline int intel_pmu_init(void)
 {
        return 0;
index 6ec8b3bfd76ebec3692aa6a37c06fbb395eb9417..9f90f460a28cc0f49b161188933dba804249acdf 100644 (file)
@@ -63,6 +63,7 @@ static bool sev_es_negotiate_protocol(void)
 
 static __always_inline void vc_ghcb_invalidate(struct ghcb *ghcb)
 {
+       ghcb->save.sw_exit_code = 0;
        memset(ghcb->save.valid_bitmap, 0, sizeof(ghcb->save.valid_bitmap));
 }
 
index 9578c82832aa272bd213f036088be2e305326b30..651b81cd648e5dc183853d90e2d5f1c33d39ed50 100644 (file)
@@ -203,8 +203,18 @@ static __always_inline struct ghcb *sev_es_get_ghcb(struct ghcb_state *state)
        if (unlikely(data->ghcb_active)) {
                /* GHCB is already in use - save its contents */
 
-               if (unlikely(data->backup_ghcb_active))
-                       return NULL;
+               if (unlikely(data->backup_ghcb_active)) {
+                       /*
+                        * Backup-GHCB is also already in use. There is no way
+                        * to continue here so just kill the machine. To make
+                        * panic() work, mark GHCBs inactive so that messages
+                        * can be printed out.
+                        */
+                       data->ghcb_active        = false;
+                       data->backup_ghcb_active = false;
+
+                       panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use");
+               }
 
                /* Mark backup_ghcb active before writing to it */
                data->backup_ghcb_active = true;
@@ -221,24 +231,6 @@ static __always_inline struct ghcb *sev_es_get_ghcb(struct ghcb_state *state)
        return ghcb;
 }
 
-static __always_inline void sev_es_put_ghcb(struct ghcb_state *state)
-{
-       struct sev_es_runtime_data *data;
-       struct ghcb *ghcb;
-
-       data = this_cpu_read(runtime_data);
-       ghcb = &data->ghcb_page;
-
-       if (state->ghcb) {
-               /* Restore GHCB from Backup */
-               *ghcb = *state->ghcb;
-               data->backup_ghcb_active = false;
-               state->ghcb = NULL;
-       } else {
-               data->ghcb_active = false;
-       }
-}
-
 /* Needed in vc_early_forward_exception */
 void do_early_exception(struct pt_regs *regs, int trapnr);
 
@@ -323,31 +315,44 @@ static enum es_result vc_write_mem(struct es_em_ctxt *ctxt,
        u16 d2;
        u8  d1;
 
-       /* If instruction ran in kernel mode and the I/O buffer is in kernel space */
-       if (!user_mode(ctxt->regs) && !access_ok(target, size)) {
-               memcpy(dst, buf, size);
-               return ES_OK;
-       }
-
+       /*
+        * This function uses __put_user() independent of whether kernel or user
+        * memory is accessed. This works fine because __put_user() does no
+        * sanity checks of the pointer being accessed. All that it does is
+        * to report when the access failed.
+        *
+        * Also, this function runs in atomic context, so __put_user() is not
+        * allowed to sleep. The page-fault handler detects that it is running
+        * in atomic context and will not try to take mmap_sem and handle the
+        * fault, so additional pagefault_enable()/disable() calls are not
+        * needed.
+        *
+        * The access can't be done via copy_to_user() here because
+        * vc_write_mem() must not use string instructions to access unsafe
+        * memory. The reason is that MOVS is emulated by the #VC handler by
+        * splitting the move up into a read and a write and taking a nested #VC
+        * exception on whatever of them is the MMIO access. Using string
+        * instructions here would cause infinite nesting.
+        */
        switch (size) {
        case 1:
                memcpy(&d1, buf, 1);
-               if (put_user(d1, target))
+               if (__put_user(d1, target))
                        goto fault;
                break;
        case 2:
                memcpy(&d2, buf, 2);
-               if (put_user(d2, target))
+               if (__put_user(d2, target))
                        goto fault;
                break;
        case 4:
                memcpy(&d4, buf, 4);
-               if (put_user(d4, target))
+               if (__put_user(d4, target))
                        goto fault;
                break;
        case 8:
                memcpy(&d8, buf, 8);
-               if (put_user(d8, target))
+               if (__put_user(d8, target))
                        goto fault;
                break;
        default:
@@ -378,30 +383,43 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
        u16 d2;
        u8  d1;
 
-       /* If instruction ran in kernel mode and the I/O buffer is in kernel space */
-       if (!user_mode(ctxt->regs) && !access_ok(s, size)) {
-               memcpy(buf, src, size);
-               return ES_OK;
-       }
-
+       /*
+        * This function uses __get_user() independent of whether kernel or user
+        * memory is accessed. This works fine because __get_user() does no
+        * sanity checks of the pointer being accessed. All that it does is
+        * to report when the access failed.
+        *
+        * Also, this function runs in atomic context, so __get_user() is not
+        * allowed to sleep. The page-fault handler detects that it is running
+        * in atomic context and will not try to take mmap_sem and handle the
+        * fault, so additional pagefault_enable()/disable() calls are not
+        * needed.
+        *
+        * The access can't be done via copy_from_user() here because
+        * vc_read_mem() must not use string instructions to access unsafe
+        * memory. The reason is that MOVS is emulated by the #VC handler by
+        * splitting the move up into a read and a write and taking a nested #VC
+        * exception on whatever of them is the MMIO access. Using string
+        * instructions here would cause infinite nesting.
+        */
        switch (size) {
        case 1:
-               if (get_user(d1, s))
+               if (__get_user(d1, s))
                        goto fault;
                memcpy(buf, &d1, 1);
                break;
        case 2:
-               if (get_user(d2, s))
+               if (__get_user(d2, s))
                        goto fault;
                memcpy(buf, &d2, 2);
                break;
        case 4:
-               if (get_user(d4, s))
+               if (__get_user(d4, s))
                        goto fault;
                memcpy(buf, &d4, 4);
                break;
        case 8:
-               if (get_user(d8, s))
+               if (__get_user(d8, s))
                        goto fault;
                memcpy(buf, &d8, 8);
                break;
@@ -461,6 +479,29 @@ static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt
 /* Include code shared with pre-decompression boot stage */
 #include "sev-shared.c"
 
+static __always_inline void sev_es_put_ghcb(struct ghcb_state *state)
+{
+       struct sev_es_runtime_data *data;
+       struct ghcb *ghcb;
+
+       data = this_cpu_read(runtime_data);
+       ghcb = &data->ghcb_page;
+
+       if (state->ghcb) {
+               /* Restore GHCB from Backup */
+               *ghcb = *state->ghcb;
+               data->backup_ghcb_active = false;
+               state->ghcb = NULL;
+       } else {
+               /*
+                * Invalidate the GHCB so a VMGEXIT instruction issued
+                * from userspace won't appear to be valid.
+                */
+               vc_ghcb_invalidate(ghcb);
+               data->ghcb_active = false;
+       }
+}
+
 void noinstr __sev_es_nmi_complete(void)
 {
        struct ghcb_state state;
@@ -1255,6 +1296,10 @@ static __always_inline void vc_forward_exception(struct es_em_ctxt *ctxt)
        case X86_TRAP_UD:
                exc_invalid_op(ctxt->regs);
                break;
+       case X86_TRAP_PF:
+               write_cr2(ctxt->fi.cr2);
+               exc_page_fault(ctxt->regs, error_code);
+               break;
        case X86_TRAP_AC:
                exc_alignment_check(ctxt->regs, error_code);
                break;
@@ -1284,7 +1329,6 @@ static __always_inline bool on_vc_fallback_stack(struct pt_regs *regs)
  */
 DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
 {
-       struct sev_es_runtime_data *data = this_cpu_read(runtime_data);
        irqentry_state_t irq_state;
        struct ghcb_state state;
        struct es_em_ctxt ctxt;
@@ -1310,16 +1354,6 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication)
         */
 
        ghcb = sev_es_get_ghcb(&state);
-       if (!ghcb) {
-               /*
-                * Mark GHCBs inactive so that panic() is able to print the
-                * message.
-                */
-               data->ghcb_active        = false;
-               data->backup_ghcb_active = false;
-
-               panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use");
-       }
 
        vc_ghcb_invalidate(ghcb);
        result = vc_init_em_ctxt(&ctxt, regs, error_code);
index 0e5d0a7e203b36f5b6171cde4b4207ee67cbb32c..06743ec054d2a99026050456094c7917b5fa7c86 100644 (file)
@@ -127,6 +127,9 @@ static inline void signal_compat_build_tests(void)
        BUILD_BUG_ON(offsetof(siginfo_t, si_addr) != 0x10);
        BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr) != 0x0C);
 
+       BUILD_BUG_ON(offsetof(siginfo_t, si_trapno) != 0x18);
+       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_trapno) != 0x10);
+
        BUILD_BUG_ON(offsetof(siginfo_t, si_addr_lsb) != 0x18);
        BUILD_BUG_ON(offsetof(compat_siginfo_t, si_addr_lsb) != 0x10);
 
@@ -138,8 +141,10 @@ static inline void signal_compat_build_tests(void)
        BUILD_BUG_ON(offsetof(siginfo_t, si_pkey) != 0x20);
        BUILD_BUG_ON(offsetof(compat_siginfo_t, si_pkey) != 0x14);
 
-       BUILD_BUG_ON(offsetof(siginfo_t, si_perf) != 0x18);
-       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf) != 0x10);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_perf_data) != 0x18);
+       BUILD_BUG_ON(offsetof(siginfo_t, si_perf_type) != 0x20);
+       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf_data) != 0x10);
+       BUILD_BUG_ON(offsetof(compat_siginfo_t, si_perf_type) != 0x14);
 
        CHECK_CSI_OFFSET(_sigpoll);
        CHECK_CSI_SIZE  (_sigpoll, 2*sizeof(int));
index 17503fed20177ba8a258848a0ce3e4e7f8499fde..e87699aa2dc8263d29054bba0adf937f7841e978 100644 (file)
@@ -1273,16 +1273,16 @@ asmlinkage __visible void __init xen_start_kernel(void)
        /* Get mfn list */
        xen_build_dynamic_phys_to_machine();
 
+       /* Work out if we support NX */
+       get_cpu_cap(&boot_cpu_data);
+       x86_configure_nx();
+
        /*
         * Set up kernel GDT and segment registers, mainly so that
         * -fstack-protector code can be executed.
         */
        xen_setup_gdt(0);
 
-       /* Work out if we support NX */
-       get_cpu_cap(&boot_cpu_data);
-       x86_configure_nx();
-
        /* Determine virtual and physical address sizes */
        get_cpu_address_sizes(&boot_cpu_data);
 
index 9d76d433d3d67012b73ae48fc7232e0294a92973..fd2f30227d961d7e356045142c1a8bb33044b269 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index 39ca97b0edc612ad2828952e7424d0a232bbf640..9f8cb7beaad1160b249912919e6fcf4e1f9c1a11 100644 (file)
@@ -29,8 +29,6 @@
 
 static struct kobject *block_depr;
 
-DECLARE_RWSEM(bdev_lookup_sem);
-
 /* for extended dynamic devt allocation, currently only one major is used */
 #define NR_EXT_DEVT            (1 << MINORBITS)
 static DEFINE_IDA(ext_devt_ida);
@@ -609,13 +607,8 @@ void del_gendisk(struct gendisk *disk)
        blk_integrity_del(disk);
        disk_del_events(disk);
 
-       /*
-        * Block lookups of the disk until all bdevs are unhashed and the
-        * disk is marked as dead (GENHD_FL_UP cleared).
-        */
-       down_write(&bdev_lookup_sem);
-
        mutex_lock(&disk->part0->bd_mutex);
+       disk->flags &= ~GENHD_FL_UP;
        blk_drop_partitions(disk);
        mutex_unlock(&disk->part0->bd_mutex);
 
@@ -629,8 +622,6 @@ void del_gendisk(struct gendisk *disk)
        remove_inode_hash(disk->part0->bd_inode);
 
        set_capacity(disk, 0);
-       disk->flags &= ~GENHD_FL_UP;
-       up_write(&bdev_lookup_sem);
 
        if (!(disk->flags & GENHD_FL_HIDDEN)) {
                sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
index 0ec5b3f69112774f176ee1b12a185d4e5350e755..6e02448d15d951967de0972843770529e6bc3852 100644 (file)
@@ -226,6 +226,7 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
        { "AMDI0010", APD_ADDR(wt_i2c_desc) },
        { "AMD0020", APD_ADDR(cz_uart_desc) },
        { "AMDI0020", APD_ADDR(cz_uart_desc) },
+       { "AMDI0022", APD_ADDR(cz_uart_desc) },
        { "AMD0030", },
        { "AMD0040", APD_ADDR(fch_misc_desc)},
        { "HYGO0010", APD_ADDR(wt_i2c_desc) },
index f973bbe90e5eeea7e3a195d8803bdfa0ed99a813..e21611c9a1703c2093aef7278ea647c06a02bfba 100644 (file)
@@ -134,7 +134,7 @@ int acpi_power_init(void);
 void acpi_power_resources_list_free(struct list_head *list);
 int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
                                 struct list_head *list);
-int acpi_add_power_resource(acpi_handle handle);
+struct acpi_device *acpi_add_power_resource(acpi_handle handle);
 void acpi_power_add_remove_device(struct acpi_device *adev, bool add);
 int acpi_power_wakeup_list_init(struct list_head *list, int *system_level);
 int acpi_device_sleep_wake(struct acpi_device *dev,
@@ -142,7 +142,7 @@ int acpi_device_sleep_wake(struct acpi_device *dev,
 int acpi_power_get_inferred_state(struct acpi_device *device, int *state);
 int acpi_power_on_resources(struct acpi_device *device, int state);
 int acpi_power_transition(struct acpi_device *device, int state);
-void acpi_turn_off_unused_power_resources(void);
+void acpi_turn_off_unused_power_resources(bool init);
 
 /* --------------------------------------------------------------------------
                               Device Power Management
index 56102eaaa2da852ac91831b8ebd1fbc78e8235df..97c9a94a1a30810bd5a685c306f4898ab5dc5054 100644 (file)
@@ -52,6 +52,7 @@ struct acpi_power_resource {
        u32 system_level;
        u32 order;
        unsigned int ref_count;
+       unsigned int users;
        bool wakeup_enabled;
        struct mutex resource_lock;
        struct list_head dependents;
@@ -147,6 +148,7 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
 
        for (i = start; i < package->package.count; i++) {
                union acpi_object *element = &package->package.elements[i];
+               struct acpi_device *rdev;
                acpi_handle rhandle;
 
                if (element->type != ACPI_TYPE_LOCAL_REFERENCE) {
@@ -163,13 +165,16 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
                if (acpi_power_resource_is_dup(package, start, i))
                        continue;
 
-               err = acpi_add_power_resource(rhandle);
-               if (err)
+               rdev = acpi_add_power_resource(rhandle);
+               if (!rdev) {
+                       err = -ENODEV;
                        break;
-
+               }
                err = acpi_power_resources_list_add(rhandle, list);
                if (err)
                        break;
+
+               to_power_resource(rdev)->users++;
        }
        if (err)
                acpi_power_resources_list_free(list);
@@ -907,7 +912,7 @@ static void acpi_power_add_resource_to_list(struct acpi_power_resource *resource
        mutex_unlock(&power_resource_list_lock);
 }
 
-int acpi_add_power_resource(acpi_handle handle)
+struct acpi_device *acpi_add_power_resource(acpi_handle handle)
 {
        struct acpi_power_resource *resource;
        struct acpi_device *device = NULL;
@@ -918,11 +923,11 @@ int acpi_add_power_resource(acpi_handle handle)
 
        acpi_bus_get_device(handle, &device);
        if (device)
-               return 0;
+               return device;
 
        resource = kzalloc(sizeof(*resource), GFP_KERNEL);
        if (!resource)
-               return -ENOMEM;
+               return NULL;
 
        device = &resource->device;
        acpi_init_device_object(device, handle, ACPI_BUS_TYPE_POWER);
@@ -959,11 +964,11 @@ int acpi_add_power_resource(acpi_handle handle)
 
        acpi_power_add_resource_to_list(resource);
        acpi_device_add_finalize(device);
-       return 0;
+       return device;
 
  err:
        acpi_release_power_resource(&device->dev);
-       return result;
+       return NULL;
 }
 
 #ifdef CONFIG_ACPI_SLEEP
@@ -997,7 +1002,38 @@ void acpi_resume_power_resources(void)
 }
 #endif
 
-void acpi_turn_off_unused_power_resources(void)
+static void acpi_power_turn_off_if_unused(struct acpi_power_resource *resource,
+                                      bool init)
+{
+       if (resource->ref_count > 0)
+               return;
+
+       if (init) {
+               if (resource->users > 0)
+                       return;
+       } else {
+               int result, state;
+
+               result = acpi_power_get_state(resource->device.handle, &state);
+               if (result || state == ACPI_POWER_RESOURCE_STATE_OFF)
+                       return;
+       }
+
+       dev_info(&resource->device.dev, "Turning OFF\n");
+       __acpi_power_off(resource);
+}
+
+/**
+ * acpi_turn_off_unused_power_resources - Turn off power resources not in use.
+ * @init: Control switch.
+ *
+ * If @ainit is set, unconditionally turn off all of the ACPI power resources
+ * without any users.
+ *
+ * Otherwise, turn off all ACPI power resources without active references (that
+ * is, the ones that should be "off" at the moment) that are "on".
+ */
+void acpi_turn_off_unused_power_resources(bool init)
 {
        struct acpi_power_resource *resource;
 
@@ -1006,10 +1042,7 @@ void acpi_turn_off_unused_power_resources(void)
        list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) {
                mutex_lock(&resource->resource_lock);
 
-               if (!resource->ref_count) {
-                       dev_info(&resource->device.dev, "Turning OFF\n");
-                       __acpi_power_off(resource);
-               }
+               acpi_power_turn_off_if_unused(resource, init);
 
                mutex_unlock(&resource->resource_lock);
        }
index 453eff8ec8c3308d4c1d42ac67718a6226a35fc9..e10d38ac7cf28d0a1d16396ff1e7faa8bab737cc 100644 (file)
@@ -2360,7 +2360,7 @@ int __init acpi_scan_init(void)
                }
        }
 
-       acpi_turn_off_unused_power_resources();
+       acpi_turn_off_unused_power_resources(true);
 
        acpi_scan_initialized = true;
 
index 09fd13757b658fad6cfa16f1cca4f72e3a76fa67..df386571da98b1777fad8c664b0d992ebc02739e 100644 (file)
@@ -504,7 +504,7 @@ static void acpi_pm_start(u32 acpi_state)
  */
 static void acpi_pm_end(void)
 {
-       acpi_turn_off_unused_power_resources();
+       acpi_turn_off_unused_power_resources(false);
        acpi_scan_lock_release();
        /*
         * This is necessary in case acpi_pm_finish() is not called during a
index 61d34e1dc59c5c6ff68924a5f4e066a4d66c4a98..bcec598b89f23d0588079a5b21818dde05380856 100644 (file)
@@ -4918,7 +4918,7 @@ static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                uint32_t enable;
 
                if (copy_from_user(&enable, ubuf, sizeof(enable))) {
-                       ret = -EINVAL;
+                       ret = -EFAULT;
                        goto err;
                }
                binder_inner_proc_lock(proc);
index 628e33939acaed4cb20c92016279b87071d4c430..54ba506e5a89dcf919a625cc0c01f6dad0401993 100644 (file)
@@ -194,6 +194,17 @@ int device_links_read_lock_held(void)
 {
        return srcu_read_lock_held(&device_links_srcu);
 }
+
+static void device_link_synchronize_removal(void)
+{
+       synchronize_srcu(&device_links_srcu);
+}
+
+static void device_link_remove_from_lists(struct device_link *link)
+{
+       list_del_rcu(&link->s_node);
+       list_del_rcu(&link->c_node);
+}
 #else /* !CONFIG_SRCU */
 static DECLARE_RWSEM(device_links_lock);
 
@@ -224,6 +235,16 @@ int device_links_read_lock_held(void)
        return lockdep_is_held(&device_links_lock);
 }
 #endif
+
+static inline void device_link_synchronize_removal(void)
+{
+}
+
+static void device_link_remove_from_lists(struct device_link *link)
+{
+       list_del(&link->s_node);
+       list_del(&link->c_node);
+}
 #endif /* !CONFIG_SRCU */
 
 static bool device_is_ancestor(struct device *dev, struct device *target)
@@ -445,8 +466,13 @@ static struct attribute *devlink_attrs[] = {
 };
 ATTRIBUTE_GROUPS(devlink);
 
-static void device_link_free(struct device_link *link)
+static void device_link_release_fn(struct work_struct *work)
 {
+       struct device_link *link = container_of(work, struct device_link, rm_work);
+
+       /* Ensure that all references to the link object have been dropped. */
+       device_link_synchronize_removal();
+
        while (refcount_dec_not_one(&link->rpm_active))
                pm_runtime_put(link->supplier);
 
@@ -455,24 +481,19 @@ static void device_link_free(struct device_link *link)
        kfree(link);
 }
 
-#ifdef CONFIG_SRCU
-static void __device_link_free_srcu(struct rcu_head *rhead)
-{
-       device_link_free(container_of(rhead, struct device_link, rcu_head));
-}
-
 static void devlink_dev_release(struct device *dev)
 {
        struct device_link *link = to_devlink(dev);
 
-       call_srcu(&device_links_srcu, &link->rcu_head, __device_link_free_srcu);
-}
-#else
-static void devlink_dev_release(struct device *dev)
-{
-       device_link_free(to_devlink(dev));
+       INIT_WORK(&link->rm_work, device_link_release_fn);
+       /*
+        * It may take a while to complete this work because of the SRCU
+        * synchronization in device_link_release_fn() and if the consumer or
+        * supplier devices get deleted when it runs, so put it into the "long"
+        * workqueue.
+        */
+       queue_work(system_long_wq, &link->rm_work);
 }
-#endif
 
 static struct class devlink_class = {
        .name = "devlink",
@@ -846,7 +867,6 @@ out:
 }
 EXPORT_SYMBOL_GPL(device_link_add);
 
-#ifdef CONFIG_SRCU
 static void __device_link_del(struct kref *kref)
 {
        struct device_link *link = container_of(kref, struct device_link, kref);
@@ -856,25 +876,9 @@ static void __device_link_del(struct kref *kref)
 
        pm_runtime_drop_link(link);
 
-       list_del_rcu(&link->s_node);
-       list_del_rcu(&link->c_node);
-       device_unregister(&link->link_dev);
-}
-#else /* !CONFIG_SRCU */
-static void __device_link_del(struct kref *kref)
-{
-       struct device_link *link = container_of(kref, struct device_link, kref);
-
-       dev_info(link->consumer, "Dropping the link to %s\n",
-                dev_name(link->supplier));
-
-       pm_runtime_drop_link(link);
-
-       list_del(&link->s_node);
-       list_del(&link->c_node);
+       device_link_remove_from_lists(link);
        device_unregister(&link->link_dev);
 }
-#endif /* !CONFIG_SRCU */
 
 static void device_link_put_kref(struct device_link *link)
 {
index 742b4a0932e3da962c802ed10703440ec7ccd00b..c6d8c0f597224bb95276b85c8fb948f63f0790e1 100644 (file)
@@ -744,6 +744,13 @@ static const struct blk_mq_ops gdrom_mq_ops = {
 static int probe_gdrom(struct platform_device *devptr)
 {
        int err;
+
+       /*
+        * Ensure our "one" device is initialized properly in case of previous
+        * usages of it
+        */
+       memset(&gd, 0, sizeof(gd));
+
        /* Start the device */
        if (gdrom_execute_diagnostic() != 1) {
                pr_warn("ATA Probe for GDROM failed\n");
@@ -830,6 +837,8 @@ static int remove_gdrom(struct platform_device *devptr)
        if (gdrom_major)
                unregister_blkdev(gdrom_major, GDROM_DEV_NAME);
        unregister_cdrom(gd.cd_info);
+       kfree(gd.cd_info);
+       kfree(gd.toc);
 
        return 0;
 }
@@ -845,7 +854,7 @@ static struct platform_driver gdrom_driver = {
 static int __init init_gdrom(void)
 {
        int rc;
-       gd.toc = NULL;
+
        rc = platform_driver_register(&gdrom_driver);
        if (rc)
                return rc;
@@ -861,8 +870,6 @@ static void __exit exit_gdrom(void)
 {
        platform_device_unregister(pd);
        platform_driver_unregister(&gdrom_driver);
-       kfree(gd.toc);
-       kfree(gd.cd_info);
 }
 
 module_init(init_gdrom);
index ed3b7dab678dbd16acc5cef239415fcaaa360816..8b55085650ad08203eea541715d9a9f7f93dcb5e 100644 (file)
@@ -984,6 +984,8 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data)
                hdp->hd_phys_address = fixmem32->address;
                hdp->hd_address = ioremap(fixmem32->address,
                                                HPET_RANGE_SIZE);
+               if (!hdp->hd_address)
+                       return AE_ERROR;
 
                if (hpet_is_known(hdp)) {
                        iounmap(hdp->hd_address);
index facc8e6bc58013cbdf48573ca7a94bf44357e416..d385daf2c71c3ee18f6b56d77cf2eed1581acd47 100644 (file)
@@ -442,7 +442,6 @@ static int nitrox_probe(struct pci_dev *pdev,
        err = pci_request_mem_regions(pdev, nitrox_driver_name);
        if (err) {
                pci_disable_device(pdev);
-               dev_err(&pdev->dev, "Failed to request mem regions!\n");
                return err;
        }
        pci_set_master(pdev);
index f264b70c383eb4ec5db083bc455296929668dc4d..eadd1eaa2fb541cd4eaff428b8d53865619ea5ad 100644 (file)
@@ -760,7 +760,7 @@ dma_buf_dynamic_attach(struct dma_buf *dmabuf, struct device *dev,
 
                if (dma_buf_is_dynamic(attach->dmabuf)) {
                        dma_resv_lock(attach->dmabuf->resv, NULL);
-                       ret = dma_buf_pin(attach);
+                       ret = dmabuf->ops->pin(attach);
                        if (ret)
                                goto err_unlock;
                }
@@ -786,7 +786,7 @@ err_attach:
 
 err_unpin:
        if (dma_buf_is_dynamic(attach->dmabuf))
-               dma_buf_unpin(attach);
+               dmabuf->ops->unpin(attach);
 
 err_unlock:
        if (dma_buf_is_dynamic(attach->dmabuf))
@@ -843,7 +843,7 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
                __unmap_dma_buf(attach, attach->sgt, attach->dir);
 
                if (dma_buf_is_dynamic(attach->dmabuf)) {
-                       dma_buf_unpin(attach);
+                       dmabuf->ops->unpin(attach);
                        dma_resv_unlock(attach->dmabuf->resv);
                }
        }
@@ -956,7 +956,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
        if (dma_buf_is_dynamic(attach->dmabuf)) {
                dma_resv_assert_held(attach->dmabuf->resv);
                if (!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) {
-                       r = dma_buf_pin(attach);
+                       r = attach->dmabuf->ops->pin(attach);
                        if (r)
                                return ERR_PTR(r);
                }
@@ -968,7 +968,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
 
        if (IS_ERR(sg_table) && dma_buf_is_dynamic(attach->dmabuf) &&
             !IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY))
-               dma_buf_unpin(attach);
+               attach->dmabuf->ops->unpin(attach);
 
        if (!IS_ERR(sg_table) && attach->dmabuf->ops->cache_sgt_mapping) {
                attach->sgt = sg_table;
index 806ca02c52d711702793c13804b1fec4ae5ea9ad..62026607f3f8bcff76e2f1cb6d89eefab8a0fd58 100644 (file)
@@ -418,8 +418,23 @@ static int __init hidma_mgmt_init(void)
                hidma_mgmt_of_populate_channels(child);
        }
 #endif
-       return platform_driver_register(&hidma_mgmt_driver);
+       /*
+        * We do not check for return value here, as it is assumed that
+        * platform_driver_register must not fail. The reason for this is that
+        * the (potential) hidma_mgmt_of_populate_channels calls above are not
+        * cleaned up if it does fail, and to do this work is quite
+        * complicated. In particular, various calls of of_address_to_resource,
+        * of_irq_to_resource, platform_device_register_full, of_dma_configure,
+        * and of_msi_configure which then call other functions and so on, must
+        * be cleaned up - this is not a trivial exercise.
+        *
+        * Currently, this module is not intended to be unloaded, and there is
+        * no module_exit function defined which does the needed cleanup. For
+        * this reason, we have to assume success here.
+        */
+       platform_driver_register(&hidma_mgmt_driver);
 
+       return 0;
 }
 module_init(hidma_mgmt_init);
 MODULE_LICENSE("GPL v2");
index ce0324be6c71df9580a8e299d3214b5ea2cf6dc9..4e9b627edfefaa819f958be55b67e188b257c1ed 100644 (file)
@@ -79,8 +79,6 @@ struct scmi_protocol_events {
 
 int scmi_notification_init(struct scmi_handle *handle);
 void scmi_notification_exit(struct scmi_handle *handle);
-
-struct scmi_protocol_handle;
 int scmi_register_protocol_events(const struct scmi_handle *handle, u8 proto_id,
                                  const struct scmi_protocol_handle *ph,
                                  const struct scmi_protocol_events *ee);
index d0dee37ad5228814e61142fe14dc9a992c6d2430..4ceba5ef789587f4e10ffb09dfa8c7892d7f82fe 100644 (file)
@@ -552,8 +552,10 @@ static unsigned long scpi_clk_get_val(u16 clk_id)
 
        ret = scpi_send_message(CMD_GET_CLOCK_VALUE, &le_clk_id,
                                sizeof(le_clk_id), &rate, sizeof(rate));
+       if (ret)
+               return 0;
 
-       return ret ? ret : le32_to_cpu(rate);
+       return le32_to_cpu(rate);
 }
 
 static int scpi_clk_set_val(u16 clk_id, unsigned long rate)
index a4d3239d25944dd772a7d1d75498331d7acce3d6..4ab3fcd9b9ba6e41a2aca13a0e747c475a9a87ff 100644 (file)
@@ -278,6 +278,7 @@ static const struct of_device_id cdns_of_ids[] = {
        { .compatible = "cdns,gpio-r1p02" },
        { /* sentinel */ },
 };
+MODULE_DEVICE_TABLE(of, cdns_of_ids);
 
 static struct platform_driver cdns_gpio_driver = {
        .driver = {
index 1bd9e44df718484bd38318142c7a1bf7a1baa3bc..05974b760796b409a0310969cdb4da4e7cf943ef 100644 (file)
@@ -444,16 +444,6 @@ static int tegra186_irq_set_wake(struct irq_data *data, unsigned int on)
        return 0;
 }
 
-static int tegra186_irq_set_affinity(struct irq_data *data,
-                                    const struct cpumask *dest,
-                                    bool force)
-{
-       if (data->parent_data)
-               return irq_chip_set_affinity_parent(data, dest, force);
-
-       return -EINVAL;
-}
-
 static void tegra186_gpio_irq(struct irq_desc *desc)
 {
        struct tegra_gpio *gpio = irq_desc_get_handler_data(desc);
@@ -700,7 +690,6 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
        gpio->intc.irq_unmask = tegra186_irq_unmask;
        gpio->intc.irq_set_type = tegra186_irq_set_type;
        gpio->intc.irq_set_wake = tegra186_irq_set_wake;
-       gpio->intc.irq_set_affinity = tegra186_irq_set_affinity;
 
        irq = &gpio->gpio.irq;
        irq->chip = &gpio->intc;
index b411d3156e0b687c39244e82ee492d6dfa3d1c54..136557e7dd3ceb00931db0c141b53e4a60381fb6 100644 (file)
@@ -542,7 +542,7 @@ static void xgpio_irqhandler(struct irq_desc *desc)
 }
 
 /**
- * xgpio_of_probe - Probe method for the GPIO device.
+ * xgpio_probe - Probe method for the GPIO device.
  * @pdev: pointer to the platform device
  *
  * Return:
index fad3b91f74f54972a4aee067bc921c5ec4b5befb..d39cff4a1fe3805c9b2f881d91e3004a6c4c8cef 100644 (file)
@@ -156,16 +156,16 @@ static uint32_t get_sdma_rlc_reg_offset(struct amdgpu_device *adev,
                                mmSDMA0_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL;
                break;
        case 1:
-               sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA1, 0,
+               sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA0, 0,
                                mmSDMA1_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL;
                break;
        case 2:
-               sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA2, 0,
-                               mmSDMA2_RLC0_RB_CNTL) - mmSDMA2_RLC0_RB_CNTL;
+               sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA0, 0,
+                               mmSDMA2_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL;
                break;
        case 3:
-               sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA3, 0,
-                               mmSDMA3_RLC0_RB_CNTL) - mmSDMA2_RLC0_RB_CNTL;
+               sdma_engine_reg_base = SOC15_REG_OFFSET(SDMA0, 0,
+                               mmSDMA3_RLC0_RB_CNTL) - mmSDMA0_RLC0_RB_CNTL;
                break;
        }
 
@@ -450,7 +450,7 @@ static int hqd_sdma_dump_v10_3(struct kgd_dev *kgd,
                        engine_id, queue_id);
        uint32_t i = 0, reg;
 #undef HQD_N_REGS
-#define HQD_N_REGS (19+6+7+10)
+#define HQD_N_REGS (19+6+7+12)
 
        *dump = kmalloc(HQD_N_REGS*2*sizeof(uint32_t), GFP_KERNEL);
        if (*dump == NULL)
index 8b2a37bf2adf1c670ece8ad50822a66e45c2d874..66ddfe4f58c2eb1ab393beb56b3a8cde01530052 100644 (file)
@@ -4479,7 +4479,6 @@ out:
                        r = amdgpu_ib_ring_tests(tmp_adev);
                        if (r) {
                                dev_err(tmp_adev->dev, "ib ring test failed (%d).\n", r);
-                               r = amdgpu_device_ip_suspend(tmp_adev);
                                need_full_reset = true;
                                r = -EAGAIN;
                                goto end;
index 4f10c452984068c08428f440ca9cc8675e23c798..09b0486475232ffbeec31d3fd70ff1332c6c168e 100644 (file)
@@ -288,10 +288,13 @@ out:
 static int amdgpu_fbdev_destroy(struct drm_device *dev, struct amdgpu_fbdev *rfbdev)
 {
        struct amdgpu_framebuffer *rfb = &rfbdev->rfb;
+       int i;
 
        drm_fb_helper_unregister_fbi(&rfbdev->helper);
 
        if (rfb->base.obj[0]) {
+               for (i = 0; i < rfb->base.format->num_planes; i++)
+                       drm_gem_object_put(rfb->base.obj[0]);
                amdgpufb_destroy_pinned_object(rfb->base.obj[0]);
                rfb->base.obj[0] = NULL;
                drm_framebuffer_unregister_private(&rfb->base);
index 3bef0432cac2f7dba196c2e23c64f25fa2a93fea..d5cbc51c5eaa8313fb1b9da91e37966351e3ca52 100644 (file)
@@ -225,7 +225,7 @@ static int amdgpu_ttm_map_buffer(struct ttm_buffer_object *bo,
        *addr += mm_cur->start & ~PAGE_MASK;
 
        num_dw = ALIGN(adev->mman.buffer_funcs->copy_num_dw, 8);
-       num_bytes = num_pages * 8;
+       num_bytes = num_pages * 8 * AMDGPU_GPU_PAGES_IN_CPU_PAGE;
 
        r = amdgpu_job_alloc_with_ib(adev, num_dw * 4 + num_bytes,
                                     AMDGPU_IB_POOL_DELAYED, &job);
@@ -1210,6 +1210,7 @@ static void amdgpu_ttm_tt_unpopulate(struct ttm_device *bdev,
        if (gtt && gtt->userptr) {
                amdgpu_ttm_tt_set_user_pages(ttm, NULL);
                kfree(ttm->sg);
+               ttm->sg = NULL;
                ttm->page_flags &= ~TTM_PAGE_FLAG_SG;
                return;
        }
index 2408ed4c7d847c570355442f88cefb3bbbf4bd47..7ce76a6b3a350237cf63fb457b4697b84d85afa0 100644 (file)
@@ -1395,9 +1395,10 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_2[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG, 0xffffffff, 0x20000000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG2, 0xffffffff, 0x00000420),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG3, 0xffffffff, 0x00000200),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x04800000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DEBUG4, 0xffffffff, 0x04900000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_DFSM_TILES_IN_FLIGHT, 0x0000ffff, 0x0000003f),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmDB_LAST_OF_BURST_CONFIG, 0xffffffff, 0x03860204),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmGB_ADDR_CONFIG, 0x0c1800ff, 0x00000044),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGCR_GENERAL_CNTL, 0x1ff0ffff, 0x00000500),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGE_PRIV_CONTROL, 0x00007fff, 0x000001fe),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmGL1_PIPE_STEER, 0xffffffff, 0xe4e4e4e4),
@@ -1415,12 +1416,13 @@ static const struct soc15_reg_golden golden_settings_gc_10_1_2[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_ENHANCE_2, 0x00000820, 0x00000820),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmPA_SC_LINE_STIPPLE_STATE, 0x0000ff0f, 0x00000000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_SPARE, 0xffffffff, 0xffff3101),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x001f0000, 0x00070104),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ALU_CLK_CTRL, 0xffffffff, 0xffffffff),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_ARB_CONFIG, 0x00000133, 0x00000130),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSQ_LDS_CLK_CTRL, 0xffffffff, 0xffffffff),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTA_CNTL_AUX, 0xfff7ffff, 0x01030000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CNTL, 0xffdf80ff, 0x479c0010),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00800000)
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmUTCL1_CTRL, 0xffffffff, 0x00c00000)
 };
 
 static bool gfx_v10_is_rlcg_rw(struct amdgpu_device *adev, u32 offset, uint32_t *flag, bool write)
index a078a38c2ceeaaf6ff97a3559e22c9dc683c3c91..516467e962b727bb3f079d20536825de0886fc9c 100644 (file)
@@ -4943,7 +4943,7 @@ static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
        amdgpu_gfx_rlc_enter_safe_mode(adev);
 
        /* Enable 3D CGCG/CGLS */
-       if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)) {
+       if (enable) {
                /* write cmd to clear cgcg/cgls ov */
                def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
                /* unset CGCG override */
@@ -4955,8 +4955,12 @@ static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
                /* enable 3Dcgcg FSM(0x0000363f) */
                def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
 
-               data = (0x36 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
-                       RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK;
+               if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)
+                       data = (0x36 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
+                               RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK;
+               else
+                       data = 0x0 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT;
+
                if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS)
                        data |= (0x000F << RLC_CGCG_CGLS_CTRL_3D__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
                                RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK;
index de5abceced0dd28ac92cacdf9a424a8388860de2..85967a5570cb41f5247e99fde958e65e3fa0122b 100644 (file)
@@ -172,6 +172,8 @@ static int jpeg_v2_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       cancel_delayed_work_sync(&adev->vcn.idle_work);
+
        if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
              RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
                jpeg_v2_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
index 83531997aeba9056bf0e802decdd9f5e254c01a7..46096ad7f0d9119a5d0e75876a16913a90039a49 100644 (file)
@@ -187,19 +187,17 @@ static int jpeg_v2_5_hw_init(void *handle)
 static int jpeg_v2_5_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct amdgpu_ring *ring;
        int i;
 
+       cancel_delayed_work_sync(&adev->vcn.idle_work);
+
        for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
                if (adev->jpeg.harvest_config & (1 << i))
                        continue;
 
-               ring = &adev->jpeg.inst[i].ring_dec;
                if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
                      RREG32_SOC15(JPEG, i, mmUVD_JRBC_STATUS))
                        jpeg_v2_5_set_powergating_state(adev, AMD_PG_STATE_GATE);
-
-               ring->sched.ready = false;
        }
 
        return 0;
index de5dfcfb385919985f983bf7a2c9b90da5fbbfa5..bd77794315bc6bea0e90b35c65237fb6e542170c 100644 (file)
@@ -159,15 +159,13 @@ static int jpeg_v3_0_hw_init(void *handle)
 static int jpeg_v3_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct amdgpu_ring *ring;
 
-       ring = &adev->jpeg.inst->ring_dec;
+       cancel_delayed_work_sync(&adev->vcn.idle_work);
+
        if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
              RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
                jpeg_v3_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
 
-       ring->sched.ready = false;
-
        return 0;
 }
 
index 920fc6d4a1273b2470c9fbe071e10385dbe3183b..8859133ce37eb64acac0a4cb8416d1654e725386 100644 (file)
@@ -123,6 +123,10 @@ static const struct soc15_reg_golden golden_settings_sdma_nv14[] = {
 
 static const struct soc15_reg_golden golden_settings_sdma_nv12[] = {
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG, 0x001877ff, 0x00000044),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG, 0x001877ff, 0x00000044),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x001877ff, 0x00000044),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSDMA1_RLC3_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000),
 };
 
index b1ad9e52b2347e7c0d2e082a749b906acfe9bc4c..240596b25fe4e32cf5263a9b901e0dcb0c125f82 100644 (file)
@@ -497,11 +497,6 @@ static void sdma_v5_2_gfx_stop(struct amdgpu_device *adev)
                ib_cntl = REG_SET_FIELD(ib_cntl, SDMA0_GFX_IB_CNTL, IB_ENABLE, 0);
                WREG32(sdma_v5_2_get_reg_offset(adev, i, mmSDMA0_GFX_IB_CNTL), ib_cntl);
        }
-
-       sdma0->sched.ready = false;
-       sdma1->sched.ready = false;
-       sdma2->sched.ready = false;
-       sdma3->sched.ready = false;
 }
 
 /**
index 8e1b9a40839fcd847c944a5fb530fa558b5a41b2..e65c286f93a6bbf80e73ea83cafa3b22f9ff470f 100644 (file)
@@ -302,6 +302,7 @@ static int soc15_query_video_codecs(struct amdgpu_device *adev, bool encode,
                        *codecs = &rv_video_codecs_decode;
                return 0;
        case CHIP_ARCTURUS:
+       case CHIP_ALDEBARAN:
        case CHIP_RENOIR:
                if (encode)
                        *codecs = &vega_video_codecs_encode;
@@ -1392,7 +1393,6 @@ static int soc15_common_early_init(void *handle)
                        adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
                                AMD_CG_SUPPORT_GFX_MGLS |
                                AMD_CG_SUPPORT_GFX_CP_LS |
-                               AMD_CG_SUPPORT_GFX_3D_CGCG |
                                AMD_CG_SUPPORT_GFX_3D_CGLS |
                                AMD_CG_SUPPORT_GFX_CGCG |
                                AMD_CG_SUPPORT_GFX_CGLS |
@@ -1412,7 +1412,6 @@ static int soc15_common_early_init(void *handle)
                                AMD_CG_SUPPORT_GFX_MGLS |
                                AMD_CG_SUPPORT_GFX_RLC_LS |
                                AMD_CG_SUPPORT_GFX_CP_LS |
-                               AMD_CG_SUPPORT_GFX_3D_CGCG |
                                AMD_CG_SUPPORT_GFX_3D_CGLS |
                                AMD_CG_SUPPORT_GFX_CGCG |
                                AMD_CG_SUPPORT_GFX_CGLS |
index 0c1beefa3e4987fd619c22b4ff9f4a619cbf2fd2..27b1ced145d2c9d60f75d62caca8d0e6db97d212 100644 (file)
@@ -231,9 +231,13 @@ static int vcn_v1_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       cancel_delayed_work_sync(&adev->vcn.idle_work);
+
        if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
-               RREG32_SOC15(VCN, 0, mmUVD_STATUS))
+               (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
+                RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
                vcn_v1_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
+       }
 
        return 0;
 }
index 116b9643d5bab315fd890dad877eaf213dbe4c24..8af567c546dbc39b9f0ad533633e682d313f86de 100644 (file)
@@ -262,6 +262,8 @@ static int vcn_v2_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       cancel_delayed_work_sync(&adev->vcn.idle_work);
+
        if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
            (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
              RREG32_SOC15(VCN, 0, mmUVD_STATUS)))
index 948813d7caa024221679ded544247602bbf72b88..888b17d84691ceb7ba6894be98cdfc288c5745e1 100644 (file)
@@ -321,6 +321,8 @@ static int vcn_v2_5_hw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        int i;
 
+       cancel_delayed_work_sync(&adev->vcn.idle_work);
+
        for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
                if (adev->vcn.harvest_config & (1 << i))
                        continue;
index cf165ab5dd26de0ad9809f990dbcfc25fad319aa..3b23de996db22195163db66f43f2d13cacbc435b 100644 (file)
@@ -372,15 +372,14 @@ done:
 static int vcn_v3_0_hw_fini(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       struct amdgpu_ring *ring;
-       int i, j;
+       int i;
+
+       cancel_delayed_work_sync(&adev->vcn.idle_work);
 
        for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
                if (adev->vcn.harvest_config & (1 << i))
                        continue;
 
-               ring = &adev->vcn.inst[i].ring_dec;
-
                if (!amdgpu_sriov_vf(adev)) {
                        if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
                                        (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
@@ -388,12 +387,6 @@ static int vcn_v3_0_hw_fini(void *handle)
                                vcn_v3_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
                        }
                }
-               ring->sched.ready = false;
-
-               for (j = 0; j < adev->vcn.num_enc_rings; ++j) {
-                       ring = &adev->vcn.inst[i].ring_enc[j];
-                       ring->sched.ready = false;
-               }
        }
 
        return 0;
index f4374d83662aeb7432a2c8e9ade1ef3644a5094b..c1f5474c205a809af9c8f5691600edf5c0e0bea6 100644 (file)
@@ -1076,6 +1076,24 @@ static bool dc_link_detect_helper(struct dc_link *link,
                            dc_is_dvi_signal(link->connector_signal)) {
                                if (prev_sink)
                                        dc_sink_release(prev_sink);
+                               link_disconnect_sink(link);
+
+                               return false;
+                       }
+                       /*
+                        * Abort detection for DP connectors if we have
+                        * no EDID and connector is active converter
+                        * as there are no display downstream
+                        *
+                        */
+                       if (dc_is_dp_sst_signal(link->connector_signal) &&
+                               (link->dpcd_caps.dongle_type ==
+                                               DISPLAY_DONGLE_DP_VGA_CONVERTER ||
+                               link->dpcd_caps.dongle_type ==
+                                               DISPLAY_DONGLE_DP_DVI_CONVERTER)) {
+                               if (prev_sink)
+                                       dc_sink_release(prev_sink);
+                               link_disconnect_sink(link);
 
                                return false;
                        }
index 4a5fa23d8e7b06911d13ed22c6e197d74df2b8f8..5fcc2e64305d574a1195a824bdd0ec879ff91fd8 100644 (file)
@@ -826,10 +826,11 @@ static const struct dc_plane_cap plane_cap = {
                        .fp16 = 16000
        },
 
+       /* 6:1 downscaling ratio: 1000/6 = 166.666 */
        .max_downscale_factor = {
-                       .argb8888 = 600,
-                       .nv12 = 600,
-                       .fp16 = 600
+                       .argb8888 = 167,
+                       .nv12 = 167,
+                       .fp16 = 167
        }
 };
 
index 5b54b7fc5105d05d75d4f04a1443923fbbbbc637..472696f949ac38aead373336669895598fffc807 100644 (file)
@@ -843,10 +843,11 @@ static const struct dc_plane_cap plane_cap = {
                        .fp16 = 16000
        },
 
+       /* 6:1 downscaling ratio: 1000/6 = 166.666 */
        .max_downscale_factor = {
-                       .argb8888 = 600,
-                       .nv12 = 600,
-                       .fp16 = 600
+                       .argb8888 = 167,
+                       .nv12 = 167,
+                       .fp16 = 167 
        },
        64,
        64
index fc2dea243d1ba06b07cae3b418a90709a7be8049..a33f0365329b9dbd3c85c2aeb8954759d34fdc63 100644 (file)
@@ -284,10 +284,11 @@ static const struct dc_plane_cap plane_cap = {
                                .nv12 = 16000,
                                .fp16 = 16000
                },
+               /* 6:1 downscaling ratio: 1000/6 = 166.666 */
                .max_downscale_factor = {
-                               .argb8888 = 600,
-                               .nv12 = 600,
-                               .fp16 = 600
+                               .argb8888 = 167,
+                               .nv12 = 167,
+                               .fp16 = 167
                },
                16,
                16
index ac13042672ea1094e1bc1b9b64e9a68d25ff7ac6..0eaf86b5e6986912606a23d61ad3b7d867f012e3 100644 (file)
@@ -2925,6 +2925,8 @@ static ssize_t navi1x_get_gpu_metrics(struct smu_context *smu,
 
 static int navi10_enable_mgpu_fan_boost(struct smu_context *smu)
 {
+       struct smu_table_context *table_context = &smu->smu_table;
+       PPTable_t *smc_pptable = table_context->driver_pptable;
        struct amdgpu_device *adev = smu->adev;
        uint32_t param = 0;
 
@@ -2932,6 +2934,13 @@ static int navi10_enable_mgpu_fan_boost(struct smu_context *smu)
        if (adev->asic_type == CHIP_NAVI12)
                return 0;
 
+       /*
+        * Skip the MGpuFanBoost setting for those ASICs
+        * which do not support it
+        */
+       if (!smc_pptable->MGpuFanBoostLimitRpm)
+               return 0;
+
        /* Workaround for WS SKU */
        if (adev->pdev->device == 0x7312 &&
            adev->pdev->revision == 0)
index d2fd44b903ca415274756d7d7bcd634c82950717..b124a5e40dd6a96f5273cc9a25276924cef557c4 100644 (file)
@@ -3027,6 +3027,16 @@ static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
 
 static int sienna_cichlid_enable_mgpu_fan_boost(struct smu_context *smu)
 {
+       struct smu_table_context *table_context = &smu->smu_table;
+       PPTable_t *smc_pptable = table_context->driver_pptable;
+
+       /*
+        * Skip the MGpuFanBoost setting for those ASICs
+        * which do not support it
+        */
+       if (!smc_pptable->MGpuFanBoostLimitRpm)
+               return 0;
+
        return smu_cmn_send_smc_msg_with_param(smu,
                                               SMU_MSG_SetMGpuFanBoostLimitRpm,
                                               0,
index b9a4b7670a899a15b3352e06915d7f6d6f692496..197b97341cad26cf53ec8b447e8d417768bca216 100644 (file)
@@ -815,10 +815,8 @@ static int exynos5433_decon_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        ctx->addr = devm_ioremap_resource(dev, res);
-       if (IS_ERR(ctx->addr)) {
-               dev_err(dev, "ioremap failed\n");
+       if (IS_ERR(ctx->addr))
                return PTR_ERR(ctx->addr);
-       }
 
        ret = decon_conf_irq(ctx, "vsync", decon_irq_handler, 0);
        if (ret < 0)
index 44e402b7cdfb6e399a4ac3416778e1a6573a8441..2d2fe5ab26e70300af7546617f90132164f4af36 100644 (file)
@@ -1786,10 +1786,8 @@ static int exynos_dsi_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dsi->reg_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(dsi->reg_base)) {
-               dev_err(dev, "failed to remap io region\n");
+       if (IS_ERR(dsi->reg_base))
                return PTR_ERR(dsi->reg_base);
-       }
 
        dsi->phy = devm_phy_get(dev, "dsim");
        if (IS_ERR(dsi->phy)) {
index 49a2e0c539187dae79b5df8857d8c0255cb6dced..ae576122873e0330224a923353e194f6c2df2f94 100644 (file)
@@ -723,7 +723,7 @@ static void fimd_win_set_colkey(struct fimd_context *ctx, unsigned int win)
 }
 
 /**
- * shadow_protect_win() - disable updating values from shadow registers at vsync
+ * fimd_shadow_protect_win() - disable updating values from shadow registers at vsync
  *
  * @ctx: local driver data
  * @win: window to protect registers for
index 69f57ca9c68d7372ba01ac846c43a9293dfbe770..93f4d059fc89f671773ef01fca7b074b9b0f3a70 100644 (file)
@@ -102,7 +102,6 @@ config DRM_I915_GVT
        bool "Enable Intel GVT-g graphics virtualization host support"
        depends on DRM_I915
        depends on 64BIT
-       depends on VFIO_MDEV=y || VFIO_MDEV=DRM_I915
        default n
        help
          Choose this option if you want to enable Intel GVT-g graphics
index 02a003fd48fb22533f0025cd8b64ca16270def35..50cae0198a3d0baf7ba44c798f1d513f7c6da1ea 100644 (file)
@@ -128,49 +128,13 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable)
        return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1;
 }
 
-/**
- * intel_dp_init_lttpr_and_dprx_caps - detect LTTPR and DPRX caps, init the LTTPR link training mode
- * @intel_dp: Intel DP struct
- *
- * Read the LTTPR common and DPRX capabilities and switch to non-transparent
- * link training mode if any is detected and read the PHY capabilities for all
- * detected LTTPRs. In case of an LTTPR detection error or if the number of
- * LTTPRs is more than is supported (8), fall back to the no-LTTPR,
- * transparent mode link training mode.
- *
- * Returns:
- *   >0  if LTTPRs were detected and the non-transparent LT mode was set. The
- *       DPRX capabilities are read out.
- *    0  if no LTTPRs or more than 8 LTTPRs were detected or in case of a
- *       detection failure and the transparent LT mode was set. The DPRX
- *       capabilities are read out.
- *   <0  Reading out the DPRX capabilities failed.
- */
-int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
+static int intel_dp_init_lttpr(struct intel_dp *intel_dp)
 {
        int lttpr_count;
-       bool ret;
        int i;
 
-       ret = intel_dp_read_lttpr_common_caps(intel_dp);
-
-       /* The DPTX shall read the DPRX caps after LTTPR detection. */
-       if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
-               intel_dp_reset_lttpr_common_caps(intel_dp);
-               return -EIO;
-       }
-
-       if (!ret)
-               return 0;
-
-       /*
-        * The 0xF0000-0xF02FF range is only valid if the DPCD revision is
-        * at least 1.4.
-        */
-       if (intel_dp->dpcd[DP_DPCD_REV] < 0x14) {
-               intel_dp_reset_lttpr_common_caps(intel_dp);
+       if (!intel_dp_read_lttpr_common_caps(intel_dp))
                return 0;
-       }
 
        lttpr_count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps);
        /*
@@ -211,6 +175,37 @@ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
 
        return lttpr_count;
 }
+
+/**
+ * intel_dp_init_lttpr_and_dprx_caps - detect LTTPR and DPRX caps, init the LTTPR link training mode
+ * @intel_dp: Intel DP struct
+ *
+ * Read the LTTPR common and DPRX capabilities and switch to non-transparent
+ * link training mode if any is detected and read the PHY capabilities for all
+ * detected LTTPRs. In case of an LTTPR detection error or if the number of
+ * LTTPRs is more than is supported (8), fall back to the no-LTTPR,
+ * transparent mode link training mode.
+ *
+ * Returns:
+ *   >0  if LTTPRs were detected and the non-transparent LT mode was set. The
+ *       DPRX capabilities are read out.
+ *    0  if no LTTPRs or more than 8 LTTPRs were detected or in case of a
+ *       detection failure and the transparent LT mode was set. The DPRX
+ *       capabilities are read out.
+ *   <0  Reading out the DPRX capabilities failed.
+ */
+int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp)
+{
+       int lttpr_count = intel_dp_init_lttpr(intel_dp);
+
+       /* The DPTX shall read the DPRX caps after LTTPR detection. */
+       if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) {
+               intel_dp_reset_lttpr_common_caps(intel_dp);
+               return -EIO;
+       }
+
+       return lttpr_count;
+}
 EXPORT_SYMBOL(intel_dp_init_lttpr_and_dprx_caps);
 
 static u8 dp_voltage_max(u8 preemph)
index aed8a37ccdc938ea4022b758d59c3a654f2e9bd9..7361971c177ddb6a7975342c184ca64f6355d91c 100644 (file)
@@ -63,6 +63,8 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj,
            i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) {
                GEM_BUG_ON(i915_gem_object_has_tiling_quirk(obj));
                i915_gem_object_set_tiling_quirk(obj);
+               GEM_BUG_ON(!list_empty(&obj->mm.link));
+               atomic_inc(&obj->mm.shrink_pin);
                shrinkable = false;
        }
 
index de575fdb033f5acb9b3c4ccf47e45af3228e586e..21f08e53889c39a1b52d6f48dd8e4d52676b801c 100644 (file)
@@ -397,7 +397,10 @@ static void emit_batch(struct i915_vma * const vma,
        gen7_emit_pipeline_invalidate(&cmds);
        batch_add(&cmds, MI_LOAD_REGISTER_IMM(2));
        batch_add(&cmds, i915_mmio_reg_offset(CACHE_MODE_0_GEN7));
-       batch_add(&cmds, 0xffff0000);
+       batch_add(&cmds, 0xffff0000 |
+                       ((IS_IVB_GT1(i915) || IS_VALLEYVIEW(i915)) ?
+                        HIZ_RAW_STALL_OPT_DISABLE :
+                        0));
        batch_add(&cmds, i915_mmio_reg_offset(CACHE_MODE_1));
        batch_add(&cmds, 0xffff0000 | PIXEL_SUBSPAN_COLLECT_OPT_DISABLE);
        gen7_emit_pipeline_invalidate(&cmds);
index e7c2babcee8b7071714150e24594773ce85cfb07..cbac409f6c8a56b84442615f04ae46420106e993 100644 (file)
@@ -46,118 +46,6 @@ static const char * const supported_hypervisors[] = {
        [INTEL_GVT_HYPERVISOR_KVM] = "KVM",
 };
 
-static struct intel_vgpu_type *
-intel_gvt_find_vgpu_type(struct intel_gvt *gvt, unsigned int type_group_id)
-{
-       if (WARN_ON(type_group_id >= gvt->num_types))
-               return NULL;
-       return &gvt->types[type_group_id];
-}
-
-static ssize_t available_instances_show(struct mdev_type *mtype,
-                                       struct mdev_type_attribute *attr,
-                                       char *buf)
-{
-       struct intel_vgpu_type *type;
-       unsigned int num = 0;
-       void *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
-
-       type = intel_gvt_find_vgpu_type(gvt, mtype_get_type_group_id(mtype));
-       if (!type)
-               num = 0;
-       else
-               num = type->avail_instance;
-
-       return sprintf(buf, "%u\n", num);
-}
-
-static ssize_t device_api_show(struct mdev_type *mtype,
-                              struct mdev_type_attribute *attr, char *buf)
-{
-       return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
-}
-
-static ssize_t description_show(struct mdev_type *mtype,
-                               struct mdev_type_attribute *attr, char *buf)
-{
-       struct intel_vgpu_type *type;
-       void *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
-
-       type = intel_gvt_find_vgpu_type(gvt, mtype_get_type_group_id(mtype));
-       if (!type)
-               return 0;
-
-       return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
-                      "fence: %d\nresolution: %s\n"
-                      "weight: %d\n",
-                      BYTES_TO_MB(type->low_gm_size),
-                      BYTES_TO_MB(type->high_gm_size),
-                      type->fence, vgpu_edid_str(type->resolution),
-                      type->weight);
-}
-
-static MDEV_TYPE_ATTR_RO(available_instances);
-static MDEV_TYPE_ATTR_RO(device_api);
-static MDEV_TYPE_ATTR_RO(description);
-
-static struct attribute *gvt_type_attrs[] = {
-       &mdev_type_attr_available_instances.attr,
-       &mdev_type_attr_device_api.attr,
-       &mdev_type_attr_description.attr,
-       NULL,
-};
-
-static struct attribute_group *gvt_vgpu_type_groups[] = {
-       [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
-};
-
-static bool intel_get_gvt_attrs(struct attribute_group ***intel_vgpu_type_groups)
-{
-       *intel_vgpu_type_groups = gvt_vgpu_type_groups;
-       return true;
-}
-
-static int intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
-{
-       int i, j;
-       struct intel_vgpu_type *type;
-       struct attribute_group *group;
-
-       for (i = 0; i < gvt->num_types; i++) {
-               type = &gvt->types[i];
-
-               group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
-               if (WARN_ON(!group))
-                       goto unwind;
-
-               group->name = type->name;
-               group->attrs = gvt_type_attrs;
-               gvt_vgpu_type_groups[i] = group;
-       }
-
-       return 0;
-
-unwind:
-       for (j = 0; j < i; j++) {
-               group = gvt_vgpu_type_groups[j];
-               kfree(group);
-       }
-
-       return -ENOMEM;
-}
-
-static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
-{
-       int i;
-       struct attribute_group *group;
-
-       for (i = 0; i < gvt->num_types; i++) {
-               group = gvt_vgpu_type_groups[i];
-               gvt_vgpu_type_groups[i] = NULL;
-               kfree(group);
-       }
-}
-
 static const struct intel_gvt_ops intel_gvt_ops = {
        .emulate_cfg_read = intel_vgpu_emulate_cfg_read,
        .emulate_cfg_write = intel_vgpu_emulate_cfg_write,
@@ -169,8 +57,6 @@ static const struct intel_gvt_ops intel_gvt_ops = {
        .vgpu_reset = intel_gvt_reset_vgpu,
        .vgpu_activate = intel_gvt_activate_vgpu,
        .vgpu_deactivate = intel_gvt_deactivate_vgpu,
-       .gvt_find_vgpu_type = intel_gvt_find_vgpu_type,
-       .get_gvt_attrs = intel_get_gvt_attrs,
        .vgpu_query_plane = intel_vgpu_query_plane,
        .vgpu_get_dmabuf = intel_vgpu_get_dmabuf,
        .write_protect_handler = intel_vgpu_page_track_handler,
@@ -274,7 +160,6 @@ void intel_gvt_clean_device(struct drm_i915_private *i915)
                return;
 
        intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
-       intel_gvt_cleanup_vgpu_type_groups(gvt);
        intel_gvt_clean_vgpu_types(gvt);
 
        intel_gvt_debugfs_clean(gvt);
@@ -363,12 +248,6 @@ int intel_gvt_init_device(struct drm_i915_private *i915)
        if (ret)
                goto out_clean_thread;
 
-       ret = intel_gvt_init_vgpu_type_groups(gvt);
-       if (ret) {
-               gvt_err("failed to init vgpu type groups: %d\n", ret);
-               goto out_clean_types;
-       }
-
        vgpu = intel_gvt_create_idle_vgpu(gvt);
        if (IS_ERR(vgpu)) {
                ret = PTR_ERR(vgpu);
@@ -454,7 +333,8 @@ EXPORT_SYMBOL_GPL(intel_gvt_register_hypervisor);
 void
 intel_gvt_unregister_hypervisor(void)
 {
-       intel_gvt_hypervisor_host_exit(intel_gvt_host.dev);
+       void *gvt = (void *)kdev_to_i915(intel_gvt_host.dev)->gvt;
+       intel_gvt_hypervisor_host_exit(intel_gvt_host.dev, gvt);
        module_put(THIS_MODULE);
 }
 EXPORT_SYMBOL_GPL(intel_gvt_unregister_hypervisor);
index 88ab360fcb31a40eed612eb9046e215bd85d2e45..0c0615602343a563bc90e0ccc78aca48faa5b4b9 100644 (file)
@@ -574,9 +574,6 @@ struct intel_gvt_ops {
        void (*vgpu_reset)(struct intel_vgpu *);
        void (*vgpu_activate)(struct intel_vgpu *);
        void (*vgpu_deactivate)(struct intel_vgpu *);
-       struct intel_vgpu_type *(*gvt_find_vgpu_type)(
-               struct intel_gvt *gvt, unsigned int type_group_id);
-       bool (*get_gvt_attrs)(struct attribute_group ***intel_vgpu_type_groups);
        int (*vgpu_query_plane)(struct intel_vgpu *vgpu, void *);
        int (*vgpu_get_dmabuf)(struct intel_vgpu *vgpu, unsigned int);
        int (*write_protect_handler)(struct intel_vgpu *, u64, void *,
index b79da5124f831cc4f4ad843545b9b031d0643529..f33e3cbd0439d3a053db16dbca8dac2aecd8f770 100644 (file)
@@ -49,7 +49,7 @@ enum hypervisor_type {
 struct intel_gvt_mpt {
        enum hypervisor_type type;
        int (*host_init)(struct device *dev, void *gvt, const void *ops);
-       void (*host_exit)(struct device *dev);
+       void (*host_exit)(struct device *dev, void *gvt);
        int (*attach_vgpu)(void *vgpu, unsigned long *handle);
        void (*detach_vgpu)(void *vgpu);
        int (*inject_msi)(unsigned long handle, u32 addr, u16 data);
index 65ff43cfc0f719edf91eaaec127d0359a4ca8f99..48b4d4cf805d11816511260b129fc68ecd448c8f 100644 (file)
@@ -144,6 +144,104 @@ static inline bool handle_valid(unsigned long handle)
        return !!(handle & ~0xff);
 }
 
+static ssize_t available_instances_show(struct mdev_type *mtype,
+                                       struct mdev_type_attribute *attr,
+                                       char *buf)
+{
+       struct intel_vgpu_type *type;
+       unsigned int num = 0;
+       struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
+
+       type = &gvt->types[mtype_get_type_group_id(mtype)];
+       if (!type)
+               num = 0;
+       else
+               num = type->avail_instance;
+
+       return sprintf(buf, "%u\n", num);
+}
+
+static ssize_t device_api_show(struct mdev_type *mtype,
+                              struct mdev_type_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
+}
+
+static ssize_t description_show(struct mdev_type *mtype,
+                               struct mdev_type_attribute *attr, char *buf)
+{
+       struct intel_vgpu_type *type;
+       struct intel_gvt *gvt = kdev_to_i915(mtype_get_parent_dev(mtype))->gvt;
+
+       type = &gvt->types[mtype_get_type_group_id(mtype)];
+       if (!type)
+               return 0;
+
+       return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
+                      "fence: %d\nresolution: %s\n"
+                      "weight: %d\n",
+                      BYTES_TO_MB(type->low_gm_size),
+                      BYTES_TO_MB(type->high_gm_size),
+                      type->fence, vgpu_edid_str(type->resolution),
+                      type->weight);
+}
+
+static MDEV_TYPE_ATTR_RO(available_instances);
+static MDEV_TYPE_ATTR_RO(device_api);
+static MDEV_TYPE_ATTR_RO(description);
+
+static struct attribute *gvt_type_attrs[] = {
+       &mdev_type_attr_available_instances.attr,
+       &mdev_type_attr_device_api.attr,
+       &mdev_type_attr_description.attr,
+       NULL,
+};
+
+static struct attribute_group *gvt_vgpu_type_groups[] = {
+       [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
+};
+
+static int intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
+{
+       int i, j;
+       struct intel_vgpu_type *type;
+       struct attribute_group *group;
+
+       for (i = 0; i < gvt->num_types; i++) {
+               type = &gvt->types[i];
+
+               group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
+               if (!group)
+                       goto unwind;
+
+               group->name = type->name;
+               group->attrs = gvt_type_attrs;
+               gvt_vgpu_type_groups[i] = group;
+       }
+
+       return 0;
+
+unwind:
+       for (j = 0; j < i; j++) {
+               group = gvt_vgpu_type_groups[j];
+               kfree(group);
+       }
+
+       return -ENOMEM;
+}
+
+static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
+{
+       int i;
+       struct attribute_group *group;
+
+       for (i = 0; i < gvt->num_types; i++) {
+               group = gvt_vgpu_type_groups[i];
+               gvt_vgpu_type_groups[i] = NULL;
+               kfree(group);
+       }
+}
+
 static int kvmgt_guest_init(struct mdev_device *mdev);
 static void intel_vgpu_release_work(struct work_struct *work);
 static bool kvmgt_guest_exit(struct kvmgt_guest_info *info);
@@ -694,14 +792,13 @@ static int intel_vgpu_create(struct mdev_device *mdev)
        struct intel_vgpu *vgpu = NULL;
        struct intel_vgpu_type *type;
        struct device *pdev;
-       void *gvt;
+       struct intel_gvt *gvt;
        int ret;
 
        pdev = mdev_parent_dev(mdev);
        gvt = kdev_to_i915(pdev)->gvt;
 
-       type = intel_gvt_ops->gvt_find_vgpu_type(gvt,
-                                                mdev_get_type_group_id(mdev));
+       type = &gvt->types[mdev_get_type_group_id(mdev)];
        if (!type) {
                ret = -EINVAL;
                goto out;
@@ -1667,19 +1764,26 @@ static struct mdev_parent_ops intel_vgpu_ops = {
 
 static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)
 {
-       struct attribute_group **kvm_vgpu_type_groups;
+       int ret;
+
+       ret = intel_gvt_init_vgpu_type_groups((struct intel_gvt *)gvt);
+       if (ret)
+               return ret;
 
        intel_gvt_ops = ops;
-       if (!intel_gvt_ops->get_gvt_attrs(&kvm_vgpu_type_groups))
-               return -EFAULT;
-       intel_vgpu_ops.supported_type_groups = kvm_vgpu_type_groups;
+       intel_vgpu_ops.supported_type_groups = gvt_vgpu_type_groups;
 
-       return mdev_register_device(dev, &intel_vgpu_ops);
+       ret = mdev_register_device(dev, &intel_vgpu_ops);
+       if (ret)
+               intel_gvt_cleanup_vgpu_type_groups((struct intel_gvt *)gvt);
+
+       return ret;
 }
 
-static void kvmgt_host_exit(struct device *dev)
+static void kvmgt_host_exit(struct device *dev, void *gvt)
 {
        mdev_unregister_device(dev);
+       intel_gvt_cleanup_vgpu_type_groups((struct intel_gvt *)gvt);
 }
 
 static int kvmgt_page_track_add(unsigned long handle, u64 gfn)
index 550a456e936fc44ee69bad487cf31d4b7596f974..e6c5a792a49a5ba50171611410c560d9be8d7f96 100644 (file)
@@ -63,13 +63,13 @@ static inline int intel_gvt_hypervisor_host_init(struct device *dev,
 /**
  * intel_gvt_hypervisor_host_exit - exit GVT-g host side
  */
-static inline void intel_gvt_hypervisor_host_exit(struct device *dev)
+static inline void intel_gvt_hypervisor_host_exit(struct device *dev, void *gvt)
 {
        /* optional to provide */
        if (!intel_gvt_host.mpt->host_exit)
                return;
 
-       intel_gvt_host.mpt->host_exit(dev);
+       intel_gvt_host.mpt->host_exit(dev, gvt);
 }
 
 /**
index b23f58e94cfb702a0ce41608ef6cc7a2d2692773..b3cedd20f3653c17a446dc5c656ee35e711c3ba6 100644 (file)
@@ -999,12 +999,11 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
                obj->mm.madv = args->madv;
 
        if (i915_gem_object_has_pages(obj)) {
-               struct list_head *list;
+               unsigned long flags;
 
-               if (i915_gem_object_is_shrinkable(obj)) {
-                       unsigned long flags;
-
-                       spin_lock_irqsave(&i915->mm.obj_lock, flags);
+               spin_lock_irqsave(&i915->mm.obj_lock, flags);
+               if (!list_empty(&obj->mm.link)) {
+                       struct list_head *list;
 
                        if (obj->mm.madv != I915_MADV_WILLNEED)
                                list = &i915->mm.purge_list;
@@ -1012,8 +1011,8 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
                                list = &i915->mm.shrink_list;
                        list_move_tail(&obj->mm.link, list);
 
-                       spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
                }
+               spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
        }
 
        /* if the object is no longer attached, discard its backing storage */
index 4c8cd08c672d2dd899ac87b78ea6c0f0ed93484b..9a777b0ff59b053604f8259bef2ffc13fb31c2ff 100644 (file)
 
 #include "i915_drv.h"
 
-#define EXPECTED_FLAGS (VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP)
+struct remap_pfn {
+       struct mm_struct *mm;
+       unsigned long pfn;
+       pgprot_t prot;
+
+       struct sgt_iter sgt;
+       resource_size_t iobase;
+};
 
 #define use_dma(io) ((io) != -1)
 
+static inline unsigned long sgt_pfn(const struct remap_pfn *r)
+{
+       if (use_dma(r->iobase))
+               return (r->sgt.dma + r->sgt.curr + r->iobase) >> PAGE_SHIFT;
+       else
+               return r->sgt.pfn + (r->sgt.curr >> PAGE_SHIFT);
+}
+
+static int remap_sg(pte_t *pte, unsigned long addr, void *data)
+{
+       struct remap_pfn *r = data;
+
+       if (GEM_WARN_ON(!r->sgt.sgp))
+               return -EINVAL;
+
+       /* Special PTE are not associated with any struct page */
+       set_pte_at(r->mm, addr, pte,
+                  pte_mkspecial(pfn_pte(sgt_pfn(r), r->prot)));
+       r->pfn++; /* track insertions in case we need to unwind later */
+
+       r->sgt.curr += PAGE_SIZE;
+       if (r->sgt.curr >= r->sgt.max)
+               r->sgt = __sgt_iter(__sg_next(r->sgt.sgp), use_dma(r->iobase));
+
+       return 0;
+}
+
+#define EXPECTED_FLAGS (VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP)
+
 /**
  * remap_io_sg - remap an IO mapping to userspace
  * @vma: user vma to map to
@@ -46,7 +82,12 @@ int remap_io_sg(struct vm_area_struct *vma,
                unsigned long addr, unsigned long size,
                struct scatterlist *sgl, resource_size_t iobase)
 {
-       unsigned long pfn, len, remapped = 0;
+       struct remap_pfn r = {
+               .mm = vma->vm_mm,
+               .prot = vma->vm_page_prot,
+               .sgt = __sgt_iter(sgl, use_dma(iobase)),
+               .iobase = iobase,
+       };
        int err;
 
        /* We rely on prevalidation of the io-mapping to skip track_pfn(). */
@@ -55,25 +96,11 @@ int remap_io_sg(struct vm_area_struct *vma,
        if (!use_dma(iobase))
                flush_cache_range(vma, addr, size);
 
-       do {
-               if (use_dma(iobase)) {
-                       if (!sg_dma_len(sgl))
-                               break;
-                       pfn = (sg_dma_address(sgl) + iobase) >> PAGE_SHIFT;
-                       len = sg_dma_len(sgl);
-               } else {
-                       pfn = page_to_pfn(sg_page(sgl));
-                       len = sgl->length;
-               }
-
-               err = remap_pfn_range(vma, addr + remapped, pfn, len,
-                                     vma->vm_page_prot);
-               if (err)
-                       break;
-               remapped += len;
-       } while ((sgl = __sg_next(sgl)));
-
-       if (err)
-               zap_vma_ptes(vma, addr, remapped);
-       return err;
+       err = apply_to_page_range(r.mm, addr, size, remap_sg, &r);
+       if (unlikely(err)) {
+               zap_vma_ptes(vma, addr, r.pfn << PAGE_SHIFT);
+               return err;
+       }
+
+       return 0;
 }
index 453d8b4c5763d9b65665ad8cca3ab0dfd0d8f4b2..07fcd12dca160d0791ebf1c5f78ef113e6870162 100644 (file)
@@ -485,11 +485,12 @@ static int meson_probe_remote(struct platform_device *pdev,
 static void meson_drv_shutdown(struct platform_device *pdev)
 {
        struct meson_drm *priv = dev_get_drvdata(&pdev->dev);
-       struct drm_device *drm = priv->drm;
 
-       DRM_DEBUG_DRIVER("\n");
-       drm_kms_helper_poll_fini(drm);
-       drm_atomic_helper_shutdown(drm);
+       if (!priv)
+               return;
+
+       drm_kms_helper_poll_fini(priv->drm);
+       drm_atomic_helper_shutdown(priv->drm);
 }
 
 static int meson_drv_probe(struct platform_device *pdev)
index 3808a753127bcb7c1eb861ea85bc85e09e0b7c12..04109a2a6fd760f10ac220bd3ff08f6b10afba3d 100644 (file)
@@ -301,7 +301,8 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
        p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
 
        for (i = 0; i < pages; i++, p++) {
-               rdev->gart.pages[p] = pagelist[i];
+               rdev->gart.pages[p] = pagelist ? pagelist[i] :
+                       rdev->dummy_page.page;
                page_base = dma_addr[i];
                for (j = 0; j < (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); j++, t++) {
                        page_entry = radeon_gart_get_page_entry(page_base, flags);
index 510e3e001dabe02c196c09d2cc10b0843daa9d7e..a1dcf7d55c903fb546b21ceea1f0a6a6f8bc35a7 100644 (file)
@@ -145,7 +145,7 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx,
                        list_for_each_entry(bo, &man->lru[j], lru) {
                                uint32_t num_pages;
 
-                               if (!bo->ttm ||
+                               if (!bo->ttm || !ttm_tt_is_populated(bo->ttm) ||
                                    bo->ttm->page_flags & TTM_PAGE_FLAG_SG ||
                                    bo->ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)
                                        continue;
index ac4adb44b224d783d44f51b2ecc2a4bffc7ab8c2..97ab491d2922cf0c81611a50ac3f09b221f0f944 100644 (file)
@@ -596,7 +596,6 @@ static int lm80_probe(struct i2c_client *client)
        struct device *dev = &client->dev;
        struct device *hwmon_dev;
        struct lm80_data *data;
-       int rv;
 
        data = devm_kzalloc(dev, sizeof(struct lm80_data), GFP_KERNEL);
        if (!data)
@@ -609,14 +608,8 @@ static int lm80_probe(struct i2c_client *client)
        lm80_init_client(client);
 
        /* A few vars need to be filled upon startup */
-       rv = lm80_read_value(client, LM80_REG_FAN_MIN(1));
-       if (rv < 0)
-               return rv;
-       data->fan[f_min][0] = rv;
-       rv = lm80_read_value(client, LM80_REG_FAN_MIN(2));
-       if (rv < 0)
-               return rv;
-       data->fan[f_min][1] = rv;
+       data->fan[f_min][0] = lm80_read_value(client, LM80_REG_FAN_MIN(1));
+       data->fan[f_min][1] = lm80_read_value(client, LM80_REG_FAN_MIN(2));
 
        hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
                                                           data, lm80_groups);
index 281a65d9b44bba75c4b542b98b5c2bd4d3c3b692..10acece9d7b9383eca6a3b67e190f194a1cb0d1b 100644 (file)
@@ -647,7 +647,7 @@ config I2C_HIGHLANDER
 
 config I2C_HISI
        tristate "HiSilicon I2C controller"
-       depends on ARM64 || COMPILE_TEST
+       depends on (ARM64 && ACPI) || COMPILE_TEST
        help
          Say Y here if you want to have Hisilicon I2C controller support
          available on the Kunpeng Server.
index 4d12e3da12f0dc658a680f458a7d2f171789efd8..55a9e93fbfeb56a55d36795e3bca21c101a12f03 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-only
-/**
+/*
  *     i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
  *
  *     Copyright (C) 2004 Patrick Mochel
index c1bbc4caeb5c948489339a923b37718d657d90c0..66aafa7d11234c5d185e3aa02ce34e327ae0cf27 100644 (file)
@@ -144,7 +144,7 @@ enum cdns_i2c_mode {
 };
 
 /**
- * enum cdns_i2c_slave_mode - Slave state when I2C is operating in slave mode
+ * enum cdns_i2c_slave_state - Slave state when I2C is operating in slave mode
  *
  * @CDNS_I2C_SLAVE_STATE_IDLE: I2C slave idle
  * @CDNS_I2C_SLAVE_STATE_SEND: I2C slave sending data to master
index 13be1d678c399cd40bdaadaa8ea17c7c7f5aea94..9b08bb5df38d29d48cd2881a212b7967bb3d2280 100644 (file)
@@ -165,7 +165,7 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev)
 }
 
 /**
- * i2c_dw_init() - Initialize the designware I2C master hardware
+ * i2c_dw_init_master() - Initialize the designware I2C master hardware
  * @dev: device private data
  *
  * This functions configures and enables the I2C master.
index 843b31a0f752bc023471c702eda32f5572627154..321b2770feabc04c91c292e106261df0fdbb3ed9 100644 (file)
@@ -148,7 +148,7 @@ struct i2c_algo_pch_data {
 
 /**
  * struct adapter_info - This structure holds the adapter information for the
                       PCH i2c controller
*                      PCH i2c controller
  * @pch_data:          stores a list of i2c_algo_pch_data
  * @pch_i2c_suspended: specifies whether the system is suspended or not
  *                     perhaps with more lines and words.
@@ -358,6 +358,7 @@ static void pch_i2c_repstart(struct i2c_algo_pch_data *adap)
 /**
  * pch_i2c_writebytes() - write data to I2C bus in normal mode
  * @i2c_adap:  Pointer to the struct i2c_adapter.
+ * @msgs:      Pointer to the i2c message structure.
  * @last:      specifies whether last message or not.
  *             In the case of compound mode it will be 1 for last message,
  *             otherwise 0.
index 99d446763530ea4028d449048d3a9e3f3486aeea..f9e1c2ceaac052496b61338b762d56262498d5a7 100644 (file)
@@ -395,11 +395,9 @@ static int i801_check_post(struct i801_priv *priv, int status)
                dev_err(&priv->pci_dev->dev, "Transaction timeout\n");
                /* try to stop the current command */
                dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n");
-               outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL,
-                      SMBHSTCNT(priv));
+               outb_p(SMBHSTCNT_KILL, SMBHSTCNT(priv));
                usleep_range(1000, 2000);
-               outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL),
-                      SMBHSTCNT(priv));
+               outb_p(0, SMBHSTCNT(priv));
 
                /* Check if it worked */
                status = inb_p(SMBHSTSTS(priv));
index c8c422e9dda4339344b6ceab728c30b0758b1497..5dae7cab7260559242a24d60005be2511d5a7743 100644 (file)
@@ -123,7 +123,6 @@ static int icy_probe(struct zorro_dev *z,
 {
        struct icy_i2c *i2c;
        struct i2c_algo_pcf_data *algo_data;
-       struct fwnode_handle *new_fwnode;
        struct i2c_board_info ltc2990_info = {
                .type           = "ltc2990",
                .swnode         = &icy_ltc2990_node,
index 30d9e89a3db20a9f83dc120beb504de93b1ffc1a..dcca9c2396db169c570f5a33c29eee3d89904bb9 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/iopoll.h>
 #include <linux/fsl_devices.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
@@ -45,6 +46,7 @@
 #define CCR_MTX  0x10
 #define CCR_TXAK 0x08
 #define CCR_RSTA 0x04
+#define CCR_RSVD 0x02
 
 #define CSR_MCF  0x80
 #define CSR_MAAS 0x40
@@ -97,7 +99,7 @@ struct mpc_i2c {
        u32 block;
        int rc;
        int expect_rxack;
-
+       bool has_errata_A004447;
 };
 
 struct mpc_i2c_divider {
@@ -136,6 +138,75 @@ static void mpc_i2c_fixup(struct mpc_i2c *i2c)
        }
 }
 
+static int i2c_mpc_wait_sr(struct mpc_i2c *i2c, int mask)
+{
+       void __iomem *addr = i2c->base + MPC_I2C_SR;
+       u8 val;
+
+       return readb_poll_timeout(addr, val, val & mask, 0, 100);
+}
+
+/*
+ * Workaround for Erratum A004447. From the P2040CE Rev Q
+ *
+ * 1.  Set up the frequency divider and sampling rate.
+ * 2.  I2CCR - a0h
+ * 3.  Poll for I2CSR[MBB] to get set.
+ * 4.  If I2CSR[MAL] is set (an indication that SDA is stuck low), then go to
+ *     step 5. If MAL is not set, then go to step 13.
+ * 5.  I2CCR - 00h
+ * 6.  I2CCR - 22h
+ * 7.  I2CCR - a2h
+ * 8.  Poll for I2CSR[MBB] to get set.
+ * 9.  Issue read to I2CDR.
+ * 10. Poll for I2CSR[MIF] to be set.
+ * 11. I2CCR - 82h
+ * 12. Workaround complete. Skip the next steps.
+ * 13. Issue read to I2CDR.
+ * 14. Poll for I2CSR[MIF] to be set.
+ * 15. I2CCR - 80h
+ */
+static void mpc_i2c_fixup_A004447(struct mpc_i2c *i2c)
+{
+       int ret;
+       u32 val;
+
+       writeccr(i2c, CCR_MEN | CCR_MSTA);
+       ret = i2c_mpc_wait_sr(i2c, CSR_MBB);
+       if (ret) {
+               dev_err(i2c->dev, "timeout waiting for CSR_MBB\n");
+               return;
+       }
+
+       val = readb(i2c->base + MPC_I2C_SR);
+
+       if (val & CSR_MAL) {
+               writeccr(i2c, 0x00);
+               writeccr(i2c, CCR_MSTA | CCR_RSVD);
+               writeccr(i2c, CCR_MEN | CCR_MSTA | CCR_RSVD);
+               ret = i2c_mpc_wait_sr(i2c, CSR_MBB);
+               if (ret) {
+                       dev_err(i2c->dev, "timeout waiting for CSR_MBB\n");
+                       return;
+               }
+               val = readb(i2c->base + MPC_I2C_DR);
+               ret = i2c_mpc_wait_sr(i2c, CSR_MIF);
+               if (ret) {
+                       dev_err(i2c->dev, "timeout waiting for CSR_MIF\n");
+                       return;
+               }
+               writeccr(i2c, CCR_MEN | CCR_RSVD);
+       } else {
+               val = readb(i2c->base + MPC_I2C_DR);
+               ret = i2c_mpc_wait_sr(i2c, CSR_MIF);
+               if (ret) {
+                       dev_err(i2c->dev, "timeout waiting for CSR_MIF\n");
+                       return;
+               }
+               writeccr(i2c, CCR_MEN);
+       }
+}
+
 #if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x)
 static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] = {
        {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23},
@@ -670,7 +741,10 @@ static int fsl_i2c_bus_recovery(struct i2c_adapter *adap)
 {
        struct mpc_i2c *i2c = i2c_get_adapdata(adap);
 
-       mpc_i2c_fixup(i2c);
+       if (i2c->has_errata_A004447)
+               mpc_i2c_fixup_A004447(i2c);
+       else
+               mpc_i2c_fixup(i2c);
 
        return 0;
 }
@@ -767,6 +841,9 @@ static int fsl_i2c_probe(struct platform_device *op)
        }
        dev_info(i2c->dev, "timeout %u us\n", mpc_ops.timeout * 1000000 / HZ);
 
+       if (of_property_read_bool(op->dev.of_node, "fsl,i2c-erratum-a004447"))
+               i2c->has_errata_A004447 = true;
+
        i2c->adap = mpc_ops;
        scnprintf(i2c->adap.name, sizeof(i2c->adap.name),
                  "MPC adapter (%s)", of_node_full_name(op->dev.of_node));
index 5ddfa4e56ee232006cf73397c2be6096f3501372..4e9fb6b44436ad5ae19d2e3c8bfbe8b0ee02bfd3 100644 (file)
@@ -479,6 +479,11 @@ static void mtk_i2c_clock_disable(struct mtk_i2c *i2c)
 static void mtk_i2c_init_hw(struct mtk_i2c *i2c)
 {
        u16 control_reg;
+       u16 intr_stat_reg;
+
+       mtk_i2c_writew(i2c, I2C_CHN_CLR_FLAG, OFFSET_START);
+       intr_stat_reg = mtk_i2c_readw(i2c, OFFSET_INTR_STAT);
+       mtk_i2c_writew(i2c, intr_stat_reg, OFFSET_INTR_STAT);
 
        if (i2c->dev_comp->apdma_sync) {
                writel(I2C_DMA_WARM_RST, i2c->pdmabase + OFFSET_RST);
index dc77e1c4e80f9d8b6741a1aeb57f921fa4aa608c..a2d12a5b1c34c1265cbe9bc6c0215bef621d5bd0 100644 (file)
@@ -159,7 +159,7 @@ struct i2c_nmk_client {
  * @clk_freq: clock frequency for the operation mode
  * @tft: Tx FIFO Threshold in bytes
  * @rft: Rx FIFO Threshold in bytes
- * @timeout Slave response timeout (ms)
+ * @timeout: Slave response timeout (ms)
  * @sm: speed mode
  * @stop: stop condition.
  * @xfer_complete: acknowledge completion for a I2C message.
index 273222e38056edda2d89aea155cbef9c1232ba97..a0af027db04c11b98fef28be555ceb7804d92eb6 100644 (file)
@@ -250,7 +250,7 @@ static irqreturn_t ocores_isr(int irq, void *dev_id)
 }
 
 /**
- * Process timeout event
+ * ocores_process_timeout() - Process timeout event
  * @i2c: ocores I2C device instance
  */
 static void ocores_process_timeout(struct ocores_i2c *i2c)
@@ -264,7 +264,7 @@ static void ocores_process_timeout(struct ocores_i2c *i2c)
 }
 
 /**
- * Wait until something change in a given register
+ * ocores_wait() - Wait until something change in a given register
  * @i2c: ocores I2C device instance
  * @reg: register to query
  * @mask: bitmask to apply on register value
@@ -296,7 +296,7 @@ static int ocores_wait(struct ocores_i2c *i2c,
 }
 
 /**
- * Wait until is possible to process some data
+ * ocores_poll_wait() - Wait until is possible to process some data
  * @i2c: ocores I2C device instance
  *
  * Used when the device is in polling mode (interrupts disabled).
@@ -334,7 +334,7 @@ static int ocores_poll_wait(struct ocores_i2c *i2c)
 }
 
 /**
- * It handles an IRQ-less transfer
+ * ocores_process_polling() - It handles an IRQ-less transfer
  * @i2c: ocores I2C device instance
  *
  * Even if IRQ are disabled, the I2C OpenCore IP behavior is exactly the same
index 8c4ec7f13f5ab26b9fe3b9b08ca3ccae2c8cb961..50f21cdbe90d3cbfae78f65238908a604a64e7c5 100644 (file)
@@ -138,7 +138,7 @@ static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
 /**
  * i2c_pnx_start - start a device
  * @slave_addr:                slave address
- * @adap:              pointer to adapter structure
+ * @alg_data:          pointer to local driver data structure
  *
  * Generate a START signal in the desired mode.
  */
@@ -194,7 +194,7 @@ static int i2c_pnx_start(unsigned char slave_addr,
 
 /**
  * i2c_pnx_stop - stop a device
- * @adap:              pointer to I2C adapter structure
+ * @alg_data:          pointer to local driver data structure
  *
  * Generate a STOP signal to terminate the master transaction.
  */
@@ -223,7 +223,7 @@ static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
 
 /**
  * i2c_pnx_master_xmit - transmit data to slave
- * @adap:              pointer to I2C adapter structure
+ * @alg_data:          pointer to local driver data structure
  *
  * Sends one byte of data to the slave
  */
@@ -293,7 +293,7 @@ static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
 
 /**
  * i2c_pnx_master_rcv - receive data from slave
- * @adap:              pointer to I2C adapter structure
+ * @alg_data:          pointer to local driver data structure
  *
  * Reads one byte data from the slave
  */
index 214b4c913a139ac872f356e0f5d10d4653f5d556..07b710a774df43227cc4d867ac51189a54daa233 100644 (file)
@@ -100,7 +100,7 @@ static const struct geni_i2c_err_log gi2c_log[] = {
        [GP_IRQ0] = {-EIO, "Unknown I2C err GP_IRQ0"},
        [NACK] = {-ENXIO, "NACK: slv unresponsive, check its power/reset-ln"},
        [GP_IRQ2] = {-EIO, "Unknown I2C err GP IRQ2"},
-       [BUS_PROTO] = {-EPROTO, "Bus proto err, noisy/unepxected start/stop"},
+       [BUS_PROTO] = {-EPROTO, "Bus proto err, noisy/unexpected start/stop"},
        [ARB_LOST] = {-EAGAIN, "Bus arbitration lost, clock line undriveable"},
        [GP_IRQ5] = {-EIO, "Unknown I2C err GP IRQ5"},
        [GENI_OVERRUN] = {-EIO, "Cmd overrun, check GENI cmd-state machine"},
index ab928613afba44a9785de522dae97d865eb63468..4d82761e1585eaf0cc02f102860b08d366ab5216 100644 (file)
@@ -480,7 +480,10 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
                                         * forces us to send a new START
                                         * when we change direction
                                         */
+                                       dev_dbg(i2c->dev,
+                                               "missing START before write->read\n");
                                        s3c24xx_i2c_stop(i2c, -EINVAL);
+                                       break;
                                }
 
                                goto retry_write;
index 3ae6ca21a02c6b9f08d737d56ead76b6dca550de..2d2e630fd438712f5de581d2319456b23d74de26 100644 (file)
@@ -807,7 +807,7 @@ static const struct sh_mobile_dt_config r8a7740_dt_config = {
 static const struct of_device_id sh_mobile_i2c_dt_ids[] = {
        { .compatible = "renesas,iic-r8a73a4", .data = &fast_clock_dt_config },
        { .compatible = "renesas,iic-r8a7740", .data = &r8a7740_dt_config },
-       { .compatible = "renesas,iic-r8a774c0", .data = &fast_clock_dt_config },
+       { .compatible = "renesas,iic-r8a774c0", .data = &v2_freq_calc_dt_config },
        { .compatible = "renesas,iic-r8a7790", .data = &v2_freq_calc_dt_config },
        { .compatible = "renesas,iic-r8a7791", .data = &v2_freq_calc_dt_config },
        { .compatible = "renesas,iic-r8a7792", .data = &v2_freq_calc_dt_config },
index faa81a95551fe98d230a2ee063b72298ad2b59c7..88482316d22a050a982a8024f046cf02d7378393 100644 (file)
@@ -524,7 +524,7 @@ static void st_i2c_handle_write(struct st_i2c_dev *i2c_dev)
 }
 
 /**
- * st_i2c_handle_write() - Handle FIFO enmpty interrupt in case of read
+ * st_i2c_handle_read() - Handle FIFO empty interrupt in case of read
  * @i2c_dev: Controller's private data
  */
 static void st_i2c_handle_read(struct st_i2c_dev *i2c_dev)
@@ -558,7 +558,7 @@ static void st_i2c_handle_read(struct st_i2c_dev *i2c_dev)
 }
 
 /**
- * st_i2c_isr() - Interrupt routine
+ * st_i2c_isr_thread() - Interrupt routine
  * @irq: interrupt number
  * @data: Controller's private data
  */
index 4933fc8ce3fd1ce0d8300005352def6b06b880a9..eebce7ecef25b7c887e3f654cbcc0266d2a59066 100644 (file)
@@ -313,7 +313,7 @@ static int stm32f4_i2c_wait_free_bus(struct stm32f4_i2c_dev *i2c_dev)
 }
 
 /**
- * stm32f4_i2c_write_ byte() - Write a byte in the data register
+ * stm32f4_i2c_write_byte() - Write a byte in the data register
  * @i2c_dev: Controller's private data
  * @byte: Data to write in the register
  */
index 6dc88902c189fbb015b3a136c0a2a79498b780a9..1c78657631f4f838196aa093640bd218b880e1c6 100644 (file)
@@ -34,7 +34,7 @@ struct i2c_arbitrator_data {
 };
 
 
-/**
+/*
  * i2c_arbitrator_select - claim the I2C bus
  *
  * Use the GPIO-based signalling protocol; return -EBUSY if we fail.
@@ -77,7 +77,7 @@ static int i2c_arbitrator_select(struct i2c_mux_core *muxc, u32 chan)
        return -EBUSY;
 }
 
-/**
+/*
  * i2c_arbitrator_deselect - release the I2C bus
  *
  * Release the I2C bus using the GPIO-based signalling protocol.
index 9d3952b4674f56a83e0f65eff65903570457a26a..a27db78ea13ee6f3b24bf345efa4e4f662a70365 100644 (file)
@@ -771,6 +771,13 @@ static int ad7124_of_parse_channel_config(struct iio_dev *indio_dev,
                if (ret)
                        goto err;
 
+               if (channel >= indio_dev->num_channels) {
+                       dev_err(indio_dev->dev.parent,
+                               "Channel index >= number of channels\n");
+                       ret = -EINVAL;
+                       goto err;
+               }
+
                ret = of_property_read_u32_array(child, "diff-channels",
                                                 ain, 2);
                if (ret)
@@ -850,6 +857,11 @@ static int ad7124_setup(struct ad7124_state *st)
        return ret;
 }
 
+static void ad7124_reg_disable(void *r)
+{
+       regulator_disable(r);
+}
+
 static int ad7124_probe(struct spi_device *spi)
 {
        const struct ad7124_chip_info *info;
@@ -895,17 +907,20 @@ static int ad7124_probe(struct spi_device *spi)
                ret = regulator_enable(st->vref[i]);
                if (ret)
                        return ret;
+
+               ret = devm_add_action_or_reset(&spi->dev, ad7124_reg_disable,
+                                              st->vref[i]);
+               if (ret)
+                       return ret;
        }
 
        st->mclk = devm_clk_get(&spi->dev, "mclk");
-       if (IS_ERR(st->mclk)) {
-               ret = PTR_ERR(st->mclk);
-               goto error_regulator_disable;
-       }
+       if (IS_ERR(st->mclk))
+               return PTR_ERR(st->mclk);
 
        ret = clk_prepare_enable(st->mclk);
        if (ret < 0)
-               goto error_regulator_disable;
+               return ret;
 
        ret = ad7124_soft_reset(st);
        if (ret < 0)
@@ -935,11 +950,6 @@ error_remove_trigger:
        ad_sd_cleanup_buffer_and_trigger(indio_dev);
 error_clk_disable_unprepare:
        clk_disable_unprepare(st->mclk);
-error_regulator_disable:
-       for (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) {
-               if (!IS_ERR_OR_NULL(st->vref[i]))
-                       regulator_disable(st->vref[i]);
-       }
 
        return ret;
 }
@@ -948,17 +958,11 @@ static int ad7124_remove(struct spi_device *spi)
 {
        struct iio_dev *indio_dev = spi_get_drvdata(spi);
        struct ad7124_state *st = iio_priv(indio_dev);
-       int i;
 
        iio_device_unregister(indio_dev);
        ad_sd_cleanup_buffer_and_trigger(indio_dev);
        clk_disable_unprepare(st->mclk);
 
-       for (i = ARRAY_SIZE(st->vref) - 1; i >= 0; i--) {
-               if (!IS_ERR_OR_NULL(st->vref[i]))
-                       regulator_disable(st->vref[i]);
-       }
-
        return 0;
 }
 
index 2ed580521d815a0b869a63275fa9ab197f5da9e2..1141cc13a1249829ee9e83fc9718ff5a8976f1df 100644 (file)
@@ -912,7 +912,7 @@ static int ad7192_probe(struct spi_device *spi)
 {
        struct ad7192_state *st;
        struct iio_dev *indio_dev;
-       int ret, voltage_uv = 0;
+       int ret;
 
        if (!spi->irq) {
                dev_err(&spi->dev, "no IRQ?\n");
@@ -949,15 +949,12 @@ static int ad7192_probe(struct spi_device *spi)
                goto error_disable_avdd;
        }
 
-       voltage_uv = regulator_get_voltage(st->avdd);
-
-       if (voltage_uv > 0) {
-               st->int_vref_mv = voltage_uv / 1000;
-       } else {
-               ret = voltage_uv;
+       ret = regulator_get_voltage(st->avdd);
+       if (ret < 0) {
                dev_err(&spi->dev, "Device tree error, reference voltage undefined\n");
                goto error_disable_avdd;
        }
+       st->int_vref_mv = ret / 1000;
 
        spi_set_drvdata(spi, indio_dev);
        st->chip_info = of_device_get_match_data(&spi->dev);
@@ -1014,7 +1011,9 @@ static int ad7192_probe(struct spi_device *spi)
        return 0;
 
 error_disable_clk:
-       clk_disable_unprepare(st->mclk);
+       if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 ||
+           st->clock_sel == AD7192_CLK_EXT_MCLK2)
+               clk_disable_unprepare(st->mclk);
 error_remove_trigger:
        ad_sd_cleanup_buffer_and_trigger(indio_dev);
 error_disable_dvdd:
@@ -1031,7 +1030,9 @@ static int ad7192_remove(struct spi_device *spi)
        struct ad7192_state *st = iio_priv(indio_dev);
 
        iio_device_unregister(indio_dev);
-       clk_disable_unprepare(st->mclk);
+       if (st->clock_sel == AD7192_CLK_EXT_MCLK1_2 ||
+           st->clock_sel == AD7192_CLK_EXT_MCLK2)
+               clk_disable_unprepare(st->mclk);
        ad_sd_cleanup_buffer_and_trigger(indio_dev);
 
        regulator_disable(st->dvdd);
index c945f1349623f7ad7f58069710ed02565f022af5..60f21fed6dcbe1a8c69336c0dbe3b3452d2be923 100644 (file)
@@ -167,6 +167,10 @@ struct ad7768_state {
         * transfer buffers to live in their own cache lines.
         */
        union {
+               struct {
+                       __be32 chan;
+                       s64 timestamp;
+               } scan;
                __be32 d32;
                u8 d8[2];
        } data ____cacheline_aligned;
@@ -469,11 +473,11 @@ static irqreturn_t ad7768_trigger_handler(int irq, void *p)
 
        mutex_lock(&st->lock);
 
-       ret = spi_read(st->spi, &st->data.d32, 3);
+       ret = spi_read(st->spi, &st->data.scan.chan, 3);
        if (ret < 0)
                goto err_unlock;
 
-       iio_push_to_buffers_with_timestamp(indio_dev, &st->data.d32,
+       iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan,
                                           iio_get_time_ns(indio_dev));
 
        iio_trigger_notify_done(indio_dev->trig);
index 5e980a06258e64753b8f0b8320c75bb4c847e92c..440ef4c7be074c1c4b9f1d680147fd47703dd944 100644 (file)
@@ -279,6 +279,7 @@ static int ad7793_setup(struct iio_dev *indio_dev,
        id &= AD7793_ID_MASK;
 
        if (id != st->chip_info->id) {
+               ret = -ENODEV;
                dev_err(&st->sd.spi->dev, "device ID query failed\n");
                goto out;
        }
index 9a649745cd0a81c2744722c9c6dba0b0118efef6..069b561ee76896fb3a4b24fb63c6c70f88f7c9ed 100644 (file)
@@ -59,8 +59,10 @@ struct ad7923_state {
        /*
         * DMA (thus cache coherency maintenance) requires the
         * transfer buffers to live in their own cache lines.
+        * Ensure rx_buf can be directly used in iio_push_to_buffers_with_timetamp
+        * Length = 8 channels + 4 extra for 8 byte timestamp
         */
-       __be16                          rx_buf[4] ____cacheline_aligned;
+       __be16                          rx_buf[12] ____cacheline_aligned;
        __be16                          tx_buf[4];
 };
 
index 7ab2ccf908639744c876f828015799529733e9a2..8107f7bbbe3c5885ddcdd5f65664a16b1278d653 100644 (file)
@@ -524,23 +524,29 @@ static int ad5770r_channel_config(struct ad5770r_state *st)
        device_for_each_child_node(&st->spi->dev, child) {
                ret = fwnode_property_read_u32(child, "num", &num);
                if (ret)
-                       return ret;
-               if (num >= AD5770R_MAX_CHANNELS)
-                       return -EINVAL;
+                       goto err_child_out;
+               if (num >= AD5770R_MAX_CHANNELS) {
+                       ret = -EINVAL;
+                       goto err_child_out;
+               }
 
                ret = fwnode_property_read_u32_array(child,
                                                     "adi,range-microamp",
                                                     tmp, 2);
                if (ret)
-                       return ret;
+                       goto err_child_out;
 
                min = tmp[0] / 1000;
                max = tmp[1] / 1000;
                ret = ad5770r_store_output_range(st, min, max, num);
                if (ret)
-                       return ret;
+                       goto err_child_out;
        }
 
+       return 0;
+
+err_child_out:
+       fwnode_handle_put(child);
        return ret;
 }
 
index 1a20c6b88e7db5cf3b28665ab25ab17c9c270882..645461c70454777f0745f128107c3e25f64bfc0a 100644 (file)
@@ -399,6 +399,7 @@ static int fxas21002c_temp_get(struct fxas21002c_data *data, int *val)
        ret = regmap_field_read(data->regmap_fields[F_TEMP], &temp);
        if (ret < 0) {
                dev_err(dev, "failed to read temp: %d\n", ret);
+               fxas21002c_pm_put(data);
                goto data_unlock;
        }
 
@@ -432,6 +433,7 @@ static int fxas21002c_axis_get(struct fxas21002c_data *data,
                               &axis_be, sizeof(axis_be));
        if (ret < 0) {
                dev_err(dev, "failed to read axis: %d: %d\n", index, ret);
+               fxas21002c_pm_put(data);
                goto data_unlock;
        }
 
index 2b9ffc21cbc4ad4a3fbbd096f610c96284b8474c..ab148a696c0cebe9995a95cf2d998c049cfbcecf 100644 (file)
@@ -473,6 +473,7 @@ static void cma_release_dev(struct rdma_id_private *id_priv)
        list_del(&id_priv->list);
        cma_dev_put(id_priv->cma_dev);
        id_priv->cma_dev = NULL;
+       id_priv->id.device = NULL;
        if (id_priv->id.route.addr.dev_addr.sgid_attr) {
                rdma_put_gid_attr(id_priv->id.route.addr.dev_addr.sgid_attr);
                id_priv->id.route.addr.dev_addr.sgid_attr = NULL;
@@ -1860,6 +1861,7 @@ static void _destroy_id(struct rdma_id_private *id_priv,
                                iw_destroy_cm_id(id_priv->cm_id.iw);
                }
                cma_leave_mc_groups(id_priv);
+               rdma_restrack_del(&id_priv->res);
                cma_release_dev(id_priv);
        }
 
@@ -1873,7 +1875,6 @@ static void _destroy_id(struct rdma_id_private *id_priv,
        kfree(id_priv->id.route.path_rec);
 
        put_net(id_priv->id.route.addr.dev_addr.net);
-       rdma_restrack_del(&id_priv->res);
        kfree(id_priv);
 }
 
@@ -3774,7 +3775,7 @@ int rdma_listen(struct rdma_cm_id *id, int backlog)
        }
 
        id_priv->backlog = backlog;
-       if (id->device) {
+       if (id_priv->cma_dev) {
                if (rdma_cap_ib_cm(id->device, 1)) {
                        ret = cma_ib_listen(id_priv);
                        if (ret)
index 9ec6971056fa853db1dad103986de213d5544047..049684880ae03df75a47c4bc9d49f8ca78ed6dd8 100644 (file)
@@ -117,8 +117,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_INFO_HANDLES)(
                return ret;
 
        uapi_object = uapi_get_object(attrs->ufile->device->uapi, object_id);
-       if (!uapi_object)
-               return -EINVAL;
+       if (IS_ERR(uapi_object))
+               return PTR_ERR(uapi_object);
 
        handles = gather_objects_handle(attrs->ufile, uapi_object, attrs,
                                        out_len, &total);
@@ -331,6 +331,9 @@ static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_GID_TABLE)(
        if (ret)
                return ret;
 
+       if (!user_entry_size)
+               return -EINVAL;
+
        max_entries = uverbs_attr_ptr_get_array_size(
                attrs, UVERBS_ATTR_QUERY_GID_TABLE_RESP_ENTRIES,
                user_entry_size);
index a0b677accd96516cc748084fb630606711ea7e93..eb9b0a2707f800a33719e4f5ab80c80cf715343a 100644 (file)
@@ -630,9 +630,8 @@ static bool devx_is_valid_obj_id(struct uverbs_attr_bundle *attrs,
        case UVERBS_OBJECT_QP:
        {
                struct mlx5_ib_qp *qp = to_mqp(uobj->object);
-               enum ib_qp_type qp_type = qp->ibqp.qp_type;
 
-               if (qp_type == IB_QPT_RAW_PACKET ||
+               if (qp->type == IB_QPT_RAW_PACKET ||
                    (qp->flags & IB_QP_CREATE_SOURCE_QPN)) {
                        struct mlx5_ib_raw_packet_qp *raw_packet_qp =
                                                         &qp->raw_packet_qp;
@@ -649,10 +648,9 @@ static bool devx_is_valid_obj_id(struct uverbs_attr_bundle *attrs,
                                               sq->tisn) == obj_id);
                }
 
-               if (qp_type == MLX5_IB_QPT_DCT)
+               if (qp->type == MLX5_IB_QPT_DCT)
                        return get_enc_obj_id(MLX5_CMD_OP_CREATE_DCT,
                                              qp->dct.mdct.mqp.qpn) == obj_id;
-
                return get_enc_obj_id(MLX5_CMD_OP_CREATE_QP,
                                      qp->ibqp.qp_num) == obj_id;
        }
index 094bf85589db501596cc58571af6e155d950fc62..001d766cf291c711361fd690deb6565dc0bfa893 100644 (file)
@@ -217,6 +217,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DM_MAP_OP_ADDR)(
        if (err)
                return err;
 
+       if (op >= BITS_PER_TYPE(u32))
+               return -EOPNOTSUPP;
+
        if (!(MLX5_CAP_DEV_MEM(dev->mdev, memic_operations) & BIT(op)))
                return -EOPNOTSUPP;
 
index 6d1dd09a4388177be9a0fedae2c89d026ace1be4..644d5d0ac54428728a3d05c21b3af9c9ca17f543 100644 (file)
@@ -4419,6 +4419,7 @@ static int mlx5r_mp_probe(struct auxiliary_device *adev,
 
                if (bound) {
                        rdma_roce_rescan_device(&dev->ib_dev);
+                       mpi->ibdev->ib_active = true;
                        break;
                }
        }
index 4388afeff2512be8513779ef4126ecb74be9ab43..9662cd39c7ffcb2a1b6087bb443b0323dfbd26cf 100644 (file)
@@ -743,10 +743,10 @@ int mlx5_mr_cache_init(struct mlx5_ib_dev *dev)
                ent->xlt = (1 << ent->order) * sizeof(struct mlx5_mtt) /
                           MLX5_IB_UMR_OCTOWORD;
                ent->access_mode = MLX5_MKC_ACCESS_MODE_MTT;
-               if ((dev->mdev->profile->mask & MLX5_PROF_MASK_MR_CACHE) &&
+               if ((dev->mdev->profile.mask & MLX5_PROF_MASK_MR_CACHE) &&
                    !dev->is_rep && mlx5_core_is_pf(dev->mdev) &&
                    mlx5_ib_can_load_pas_with_umr(dev, 0))
-                       ent->limit = dev->mdev->profile->mr_cache[i].limit;
+                       ent->limit = dev->mdev->profile.mr_cache[i].limit;
                else
                        ent->limit = 0;
                spin_lock_irq(&ent->lock);
index 2af26737d32dc80b12f117c069f3e826969bc012..a6712e373eed633cdddf0a993f57e45e521a6f06 100644 (file)
@@ -346,13 +346,15 @@ static inline enum comp_state do_read(struct rxe_qp *qp,
        ret = copy_data(qp->pd, IB_ACCESS_LOCAL_WRITE,
                        &wqe->dma, payload_addr(pkt),
                        payload_size(pkt), to_mr_obj, NULL);
-       if (ret)
+       if (ret) {
+               wqe->status = IB_WC_LOC_PROT_ERR;
                return COMPST_ERROR;
+       }
 
        if (wqe->dma.resid == 0 && (pkt->mask & RXE_END_MASK))
                return COMPST_COMP_ACK;
-       else
-               return COMPST_UPDATE_COMP;
+
+       return COMPST_UPDATE_COMP;
 }
 
 static inline enum comp_state do_atomic(struct rxe_qp *qp,
@@ -366,10 +368,12 @@ static inline enum comp_state do_atomic(struct rxe_qp *qp,
        ret = copy_data(qp->pd, IB_ACCESS_LOCAL_WRITE,
                        &wqe->dma, &atomic_orig,
                        sizeof(u64), to_mr_obj, NULL);
-       if (ret)
+       if (ret) {
+               wqe->status = IB_WC_LOC_PROT_ERR;
                return COMPST_ERROR;
-       else
-               return COMPST_COMP_ACK;
+       }
+
+       return COMPST_COMP_ACK;
 }
 
 static void make_send_cqe(struct rxe_qp *qp, struct rxe_send_wqe *wqe,
index 34ae957a315ca91ebcf240244d3b639b540fb416..b0f350d674fdbf79d0ab487afc04ec49087de382 100644 (file)
@@ -242,6 +242,7 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp,
        if (err) {
                vfree(qp->sq.queue->buf);
                kfree(qp->sq.queue);
+               qp->sq.queue = NULL;
                return err;
        }
 
@@ -295,6 +296,7 @@ static int rxe_qp_init_resp(struct rxe_dev *rxe, struct rxe_qp *qp,
                if (err) {
                        vfree(qp->rq.queue->buf);
                        kfree(qp->rq.queue);
+                       qp->rq.queue = NULL;
                        return err;
                }
        }
@@ -355,6 +357,11 @@ int rxe_qp_from_init(struct rxe_dev *rxe, struct rxe_qp *qp, struct rxe_pd *pd,
 err2:
        rxe_queue_cleanup(qp->sq.queue);
 err1:
+       qp->pd = NULL;
+       qp->rcq = NULL;
+       qp->scq = NULL;
+       qp->srq = NULL;
+
        if (srq)
                rxe_drop_ref(srq);
        rxe_drop_ref(scq);
index d2313efb26db833e4307683a3a8ca910254de635..3f175f220a2299bc74e025b6fbcf73729357f5a3 100644 (file)
@@ -300,7 +300,6 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
        struct siw_ucontext *uctx =
                rdma_udata_to_drv_context(udata, struct siw_ucontext,
                                          base_ucontext);
-       struct siw_cq *scq = NULL, *rcq = NULL;
        unsigned long flags;
        int num_sqe, num_rqe, rv = 0;
        size_t length;
@@ -343,10 +342,8 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
                rv = -EINVAL;
                goto err_out;
        }
-       scq = to_siw_cq(attrs->send_cq);
-       rcq = to_siw_cq(attrs->recv_cq);
 
-       if (!scq || (!rcq && !attrs->srq)) {
+       if (!attrs->send_cq || (!attrs->recv_cq && !attrs->srq)) {
                siw_dbg(base_dev, "send CQ or receive CQ invalid\n");
                rv = -EINVAL;
                goto err_out;
@@ -378,7 +375,7 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
        else {
                /* Zero sized SQ is not supported */
                rv = -EINVAL;
-               goto err_out;
+               goto err_out_xa;
        }
        if (num_rqe)
                num_rqe = roundup_pow_of_two(num_rqe);
@@ -401,8 +398,8 @@ struct ib_qp *siw_create_qp(struct ib_pd *pd,
                }
        }
        qp->pd = pd;
-       qp->scq = scq;
-       qp->rcq = rcq;
+       qp->scq = to_siw_cq(attrs->send_cq);
+       qp->rcq = to_siw_cq(attrs->recv_cq);
 
        if (attrs->srq) {
                /*
index d1591a28b74388cbfb5e9df0bbaae65727425139..8f385f9c2dd382e18f3ce17ae2a66b4f83c8e68b 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (c) 2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved.
  */
 
 #include <asm/div64.h>
@@ -205,6 +205,7 @@ struct bcm_voter *of_bcm_voter_get(struct device *dev, const char *name)
        }
        mutex_unlock(&bcm_voter_lock);
 
+       of_node_put(node);
        return voter;
 }
 EXPORT_SYMBOL_GPL(of_bcm_voter_get);
@@ -362,6 +363,7 @@ static const struct of_device_id bcm_voter_of_match[] = {
        { .compatible = "qcom,bcm-voter" },
        { }
 };
+MODULE_DEVICE_TABLE(of, bcm_voter_of_match);
 
 static struct platform_driver qcom_icc_bcm_voter_driver = {
        .probe = qcom_icc_bcm_voter_probe,
index 80e8e1916dd17c9c3ef2b46841103830d2ff95b6..3ac42bbdefc634bed6c31eaf38efdc4142fd3184 100644 (file)
@@ -884,7 +884,7 @@ static inline u64 build_inv_address(u64 address, size_t size)
                 * The msb-bit must be clear on the address. Just set all the
                 * lower bits.
                 */
-               address |= 1ull << (msb_diff - 1);
+               address |= (1ull << msb_diff) - 1;
        }
 
        /* Clear bits 11:0 */
@@ -1714,6 +1714,8 @@ static void amd_iommu_probe_finalize(struct device *dev)
        domain = iommu_get_domain_for_dev(dev);
        if (domain->type == IOMMU_DOMAIN_DMA)
                iommu_setup_dma_ops(dev, IOVA_START_PFN << PAGE_SHIFT, 0);
+       else
+               set_dma_ops(dev, NULL);
 }
 
 static void amd_iommu_release_device(struct device *dev)
index 1757ac1e1623e9aef3583d7a8ae819fd2baa968c..84057cb9596cb2a62acfeecc52839e198aee50d0 100644 (file)
@@ -1142,7 +1142,7 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
 
                err = iommu_device_register(&iommu->iommu, &intel_iommu_ops, NULL);
                if (err)
-                       goto err_unmap;
+                       goto err_sysfs;
        }
 
        drhd->iommu = iommu;
@@ -1150,6 +1150,8 @@ static int alloc_iommu(struct dmar_drhd_unit *drhd)
 
        return 0;
 
+err_sysfs:
+       iommu_device_sysfs_remove(&iommu->iommu);
 err_unmap:
        unmap_iommu(iommu);
 error_free_seq_id:
index 708f430af1c4403662245c08530dbab79c83f078..be35284a201600a9bf924204e735361bf75cf515 100644 (file)
@@ -2525,9 +2525,9 @@ static int domain_setup_first_level(struct intel_iommu *iommu,
                                    struct device *dev,
                                    u32 pasid)
 {
-       int flags = PASID_FLAG_SUPERVISOR_MODE;
        struct dma_pte *pgd = domain->pgd;
        int agaw, level;
+       int flags = 0;
 
        /*
         * Skip top levels of page tables for iommu which has
@@ -2543,7 +2543,10 @@ static int domain_setup_first_level(struct intel_iommu *iommu,
        if (level != 4 && level != 5)
                return -EINVAL;
 
-       flags |= (level == 5) ? PASID_FLAG_FL5LP : 0;
+       if (pasid != PASID_RID2PASID)
+               flags |= PASID_FLAG_SUPERVISOR_MODE;
+       if (level == 5)
+               flags |= PASID_FLAG_FL5LP;
 
        if (domain->domain.type == IOMMU_DOMAIN_UNMANAGED)
                flags |= PASID_FLAG_PAGE_SNOOP;
@@ -4606,6 +4609,8 @@ static int auxiliary_link_device(struct dmar_domain *domain,
 
        if (!sinfo) {
                sinfo = kzalloc(sizeof(*sinfo), GFP_ATOMIC);
+               if (!sinfo)
+                       return -ENOMEM;
                sinfo->domain = domain;
                sinfo->pdev = dev;
                list_add(&sinfo->link_phys, &info->subdevices);
index 72646bafc52f418bb39fe60800d05f1b992cb40d..72dc84821dad2de15f56c0ea26c222afb7b338a5 100644 (file)
@@ -699,7 +699,8 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
         * Since it is a second level only translation setup, we should
         * set SRE bit as well (addresses are expected to be GPAs).
         */
-       pasid_set_sre(pte);
+       if (pasid != PASID_RID2PASID)
+               pasid_set_sre(pte);
        pasid_set_present(pte);
        pasid_flush_caches(iommu, pte, pasid, did);
 
index 7c02481a81b4e9ebd6ed3cd1c3e271b22e0d35d2..c6e5ee4d9cef83e81b0896d0811c673d3be09b89 100644 (file)
@@ -1136,6 +1136,7 @@ static struct virtio_device_id id_table[] = {
        { VIRTIO_ID_IOMMU, VIRTIO_DEV_ANY_ID },
        { 0 },
 };
+MODULE_DEVICE_TABLE(virtio, id_table);
 
 static struct virtio_driver virtio_iommu_drv = {
        .driver.name            = KBUILD_MODNAME,
index b90e825df7e1470f125fab3760b025473b01e9b9..62543a4eccc086c989a6045d331c60d85b8903a7 100644 (file)
@@ -596,7 +596,7 @@ config IRQ_IDT3243X
 config APPLE_AIC
        bool "Apple Interrupt Controller (AIC)"
        depends on ARM64
-       default ARCH_APPLE
+       depends on ARCH_APPLE || COMPILE_TEST
        help
          Support for the Apple Interrupt Controller found on Apple Silicon SoCs,
          such as the M1.
index c179e27062fd52baffb2edca3bac25bd2e2ab349..b8c06bd8659e91c1b119b68efd4a0ad7f0b837e9 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/cpuhotplug.h>
 #include <linux/io.h>
 #include <linux/irqchip.h>
+#include <linux/irqchip/arm-vgic-info.h>
 #include <linux/irqdomain.h>
 #include <linux/limits.h>
 #include <linux/of_address.h>
@@ -787,6 +788,12 @@ static int aic_init_cpu(unsigned int cpu)
        return 0;
 }
 
+static struct gic_kvm_info vgic_info __initdata = {
+       .type                   = GIC_V3,
+       .no_maint_irq_mask      = true,
+       .no_hw_deactivation     = true,
+};
+
 static int __init aic_of_ic_init(struct device_node *node, struct device_node *parent)
 {
        int i;
@@ -843,6 +850,8 @@ static int __init aic_of_ic_init(struct device_node *node, struct device_node *p
                          "irqchip/apple-aic/ipi:starting",
                          aic_init_cpu, NULL);
 
+       vgic_set_kvm_info(&vgic_info);
+
        pr_info("Initialized with %d IRQs, %d FIQs, %d vIPIs\n",
                irqc->nr_hw, AIC_NR_FIQ, AIC_NR_SWIPI);
 
index f47b41dfd0238c64e93ce39c179cab5b541047b8..a610821c8ff2af1e8485046480b047c6d3538a27 100644 (file)
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
 
-static const struct gic_kvm_info *gic_kvm_info;
-
-const struct gic_kvm_info *gic_get_kvm_info(void)
-{
-       return gic_kvm_info;
-}
-
-void gic_set_kvm_info(const struct gic_kvm_info *info)
-{
-       BUG_ON(gic_kvm_info != NULL);
-       gic_kvm_info = info;
-}
-
 void gic_enable_of_quirks(const struct device_node *np,
                          const struct gic_quirk *quirks, void *data)
 {
index ccba8b0fe0f582696f98c36f18d9c02b99d85e0e..27e3d4ed4f32861a4c46eebcc4634eb835a8e45b 100644 (file)
@@ -28,6 +28,4 @@ void gic_enable_quirks(u32 iidr, const struct gic_quirk *quirks,
 void gic_enable_of_quirks(const struct device_node *np,
                          const struct gic_quirk *quirks, void *data);
 
-void gic_set_kvm_info(const struct gic_kvm_info *info);
-
 #endif /* _IRQ_GIC_COMMON_H */
index 37a23aa6de37c13f5dbb2ea1bbec185bcc49e530..453fc425eede2afd7008d471ce0634692202b1e1 100644 (file)
@@ -103,7 +103,7 @@ EXPORT_SYMBOL(gic_nonsecure_priorities);
 /* ppi_nmi_refs[n] == number of cpus having ppi[n + 16] set as NMI */
 static refcount_t *ppi_nmi_refs;
 
-static struct gic_kvm_info gic_v3_kvm_info;
+static struct gic_kvm_info gic_v3_kvm_info __initdata;
 static DEFINE_PER_CPU(bool, has_rss);
 
 #define MPIDR_RS(mpidr)                        (((mpidr) & 0xF0UL) >> 4)
@@ -1852,7 +1852,7 @@ static void __init gic_of_setup_kvm_info(struct device_node *node)
 
        gic_v3_kvm_info.has_v4 = gic_data.rdists.has_vlpis;
        gic_v3_kvm_info.has_v4_1 = gic_data.rdists.has_rvpeid;
-       gic_set_kvm_info(&gic_v3_kvm_info);
+       vgic_set_kvm_info(&gic_v3_kvm_info);
 }
 
 static int __init gic_of_init(struct device_node *node, struct device_node *parent)
@@ -2168,7 +2168,7 @@ static void __init gic_acpi_setup_kvm_info(void)
 
        gic_v3_kvm_info.has_v4 = gic_data.rdists.has_vlpis;
        gic_v3_kvm_info.has_v4_1 = gic_data.rdists.has_rvpeid;
-       gic_set_kvm_info(&gic_v3_kvm_info);
+       vgic_set_kvm_info(&gic_v3_kvm_info);
 }
 
 static int __init
index b1d9c22caf2e6ba0040dd9b438ccae6477fbb8df..2de9ec8ece0c29c0ab7d609c4b9d265a5d37e247 100644 (file)
@@ -119,7 +119,7 @@ static DEFINE_STATIC_KEY_TRUE(supports_deactivate_key);
 
 static struct gic_chip_data gic_data[CONFIG_ARM_GIC_MAX_NR] __read_mostly;
 
-static struct gic_kvm_info gic_v2_kvm_info;
+static struct gic_kvm_info gic_v2_kvm_info __initdata;
 
 static DEFINE_PER_CPU(u32, sgi_intid);
 
@@ -1451,7 +1451,7 @@ static void __init gic_of_setup_kvm_info(struct device_node *node)
                return;
 
        if (static_branch_likely(&supports_deactivate_key))
-               gic_set_kvm_info(&gic_v2_kvm_info);
+               vgic_set_kvm_info(&gic_v2_kvm_info);
 }
 
 int __init
@@ -1618,7 +1618,7 @@ static void __init gic_acpi_setup_kvm_info(void)
 
        gic_v2_kvm_info.maint_irq = irq;
 
-       gic_set_kvm_info(&gic_v2_kvm_info);
+       vgic_set_kvm_info(&gic_v2_kvm_info);
 }
 
 static int __init gic_v2_acpi_init(union acpi_subtable_headers *header,
index 91adf771f1859737157af823d231669e99b7f97b..090bc3f4f7d883d226d25d5e7e45e2da9fff1bf1 100644 (file)
@@ -359,10 +359,8 @@ static int mvebu_icu_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        icu->base = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(icu->base)) {
-               dev_err(&pdev->dev, "Failed to map icu base address.\n");
+       if (IS_ERR(icu->base))
                return PTR_ERR(icu->base);
-       }
 
        /*
         * Legacy bindings: ICU is one node with one MSI parent: force manually
index 18832ccc8ff8751d2562f56e53466b6b5e5b84fb..3a7b7a7f20ca7a4223888bab5ae6392f9b3b45d4 100644 (file)
@@ -384,10 +384,8 @@ static int mvebu_sei_probe(struct platform_device *pdev)
 
        sei->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        sei->base = devm_ioremap_resource(sei->dev, sei->res);
-       if (IS_ERR(sei->base)) {
-               dev_err(sei->dev, "Failed to remap SEI resource\n");
+       if (IS_ERR(sei->base))
                return PTR_ERR(sei->base);
-       }
 
        /* Retrieve the SEI capabilities with the interrupt ranges */
        sei->caps = of_device_get_match_data(&pdev->dev);
index b9db90c4aa566f186622fe05b50c07b8bbc5e986..4704f2ee5797a1de2e13a1442b0618f6438eb817 100644 (file)
@@ -892,10 +892,8 @@ static int stm32_exti_probe(struct platform_device *pdev)
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        host_data->base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(host_data->base)) {
-               dev_err(dev, "Unable to map registers\n");
+       if (IS_ERR(host_data->base))
                return PTR_ERR(host_data->base);
-       }
 
        for (i = 0; i < drv_data->bank_nr; i++)
                stm32_exti_chip_init(host_data, i, np);
index 70061991915a5833acd33d6354ba08e60177ee20..cd5642cef01fd667b2bba54262aec4e5de5017ea 100644 (file)
@@ -46,7 +46,7 @@ static void hfcsusb_start_endpoint(struct hfcsusb *hw, int channel);
 static void hfcsusb_stop_endpoint(struct hfcsusb *hw, int channel);
 static int  hfcsusb_setup_bch(struct bchannel *bch, int protocol);
 static void deactivate_bchannel(struct bchannel *bch);
-static void hfcsusb_ph_info(struct hfcsusb *hw);
+static int  hfcsusb_ph_info(struct hfcsusb *hw);
 
 /* start next background transfer for control channel */
 static void
@@ -241,7 +241,7 @@ hfcusb_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb)
  * send full D/B channel status information
  * as MPH_INFORMATION_IND
  */
-static void
+static int
 hfcsusb_ph_info(struct hfcsusb *hw)
 {
        struct ph_info *phi;
@@ -250,7 +250,7 @@ hfcsusb_ph_info(struct hfcsusb *hw)
 
        phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
        if (!phi)
-               return;
+               return -ENOMEM;
 
        phi->dch.ch.protocol = hw->protocol;
        phi->dch.ch.Flags = dch->Flags;
@@ -263,6 +263,8 @@ hfcsusb_ph_info(struct hfcsusb *hw)
        _queue_data(&dch->dev.D, MPH_INFORMATION_IND, MISDN_ID_ANY,
                    struct_size(phi, bch, dch->dev.nrbchan), phi, GFP_ATOMIC);
        kfree(phi);
+
+       return 0;
 }
 
 /*
@@ -347,8 +349,7 @@ hfcusb_l2l1D(struct mISDNchannel *ch, struct sk_buff *skb)
                        ret = l1_event(dch->l1, hh->prim);
                break;
        case MPH_INFORMATION_REQ:
-               hfcsusb_ph_info(hw);
-               ret = 0;
+               ret = hfcsusb_ph_info(hw);
                break;
        }
 
@@ -403,8 +404,7 @@ hfc_l1callback(struct dchannel *dch, u_int cmd)
                               hw->name, __func__, cmd);
                return -1;
        }
-       hfcsusb_ph_info(hw);
-       return 0;
+       return hfcsusb_ph_info(hw);
 }
 
 static int
@@ -746,8 +746,7 @@ hfcsusb_setup_bch(struct bchannel *bch, int protocol)
                        handle_led(hw, (bch->nr == 1) ? LED_B1_OFF :
                                   LED_B2_OFF);
        }
-       hfcsusb_ph_info(hw);
-       return 0;
+       return hfcsusb_ph_info(hw);
 }
 
 static void
index a16c7a2a7f3d0d22bf03713a58640db143440a25..88d592bafdb0279635e2ac9ae57798b715282614 100644 (file)
@@ -630,17 +630,19 @@ static void
 release_io(struct inf_hw *hw)
 {
        if (hw->cfg.mode) {
-               if (hw->cfg.p) {
+               if (hw->cfg.mode == AM_MEMIO) {
                        release_mem_region(hw->cfg.start, hw->cfg.size);
-                       iounmap(hw->cfg.p);
+                       if (hw->cfg.p)
+                               iounmap(hw->cfg.p);
                } else
                        release_region(hw->cfg.start, hw->cfg.size);
                hw->cfg.mode = AM_NONE;
        }
        if (hw->addr.mode) {
-               if (hw->addr.p) {
+               if (hw->addr.mode == AM_MEMIO) {
                        release_mem_region(hw->addr.start, hw->addr.size);
-                       iounmap(hw->addr.p);
+                       if (hw->addr.p)
+                               iounmap(hw->addr.p);
                } else
                        release_region(hw->addr.start, hw->addr.size);
                hw->addr.mode = AM_NONE;
@@ -670,9 +672,12 @@ setup_io(struct inf_hw *hw)
                                (ulong)hw->cfg.start, (ulong)hw->cfg.size);
                        return err;
                }
-               if (hw->ci->cfg_mode == AM_MEMIO)
-                       hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
                hw->cfg.mode = hw->ci->cfg_mode;
+               if (hw->ci->cfg_mode == AM_MEMIO) {
+                       hw->cfg.p = ioremap(hw->cfg.start, hw->cfg.size);
+                       if (!hw->cfg.p)
+                               return -ENOMEM;
+               }
                if (debug & DEBUG_HW)
                        pr_notice("%s: IO cfg %lx (%lu bytes) mode%d\n",
                                  hw->name, (ulong)hw->cfg.start,
@@ -697,12 +702,12 @@ setup_io(struct inf_hw *hw)
                                (ulong)hw->addr.start, (ulong)hw->addr.size);
                        return err;
                }
+               hw->addr.mode = hw->ci->addr_mode;
                if (hw->ci->addr_mode == AM_MEMIO) {
                        hw->addr.p = ioremap(hw->addr.start, hw->addr.size);
-                       if (unlikely(!hw->addr.p))
+                       if (!hw->addr.p)
                                return -ENOMEM;
                }
-               hw->addr.mode = hw->ci->addr_mode;
                if (debug & DEBUG_HW)
                        pr_notice("%s: IO addr %lx (%lu bytes) mode%d\n",
                                  hw->name, (ulong)hw->addr.start,
index ee925b58bbcea7ab0a411069cc5b394f3b276165..2a1ddd47a0968da8db09c9800b5219547ca5e43f 100644 (file)
@@ -1100,7 +1100,6 @@ nj_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                card->typ = NETJET_S_TJ300;
 
        card->base = pci_resource_start(pdev, 0);
-       card->irq = pdev->irq;
        pci_set_drvdata(pdev, card);
        err = setup_instance(card);
        if (err)
index fc433e63b1dc0319966fb52493f9c6d99d218368..b1590cb4a188783b0595d9c713357ac8cf12fccb 100644 (file)
@@ -307,7 +307,7 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
        usleep_range(3000, 6000);
        ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
        if (ret)
-               return ret;
+               goto out;
        status &= LP5523_ENG_STATUS_MASK;
 
        if (status != LP5523_ENG_STATUS_MASK) {
index 781942aeddd153f4ec3591194be9a143712783a6..20f2510db1f673ba9104222b85163df57ca7c7ad 100644 (file)
@@ -66,14 +66,14 @@ struct superblock {
        __u8 magic[8];
        __u8 version;
        __u8 log2_interleave_sectors;
-       __u16 integrity_tag_size;
-       __u32 journal_sections;
-       __u64 provided_data_sectors;    /* userspace uses this value */
-       __u32 flags;
+       __le16 integrity_tag_size;
+       __le32 journal_sections;
+       __le64 provided_data_sectors;   /* userspace uses this value */
+       __le32 flags;
        __u8 log2_sectors_per_block;
        __u8 log2_blocks_per_bitmap_bit;
        __u8 pad[2];
-       __u64 recalc_sector;
+       __le64 recalc_sector;
        __u8 pad2[8];
        __u8 salt[SALT_SIZE];
 };
@@ -86,16 +86,16 @@ struct superblock {
 
 #define        JOURNAL_ENTRY_ROUNDUP           8
 
-typedef __u64 commit_id_t;
+typedef __le64 commit_id_t;
 #define JOURNAL_MAC_PER_SECTOR         8
 
 struct journal_entry {
        union {
                struct {
-                       __u32 sector_lo;
-                       __u32 sector_hi;
+                       __le32 sector_lo;
+                       __le32 sector_hi;
                } s;
-               __u64 sector;
+               __le64 sector;
        } u;
        commit_id_t last_bytes[];
        /* __u8 tag[0]; */
@@ -806,7 +806,7 @@ static void section_mac(struct dm_integrity_c *ic, unsigned section, __u8 result
        }
 
        if (ic->sb->flags & cpu_to_le32(SB_FLAG_FIXED_HMAC)) {
-               uint64_t section_le;
+               __le64 section_le;
 
                r = crypto_shash_update(desc, (__u8 *)&ic->sb->salt, SALT_SIZE);
                if (unlikely(r < 0)) {
@@ -1640,7 +1640,7 @@ static void integrity_end_io(struct bio *bio)
 static void integrity_sector_checksum(struct dm_integrity_c *ic, sector_t sector,
                                      const char *data, char *result)
 {
-       __u64 sector_le = cpu_to_le64(sector);
+       __le64 sector_le = cpu_to_le64(sector);
        SHASH_DESC_ON_STACK(req, ic->internal_hash);
        int r;
        unsigned digest_size;
@@ -2689,30 +2689,26 @@ next_chunk:
        if (unlikely(dm_integrity_failed(ic)))
                goto err;
 
-       if (!ic->discard) {
-               io_req.bi_op = REQ_OP_READ;
-               io_req.bi_op_flags = 0;
-               io_req.mem.type = DM_IO_VMA;
-               io_req.mem.ptr.addr = ic->recalc_buffer;
-               io_req.notify.fn = NULL;
-               io_req.client = ic->io;
-               io_loc.bdev = ic->dev->bdev;
-               io_loc.sector = get_data_sector(ic, area, offset);
-               io_loc.count = n_sectors;
+       io_req.bi_op = REQ_OP_READ;
+       io_req.bi_op_flags = 0;
+       io_req.mem.type = DM_IO_VMA;
+       io_req.mem.ptr.addr = ic->recalc_buffer;
+       io_req.notify.fn = NULL;
+       io_req.client = ic->io;
+       io_loc.bdev = ic->dev->bdev;
+       io_loc.sector = get_data_sector(ic, area, offset);
+       io_loc.count = n_sectors;
 
-               r = dm_io(&io_req, 1, &io_loc, NULL);
-               if (unlikely(r)) {
-                       dm_integrity_io_error(ic, "reading data", r);
-                       goto err;
-               }
+       r = dm_io(&io_req, 1, &io_loc, NULL);
+       if (unlikely(r)) {
+               dm_integrity_io_error(ic, "reading data", r);
+               goto err;
+       }
 
-               t = ic->recalc_tags;
-               for (i = 0; i < n_sectors; i += ic->sectors_per_block) {
-                       integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t);
-                       t += ic->tag_size;
-               }
-       } else {
-               t = ic->recalc_tags + (n_sectors >> ic->sb->log2_sectors_per_block) * ic->tag_size;
+       t = ic->recalc_tags;
+       for (i = 0; i < n_sectors; i += ic->sectors_per_block) {
+               integrity_sector_checksum(ic, logical_sector + i, ic->recalc_buffer + (i << SECTOR_SHIFT), t);
+               t += ic->tag_size;
        }
 
        metadata_block = get_metadata_sector_and_offset(ic, area, offset, &metadata_offset);
@@ -3826,7 +3822,7 @@ static int create_journal(struct dm_integrity_c *ic, char **error)
                        for (i = 0; i < ic->journal_sections; i++) {
                                struct scatterlist sg;
                                struct skcipher_request *section_req;
-                               __u32 section_le = cpu_to_le32(i);
+                               __le32 section_le = cpu_to_le32(i);
 
                                memset(crypt_iv, 0x00, ivsize);
                                memset(crypt_data, 0x00, crypt_len);
@@ -4368,13 +4364,11 @@ try_smaller_buffer:
                        goto bad;
                }
                INIT_WORK(&ic->recalc_work, integrity_recalc);
-               if (!ic->discard) {
-                       ic->recalc_buffer = vmalloc(RECALC_SECTORS << SECTOR_SHIFT);
-                       if (!ic->recalc_buffer) {
-                               ti->error = "Cannot allocate buffer for recalculating";
-                               r = -ENOMEM;
-                               goto bad;
-                       }
+               ic->recalc_buffer = vmalloc(RECALC_SECTORS << SECTOR_SHIFT);
+               if (!ic->recalc_buffer) {
+                       ti->error = "Cannot allocate buffer for recalculating";
+                       r = -ENOMEM;
+                       goto bad;
                }
                ic->recalc_tags = kvmalloc_array(RECALC_SECTORS >> ic->sb->log2_sectors_per_block,
                                                 ic->tag_size, GFP_KERNEL);
@@ -4383,9 +4377,6 @@ try_smaller_buffer:
                        r = -ENOMEM;
                        goto bad;
                }
-               if (ic->discard)
-                       memset(ic->recalc_tags, DISCARD_FILLER,
-                              (RECALC_SECTORS >> ic->sb->log2_sectors_per_block) * ic->tag_size);
        } else {
                if (ic->sb->flags & cpu_to_le32(SB_FLAG_RECALCULATING)) {
                        ti->error = "Recalculate can only be specified with internal_hash";
@@ -4579,7 +4570,7 @@ static void dm_integrity_dtr(struct dm_target *ti)
 
 static struct target_type integrity_target = {
        .name                   = "integrity",
-       .version                = {1, 9, 0},
+       .version                = {1, 10, 0},
        .module                 = THIS_MODULE,
        .features               = DM_TARGET_SINGLETON | DM_TARGET_INTEGRITY,
        .ctr                    = dm_integrity_ctr,
index a2acb014c13ae45b7394545a57645d729bdbc764..751ec5ea1dbb5fcfaf23a28ad171a13b0f44ee92 100644 (file)
@@ -855,7 +855,7 @@ static int dm_add_exception(void *context, chunk_t old, chunk_t new)
 static uint32_t __minimum_chunk_size(struct origin *o)
 {
        struct dm_snapshot *snap;
-       unsigned chunk_size = 0;
+       unsigned chunk_size = rounddown_pow_of_two(UINT_MAX);
 
        if (o)
                list_for_each_entry(snap, &o->snapshots, list)
@@ -1409,6 +1409,7 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
 
        if (!s->store->chunk_size) {
                ti->error = "Chunk size not set";
+               r = -EINVAL;
                goto bad_read_metadata;
        }
 
index 29385dc470d5d9509c41a127ea0e4478017a6cac..db61a1f43ae91e3328c9b8bfc1bb83fd0a0012da 100644 (file)
@@ -15,7 +15,7 @@
 #define DM_VERITY_VERIFY_ERR(s) DM_VERITY_ROOT_HASH_VERIFICATION " " s
 
 static bool require_signatures;
-module_param(require_signatures, bool, false);
+module_param(require_signatures, bool, 0444);
 MODULE_PARM_DESC(require_signatures,
                "Verify the roothash of dm-verity hash tree");
 
index 841e1c1aa5e63aa51677794f0cf578fc9635b65d..7d4ff8a5c55e2f2196c88f77401444a6c8141448 100644 (file)
@@ -5311,8 +5311,6 @@ static int in_chunk_boundary(struct mddev *mddev, struct bio *bio)
        unsigned int chunk_sectors;
        unsigned int bio_sectors = bio_sectors(bio);
 
-       WARN_ON_ONCE(bio->bi_bdev->bd_partno);
-
        chunk_sectors = min(conf->chunk_sectors, conf->prev_chunk_sectors);
        return  chunk_sectors >=
                ((sector & (chunk_sectors - 1)) + bio_sectors);
index 655db8272268d56ef882393923515f8577bc3962..9767159aeb9b2f80ec5d307bb7ae74ea3ef5f2be 100644 (file)
@@ -281,7 +281,7 @@ static int sp8870_set_frontend_parameters(struct dvb_frontend *fe)
 
        // read status reg in order to clear pending irqs
        err = sp8870_readreg(state, 0x200);
-       if (err)
+       if (err < 0)
                return err;
 
        // system controller start
index 83bd9a412a560751a5d7e3418f07606df603030b..1e3b68a8743af1bcd8aaeeaf008d1ed8ded927ed 100644 (file)
@@ -915,7 +915,6 @@ static int rcar_drif_g_fmt_sdr_cap(struct file *file, void *priv,
 {
        struct rcar_drif_sdr *sdr = video_drvdata(file);
 
-       memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
        f->fmt.sdr.pixelformat = sdr->fmt->pixelformat;
        f->fmt.sdr.buffersize = sdr->fmt->buffersize;
 
index a4f7431486f317326cf4074e33a892f1f9ad017f..d93d384286c165856c2f76ab7e7a4cd632003b99 100644 (file)
@@ -1424,7 +1424,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
 {
        struct sd *sd = (struct sd *) gspca_dev;
        struct cam *cam;
-       int ret;
 
        sd->mainsFreq = FREQ_DEF == V4L2_CID_POWER_LINE_FREQUENCY_60HZ;
        reset_camera_params(gspca_dev);
@@ -1436,10 +1435,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
        cam->cam_mode = mode;
        cam->nmodes = ARRAY_SIZE(mode);
 
-       ret = goto_low_power(gspca_dev);
-       if (ret)
-               gspca_err(gspca_dev, "Cannot go to low power mode: %d\n",
-                         ret);
+       goto_low_power(gspca_dev);
        /* Check the firmware version. */
        sd->params.version.firmwareVersion = 0;
        get_version_information(gspca_dev);
index bfa3b381d8a26ee672715648a94d7a77b85e0d6c..bf1af6ed9131e914dd4f0debb37728dcae28052e 100644 (file)
@@ -195,7 +195,7 @@ static const struct v4l2_ctrl_config mt9m111_greenbal_cfg = {
 int mt9m111_probe(struct sd *sd)
 {
        u8 data[2] = {0x00, 0x00};
-       int i, rc = 0;
+       int i, err;
        struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
        if (force_sensor) {
@@ -213,18 +213,18 @@ int mt9m111_probe(struct sd *sd)
        /* Do the preinit */
        for (i = 0; i < ARRAY_SIZE(preinit_mt9m111); i++) {
                if (preinit_mt9m111[i][0] == BRIDGE) {
-                       rc |= m5602_write_bridge(sd,
-                               preinit_mt9m111[i][1],
-                               preinit_mt9m111[i][2]);
+                       err = m5602_write_bridge(sd,
+                                       preinit_mt9m111[i][1],
+                                       preinit_mt9m111[i][2]);
                } else {
                        data[0] = preinit_mt9m111[i][2];
                        data[1] = preinit_mt9m111[i][3];
-                       rc |= m5602_write_sensor(sd,
-                               preinit_mt9m111[i][1], data, 2);
+                       err = m5602_write_sensor(sd,
+                                       preinit_mt9m111[i][1], data, 2);
                }
+               if (err < 0)
+                       return err;
        }
-       if (rc < 0)
-               return rc;
 
        if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
                return -ENODEV;
index d680b777f097fd092a77e578ca272b8494516edb..8fd99ceee4b67e29133cc388ae37eb7ba2b6e25a 100644 (file)
@@ -154,8 +154,8 @@ static const struct v4l2_ctrl_config po1030_greenbal_cfg = {
 
 int po1030_probe(struct sd *sd)
 {
-       int rc = 0;
        u8 dev_id_h = 0, i;
+       int err;
        struct gspca_dev *gspca_dev = (struct gspca_dev *)sd;
 
        if (force_sensor) {
@@ -174,14 +174,14 @@ int po1030_probe(struct sd *sd)
        for (i = 0; i < ARRAY_SIZE(preinit_po1030); i++) {
                u8 data = preinit_po1030[i][2];
                if (preinit_po1030[i][0] == SENSOR)
-                       rc |= m5602_write_sensor(sd,
-                               preinit_po1030[i][1], &data, 1);
+                       err = m5602_write_sensor(sd, preinit_po1030[i][1],
+                                                &data, 1);
                else
-                       rc |= m5602_write_bridge(sd, preinit_po1030[i][1],
-                                               data);
+                       err = m5602_write_bridge(sd, preinit_po1030[i][1],
+                                                data);
+               if (err < 0)
+                       return err;
        }
-       if (rc < 0)
-               return rc;
 
        if (m5602_read_sensor(sd, PO1030_DEVID_H, &dev_id_h, 1))
                return -ENODEV;
index 926408b41270c2a62e6261e455510e5fdc76d219..7a6f01ace78ace991362a99abc45a4b4b741709f 100644 (file)
@@ -763,7 +763,8 @@ static int at24_probe(struct i2c_client *client)
        at24->nvmem = devm_nvmem_register(dev, &nvmem_config);
        if (IS_ERR(at24->nvmem)) {
                pm_runtime_disable(dev);
-               regulator_disable(at24->vcc_reg);
+               if (!pm_runtime_status_suspended(dev))
+                       regulator_disable(at24->vcc_reg);
                return PTR_ERR(at24->nvmem);
        }
 
@@ -774,7 +775,8 @@ static int at24_probe(struct i2c_client *client)
        err = at24_read(at24, 0, &test_byte, 1);
        if (err) {
                pm_runtime_disable(dev);
-               regulator_disable(at24->vcc_reg);
+               if (!pm_runtime_status_suspended(dev))
+                       regulator_disable(at24->vcc_reg);
                return -ENODEV;
        }
 
index ff8791a651fd1030b7091b709141f367771c2bd3..af3c497defb1053b334535dd0f958e3f2b71df92 100644 (file)
@@ -2017,7 +2017,7 @@ wait_again:
                if (completion_value >= target_value) {
                        *status = CS_WAIT_STATUS_COMPLETED;
                } else {
-                       timeout -= jiffies_to_usecs(completion_rc);
+                       timeout = completion_rc;
                        goto wait_again;
                }
        } else {
index 832dd5c5bb0653952e682f4cf5385c2abd4aa3c0..0713b2c12d54f4fded7b38bf79538c02e1f0fe1e 100644 (file)
@@ -362,12 +362,9 @@ static int fw_read_errors(struct hl_device *hdev, u32 boot_err0_reg,
        }
 
        if (err_val & CPU_BOOT_ERR0_SECURITY_NOT_RDY) {
-               dev_warn(hdev->dev,
+               dev_err(hdev->dev,
                        "Device boot warning - security not ready\n");
-               /* This is a warning so we don't want it to disable the
-                * device
-                */
-               err_val &= ~CPU_BOOT_ERR0_SECURITY_NOT_RDY;
+               err_exists = true;
        }
 
        if (err_val & CPU_BOOT_ERR0_SECURITY_FAIL) {
@@ -403,7 +400,8 @@ static int fw_read_errors(struct hl_device *hdev, u32 boot_err0_reg,
                err_exists = true;
        }
 
-       if (err_exists)
+       if (err_exists && ((err_val & ~CPU_BOOT_ERR0_ENABLED) &
+                               lower_32_bits(hdev->boot_error_status_mask)))
                return -EIO;
 
        return 0;
@@ -661,18 +659,13 @@ int hl_fw_cpucp_total_energy_get(struct hl_device *hdev, u64 *total_energy)
        return rc;
 }
 
-int get_used_pll_index(struct hl_device *hdev, enum pll_index input_pll_index,
+int get_used_pll_index(struct hl_device *hdev, u32 input_pll_index,
                                                enum pll_index *pll_index)
 {
        struct asic_fixed_properties *prop = &hdev->asic_prop;
        u8 pll_byte, pll_bit_off;
        bool dynamic_pll;
-
-       if (input_pll_index >= PLL_MAX) {
-               dev_err(hdev->dev, "PLL index %d is out of range\n",
-                                                       input_pll_index);
-               return -EINVAL;
-       }
+       int fw_pll_idx;
 
        dynamic_pll = prop->fw_security_status_valid &&
                (prop->fw_app_security_map & CPU_BOOT_DEV_STS0_DYN_PLL_EN);
@@ -680,28 +673,39 @@ int get_used_pll_index(struct hl_device *hdev, enum pll_index input_pll_index,
        if (!dynamic_pll) {
                /*
                 * in case we are working with legacy FW (each asic has unique
-                * PLL numbering) extract the legacy numbering
+                * PLL numbering) use the driver based index as they are
+                * aligned with fw legacy numbering
                 */
-               *pll_index = hdev->legacy_pll_map[input_pll_index];
+               *pll_index = input_pll_index;
                return 0;
        }
 
+       /* retrieve a FW compatible PLL index based on
+        * ASIC specific user request
+        */
+       fw_pll_idx = hdev->asic_funcs->map_pll_idx_to_fw_idx(input_pll_index);
+       if (fw_pll_idx < 0) {
+               dev_err(hdev->dev, "Invalid PLL index (%u) error %d\n",
+                       input_pll_index, fw_pll_idx);
+               return -EINVAL;
+       }
+
        /* PLL map is a u8 array */
-       pll_byte = prop->cpucp_info.pll_map[input_pll_index >> 3];
-       pll_bit_off = input_pll_index & 0x7;
+       pll_byte = prop->cpucp_info.pll_map[fw_pll_idx >> 3];
+       pll_bit_off = fw_pll_idx & 0x7;
 
        if (!(pll_byte & BIT(pll_bit_off))) {
                dev_err(hdev->dev, "PLL index %d is not supported\n",
-                                                       input_pll_index);
+                       fw_pll_idx);
                return -EINVAL;
        }
 
-       *pll_index = input_pll_index;
+       *pll_index = fw_pll_idx;
 
        return 0;
 }
 
-int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, enum pll_index pll_index,
+int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, u32 pll_index,
                u16 *pll_freq_arr)
 {
        struct cpucp_packet pkt;
@@ -844,8 +848,13 @@ int hl_fw_read_preboot_status(struct hl_device *hdev, u32 cpu_boot_status_reg,
        if (rc) {
                dev_err(hdev->dev, "Failed to read preboot version\n");
                detect_cpu_boot_status(hdev, status);
-               fw_read_errors(hdev, boot_err0_reg,
-                               cpu_security_boot_status_reg);
+
+               /* If we read all FF, then something is totally wrong, no point
+                * of reading specific errors
+                */
+               if (status != -1)
+                       fw_read_errors(hdev, boot_err0_reg,
+                                       cpu_security_boot_status_reg);
                return -EIO;
        }
 
index 44e89da30b4a70040488c2d838755b62275aa44f..6579f8767abdaccc6edee903449a44541b789815 100644 (file)
@@ -930,6 +930,9 @@ enum div_select_defs {
  *                         driver is ready to receive asynchronous events. This
  *                         function should be called during the first init and
  *                         after every hard-reset of the device
+ * @get_msi_info: Retrieve asic-specific MSI ID of the f/w async event
+ * @map_pll_idx_to_fw_idx: convert driver specific per asic PLL index to
+ *                         generic f/w compatible PLL Indexes
  */
 struct hl_asic_funcs {
        int (*early_init)(struct hl_device *hdev);
@@ -1054,6 +1057,7 @@ struct hl_asic_funcs {
                        u32 block_id, u32 block_size);
        void (*enable_events_from_fw)(struct hl_device *hdev);
        void (*get_msi_info)(u32 *table);
+       int (*map_pll_idx_to_fw_idx)(u32 pll_idx);
 };
 
 
@@ -1950,8 +1954,6 @@ struct hl_mmu_funcs {
  * @aggregated_cs_counters: aggregated cs counters among all contexts
  * @mmu_priv: device-specific MMU data.
  * @mmu_func: device-related MMU functions.
- * @legacy_pll_map: map holding map between dynamic (common) PLL indexes and
- *                  static (asic specific) PLL indexes.
  * @dram_used_mem: current DRAM memory consumption.
  * @timeout_jiffies: device CS timeout value.
  * @max_power: the max power of the device, as configured by the sysadmin. This
@@ -1960,6 +1962,12 @@ struct hl_mmu_funcs {
  * @clock_gating_mask: is clock gating enabled. bitmask that represents the
  *                     different engines. See debugfs-driver-habanalabs for
  *                     details.
+ * @boot_error_status_mask: contains a mask of the device boot error status.
+ *                          Each bit represents a different error, according to
+ *                          the defines in hl_boot_if.h. If the bit is cleared,
+ *                          the error will be ignored by the driver during
+ *                          device initialization. Mainly used to debug and
+ *                          workaround firmware bugs
  * @in_reset: is device in reset flow.
  * @curr_pll_profile: current PLL profile.
  * @card_type: Various ASICs have several card types. This indicates the card
@@ -2071,12 +2079,11 @@ struct hl_device {
        struct hl_mmu_priv              mmu_priv;
        struct hl_mmu_funcs             mmu_func[MMU_NUM_PGT_LOCATIONS];
 
-       enum pll_index                  *legacy_pll_map;
-
        atomic64_t                      dram_used_mem;
        u64                             timeout_jiffies;
        u64                             max_power;
        u64                             clock_gating_mask;
+       u64                             boot_error_status_mask;
        atomic_t                        in_reset;
        enum hl_pll_frequency           curr_pll_profile;
        enum cpucp_card_types           card_type;
@@ -2387,9 +2394,9 @@ int hl_fw_cpucp_pci_counters_get(struct hl_device *hdev,
                struct hl_info_pci_counters *counters);
 int hl_fw_cpucp_total_energy_get(struct hl_device *hdev,
                        u64 *total_energy);
-int get_used_pll_index(struct hl_device *hdev, enum pll_index input_pll_index,
+int get_used_pll_index(struct hl_device *hdev, u32 input_pll_index,
                                                enum pll_index *pll_index);
-int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, enum pll_index pll_index,
+int hl_fw_cpucp_pll_info_get(struct hl_device *hdev, u32 pll_index,
                u16 *pll_freq_arr);
 int hl_fw_cpucp_power_get(struct hl_device *hdev, u64 *power);
 int hl_fw_init_cpu(struct hl_device *hdev, u32 cpu_boot_status_reg,
@@ -2411,9 +2418,9 @@ int hl_pci_set_outbound_region(struct hl_device *hdev,
 int hl_pci_init(struct hl_device *hdev);
 void hl_pci_fini(struct hl_device *hdev);
 
-long hl_get_frequency(struct hl_device *hdev, enum pll_index pll_index,
+long hl_get_frequency(struct hl_device *hdev, u32 pll_index,
                                                                bool curr);
-void hl_set_frequency(struct hl_device *hdev, enum pll_index pll_index,
+void hl_set_frequency(struct hl_device *hdev, u32 pll_index,
                                                                u64 freq);
 int hl_get_temperature(struct hl_device *hdev,
                       int sensor_index, u32 attr, long *value);
index 7135f1e03864107b6bcdf8b6040f1f8ff15dfe3e..64d1530db9854501047da270e80f07f5bbb39f08 100644 (file)
@@ -30,6 +30,7 @@ static DEFINE_MUTEX(hl_devs_idr_lock);
 static int timeout_locked = 30;
 static int reset_on_lockup = 1;
 static int memory_scrub = 1;
+static ulong boot_error_status_mask = ULONG_MAX;
 
 module_param(timeout_locked, int, 0444);
 MODULE_PARM_DESC(timeout_locked,
@@ -43,6 +44,10 @@ module_param(memory_scrub, int, 0444);
 MODULE_PARM_DESC(memory_scrub,
        "Scrub device memory in various states (0 = no, 1 = yes, default yes)");
 
+module_param(boot_error_status_mask, ulong, 0444);
+MODULE_PARM_DESC(boot_error_status_mask,
+       "Mask of the error status during device CPU boot (If bitX is cleared then error X is masked. Default all 1's)");
+
 #define PCI_VENDOR_ID_HABANALABS       0x1da3
 
 #define PCI_IDS_GOYA                   0x0001
@@ -319,6 +324,8 @@ int create_hdev(struct hl_device **dev, struct pci_dev *pdev,
        hdev->major = hl_major;
        hdev->reset_on_lockup = reset_on_lockup;
        hdev->memory_scrub = memory_scrub;
+       hdev->boot_error_status_mask = boot_error_status_mask;
+
        hdev->pldm = 0;
 
        set_driver_behavior_per_device(hdev);
index 9fa61573a89de89e15d4f80e5a228bb66a890536..c9f649b31e3a96302d938d53fa02a89c76dd4439 100644 (file)
@@ -9,7 +9,7 @@
 
 #include <linux/pci.h>
 
-long hl_get_frequency(struct hl_device *hdev, enum pll_index pll_index,
+long hl_get_frequency(struct hl_device *hdev, u32 pll_index,
                                                                bool curr)
 {
        struct cpucp_packet pkt;
@@ -44,7 +44,7 @@ long hl_get_frequency(struct hl_device *hdev, enum pll_index pll_index,
        return (long) result;
 }
 
-void hl_set_frequency(struct hl_device *hdev, enum pll_index pll_index,
+void hl_set_frequency(struct hl_device *hdev, u32 pll_index,
                                                                u64 freq)
 {
        struct cpucp_packet pkt;
index b751652f80a8ce043359bae5be7b18c98878ecda..9e4a6bb3acd11c0e5a3d11bed9a245ec11e12df0 100644 (file)
 
 #define GAUDI_PLL_MAX 10
 
-/*
- * this enum kept here for compatibility with old FW (in which each asic has
- * unique PLL numbering
- */
-enum gaudi_pll_index {
-       GAUDI_CPU_PLL = 0,
-       GAUDI_PCI_PLL,
-       GAUDI_SRAM_PLL,
-       GAUDI_HBM_PLL,
-       GAUDI_NIC_PLL,
-       GAUDI_DMA_PLL,
-       GAUDI_MESH_PLL,
-       GAUDI_MME_PLL,
-       GAUDI_TPC_PLL,
-       GAUDI_IF_PLL,
-};
-
-static enum pll_index gaudi_pll_map[PLL_MAX] = {
-       [CPU_PLL] = GAUDI_CPU_PLL,
-       [PCI_PLL] = GAUDI_PCI_PLL,
-       [SRAM_PLL] = GAUDI_SRAM_PLL,
-       [HBM_PLL] = GAUDI_HBM_PLL,
-       [NIC_PLL] = GAUDI_NIC_PLL,
-       [DMA_PLL] = GAUDI_DMA_PLL,
-       [MESH_PLL] = GAUDI_MESH_PLL,
-       [MME_PLL] = GAUDI_MME_PLL,
-       [TPC_PLL] = GAUDI_TPC_PLL,
-       [IF_PLL] = GAUDI_IF_PLL,
-};
-
 static const char gaudi_irq_name[GAUDI_MSI_ENTRIES][GAUDI_MAX_STRING_LEN] = {
                "gaudi cq 0_0", "gaudi cq 0_1", "gaudi cq 0_2", "gaudi cq 0_3",
                "gaudi cq 1_0", "gaudi cq 1_1", "gaudi cq 1_2", "gaudi cq 1_3",
@@ -810,7 +780,7 @@ static int gaudi_fetch_psoc_frequency(struct hl_device *hdev)
                        freq = 0;
                }
        } else {
-               rc = hl_fw_cpucp_pll_info_get(hdev, CPU_PLL, pll_freq_arr);
+               rc = hl_fw_cpucp_pll_info_get(hdev, HL_GAUDI_CPU_PLL, pll_freq_arr);
 
                if (rc)
                        return rc;
@@ -1652,9 +1622,6 @@ static int gaudi_sw_init(struct hl_device *hdev)
 
        hdev->asic_specific = gaudi;
 
-       /* store legacy PLL map */
-       hdev->legacy_pll_map = gaudi_pll_map;
-
        /* Create DMA pool for small allocations */
        hdev->dma_pool = dma_pool_create(dev_name(hdev->dev),
                        &hdev->pdev->dev, GAUDI_DMA_POOL_BLK_SIZE, 8, 0);
@@ -5612,6 +5579,7 @@ static int gaudi_memset_device_memory(struct hl_device *hdev, u64 addr,
        struct hl_cs_job *job;
        u32 cb_size, ctl, err_cause;
        struct hl_cb *cb;
+       u64 id;
        int rc;
 
        cb = hl_cb_kernel_create(hdev, PAGE_SIZE, false);
@@ -5678,8 +5646,9 @@ static int gaudi_memset_device_memory(struct hl_device *hdev, u64 addr,
        }
 
 release_cb:
+       id = cb->id;
        hl_cb_put(cb);
-       hl_cb_destroy(hdev, &hdev->kernel_cb_mgr, cb->id << PAGE_SHIFT);
+       hl_cb_destroy(hdev, &hdev->kernel_cb_mgr, id << PAGE_SHIFT);
 
        return rc;
 }
@@ -8783,6 +8752,23 @@ static void gaudi_enable_events_from_fw(struct hl_device *hdev)
        WREG32(mmGIC_DISTRIBUTOR__5_GICD_SETSPI_NSR, GAUDI_EVENT_INTS_REGISTER);
 }
 
+static int gaudi_map_pll_idx_to_fw_idx(u32 pll_idx)
+{
+       switch (pll_idx) {
+       case HL_GAUDI_CPU_PLL: return CPU_PLL;
+       case HL_GAUDI_PCI_PLL: return PCI_PLL;
+       case HL_GAUDI_NIC_PLL: return NIC_PLL;
+       case HL_GAUDI_DMA_PLL: return DMA_PLL;
+       case HL_GAUDI_MESH_PLL: return MESH_PLL;
+       case HL_GAUDI_MME_PLL: return MME_PLL;
+       case HL_GAUDI_TPC_PLL: return TPC_PLL;
+       case HL_GAUDI_IF_PLL: return IF_PLL;
+       case HL_GAUDI_SRAM_PLL: return SRAM_PLL;
+       case HL_GAUDI_HBM_PLL: return HBM_PLL;
+       default: return -EINVAL;
+       }
+}
+
 static const struct hl_asic_funcs gaudi_funcs = {
        .early_init = gaudi_early_init,
        .early_fini = gaudi_early_fini,
@@ -8866,7 +8852,8 @@ static const struct hl_asic_funcs gaudi_funcs = {
        .ack_protection_bits_errors = gaudi_ack_protection_bits_errors,
        .get_hw_block_id = gaudi_get_hw_block_id,
        .hw_block_mmap = gaudi_block_mmap,
-       .enable_events_from_fw = gaudi_enable_events_from_fw
+       .enable_events_from_fw = gaudi_enable_events_from_fw,
+       .map_pll_idx_to_fw_idx = gaudi_map_pll_idx_to_fw_idx
 };
 
 /**
index 8c49da4bcbd58a1ad07f024e5430dee72b5cde7c..9b60eadd4c355ee8ccd55ce1a37169dada71e915 100644 (file)
@@ -13,7 +13,7 @@ void gaudi_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
        struct gaudi_device *gaudi = hdev->asic_specific;
 
        if (freq == PLL_LAST)
-               hl_set_frequency(hdev, MME_PLL, gaudi->max_freq_value);
+               hl_set_frequency(hdev, HL_GAUDI_MME_PLL, gaudi->max_freq_value);
 }
 
 int gaudi_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk)
@@ -23,7 +23,7 @@ int gaudi_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk)
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, MME_PLL, false);
+       value = hl_get_frequency(hdev, HL_GAUDI_MME_PLL, false);
 
        if (value < 0) {
                dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n",
@@ -33,7 +33,7 @@ int gaudi_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk)
 
        *max_clk = (value / 1000 / 1000);
 
-       value = hl_get_frequency(hdev, MME_PLL, true);
+       value = hl_get_frequency(hdev, HL_GAUDI_MME_PLL, true);
 
        if (value < 0) {
                dev_err(hdev->dev,
@@ -57,7 +57,7 @@ static ssize_t clk_max_freq_mhz_show(struct device *dev,
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, MME_PLL, false);
+       value = hl_get_frequency(hdev, HL_GAUDI_MME_PLL, false);
 
        gaudi->max_freq_value = value;
 
@@ -85,7 +85,7 @@ static ssize_t clk_max_freq_mhz_store(struct device *dev,
 
        gaudi->max_freq_value = value * 1000 * 1000;
 
-       hl_set_frequency(hdev, MME_PLL, gaudi->max_freq_value);
+       hl_set_frequency(hdev, HL_GAUDI_MME_PLL, gaudi->max_freq_value);
 
 fail:
        return count;
@@ -100,7 +100,7 @@ static ssize_t clk_cur_freq_mhz_show(struct device *dev,
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, MME_PLL, true);
+       value = hl_get_frequency(hdev, HL_GAUDI_MME_PLL, true);
 
        return sprintf(buf, "%lu\n", (value / 1000 / 1000));
 }
index e27338f4aad2f68afebc1d736ea2014d7e5231e7..e0ad2a269779b1f3b103f97340d2e7bec6a4ef68 100644 (file)
 #define IS_MME_IDLE(mme_arch_sts) \
        (((mme_arch_sts) & MME_ARCH_IDLE_MASK) == MME_ARCH_IDLE_MASK)
 
-/*
- * this enum kept here for compatibility with old FW (in which each asic has
- * unique PLL numbering
- */
-enum goya_pll_index {
-       GOYA_CPU_PLL = 0,
-       GOYA_IC_PLL,
-       GOYA_MC_PLL,
-       GOYA_MME_PLL,
-       GOYA_PCI_PLL,
-       GOYA_EMMC_PLL,
-       GOYA_TPC_PLL,
-};
-
-static enum pll_index goya_pll_map[PLL_MAX] = {
-       [CPU_PLL] = GOYA_CPU_PLL,
-       [IC_PLL] = GOYA_IC_PLL,
-       [MC_PLL] = GOYA_MC_PLL,
-       [MME_PLL] = GOYA_MME_PLL,
-       [PCI_PLL] = GOYA_PCI_PLL,
-       [EMMC_PLL] = GOYA_EMMC_PLL,
-       [TPC_PLL] = GOYA_TPC_PLL,
-};
-
 static const char goya_irq_name[GOYA_MSIX_ENTRIES][GOYA_MAX_STRING_LEN] = {
                "goya cq 0", "goya cq 1", "goya cq 2", "goya cq 3",
                "goya cq 4", "goya cpu eq"
@@ -775,7 +751,8 @@ static void goya_fetch_psoc_frequency(struct hl_device *hdev)
                        freq = 0;
                }
        } else {
-               rc = hl_fw_cpucp_pll_info_get(hdev, PCI_PLL, pll_freq_arr);
+               rc = hl_fw_cpucp_pll_info_get(hdev, HL_GOYA_PCI_PLL,
+                               pll_freq_arr);
 
                if (rc)
                        return;
@@ -897,9 +874,6 @@ static int goya_sw_init(struct hl_device *hdev)
 
        hdev->asic_specific = goya;
 
-       /* store legacy PLL map */
-       hdev->legacy_pll_map = goya_pll_map;
-
        /* Create DMA pool for small allocations */
        hdev->dma_pool = dma_pool_create(dev_name(hdev->dev),
                        &hdev->pdev->dev, GOYA_DMA_POOL_BLK_SIZE, 8, 0);
@@ -5512,6 +5486,20 @@ static void goya_enable_events_from_fw(struct hl_device *hdev)
                        GOYA_ASYNC_EVENT_ID_INTS_REGISTER);
 }
 
+static int goya_map_pll_idx_to_fw_idx(u32 pll_idx)
+{
+       switch (pll_idx) {
+       case HL_GOYA_CPU_PLL: return CPU_PLL;
+       case HL_GOYA_PCI_PLL: return PCI_PLL;
+       case HL_GOYA_MME_PLL: return MME_PLL;
+       case HL_GOYA_TPC_PLL: return TPC_PLL;
+       case HL_GOYA_IC_PLL: return IC_PLL;
+       case HL_GOYA_MC_PLL: return MC_PLL;
+       case HL_GOYA_EMMC_PLL: return EMMC_PLL;
+       default: return -EINVAL;
+       }
+}
+
 static const struct hl_asic_funcs goya_funcs = {
        .early_init = goya_early_init,
        .early_fini = goya_early_fini,
@@ -5595,7 +5583,8 @@ static const struct hl_asic_funcs goya_funcs = {
        .ack_protection_bits_errors = goya_ack_protection_bits_errors,
        .get_hw_block_id = goya_get_hw_block_id,
        .hw_block_mmap = goya_block_mmap,
-       .enable_events_from_fw = goya_enable_events_from_fw
+       .enable_events_from_fw = goya_enable_events_from_fw,
+       .map_pll_idx_to_fw_idx = goya_map_pll_idx_to_fw_idx
 };
 
 /*
index 3acb36a1a902ea7129b23b5de379de88430c554b..7d007125727ffef8f1b153c77c1f1778247322ac 100644 (file)
@@ -13,19 +13,19 @@ void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq)
 
        switch (freq) {
        case PLL_HIGH:
-               hl_set_frequency(hdev, MME_PLL, hdev->high_pll);
-               hl_set_frequency(hdev, TPC_PLL, hdev->high_pll);
-               hl_set_frequency(hdev, IC_PLL, hdev->high_pll);
+               hl_set_frequency(hdev, HL_GOYA_MME_PLL, hdev->high_pll);
+               hl_set_frequency(hdev, HL_GOYA_TPC_PLL, hdev->high_pll);
+               hl_set_frequency(hdev, HL_GOYA_IC_PLL, hdev->high_pll);
                break;
        case PLL_LOW:
-               hl_set_frequency(hdev, MME_PLL, GOYA_PLL_FREQ_LOW);
-               hl_set_frequency(hdev, TPC_PLL, GOYA_PLL_FREQ_LOW);
-               hl_set_frequency(hdev, IC_PLL, GOYA_PLL_FREQ_LOW);
+               hl_set_frequency(hdev, HL_GOYA_MME_PLL, GOYA_PLL_FREQ_LOW);
+               hl_set_frequency(hdev, HL_GOYA_TPC_PLL, GOYA_PLL_FREQ_LOW);
+               hl_set_frequency(hdev, HL_GOYA_IC_PLL, GOYA_PLL_FREQ_LOW);
                break;
        case PLL_LAST:
-               hl_set_frequency(hdev, MME_PLL, goya->mme_clk);
-               hl_set_frequency(hdev, TPC_PLL, goya->tpc_clk);
-               hl_set_frequency(hdev, IC_PLL, goya->ic_clk);
+               hl_set_frequency(hdev, HL_GOYA_MME_PLL, goya->mme_clk);
+               hl_set_frequency(hdev, HL_GOYA_TPC_PLL, goya->tpc_clk);
+               hl_set_frequency(hdev, HL_GOYA_IC_PLL, goya->ic_clk);
                break;
        default:
                dev_err(hdev->dev, "unknown frequency setting\n");
@@ -39,7 +39,7 @@ int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk)
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, MME_PLL, false);
+       value = hl_get_frequency(hdev, HL_GOYA_MME_PLL, false);
 
        if (value < 0) {
                dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n",
@@ -49,7 +49,7 @@ int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk)
 
        *max_clk = (value / 1000 / 1000);
 
-       value = hl_get_frequency(hdev, MME_PLL, true);
+       value = hl_get_frequency(hdev, HL_GOYA_MME_PLL, true);
 
        if (value < 0) {
                dev_err(hdev->dev,
@@ -72,7 +72,7 @@ static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr,
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, MME_PLL, false);
+       value = hl_get_frequency(hdev, HL_GOYA_MME_PLL, false);
 
        if (value < 0)
                return value;
@@ -105,7 +105,7 @@ static ssize_t mme_clk_store(struct device *dev, struct device_attribute *attr,
                goto fail;
        }
 
-       hl_set_frequency(hdev, MME_PLL, value);
+       hl_set_frequency(hdev, HL_GOYA_MME_PLL, value);
        goya->mme_clk = value;
 
 fail:
@@ -121,7 +121,7 @@ static ssize_t tpc_clk_show(struct device *dev, struct device_attribute *attr,
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, TPC_PLL, false);
+       value = hl_get_frequency(hdev, HL_GOYA_TPC_PLL, false);
 
        if (value < 0)
                return value;
@@ -154,7 +154,7 @@ static ssize_t tpc_clk_store(struct device *dev, struct device_attribute *attr,
                goto fail;
        }
 
-       hl_set_frequency(hdev, TPC_PLL, value);
+       hl_set_frequency(hdev, HL_GOYA_TPC_PLL, value);
        goya->tpc_clk = value;
 
 fail:
@@ -170,7 +170,7 @@ static ssize_t ic_clk_show(struct device *dev, struct device_attribute *attr,
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, IC_PLL, false);
+       value = hl_get_frequency(hdev, HL_GOYA_IC_PLL, false);
 
        if (value < 0)
                return value;
@@ -203,7 +203,7 @@ static ssize_t ic_clk_store(struct device *dev, struct device_attribute *attr,
                goto fail;
        }
 
-       hl_set_frequency(hdev, IC_PLL, value);
+       hl_set_frequency(hdev, HL_GOYA_IC_PLL, value);
        goya->ic_clk = value;
 
 fail:
@@ -219,7 +219,7 @@ static ssize_t mme_clk_curr_show(struct device *dev,
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, MME_PLL, true);
+       value = hl_get_frequency(hdev, HL_GOYA_MME_PLL, true);
 
        if (value < 0)
                return value;
@@ -236,7 +236,7 @@ static ssize_t tpc_clk_curr_show(struct device *dev,
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, TPC_PLL, true);
+       value = hl_get_frequency(hdev, HL_GOYA_TPC_PLL, true);
 
        if (value < 0)
                return value;
@@ -253,7 +253,7 @@ static ssize_t ic_clk_curr_show(struct device *dev,
        if (!hl_device_operational(hdev, NULL))
                return -ENODEV;
 
-       value = hl_get_frequency(hdev, IC_PLL, true);
+       value = hl_get_frequency(hdev, HL_GOYA_IC_PLL, true);
 
        if (value < 0)
                return value;
index 2bdf560ee681ba7cbe3535379f7ffe75e5e90627..0f9ea75b0b18976d0807e05c95c342639e2bf55d 100644 (file)
@@ -134,7 +134,7 @@ static struct ics932s401_data *ics932s401_update_device(struct device *dev)
        for (i = 0; i < NUM_MIRRORED_REGS; i++) {
                temp = i2c_smbus_read_word_data(client, regs_to_copy[i]);
                if (temp < 0)
-                       data->regs[regs_to_copy[i]] = 0;
+                       temp = 0;
                data->regs[regs_to_copy[i]] = temp >> 8;
        }
 
index 64d33e3685091352aa6cab2b8ffd4a70c109bb5c..67c5b452dd35632b011028a078401d94ae112c2d 100644 (file)
                printk(KERN_INFO a);    \
 } while (0)
 #define v2printk(a...) do {            \
-       if (verbose > 1)                \
+       if (verbose > 1) {              \
                printk(KERN_INFO a);    \
+       }                               \
        touch_nmi_watchdog();           \
 } while (0)
 #define eprintk(a...) do {             \
index c394c0b08519aa4a44290ebaf717a52b36051667..7ac788fae1b8647b0641c1a50c2a41c39a9c39e3 100644 (file)
@@ -271,6 +271,7 @@ struct lis3lv02d {
        int                     regs_size;
        u8                      *reg_cache;
        bool                    regs_stored;
+       bool                    init_required;
        u8                      odr_mask;  /* ODR bit mask */
        u8                      whoami;    /* indicates measurement precision */
        s16 (*read_data) (struct lis3lv02d *lis3, int reg);
index a98f6b895af71dfa7f2657f9b072abb4232b0c08..aab3ebfa9fc4ddaabea8cb301c9aab5998a847db 100644 (file)
@@ -277,6 +277,9 @@ static int mei_cl_irq_read(struct mei_cl *cl, struct mei_cl_cb *cb,
                return ret;
        }
 
+       pm_runtime_mark_last_busy(dev->dev);
+       pm_request_autosuspend(dev->dev);
+
        list_move_tail(&cb->list, &cl->rd_pending);
 
        return 0;
index b8b771b643cc8bfc9fb685d53936cd614104846c..016a6106151a5bcdd75a66483ed2d57842c69124 100644 (file)
@@ -236,7 +236,8 @@ static void meson_mmc_get_transfer_mode(struct mmc_host *mmc,
        if (host->dram_access_quirk)
                return;
 
-       if (data->blocks > 1) {
+       /* SD_IO_RW_EXTENDED (CMD53) can also use block mode under the hood */
+       if (data->blocks > 1 || mrq->cmd->opcode == SD_IO_RW_EXTENDED) {
                /*
                 * In block mode DMA descriptor format, "length" field indicates
                 * number of blocks and there is no way to pass DMA size that
@@ -258,7 +259,9 @@ static void meson_mmc_get_transfer_mode(struct mmc_host *mmc,
        for_each_sg(data->sg, sg, data->sg_len, i) {
                /* check for 8 byte alignment */
                if (sg->offset % 8) {
-                       WARN_ONCE(1, "unaligned scatterlist buffer\n");
+                       dev_warn_once(mmc_dev(mmc),
+                                     "unaligned sg offset %u, disabling descriptor DMA for transfer\n",
+                                     sg->offset);
                        return;
                }
        }
index 592d79082f58cd71767095b96fe774ebf60ad1a6..061618aa247f5d1865b22959d558aab77218c91d 100644 (file)
@@ -627,8 +627,13 @@ static void sdhci_gli_voltage_switch(struct sdhci_host *host)
         *
         * Wait 5ms after set 1.8V signal enable in Host Control 2 register
         * to ensure 1.8V signal enable bit is set by GL9750/GL9755.
+        *
+        * ...however, the controller in the NUC10i3FNK4 (a 9755) requires
+        * slightly longer than 5ms before the control register reports that
+        * 1.8V is ready, and far longer still before the card will actually
+        * work reliably.
         */
-       usleep_range(5000, 5500);
+       usleep_range(100000, 110000);
 }
 
 static void sdhci_gl9750_reset(struct sdhci_host *host, u8 mask)
index 6edf78c16fc8b0a5a1abceb4281e8764886892c2..df40927e56788fa30ce5a42bffdd3c53673a3f13 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/iopoll.h>
@@ -240,6 +241,15 @@ static int cs_calculate_ecc(struct nand_chip *this, const u_char *dat,
        return 0;
 }
 
+static int cs553x_ecc_correct(struct nand_chip *chip,
+                             unsigned char *buf,
+                             unsigned char *read_ecc,
+                             unsigned char *calc_ecc)
+{
+       return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc,
+                                     chip->ecc.size, false);
+}
+
 static struct cs553x_nand_controller *controllers[4];
 
 static int cs553x_attach_chip(struct nand_chip *chip)
@@ -251,7 +261,7 @@ static int cs553x_attach_chip(struct nand_chip *chip)
        chip->ecc.bytes = 3;
        chip->ecc.hwctl  = cs_enable_hwecc;
        chip->ecc.calculate = cs_calculate_ecc;
-       chip->ecc.correct  = rawnand_sw_hamming_correct;
+       chip->ecc.correct  = cs553x_ecc_correct;
        chip->ecc.strength = 1;
 
        return 0;
index bf695255b43a25ae213db314ee836cb783127e96..a3e66155ae4055262656ab1ca64eb8c3691c54df 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
@@ -432,6 +433,15 @@ static int fsmc_read_hwecc_ecc1(struct nand_chip *chip, const u8 *data,
        return 0;
 }
 
+static int fsmc_correct_ecc1(struct nand_chip *chip,
+                            unsigned char *buf,
+                            unsigned char *read_ecc,
+                            unsigned char *calc_ecc)
+{
+       return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc,
+                                     chip->ecc.size, false);
+}
+
 /* Count the number of 0's in buff upto a max of max_bits */
 static int count_written_bits(u8 *buff, int size, int max_bits)
 {
@@ -917,7 +927,7 @@ static int fsmc_nand_attach_chip(struct nand_chip *nand)
        case NAND_ECC_ENGINE_TYPE_ON_HOST:
                dev_info(host->dev, "Using 1-bit HW ECC scheme\n");
                nand->ecc.calculate = fsmc_read_hwecc_ecc1;
-               nand->ecc.correct = rawnand_sw_hamming_correct;
+               nand->ecc.correct = fsmc_correct_ecc1;
                nand->ecc.hwctl = fsmc_enable_hwecc;
                nand->ecc.bytes = 3;
                nand->ecc.strength = 1;
index 6b7269cfb7d8390ef3372ef755102454fe76624c..d7dfc6fd85ca73eb90fd5c2add1e2bb20c5993e7 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/mtd/lpc32xx_slc.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 
 #define LPC32XX_MODNAME                "lpc32xx-nand"
 
@@ -344,6 +345,18 @@ static int lpc32xx_nand_ecc_calculate(struct nand_chip *chip,
        return 0;
 }
 
+/*
+ * Corrects the data
+ */
+static int lpc32xx_nand_ecc_correct(struct nand_chip *chip,
+                                   unsigned char *buf,
+                                   unsigned char *read_ecc,
+                                   unsigned char *calc_ecc)
+{
+       return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc,
+                                     chip->ecc.size, false);
+}
+
 /*
  * Read a single byte from NAND device
  */
@@ -802,7 +815,7 @@ static int lpc32xx_nand_attach_chip(struct nand_chip *chip)
        chip->ecc.write_oob = lpc32xx_nand_write_oob_syndrome;
        chip->ecc.read_oob = lpc32xx_nand_read_oob_syndrome;
        chip->ecc.calculate = lpc32xx_nand_ecc_calculate;
-       chip->ecc.correct = rawnand_sw_hamming_correct;
+       chip->ecc.correct = lpc32xx_nand_ecc_correct;
        chip->ecc.hwctl = lpc32xx_nand_ecc_enable;
 
        /*
index 338d6b1a189eb69d112f069f1763554d97fbf239..98d5a94c3a24238b43cd0c60b73a6c59f2084503 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/mtd/ndfc.h>
 #include <linux/slab.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 #include <asm/io.h>
@@ -100,6 +101,15 @@ static int ndfc_calculate_ecc(struct nand_chip *chip,
        return 0;
 }
 
+static int ndfc_correct_ecc(struct nand_chip *chip,
+                           unsigned char *buf,
+                           unsigned char *read_ecc,
+                           unsigned char *calc_ecc)
+{
+       return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc,
+                                     chip->ecc.size, false);
+}
+
 /*
  * Speedups for buffer read/write/verify
  *
@@ -145,7 +155,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
        chip->controller = &ndfc->ndfc_control;
        chip->legacy.read_buf = ndfc_read_buf;
        chip->legacy.write_buf = ndfc_write_buf;
-       chip->ecc.correct = rawnand_sw_hamming_correct;
+       chip->ecc.correct = ndfc_correct_ecc;
        chip->ecc.hwctl = ndfc_enable_hwecc;
        chip->ecc.calculate = ndfc_calculate_ecc;
        chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST;
index 5612ee628425b733bc4bdadfde9aa27c2848f108..2f1fe464e66377f6a0ee6a69bbc66e8421654741 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/sharpsl.h>
@@ -96,6 +97,15 @@ static int sharpsl_nand_calculate_ecc(struct nand_chip *chip,
        return readb(sharpsl->io + ECCCNTR) != 0;
 }
 
+static int sharpsl_nand_correct_ecc(struct nand_chip *chip,
+                                   unsigned char *buf,
+                                   unsigned char *read_ecc,
+                                   unsigned char *calc_ecc)
+{
+       return ecc_sw_hamming_correct(buf, read_ecc, calc_ecc,
+                                     chip->ecc.size, false);
+}
+
 static int sharpsl_attach_chip(struct nand_chip *chip)
 {
        if (chip->ecc.engine_type != NAND_ECC_ENGINE_TYPE_ON_HOST)
@@ -106,7 +116,7 @@ static int sharpsl_attach_chip(struct nand_chip *chip)
        chip->ecc.strength = 1;
        chip->ecc.hwctl = sharpsl_nand_enable_hwecc;
        chip->ecc.calculate = sharpsl_nand_calculate_ecc;
-       chip->ecc.correct = rawnand_sw_hamming_correct;
+       chip->ecc.correct = sharpsl_nand_correct_ecc;
 
        return 0;
 }
index de8e919d0ebe647ab39f474f01e445c303b0c051..6d93dd31969b22bf829291f745be7ce7f14f62ea 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/slab.h>
@@ -292,11 +293,12 @@ static int tmio_nand_correct_data(struct nand_chip *chip, unsigned char *buf,
        int r0, r1;
 
        /* assume ecc.size = 512 and ecc.bytes = 6 */
-       r0 = rawnand_sw_hamming_correct(chip, buf, read_ecc, calc_ecc);
+       r0 = ecc_sw_hamming_correct(buf, read_ecc, calc_ecc,
+                                   chip->ecc.size, false);
        if (r0 < 0)
                return r0;
-       r1 = rawnand_sw_hamming_correct(chip, buf + 256, read_ecc + 3,
-                                       calc_ecc + 3);
+       r1 = ecc_sw_hamming_correct(buf + 256, read_ecc + 3, calc_ecc + 3,
+                                   chip->ecc.size, false);
        if (r1 < 0)
                return r1;
        return r0 + r1;
index 1a9449e53bf9dea75d9782e14a3f238c4fc0ef97..b8894ac27073c29b5f432aae385f15c63fe30b9e 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/nand-ecc-sw-hamming.h>
 #include <linux/mtd/rawnand.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
@@ -193,8 +194,8 @@ static int txx9ndfmc_correct_data(struct nand_chip *chip, unsigned char *buf,
        int stat;
 
        for (eccsize = chip->ecc.size; eccsize > 0; eccsize -= 256) {
-               stat = rawnand_sw_hamming_correct(chip, buf, read_ecc,
-                                                 calc_ecc);
+               stat = ecc_sw_hamming_correct(buf, read_ecc, calc_ecc,
+                                             chip->ecc.size, false);
                if (stat < 0)
                        return stat;
                corrected += stat;
index 0fd8d2a0db973c5233ce978835360d777d683adb..192190c42fc84d3f8c8ba72465fa3c44bf5243e7 100644 (file)
@@ -57,20 +57,22 @@ static int parse_fixed_partitions(struct mtd_info *master,
        if (!mtd_node)
                return 0;
 
-       ofpart_node = of_get_child_by_name(mtd_node, "partitions");
-       if (!ofpart_node && !master->parent) {
-               /*
-                * We might get here even when ofpart isn't used at all (e.g.,
-                * when using another parser), so don't be louder than
-                * KERN_DEBUG
-                */
-               pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n",
-                        master->name, mtd_node);
+       if (!master->parent) { /* Master */
+               ofpart_node = of_get_child_by_name(mtd_node, "partitions");
+               if (!ofpart_node) {
+                       /*
+                        * We might get here even when ofpart isn't used at all (e.g.,
+                        * when using another parser), so don't be louder than
+                        * KERN_DEBUG
+                        */
+                       pr_debug("%s: 'partitions' subnode not found on %pOF. Trying to parse direct subnodes as partitions.\n",
+                               master->name, mtd_node);
+                       ofpart_node = mtd_node;
+                       dedicated = false;
+               }
+       } else { /* Partition */
                ofpart_node = mtd_node;
-               dedicated = false;
        }
-       if (!ofpart_node)
-               return 0;
 
        of_id = of_match_node(parse_ofpart_match_table, ofpart_node);
        if (dedicated && !of_id) {
index ba8e70a8e3125d45b14d1aad19f87ee2d188ee45..6b12ce822e51a8da1d18a3c4ca55fb1a72ed7542 100644 (file)
@@ -327,6 +327,8 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
                        break;
        }
 
+       dev->base_addr = ioaddr;
+
        /* Reserve any actual interrupt. */
        if (dev->irq) {
                retval = request_irq(dev->irq, cops_interrupt, 0, dev->name, dev);
@@ -334,8 +336,6 @@ static int __init cops_probe1(struct net_device *dev, int ioaddr)
                        goto err_out;
        }
 
-       dev->base_addr = ioaddr;
-
         lp = netdev_priv(dev);
         spin_lock_init(&lp->lock);
 
index 20bbda1b36e1e71968ce2498bce098529b7e00cb..c5a646d06102a7f73b820978cc294e0c97218267 100644 (file)
@@ -1526,6 +1526,7 @@ static struct slave *bond_alloc_slave(struct bonding *bond,
 
        slave->bond = bond;
        slave->dev = slave_dev;
+       INIT_DELAYED_WORK(&slave->notify_work, bond_netdev_notify_work);
 
        if (bond_kobj_init(slave))
                return NULL;
@@ -1538,7 +1539,6 @@ static struct slave *bond_alloc_slave(struct bonding *bond,
                        return NULL;
                }
        }
-       INIT_DELAYED_WORK(&slave->notify_work, bond_netdev_notify_work);
 
        return slave;
 }
index da6fffb4d5a8eb689bd1a74e81d3659e883135bc..d17482395a4dace2cfa319a675be463849be3366 100644 (file)
@@ -269,9 +269,6 @@ static netdev_tx_t caif_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ser_device *ser;
 
-       if (WARN_ON(!dev))
-               return -EINVAL;
-
        ser = netdev_priv(dev);
 
        /* Send flow off once, on high water mark */
index 9150038b60cb4ed8d84c211682e7a02ac2d1f9ba..3b018fcf44124ac8ba04ed5d979206a8fe2304f3 100644 (file)
@@ -821,11 +821,9 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
        bcm_sf2_sw_mac_link_set(ds, port, interface, true);
 
        if (port != core_readl(priv, CORE_IMP0_PRT_ID)) {
-               u32 reg_rgmii_ctrl;
+               u32 reg_rgmii_ctrl = 0;
                u32 reg, offset;
 
-               reg_rgmii_ctrl = bcm_sf2_reg_rgmii_cntrl(priv, port);
-
                if (priv->type == BCM4908_DEVICE_ID ||
                    priv->type == BCM7445_DEVICE_ID)
                        offset = CORE_STS_OVERRIDE_GMIIP_PORT(port);
@@ -836,6 +834,7 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
                    interface == PHY_INTERFACE_MODE_RGMII_TXID ||
                    interface == PHY_INTERFACE_MODE_MII ||
                    interface == PHY_INTERFACE_MODE_REVMII) {
+                       reg_rgmii_ctrl = bcm_sf2_reg_rgmii_cntrl(priv, port);
                        reg = reg_readl(priv, reg_rgmii_ctrl);
                        reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN);
 
index 55e5d479acce332046aa177ddbcc72f6e5920c09..854e25f43fa708157cf4785ca1c170763b96c0ee 100644 (file)
@@ -1530,6 +1530,7 @@ static const struct ksz_chip_data ksz9477_switch_chips[] = {
                .num_statics = 16,
                .cpu_ports = 0x7F,      /* can be configured as cpu port */
                .port_cnt = 7,          /* total physical port count */
+               .phy_errata_9477 = true,
        },
 };
 
index 96f7c9eede358ef781a4d72ca19759a44fe1cd7b..9b90f3d3a8f505f360bbc88366ff5b442a5275a5 100644 (file)
@@ -1262,14 +1262,6 @@ mt7530_port_set_vlan_aware(struct dsa_switch *ds, int port)
 {
        struct mt7530_priv *priv = ds->priv;
 
-       /* The real fabric path would be decided on the membership in the
-        * entry of VLAN table. PCR_MATRIX set up here with ALL_MEMBERS
-        * means potential VLAN can be consisting of certain subset of all
-        * ports.
-        */
-       mt7530_rmw(priv, MT7530_PCR_P(port),
-                  PCR_MATRIX_MASK, PCR_MATRIX(MT7530_ALL_MEMBERS));
-
        /* Trapped into security mode allows packet forwarding through VLAN
         * table lookup. CPU port is set to fallback mode to let untagged
         * frames pass through.
index 2473bebe48e6ee19af24890f9b5d4f57f96516ac..f966a253d1c77a9aa6af3b6f27327e61c9951d56 100644 (file)
@@ -1227,12 +1227,17 @@ static int vsc9959_qos_port_tas_set(struct ocelot *ocelot, int port,
        if (taprio->num_entries > VSC9959_TAS_GCL_ENTRY_MAX)
                return -ERANGE;
 
-       /* Set port num and disable ALWAYS_GUARD_BAND_SCH_Q, which means set
-        * guard band to be implemented for nonschedule queues to schedule
-        * queues transition.
+       /* Enable guard band. The switch will schedule frames without taking
+        * their length into account. Thus we'll always need to enable the
+        * guard band which reserves the time of a maximum sized frame at the
+        * end of the time window.
+        *
+        * Although the ALWAYS_GUARD_BAND_SCH_Q bit is global for all ports, we
+        * need to set PORT_NUM, because subsequent writes to PARAM_CFG_REG_n
+        * operate on the port number.
         */
-       ocelot_rmw(ocelot,
-                  QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port),
+       ocelot_rmw(ocelot, QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM(port) |
+                  QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,
                   QSYS_TAS_PARAM_CFG_CTRL_PORT_NUM_M |
                   QSYS_TAS_PARAM_CFG_CTRL_ALWAYS_GUARD_BAND_SCH_Q,
                   QSYS_TAS_PARAM_CFG_CTRL);
index b777d3f375736e891f91fb6b54b838973e4aa4b6..12cd04b56803056e6c4e687d543f9ff872676664 100644 (file)
@@ -167,9 +167,10 @@ enum sja1105_hostcmd {
        SJA1105_HOSTCMD_INVALIDATE = 4,
 };
 
+/* Command and entry overlap */
 static void
-sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
-                             enum packing_op op)
+sja1105et_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
+                               enum packing_op op)
 {
        const int size = SJA1105_SIZE_DYN_CMD;
 
@@ -179,6 +180,20 @@ sja1105_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
        sja1105_packing(buf, &cmd->index,    9,  0, size, op);
 }
 
+/* Command and entry are separate */
+static void
+sja1105pqrs_vl_lookup_cmd_packing(void *buf, struct sja1105_dyn_cmd *cmd,
+                                 enum packing_op op)
+{
+       u8 *p = buf + SJA1105_SIZE_VL_LOOKUP_ENTRY;
+       const int size = SJA1105_SIZE_DYN_CMD;
+
+       sja1105_packing(p, &cmd->valid,   31, 31, size, op);
+       sja1105_packing(p, &cmd->errors,  30, 30, size, op);
+       sja1105_packing(p, &cmd->rdwrset, 29, 29, size, op);
+       sja1105_packing(p, &cmd->index,    9,  0, size, op);
+}
+
 static size_t sja1105et_vl_lookup_entry_packing(void *buf, void *entry_ptr,
                                                enum packing_op op)
 {
@@ -641,7 +656,7 @@ static size_t sja1105pqrs_cbs_entry_packing(void *buf, void *entry_ptr,
 const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
        [BLK_IDX_VL_LOOKUP] = {
                .entry_packing = sja1105et_vl_lookup_entry_packing,
-               .cmd_packing = sja1105_vl_lookup_cmd_packing,
+               .cmd_packing = sja1105et_vl_lookup_cmd_packing,
                .access = OP_WRITE,
                .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
                .packed_size = SJA1105ET_SIZE_VL_LOOKUP_DYN_CMD,
@@ -725,7 +740,7 @@ const struct sja1105_dynamic_table_ops sja1105et_dyn_ops[BLK_IDX_MAX_DYN] = {
 const struct sja1105_dynamic_table_ops sja1105pqrs_dyn_ops[BLK_IDX_MAX_DYN] = {
        [BLK_IDX_VL_LOOKUP] = {
                .entry_packing = sja1105_vl_lookup_entry_packing,
-               .cmd_packing = sja1105_vl_lookup_cmd_packing,
+               .cmd_packing = sja1105pqrs_vl_lookup_cmd_packing,
                .access = (OP_READ | OP_WRITE),
                .max_entry_count = SJA1105_MAX_VL_LOOKUP_COUNT,
                .packed_size = SJA1105PQRS_SIZE_VL_LOOKUP_DYN_CMD,
index 405024b637d6c0ee43034653f2368fdf2f239753..b88d9ef45a1f1d138861bc454dcf197171dd0e6b 100644 (file)
@@ -26,6 +26,7 @@
 #include "sja1105_tas.h"
 
 #define SJA1105_UNKNOWN_MULTICAST      0x010000000000ull
+#define SJA1105_DEFAULT_VLAN           (VLAN_N_VID - 1)
 
 static const struct dsa_switch_ops sja1105_switch_ops;
 
@@ -207,6 +208,7 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv,
                default:
                        dev_err(dev, "Unsupported PHY mode %s!\n",
                                phy_modes(ports[i].phy_mode));
+                       return -EINVAL;
                }
 
                /* Even though the SerDes port is able to drive SGMII autoneg
@@ -321,6 +323,13 @@ static int sja1105_init_l2_lookup_params(struct sja1105_private *priv)
        return 0;
 }
 
+/* Set up a default VLAN for untagged traffic injected from the CPU
+ * using management routes (e.g. STP, PTP) as opposed to tag_8021q.
+ * All DT-defined ports are members of this VLAN, and there are no
+ * restrictions on forwarding (since the CPU selects the destination).
+ * Frames from this VLAN will always be transmitted as untagged, and
+ * neither the bridge nor the 8021q module cannot create this VLAN ID.
+ */
 static int sja1105_init_static_vlan(struct sja1105_private *priv)
 {
        struct sja1105_table *table;
@@ -330,17 +339,13 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv)
                .vmemb_port = 0,
                .vlan_bc = 0,
                .tag_port = 0,
-               .vlanid = 1,
+               .vlanid = SJA1105_DEFAULT_VLAN,
        };
        struct dsa_switch *ds = priv->ds;
        int port;
 
        table = &priv->static_config.tables[BLK_IDX_VLAN_LOOKUP];
 
-       /* The static VLAN table will only contain the initial pvid of 1.
-        * All other VLANs are to be configured through dynamic entries,
-        * and kept in the static configuration table as backing memory.
-        */
        if (table->entry_count) {
                kfree(table->entries);
                table->entry_count = 0;
@@ -353,9 +358,6 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv)
 
        table->entry_count = 1;
 
-       /* VLAN 1: all DT-defined ports are members; no restrictions on
-        * forwarding; always transmit as untagged.
-        */
        for (port = 0; port < ds->num_ports; port++) {
                struct sja1105_bridge_vlan *v;
 
@@ -366,15 +368,12 @@ static int sja1105_init_static_vlan(struct sja1105_private *priv)
                pvid.vlan_bc |= BIT(port);
                pvid.tag_port &= ~BIT(port);
 
-               /* Let traffic that don't need dsa_8021q (e.g. STP, PTP) be
-                * transmitted as untagged.
-                */
                v = kzalloc(sizeof(*v), GFP_KERNEL);
                if (!v)
                        return -ENOMEM;
 
                v->port = port;
-               v->vid = 1;
+               v->vid = SJA1105_DEFAULT_VLAN;
                v->untagged = true;
                if (dsa_is_cpu_port(ds, port))
                        v->pvid = true;
@@ -2817,11 +2816,22 @@ static int sja1105_vlan_add_one(struct dsa_switch *ds, int port, u16 vid,
        bool pvid = flags & BRIDGE_VLAN_INFO_PVID;
        struct sja1105_bridge_vlan *v;
 
-       list_for_each_entry(v, vlan_list, list)
-               if (v->port == port && v->vid == vid &&
-                   v->untagged == untagged && v->pvid == pvid)
+       list_for_each_entry(v, vlan_list, list) {
+               if (v->port == port && v->vid == vid) {
                        /* Already added */
-                       return 0;
+                       if (v->untagged == untagged && v->pvid == pvid)
+                               /* Nothing changed */
+                               return 0;
+
+                       /* It's the same VLAN, but some of the flags changed
+                        * and the user did not bother to delete it first.
+                        * Update it and trigger sja1105_build_vlan_table.
+                        */
+                       v->untagged = untagged;
+                       v->pvid = pvid;
+                       return 1;
+               }
+       }
 
        v = kzalloc(sizeof(*v), GFP_KERNEL);
        if (!v) {
@@ -2976,13 +2986,13 @@ static int sja1105_setup(struct dsa_switch *ds)
        rc = sja1105_static_config_load(priv, ports);
        if (rc < 0) {
                dev_err(ds->dev, "Failed to load static config: %d\n", rc);
-               return rc;
+               goto out_ptp_clock_unregister;
        }
        /* Configure the CGU (PHY link modes and speeds) */
        rc = sja1105_clocking_setup(priv);
        if (rc < 0) {
                dev_err(ds->dev, "Failed to configure MII clocking: %d\n", rc);
-               return rc;
+               goto out_static_config_free;
        }
        /* On SJA1105, VLAN filtering per se is always enabled in hardware.
         * The only thing we can do to disable it is lie about what the 802.1Q
@@ -3003,7 +3013,7 @@ static int sja1105_setup(struct dsa_switch *ds)
 
        rc = sja1105_devlink_setup(ds);
        if (rc < 0)
-               return rc;
+               goto out_static_config_free;
 
        /* The DSA/switchdev model brings up switch ports in standalone mode by
         * default, and that means vlan_filtering is 0 since they're not under
@@ -3012,6 +3022,17 @@ static int sja1105_setup(struct dsa_switch *ds)
        rtnl_lock();
        rc = sja1105_setup_8021q_tagging(ds, true);
        rtnl_unlock();
+       if (rc)
+               goto out_devlink_teardown;
+
+       return 0;
+
+out_devlink_teardown:
+       sja1105_devlink_teardown(ds);
+out_ptp_clock_unregister:
+       sja1105_ptp_clock_unregister(ds);
+out_static_config_free:
+       sja1105_static_config_free(&priv->static_config);
 
        return rc;
 }
@@ -3646,8 +3667,10 @@ static int sja1105_probe(struct spi_device *spi)
                priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers,
                                         sizeof(struct sja1105_cbs_entry),
                                         GFP_KERNEL);
-               if (!priv->cbs)
-                       return -ENOMEM;
+               if (!priv->cbs) {
+                       rc = -ENOMEM;
+                       goto out_unregister_switch;
+               }
        }
 
        /* Connections between dsa_port and sja1105_port */
@@ -3672,7 +3695,7 @@ static int sja1105_probe(struct spi_device *spi)
                        dev_err(ds->dev,
                                "failed to create deferred xmit thread: %d\n",
                                rc);
-                       goto out;
+                       goto out_destroy_workers;
                }
                skb_queue_head_init(&sp->xmit_queue);
                sp->xmit_tpid = ETH_P_SJA1105;
@@ -3682,7 +3705,8 @@ static int sja1105_probe(struct spi_device *spi)
        }
 
        return 0;
-out:
+
+out_destroy_workers:
        while (port-- > 0) {
                struct sja1105_port *sp = &priv->ports[port];
 
@@ -3691,6 +3715,10 @@ out:
 
                kthread_destroy_worker(sp->xmit_worker);
        }
+
+out_unregister_switch:
+       dsa_unregister_switch(ds);
+
        return rc;
 }
 
index c0986096c701d368952ae3a8148e0a045ed89be1..5bace8a93d73be50d79f5da89abb2946998b9540 100644 (file)
@@ -8247,9 +8247,9 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev)
                BNX2_WR(bp, PCI_COMMAND, reg);
        } else if ((BNX2_CHIP_ID(bp) == BNX2_CHIP_ID_5706_A1) &&
                !(bp->flags & BNX2_FLAG_PCIX)) {
-
                dev_err(&pdev->dev,
                        "5706 A1 can only be used in a PCIX bus, aborting\n");
+               rc = -EPERM;
                goto err_out_unmap;
        }
 
index d21f085044cddd81ec46fbac2e3ad1ca6587f407..27943b0446c28465abd249aa65c875eb2bb900b1 100644 (file)
@@ -1223,8 +1223,10 @@ int bnx2x_iov_init_one(struct bnx2x *bp, int int_mode_param,
                goto failed;
 
        /* SR-IOV capability was enabled but there are no VFs*/
-       if (iov->total == 0)
+       if (iov->total == 0) {
+               err = -EINVAL;
                goto failed;
+       }
 
        iov->nr_virtfn = min_t(u16, iov->total, num_vfs_param);
 
index 2985844634c8b1a59ab27d4ef680c164eef50ea4..fcc729d52b17450f1678f4517b67b89d9a7a5433 100644 (file)
@@ -282,7 +282,8 @@ static bool bnxt_vf_pciid(enum board_idx idx)
 {
        return (idx == NETXTREME_C_VF || idx == NETXTREME_E_VF ||
                idx == NETXTREME_S_VF || idx == NETXTREME_C_VF_HV ||
-               idx == NETXTREME_E_VF_HV || idx == NETXTREME_E_P5_VF);
+               idx == NETXTREME_E_VF_HV || idx == NETXTREME_E_P5_VF ||
+               idx == NETXTREME_E_P5_VF_HV);
 }
 
 #define DB_CP_REARM_FLAGS      (DB_KEY_CP | DB_IDX_VALID)
@@ -6932,17 +6933,10 @@ ctx_err:
 static void bnxt_hwrm_set_pg_attr(struct bnxt_ring_mem_info *rmem, u8 *pg_attr,
                                  __le64 *pg_dir)
 {
-       u8 pg_size = 0;
-
        if (!rmem->nr_pages)
                return;
 
-       if (BNXT_PAGE_SHIFT == 13)
-               pg_size = 1 << 4;
-       else if (BNXT_PAGE_SIZE == 16)
-               pg_size = 2 << 4;
-
-       *pg_attr = pg_size;
+       BNXT_SET_CTX_PAGE_ATTR(*pg_attr);
        if (rmem->depth >= 1) {
                if (rmem->depth == 2)
                        *pg_attr |= 2;
@@ -10785,37 +10779,125 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)
        return rc;
 }
 
+static bool bnxt_exthdr_check(struct bnxt *bp, struct sk_buff *skb, int nw_off,
+                             u8 **nextp)
+{
+       struct ipv6hdr *ip6h = (struct ipv6hdr *)(skb->data + nw_off);
+       int hdr_count = 0;
+       u8 *nexthdr;
+       int start;
+
+       /* Check that there are at most 2 IPv6 extension headers, no
+        * fragment header, and each is <= 64 bytes.
+        */
+       start = nw_off + sizeof(*ip6h);
+       nexthdr = &ip6h->nexthdr;
+       while (ipv6_ext_hdr(*nexthdr)) {
+               struct ipv6_opt_hdr *hp;
+               int hdrlen;
+
+               if (hdr_count >= 3 || *nexthdr == NEXTHDR_NONE ||
+                   *nexthdr == NEXTHDR_FRAGMENT)
+                       return false;
+               hp = __skb_header_pointer(NULL, start, sizeof(*hp), skb->data,
+                                         skb_headlen(skb), NULL);
+               if (!hp)
+                       return false;
+               if (*nexthdr == NEXTHDR_AUTH)
+                       hdrlen = ipv6_authlen(hp);
+               else
+                       hdrlen = ipv6_optlen(hp);
+
+               if (hdrlen > 64)
+                       return false;
+               nexthdr = &hp->nexthdr;
+               start += hdrlen;
+               hdr_count++;
+       }
+       if (nextp) {
+               /* Caller will check inner protocol */
+               if (skb->encapsulation) {
+                       *nextp = nexthdr;
+                       return true;
+               }
+               *nextp = NULL;
+       }
+       /* Only support TCP/UDP for non-tunneled ipv6 and inner ipv6 */
+       return *nexthdr == IPPROTO_TCP || *nexthdr == IPPROTO_UDP;
+}
+
+/* For UDP, we can only handle 1 Vxlan port and 1 Geneve port. */
+static bool bnxt_udp_tunl_check(struct bnxt *bp, struct sk_buff *skb)
+{
+       struct udphdr *uh = udp_hdr(skb);
+       __be16 udp_port = uh->dest;
+
+       if (udp_port != bp->vxlan_port && udp_port != bp->nge_port)
+               return false;
+       if (skb->inner_protocol_type == ENCAP_TYPE_ETHER) {
+               struct ethhdr *eh = inner_eth_hdr(skb);
+
+               switch (eh->h_proto) {
+               case htons(ETH_P_IP):
+                       return true;
+               case htons(ETH_P_IPV6):
+                       return bnxt_exthdr_check(bp, skb,
+                                                skb_inner_network_offset(skb),
+                                                NULL);
+               }
+       }
+       return false;
+}
+
+static bool bnxt_tunl_check(struct bnxt *bp, struct sk_buff *skb, u8 l4_proto)
+{
+       switch (l4_proto) {
+       case IPPROTO_UDP:
+               return bnxt_udp_tunl_check(bp, skb);
+       case IPPROTO_IPIP:
+               return true;
+       case IPPROTO_GRE: {
+               switch (skb->inner_protocol) {
+               default:
+                       return false;
+               case htons(ETH_P_IP):
+                       return true;
+               case htons(ETH_P_IPV6):
+                       fallthrough;
+               }
+       }
+       case IPPROTO_IPV6:
+               /* Check ext headers of inner ipv6 */
+               return bnxt_exthdr_check(bp, skb, skb_inner_network_offset(skb),
+                                        NULL);
+       }
+       return false;
+}
+
 static netdev_features_t bnxt_features_check(struct sk_buff *skb,
                                             struct net_device *dev,
                                             netdev_features_t features)
 {
-       struct bnxt *bp;
-       __be16 udp_port;
-       u8 l4_proto = 0;
+       struct bnxt *bp = netdev_priv(dev);
+       u8 *l4_proto;
 
        features = vlan_features_check(skb, features);
-       if (!skb->encapsulation)
-               return features;
-
        switch (vlan_get_protocol(skb)) {
        case htons(ETH_P_IP):
-               l4_proto = ip_hdr(skb)->protocol;
+               if (!skb->encapsulation)
+                       return features;
+               l4_proto = &ip_hdr(skb)->protocol;
+               if (bnxt_tunl_check(bp, skb, *l4_proto))
+                       return features;
                break;
        case htons(ETH_P_IPV6):
-               l4_proto = ipv6_hdr(skb)->nexthdr;
+               if (!bnxt_exthdr_check(bp, skb, skb_network_offset(skb),
+                                      &l4_proto))
+                       break;
+               if (!l4_proto || bnxt_tunl_check(bp, skb, *l4_proto))
+                       return features;
                break;
-       default:
-               return features;
        }
-
-       if (l4_proto != IPPROTO_UDP)
-               return features;
-
-       bp = netdev_priv(dev);
-       /* For UDP, we can only handle 1 Vxlan port and 1 Geneve port. */
-       udp_port = udp_hdr(skb)->dest;
-       if (udp_port == bp->vxlan_port || udp_port == bp->nge_port)
-               return features;
        return features & ~(NETIF_F_CSUM_MASK | NETIF_F_GSO_MASK);
 }
 
index 98e0cef4532cbacb90ef2e464b5c552d373e5aef..30e47ea343f916759e877161639962cc40af6546 100644 (file)
@@ -1457,6 +1457,16 @@ struct bnxt_ctx_pg_info {
 
 #define BNXT_BACKING_STORE_CFG_LEGACY_LEN      256
 
+#define BNXT_SET_CTX_PAGE_ATTR(attr)                                   \
+do {                                                                   \
+       if (BNXT_PAGE_SIZE == 0x2000)                                   \
+               attr = FUNC_BACKING_STORE_CFG_REQ_SRQ_PG_SIZE_PG_8K;    \
+       else if (BNXT_PAGE_SIZE == 0x10000)                             \
+               attr = FUNC_BACKING_STORE_CFG_REQ_QPC_PG_SIZE_PG_64K;   \
+       else                                                            \
+               attr = FUNC_BACKING_STORE_CFG_REQ_QPC_PG_SIZE_PG_4K;    \
+} while (0)
+
 struct bnxt_ctx_mem_info {
        u32     qp_max_entries;
        u16     qp_min_qp1_entries;
index 6bc7d41d519b7065f809b18be4f5b450b871c2d3..a0c7b1167dbb243d436b58d5e948332b72a513f4 100644 (file)
@@ -2867,6 +2867,9 @@ static struct net_device_stats *gem_get_stats(struct macb *bp)
        struct gem_stats *hwstat = &bp->hw_stats.gem;
        struct net_device_stats *nstat = &bp->dev->stats;
 
+       if (!netif_running(bp->dev))
+               return nstat;
+
        gem_update_stats(bp);
 
        nstat->rx_errors = (hwstat->rx_frame_check_sequence_errors +
index 7c5af4beedc6d31318fb6f46a6f5f8470e5b33fb..591229b96257e4e5cc379a7dd19670e280902d66 100644 (file)
@@ -1153,7 +1153,7 @@ static void octeon_destroy_resources(struct octeon_device *oct)
  * @lio: per-network private data
  * @start_stop: whether to start or stop
  */
-static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
+static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
 {
        struct octeon_soft_command *sc;
        union octnet_cmd *ncmd;
@@ -1161,15 +1161,15 @@ static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
        int retval;
 
        if (oct->props[lio->ifidx].rx_on == start_stop)
-               return;
+               return 0;
 
        sc = (struct octeon_soft_command *)
                octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
                                          16, 0);
        if (!sc) {
                netif_info(lio, rx_err, lio->netdev,
-                          "Failed to allocate octeon_soft_command\n");
-               return;
+                          "Failed to allocate octeon_soft_command struct\n");
+               return -ENOMEM;
        }
 
        ncmd = (union octnet_cmd *)sc->virtdptr;
@@ -1192,18 +1192,19 @@ static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
        if (retval == IQ_SEND_FAILED) {
                netif_info(lio, rx_err, lio->netdev, "Failed to send RX Control message\n");
                octeon_free_soft_command(oct, sc);
-               return;
        } else {
                /* Sleep on a wait queue till the cond flag indicates that the
                 * response arrived or timed-out.
                 */
                retval = wait_for_sc_completion_timeout(oct, sc, 0);
                if (retval)
-                       return;
+                       return retval;
 
                oct->props[lio->ifidx].rx_on = start_stop;
                WRITE_ONCE(sc->caller_is_done, true);
        }
+
+       return retval;
 }
 
 /**
@@ -1778,6 +1779,7 @@ static int liquidio_open(struct net_device *netdev)
        struct octeon_device_priv *oct_priv =
                (struct octeon_device_priv *)oct->priv;
        struct napi_struct *napi, *n;
+       int ret = 0;
 
        if (oct->props[lio->ifidx].napi_enabled == 0) {
                tasklet_disable(&oct_priv->droq_tasklet);
@@ -1813,7 +1815,9 @@ static int liquidio_open(struct net_device *netdev)
        netif_info(lio, ifup, lio->netdev, "Interface Open, ready for traffic\n");
 
        /* tell Octeon to start forwarding packets to host */
-       send_rx_ctrl_cmd(lio, 1);
+       ret = send_rx_ctrl_cmd(lio, 1);
+       if (ret)
+               return ret;
 
        /* start periodical statistics fetch */
        INIT_DELAYED_WORK(&lio->stats_wk.work, lio_fetch_stats);
@@ -1824,7 +1828,7 @@ static int liquidio_open(struct net_device *netdev)
        dev_info(&oct->pci_dev->dev, "%s interface is opened\n",
                 netdev->name);
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -1838,6 +1842,7 @@ static int liquidio_stop(struct net_device *netdev)
        struct octeon_device_priv *oct_priv =
                (struct octeon_device_priv *)oct->priv;
        struct napi_struct *napi, *n;
+       int ret = 0;
 
        ifstate_reset(lio, LIO_IFSTATE_RUNNING);
 
@@ -1854,7 +1859,9 @@ static int liquidio_stop(struct net_device *netdev)
        lio->link_changes++;
 
        /* Tell Octeon that nic interface is down. */
-       send_rx_ctrl_cmd(lio, 0);
+       ret = send_rx_ctrl_cmd(lio, 0);
+       if (ret)
+               return ret;
 
        if (OCTEON_CN23XX_PF(oct)) {
                if (!oct->msix_on)
@@ -1889,7 +1896,7 @@ static int liquidio_stop(struct net_device *netdev)
 
        dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
 
-       return 0;
+       return ret;
 }
 
 /**
index 516f166ceff8c3195864e6bfa4a5c7a0a3a8ea62..ffddb3126a3236d5bd99d6755400335adc167dbf 100644 (file)
@@ -595,7 +595,7 @@ static void octeon_destroy_resources(struct octeon_device *oct)
  * @lio: per-network private data
  * @start_stop: whether to start or stop
  */
-static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
+static int send_rx_ctrl_cmd(struct lio *lio, int start_stop)
 {
        struct octeon_device *oct = (struct octeon_device *)lio->oct_dev;
        struct octeon_soft_command *sc;
@@ -603,11 +603,16 @@ static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
        int retval;
 
        if (oct->props[lio->ifidx].rx_on == start_stop)
-               return;
+               return 0;
 
        sc = (struct octeon_soft_command *)
                octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE,
                                          16, 0);
+       if (!sc) {
+               netif_info(lio, rx_err, lio->netdev,
+                          "Failed to allocate octeon_soft_command struct\n");
+               return -ENOMEM;
+       }
 
        ncmd = (union octnet_cmd *)sc->virtdptr;
 
@@ -635,11 +640,13 @@ static void send_rx_ctrl_cmd(struct lio *lio, int start_stop)
                 */
                retval = wait_for_sc_completion_timeout(oct, sc, 0);
                if (retval)
-                       return;
+                       return retval;
 
                oct->props[lio->ifidx].rx_on = start_stop;
                WRITE_ONCE(sc->caller_is_done, true);
        }
+
+       return retval;
 }
 
 /**
@@ -906,6 +913,7 @@ static int liquidio_open(struct net_device *netdev)
        struct octeon_device_priv *oct_priv =
                (struct octeon_device_priv *)oct->priv;
        struct napi_struct *napi, *n;
+       int ret = 0;
 
        if (!oct->props[lio->ifidx].napi_enabled) {
                tasklet_disable(&oct_priv->droq_tasklet);
@@ -932,11 +940,13 @@ static int liquidio_open(struct net_device *netdev)
                                        (LIQUIDIO_NDEV_STATS_POLL_TIME_MS));
 
        /* tell Octeon to start forwarding packets to host */
-       send_rx_ctrl_cmd(lio, 1);
+       ret = send_rx_ctrl_cmd(lio, 1);
+       if (ret)
+               return ret;
 
        dev_info(&oct->pci_dev->dev, "%s interface is opened\n", netdev->name);
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -950,9 +960,12 @@ static int liquidio_stop(struct net_device *netdev)
        struct octeon_device_priv *oct_priv =
                (struct octeon_device_priv *)oct->priv;
        struct napi_struct *napi, *n;
+       int ret = 0;
 
        /* tell Octeon to stop forwarding packets to host */
-       send_rx_ctrl_cmd(lio, 0);
+       ret = send_rx_ctrl_cmd(lio, 0);
+       if (ret)
+               return ret;
 
        netif_info(lio, ifdown, lio->netdev, "Stopping interface!\n");
        /* Inform that netif carrier is down */
@@ -986,7 +999,7 @@ static int liquidio_stop(struct net_device *netdev)
 
        dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name);
 
-       return 0;
+       return ret;
 }
 
 /**
index bc581b149b113608b0f2de68069121c1f26ad80d..22c9ac922ebae9bee87bb403e17ccfaed08557cc 100644 (file)
@@ -1042,7 +1042,7 @@ void clear_all_filters(struct adapter *adapter)
                                cxgb4_del_filter(dev, f->tid, &f->fs);
                }
 
-               sb = t4_read_reg(adapter, LE_DB_SRVR_START_INDEX_A);
+               sb = adapter->tids.stid_base;
                for (i = 0; i < sb; i++) {
                        f = (struct filter_entry *)adapter->tids.tid_tab[i];
 
index 6264bc66a4fc9aa3472ab33f09f472cf6f4a78d2..421bd9b88028d3bb8a2e0906550a87aa0eba3bf7 100644 (file)
@@ -6480,9 +6480,9 @@ static void cxgb4_ktls_dev_del(struct net_device *netdev,
 
        adap->uld[CXGB4_ULD_KTLS].tlsdev_ops->tls_dev_del(netdev, tls_ctx,
                                                          direction);
-       cxgb4_set_ktls_feature(adap, FW_PARAMS_PARAM_DEV_KTLS_HW_DISABLE);
 
 out_unlock:
+       cxgb4_set_ktls_feature(adap, FW_PARAMS_PARAM_DEV_KTLS_HW_DISABLE);
        mutex_unlock(&uld_mutex);
 }
 
index ef3f1e92632f3512b4780fe53d4d530231590abf..59683f79959ced63f03b02d6a5ac8d00d489b162 100644 (file)
@@ -59,6 +59,7 @@ static int chcr_get_nfrags_to_send(struct sk_buff *skb, u32 start, u32 len)
 }
 
 static int chcr_init_tcb_fields(struct chcr_ktls_info *tx_info);
+static void clear_conn_resources(struct chcr_ktls_info *tx_info);
 /*
  * chcr_ktls_save_keys: calculate and save crypto keys.
  * @tx_info - driver specific tls info.
@@ -364,10 +365,14 @@ static void chcr_ktls_dev_del(struct net_device *netdev,
                                chcr_get_ktls_tx_context(tls_ctx);
        struct chcr_ktls_info *tx_info = tx_ctx->chcr_info;
        struct ch_ktls_port_stats_debug *port_stats;
+       struct chcr_ktls_uld_ctx *u_ctx;
 
        if (!tx_info)
                return;
 
+       u_ctx = tx_info->adap->uld[CXGB4_ULD_KTLS].handle;
+       if (u_ctx && u_ctx->detach)
+               return;
        /* clear l2t entry */
        if (tx_info->l2te)
                cxgb4_l2t_release(tx_info->l2te);
@@ -384,6 +389,8 @@ static void chcr_ktls_dev_del(struct net_device *netdev,
        if (tx_info->tid != -1) {
                cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan,
                                 tx_info->tid, tx_info->ip_family);
+
+               xa_erase(&u_ctx->tid_list, tx_info->tid);
        }
 
        port_stats = &tx_info->adap->ch_ktls_stats.ktls_port[tx_info->port_id];
@@ -411,6 +418,7 @@ static int chcr_ktls_dev_add(struct net_device *netdev, struct sock *sk,
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct ch_ktls_port_stats_debug *port_stats;
        struct chcr_ktls_ofld_ctx_tx *tx_ctx;
+       struct chcr_ktls_uld_ctx *u_ctx;
        struct chcr_ktls_info *tx_info;
        struct dst_entry *dst;
        struct adapter *adap;
@@ -425,6 +433,7 @@ static int chcr_ktls_dev_add(struct net_device *netdev, struct sock *sk,
        adap = pi->adapter;
        port_stats = &adap->ch_ktls_stats.ktls_port[pi->port_id];
        atomic64_inc(&port_stats->ktls_tx_connection_open);
+       u_ctx = adap->uld[CXGB4_ULD_KTLS].handle;
 
        if (direction == TLS_OFFLOAD_CTX_DIR_RX) {
                pr_err("not expecting for RX direction\n");
@@ -434,6 +443,9 @@ static int chcr_ktls_dev_add(struct net_device *netdev, struct sock *sk,
        if (tx_ctx->chcr_info)
                goto out;
 
+       if (u_ctx && u_ctx->detach)
+               goto out;
+
        tx_info = kvzalloc(sizeof(*tx_info), GFP_KERNEL);
        if (!tx_info)
                goto out;
@@ -569,6 +581,8 @@ free_tid:
        cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan,
                         tx_info->tid, tx_info->ip_family);
 
+       xa_erase(&u_ctx->tid_list, tx_info->tid);
+
 put_module:
        /* release module refcount */
        module_put(THIS_MODULE);
@@ -633,8 +647,12 @@ static int chcr_ktls_cpl_act_open_rpl(struct adapter *adap,
 {
        const struct cpl_act_open_rpl *p = (void *)input;
        struct chcr_ktls_info *tx_info = NULL;
+       struct chcr_ktls_ofld_ctx_tx *tx_ctx;
+       struct chcr_ktls_uld_ctx *u_ctx;
        unsigned int atid, tid, status;
+       struct tls_context *tls_ctx;
        struct tid_info *t;
+       int ret = 0;
 
        tid = GET_TID(p);
        status = AOPEN_STATUS_G(ntohl(p->atid_status));
@@ -666,14 +684,29 @@ static int chcr_ktls_cpl_act_open_rpl(struct adapter *adap,
        if (!status) {
                tx_info->tid = tid;
                cxgb4_insert_tid(t, tx_info, tx_info->tid, tx_info->ip_family);
+               /* Adding tid */
+               tls_ctx = tls_get_ctx(tx_info->sk);
+               tx_ctx = chcr_get_ktls_tx_context(tls_ctx);
+               u_ctx = adap->uld[CXGB4_ULD_KTLS].handle;
+               if (u_ctx) {
+                       ret = xa_insert_bh(&u_ctx->tid_list, tid, tx_ctx,
+                                          GFP_NOWAIT);
+                       if (ret < 0) {
+                               pr_err("%s: Failed to allocate tid XA entry = %d\n",
+                                      __func__, tx_info->tid);
+                               tx_info->open_state = CH_KTLS_OPEN_FAILURE;
+                               goto out;
+                       }
+               }
                tx_info->open_state = CH_KTLS_OPEN_SUCCESS;
        } else {
                tx_info->open_state = CH_KTLS_OPEN_FAILURE;
        }
+out:
        spin_unlock(&tx_info->lock);
 
        complete(&tx_info->completion);
-       return 0;
+       return ret;
 }
 
 /*
@@ -2090,6 +2123,8 @@ static void *chcr_ktls_uld_add(const struct cxgb4_lld_info *lldi)
                goto out;
        }
        u_ctx->lldi = *lldi;
+       u_ctx->detach = false;
+       xa_init_flags(&u_ctx->tid_list, XA_FLAGS_LOCK_BH);
 out:
        return u_ctx;
 }
@@ -2123,6 +2158,45 @@ static int chcr_ktls_uld_rx_handler(void *handle, const __be64 *rsp,
        return 0;
 }
 
+static void clear_conn_resources(struct chcr_ktls_info *tx_info)
+{
+       /* clear l2t entry */
+       if (tx_info->l2te)
+               cxgb4_l2t_release(tx_info->l2te);
+
+#if IS_ENABLED(CONFIG_IPV6)
+       /* clear clip entry */
+       if (tx_info->ip_family == AF_INET6)
+               cxgb4_clip_release(tx_info->netdev, (const u32 *)
+                                  &tx_info->sk->sk_v6_rcv_saddr,
+                                  1);
+#endif
+
+       /* clear tid */
+       if (tx_info->tid != -1)
+               cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan,
+                                tx_info->tid, tx_info->ip_family);
+}
+
+static void ch_ktls_reset_all_conn(struct chcr_ktls_uld_ctx *u_ctx)
+{
+       struct ch_ktls_port_stats_debug *port_stats;
+       struct chcr_ktls_ofld_ctx_tx *tx_ctx;
+       struct chcr_ktls_info *tx_info;
+       unsigned long index;
+
+       xa_for_each(&u_ctx->tid_list, index, tx_ctx) {
+               tx_info = tx_ctx->chcr_info;
+               clear_conn_resources(tx_info);
+               port_stats = &tx_info->adap->ch_ktls_stats.ktls_port[tx_info->port_id];
+               atomic64_inc(&port_stats->ktls_tx_connection_close);
+               kvfree(tx_info);
+               tx_ctx->chcr_info = NULL;
+               /* release module refcount */
+               module_put(THIS_MODULE);
+       }
+}
+
 static int chcr_ktls_uld_state_change(void *handle, enum cxgb4_state new_state)
 {
        struct chcr_ktls_uld_ctx *u_ctx = handle;
@@ -2139,7 +2213,10 @@ static int chcr_ktls_uld_state_change(void *handle, enum cxgb4_state new_state)
        case CXGB4_STATE_DETACH:
                pr_info("%s: Down\n", pci_name(u_ctx->lldi.pdev));
                mutex_lock(&dev_mutex);
+               u_ctx->detach = true;
                list_del(&u_ctx->entry);
+               ch_ktls_reset_all_conn(u_ctx);
+               xa_destroy(&u_ctx->tid_list);
                mutex_unlock(&dev_mutex);
                break;
        default:
@@ -2178,6 +2255,7 @@ static void __exit chcr_ktls_exit(void)
                adap = pci_get_drvdata(u_ctx->lldi.pdev);
                memset(&adap->ch_ktls_stats, 0, sizeof(adap->ch_ktls_stats));
                list_del(&u_ctx->entry);
+               xa_destroy(&u_ctx->tid_list);
                kfree(u_ctx);
        }
        mutex_unlock(&dev_mutex);
index 18b3b1f024156cdbd4a503b0f51ce26f56775e32..10572dc55365a9e418eb9f02587ea3841a5e78a3 100644 (file)
@@ -75,6 +75,8 @@ struct chcr_ktls_ofld_ctx_tx {
 struct chcr_ktls_uld_ctx {
        struct list_head entry;
        struct cxgb4_lld_info lldi;
+       struct xarray tid_list;
+       bool detach;
 };
 
 static inline struct chcr_ktls_ofld_ctx_tx *
index 188d871f6b8cdbf613a50edd09b48aa1fde39b88..c320cc8ca68d61070fdb069316088aae67ba01af 100644 (file)
@@ -1564,8 +1564,10 @@ found_ok_skb:
                        cerr = put_cmsg(msg, SOL_TLS, TLS_GET_RECORD_TYPE,
                                        sizeof(thdr->type), &thdr->type);
 
-                       if (cerr && thdr->type != TLS_RECORD_TYPE_DATA)
-                               return -EIO;
+                       if (cerr && thdr->type != TLS_RECORD_TYPE_DATA) {
+                               copied = -EIO;
+                               break;
+                       }
                        /*  don't send tls header, skip copy */
                        goto skip_copy;
                }
index f2065f9d02e62b11944986b0207cf63e0ee15ece..ad82cffc6f3f59f591339a5426e9856a8de20374 100644 (file)
@@ -1662,7 +1662,7 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget)
 }
 
 /* ------------------------------------------------------------------------- */
-static void fec_get_mac(struct net_device *ndev)
+static int fec_get_mac(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
        unsigned char *iap, tmpaddr[ETH_ALEN];
@@ -1685,6 +1685,8 @@ static void fec_get_mac(struct net_device *ndev)
                        ret = of_get_mac_address(np, tmpaddr);
                        if (!ret)
                                iap = tmpaddr;
+                       else if (ret == -EPROBE_DEFER)
+                               return ret;
                }
        }
 
@@ -1723,7 +1725,7 @@ static void fec_get_mac(struct net_device *ndev)
                eth_hw_addr_random(ndev);
                dev_info(&fep->pdev->dev, "Using random MAC address: %pM\n",
                         ndev->dev_addr);
-               return;
+               return 0;
        }
 
        memcpy(ndev->dev_addr, iap, ETH_ALEN);
@@ -1731,6 +1733,8 @@ static void fec_get_mac(struct net_device *ndev)
        /* Adjust MAC if using macaddr */
        if (iap == macaddr)
                 ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->dev_id;
+
+       return 0;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -3290,7 +3294,9 @@ static int fec_enet_init(struct net_device *ndev)
                return ret;
        }
 
-       fec_enet_alloc_queue(ndev);
+       ret = fec_enet_alloc_queue(ndev);
+       if (ret)
+               return ret;
 
        bd_size = (fep->total_tx_ring_size + fep->total_rx_ring_size) * dsize;
 
@@ -3298,11 +3304,15 @@ static int fec_enet_init(struct net_device *ndev)
        cbd_base = dmam_alloc_coherent(&fep->pdev->dev, bd_size, &bd_dma,
                                       GFP_KERNEL);
        if (!cbd_base) {
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto free_queue_mem;
        }
 
        /* Get the Ethernet address */
-       fec_get_mac(ndev);
+       ret = fec_get_mac(ndev);
+       if (ret)
+               goto free_queue_mem;
+
        /* make sure MAC we just acquired is programmed into the hw */
        fec_set_mac_address(ndev, NULL);
 
@@ -3376,6 +3386,10 @@ static int fec_enet_init(struct net_device *ndev)
                fec_enet_update_ethtool_stats(ndev);
 
        return 0;
+
+free_queue_mem:
+       fec_enet_free_queue(ndev);
+       return ret;
 }
 
 #ifdef CONFIG_OF
index a7b7a4aace7913a9780d17ecdcaf43cab25da8d6..b0c0504950d8118c034b7fc73096423833d4eae0 100644 (file)
@@ -548,8 +548,8 @@ static int fmvj18x_get_hwinfo(struct pcmcia_device *link, u_char *node_id)
 
     base = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
     if (!base) {
-           pcmcia_release_window(link, link->resource[2]);
-           return -ENOMEM;
+       pcmcia_release_window(link, link->resource[2]);
+       return -1;
     }
 
     pcmcia_map_mem_page(link, link->resource[2], 0);
index 7302498c6df3608f3ffe6e0727c511c0797959c9..bbc423e931223c27f1516f470108c3ddf5c19ef0 100644 (file)
@@ -180,7 +180,7 @@ static int gve_napi_poll(struct napi_struct *napi, int budget)
        /* Double check we have no extra work.
         * Ensure unmask synchronizes with checking for work.
         */
-       dma_rmb();
+       mb();
        if (block->tx)
                reschedule |= gve_tx_poll(block, -1);
        if (block->rx)
@@ -220,6 +220,7 @@ static int gve_alloc_notify_blocks(struct gve_priv *priv)
                int vecs_left = new_num_ntfy_blks % 2;
 
                priv->num_ntfy_blks = new_num_ntfy_blks;
+               priv->mgmt_msix_idx = priv->num_ntfy_blks;
                priv->tx_cfg.max_queues = min_t(int, priv->tx_cfg.max_queues,
                                                vecs_per_type);
                priv->rx_cfg.max_queues = min_t(int, priv->rx_cfg.max_queues,
@@ -300,20 +301,22 @@ static void gve_free_notify_blocks(struct gve_priv *priv)
 {
        int i;
 
-       /* Free the irqs */
-       for (i = 0; i < priv->num_ntfy_blks; i++) {
-               struct gve_notify_block *block = &priv->ntfy_blocks[i];
-               int msix_idx = i;
+       if (priv->msix_vectors) {
+               /* Free the irqs */
+               for (i = 0; i < priv->num_ntfy_blks; i++) {
+                       struct gve_notify_block *block = &priv->ntfy_blocks[i];
+                       int msix_idx = i;
 
-               irq_set_affinity_hint(priv->msix_vectors[msix_idx].vector,
-                                     NULL);
-               free_irq(priv->msix_vectors[msix_idx].vector, block);
+                       irq_set_affinity_hint(priv->msix_vectors[msix_idx].vector,
+                                             NULL);
+                       free_irq(priv->msix_vectors[msix_idx].vector, block);
+               }
+               free_irq(priv->msix_vectors[priv->mgmt_msix_idx].vector, priv);
        }
        dma_free_coherent(&priv->pdev->dev,
                          priv->num_ntfy_blks * sizeof(*priv->ntfy_blocks),
                          priv->ntfy_blocks, priv->ntfy_block_bus);
        priv->ntfy_blocks = NULL;
-       free_irq(priv->msix_vectors[priv->mgmt_msix_idx].vector, priv);
        pci_disable_msix(priv->pdev);
        kvfree(priv->msix_vectors);
        priv->msix_vectors = NULL;
index 6938f3a939d64654ef9982865d34b18d4005e6fa..3e04a3973d6803bbe4ed6068bbcac76219d017f3 100644 (file)
@@ -212,10 +212,11 @@ static int gve_tx_alloc_ring(struct gve_priv *priv, int idx)
        tx->dev = &priv->pdev->dev;
        if (!tx->raw_addressing) {
                tx->tx_fifo.qpl = gve_assign_tx_qpl(priv);
-
+               if (!tx->tx_fifo.qpl)
+                       goto abort_with_desc;
                /* map Tx FIFO */
                if (gve_tx_fifo_init(priv, &tx->tx_fifo))
-                       goto abort_with_desc;
+                       goto abort_with_qpl;
        }
 
        tx->q_resources =
@@ -236,6 +237,9 @@ static int gve_tx_alloc_ring(struct gve_priv *priv, int idx)
 abort_with_fifo:
        if (!tx->raw_addressing)
                gve_tx_fifo_release(priv, &tx->tx_fifo);
+abort_with_qpl:
+       if (!tx->raw_addressing)
+               gve_unassign_qpl(priv, tx->tx_fifo.qpl->id);
 abort_with_desc:
        dma_free_coherent(hdev, bytes, tx->desc, tx->bus);
        tx->desc = NULL;
@@ -589,7 +593,7 @@ netdev_tx_t gve_tx(struct sk_buff *skb, struct net_device *dev)
        struct gve_tx_ring *tx;
        int nsegs;
 
-       WARN(skb_get_queue_mapping(skb) > priv->tx_cfg.num_queues,
+       WARN(skb_get_queue_mapping(skb) >= priv->tx_cfg.num_queues,
             "skb queue index out of range");
        tx = &priv->tx[skb_get_queue_mapping(skb)];
        if (unlikely(gve_maybe_stop_tx(tx, skb))) {
index da48c05435ea6cc07537293867a17764353c5bcd..7e62dcff242647cfb975d713d1decc219387f13e 100644 (file)
@@ -192,7 +192,7 @@ static int hns_nic_get_link_ksettings(struct net_device *net_dev,
 }
 
 /**
- *hns_nic_set_link_settings - implement ethtool set link ksettings
+ *hns_nic_set_link_ksettings - implement ethtool set link ksettings
  *@net_dev: net_device
  *@cmd: ethtool_link_ksettings
  *retuen 0 - success , negative --fail
@@ -827,7 +827,7 @@ hns_get_channels(struct net_device *net_dev, struct ethtool_channels *ch)
 }
 
 /**
- * get_ethtool_stats - get detail statistics.
+ * hns_get_ethtool_stats - get detail statistics.
  * @netdev: net device
  * @stats: statistics info.
  * @data: statistics data.
@@ -885,7 +885,7 @@ static void hns_get_ethtool_stats(struct net_device *netdev,
 }
 
 /**
- * get_strings: Return a set of strings that describe the requested objects
+ * hns_get_strings: Return a set of strings that describe the requested objects
  * @netdev: net device
  * @stringset: string set ID.
  * @data: objects data.
index 783fdaf8f8d64ec1ab5c1f28e7f5fead31135986..026558f8e04b950da306c479e27d54b86a8c4317 100644 (file)
@@ -264,22 +264,17 @@ static void hns3_vector_coalesce_init(struct hns3_enet_tqp_vector *tqp_vector,
        struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev);
        struct hns3_enet_coalesce *tx_coal = &tqp_vector->tx_group.coal;
        struct hns3_enet_coalesce *rx_coal = &tqp_vector->rx_group.coal;
+       struct hns3_enet_coalesce *ptx_coal = &priv->tx_coal;
+       struct hns3_enet_coalesce *prx_coal = &priv->rx_coal;
 
-       /* initialize the configuration for interrupt coalescing.
-        * 1. GL (Interrupt Gap Limiter)
-        * 2. RL (Interrupt Rate Limiter)
-        * 3. QL (Interrupt Quantity Limiter)
-        *
-        * Default: enable interrupt coalescing self-adaptive and GL
-        */
-       tx_coal->adapt_enable = 1;
-       rx_coal->adapt_enable = 1;
+       tx_coal->adapt_enable = ptx_coal->adapt_enable;
+       rx_coal->adapt_enable = prx_coal->adapt_enable;
 
-       tx_coal->int_gl = HNS3_INT_GL_50K;
-       rx_coal->int_gl = HNS3_INT_GL_50K;
+       tx_coal->int_gl = ptx_coal->int_gl;
+       rx_coal->int_gl = prx_coal->int_gl;
 
-       rx_coal->flow_level = HNS3_FLOW_LOW;
-       tx_coal->flow_level = HNS3_FLOW_LOW;
+       rx_coal->flow_level = prx_coal->flow_level;
+       tx_coal->flow_level = ptx_coal->flow_level;
 
        /* device version above V3(include V3), GL can configure 1us
         * unit, so uses 1us unit.
@@ -294,8 +289,8 @@ static void hns3_vector_coalesce_init(struct hns3_enet_tqp_vector *tqp_vector,
                rx_coal->ql_enable = 1;
                tx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max;
                rx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max;
-               tx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
-               rx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
+               tx_coal->int_ql = ptx_coal->int_ql;
+               rx_coal->int_ql = prx_coal->int_ql;
        }
 }
 
@@ -846,8 +841,6 @@ static bool hns3_tunnel_csum_bug(struct sk_buff *skb)
              l4.udp->dest == htons(4790))))
                return false;
 
-       skb_checksum_help(skb);
-
        return true;
 }
 
@@ -924,8 +917,7 @@ static int hns3_set_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
                        /* the stack computes the IP header already,
                         * driver calculate l4 checksum when not TSO.
                         */
-                       skb_checksum_help(skb);
-                       return 0;
+                       return skb_checksum_help(skb);
                }
 
                hns3_set_outer_l2l3l4(skb, ol4_proto, ol_type_vlan_len_msec);
@@ -970,7 +962,7 @@ static int hns3_set_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
                break;
        case IPPROTO_UDP:
                if (hns3_tunnel_csum_bug(skb))
-                       break;
+                       return skb_checksum_help(skb);
 
                hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4CS_B, 1);
                hns3_set_field(*type_cs_vlan_tso, HNS3_TXD_L4T_S,
@@ -995,8 +987,7 @@ static int hns3_set_l2l3l4(struct sk_buff *skb, u8 ol4_proto,
                /* the stack computes the IP header already,
                 * driver calculate l4 checksum when not TSO.
                 */
-               skb_checksum_help(skb);
-               return 0;
+               return skb_checksum_help(skb);
        }
 
        return 0;
@@ -3844,6 +3835,34 @@ map_ring_fail:
        return ret;
 }
 
+static void hns3_nic_init_coal_cfg(struct hns3_nic_priv *priv)
+{
+       struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev);
+       struct hns3_enet_coalesce *tx_coal = &priv->tx_coal;
+       struct hns3_enet_coalesce *rx_coal = &priv->rx_coal;
+
+       /* initialize the configuration for interrupt coalescing.
+        * 1. GL (Interrupt Gap Limiter)
+        * 2. RL (Interrupt Rate Limiter)
+        * 3. QL (Interrupt Quantity Limiter)
+        *
+        * Default: enable interrupt coalescing self-adaptive and GL
+        */
+       tx_coal->adapt_enable = 1;
+       rx_coal->adapt_enable = 1;
+
+       tx_coal->int_gl = HNS3_INT_GL_50K;
+       rx_coal->int_gl = HNS3_INT_GL_50K;
+
+       rx_coal->flow_level = HNS3_FLOW_LOW;
+       tx_coal->flow_level = HNS3_FLOW_LOW;
+
+       if (ae_dev->dev_specs.int_ql_max) {
+               tx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
+               rx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
+       }
+}
+
 static int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv)
 {
        struct hnae3_handle *h = priv->ae_handle;
@@ -4295,6 +4314,8 @@ static int hns3_client_init(struct hnae3_handle *handle)
                goto out_get_ring_cfg;
        }
 
+       hns3_nic_init_coal_cfg(priv);
+
        ret = hns3_nic_alloc_vector_data(priv);
        if (ret) {
                ret = -ENOMEM;
@@ -4317,12 +4338,6 @@ static int hns3_client_init(struct hnae3_handle *handle)
        if (ret)
                goto out_init_phy;
 
-       ret = register_netdev(netdev);
-       if (ret) {
-               dev_err(priv->dev, "probe register netdev fail!\n");
-               goto out_reg_netdev_fail;
-       }
-
        /* the device can work without cpu rmap, only aRFS needs it */
        ret = hns3_set_rx_cpu_rmap(netdev);
        if (ret)
@@ -4355,17 +4370,23 @@ static int hns3_client_init(struct hnae3_handle *handle)
        if (ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V3)
                set_bit(HNAE3_PFLAG_LIMIT_PROMISC, &handle->supported_pflags);
 
+       ret = register_netdev(netdev);
+       if (ret) {
+               dev_err(priv->dev, "probe register netdev fail!\n");
+               goto out_reg_netdev_fail;
+       }
+
        if (netif_msg_drv(handle))
                hns3_info_show(priv);
 
        return ret;
 
+out_reg_netdev_fail:
+       hns3_dbg_uninit(handle);
 out_client_start:
        hns3_free_rx_cpu_rmap(netdev);
        hns3_nic_uninit_irq(priv);
 out_init_irq_fail:
-       unregister_netdev(netdev);
-out_reg_netdev_fail:
        hns3_uninit_phy(netdev);
 out_init_phy:
        hns3_uninit_all_ring(priv);
@@ -4571,31 +4592,6 @@ int hns3_nic_reset_all_ring(struct hnae3_handle *h)
        return 0;
 }
 
-static void hns3_store_coal(struct hns3_nic_priv *priv)
-{
-       /* ethtool only support setting and querying one coal
-        * configuration for now, so save the vector 0' coal
-        * configuration here in order to restore it.
-        */
-       memcpy(&priv->tx_coal, &priv->tqp_vector[0].tx_group.coal,
-              sizeof(struct hns3_enet_coalesce));
-       memcpy(&priv->rx_coal, &priv->tqp_vector[0].rx_group.coal,
-              sizeof(struct hns3_enet_coalesce));
-}
-
-static void hns3_restore_coal(struct hns3_nic_priv *priv)
-{
-       u16 vector_num = priv->vector_num;
-       int i;
-
-       for (i = 0; i < vector_num; i++) {
-               memcpy(&priv->tqp_vector[i].tx_group.coal, &priv->tx_coal,
-                      sizeof(struct hns3_enet_coalesce));
-               memcpy(&priv->tqp_vector[i].rx_group.coal, &priv->rx_coal,
-                      sizeof(struct hns3_enet_coalesce));
-       }
-}
-
 static int hns3_reset_notify_down_enet(struct hnae3_handle *handle)
 {
        struct hnae3_knic_private_info *kinfo = &handle->kinfo;
@@ -4654,8 +4650,6 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)
        if (ret)
                goto err_put_ring;
 
-       hns3_restore_coal(priv);
-
        ret = hns3_nic_init_vector_data(priv);
        if (ret)
                goto err_dealloc_vector;
@@ -4721,8 +4715,6 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)
 
        hns3_nic_uninit_vector_data(priv);
 
-       hns3_store_coal(priv);
-
        hns3_nic_dealloc_vector_data(priv);
 
        hns3_uninit_all_ring(priv);
index b48faf769b1c9b88e30a87b388f913e49af64077..c1ea403d2b56798acdbda19b4d386c328abb5dbc 100644 (file)
@@ -1134,50 +1134,32 @@ static void hns3_get_channels(struct net_device *netdev,
                h->ae_algo->ops->get_channels(h, ch);
 }
 
-static int hns3_get_coalesce_per_queue(struct net_device *netdev, u32 queue,
-                                      struct ethtool_coalesce *cmd)
+static int hns3_get_coalesce(struct net_device *netdev,
+                            struct ethtool_coalesce *cmd)
 {
-       struct hns3_enet_tqp_vector *tx_vector, *rx_vector;
        struct hns3_nic_priv *priv = netdev_priv(netdev);
+       struct hns3_enet_coalesce *tx_coal = &priv->tx_coal;
+       struct hns3_enet_coalesce *rx_coal = &priv->rx_coal;
        struct hnae3_handle *h = priv->ae_handle;
-       u16 queue_num = h->kinfo.num_tqps;
 
        if (hns3_nic_resetting(netdev))
                return -EBUSY;
 
-       if (queue >= queue_num) {
-               netdev_err(netdev,
-                          "Invalid queue value %u! Queue max id=%u\n",
-                          queue, queue_num - 1);
-               return -EINVAL;
-       }
-
-       tx_vector = priv->ring[queue].tqp_vector;
-       rx_vector = priv->ring[queue_num + queue].tqp_vector;
+       cmd->use_adaptive_tx_coalesce = tx_coal->adapt_enable;
+       cmd->use_adaptive_rx_coalesce = rx_coal->adapt_enable;
 
-       cmd->use_adaptive_tx_coalesce =
-                       tx_vector->tx_group.coal.adapt_enable;
-       cmd->use_adaptive_rx_coalesce =
-                       rx_vector->rx_group.coal.adapt_enable;
-
-       cmd->tx_coalesce_usecs = tx_vector->tx_group.coal.int_gl;
-       cmd->rx_coalesce_usecs = rx_vector->rx_group.coal.int_gl;
+       cmd->tx_coalesce_usecs = tx_coal->int_gl;
+       cmd->rx_coalesce_usecs = rx_coal->int_gl;
 
        cmd->tx_coalesce_usecs_high = h->kinfo.int_rl_setting;
        cmd->rx_coalesce_usecs_high = h->kinfo.int_rl_setting;
 
-       cmd->tx_max_coalesced_frames = tx_vector->tx_group.coal.int_ql;
-       cmd->rx_max_coalesced_frames = rx_vector->rx_group.coal.int_ql;
+       cmd->tx_max_coalesced_frames = tx_coal->int_ql;
+       cmd->rx_max_coalesced_frames = rx_coal->int_ql;
 
        return 0;
 }
 
-static int hns3_get_coalesce(struct net_device *netdev,
-                            struct ethtool_coalesce *cmd)
-{
-       return hns3_get_coalesce_per_queue(netdev, 0, cmd);
-}
-
 static int hns3_check_gl_coalesce_para(struct net_device *netdev,
                                       struct ethtool_coalesce *cmd)
 {
@@ -1292,19 +1274,7 @@ static int hns3_check_coalesce_para(struct net_device *netdev,
                return ret;
        }
 
-       ret = hns3_check_ql_coalesce_param(netdev, cmd);
-       if (ret)
-               return ret;
-
-       if (cmd->use_adaptive_tx_coalesce == 1 ||
-           cmd->use_adaptive_rx_coalesce == 1) {
-               netdev_info(netdev,
-                           "adaptive-tx=%u and adaptive-rx=%u, tx_usecs or rx_usecs will changed dynamically.\n",
-                           cmd->use_adaptive_tx_coalesce,
-                           cmd->use_adaptive_rx_coalesce);
-       }
-
-       return 0;
+       return hns3_check_ql_coalesce_param(netdev, cmd);
 }
 
 static void hns3_set_coalesce_per_queue(struct net_device *netdev,
@@ -1350,6 +1320,9 @@ static int hns3_set_coalesce(struct net_device *netdev,
                             struct ethtool_coalesce *cmd)
 {
        struct hnae3_handle *h = hns3_get_handle(netdev);
+       struct hns3_nic_priv *priv = netdev_priv(netdev);
+       struct hns3_enet_coalesce *tx_coal = &priv->tx_coal;
+       struct hns3_enet_coalesce *rx_coal = &priv->rx_coal;
        u16 queue_num = h->kinfo.num_tqps;
        int ret;
        int i;
@@ -1364,6 +1337,15 @@ static int hns3_set_coalesce(struct net_device *netdev,
        h->kinfo.int_rl_setting =
                hns3_rl_round_down(cmd->rx_coalesce_usecs_high);
 
+       tx_coal->adapt_enable = cmd->use_adaptive_tx_coalesce;
+       rx_coal->adapt_enable = cmd->use_adaptive_rx_coalesce;
+
+       tx_coal->int_gl = cmd->tx_coalesce_usecs;
+       rx_coal->int_gl = cmd->rx_coalesce_usecs;
+
+       tx_coal->int_ql = cmd->tx_max_coalesced_frames;
+       rx_coal->int_ql = cmd->rx_max_coalesced_frames;
+
        for (i = 0; i < queue_num; i++)
                hns3_set_coalesce_per_queue(netdev, cmd, i);
 
index 8e5f9dc8791d289187430d251a8e253b85ad3f0d..f1c9f4ada348a77e8cda8fb974c9fd6795e73854 100644 (file)
@@ -710,7 +710,6 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
        unsigned int flag;
        int ret = 0;
 
-       memset(&resp_msg, 0, sizeof(resp_msg));
        /* handle all the mailbox requests in the queue */
        while (!hclge_cmd_crq_empty(&hdev->hw)) {
                if (test_bit(HCLGE_STATE_CMD_DISABLE, &hdev->state)) {
@@ -738,6 +737,9 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
 
                trace_hclge_pf_mbx_get(hdev, req);
 
+               /* clear the resp_msg before processing every mailbox message */
+               memset(&resp_msg, 0, sizeof(resp_msg));
+
                switch (req->msg.code) {
                case HCLGE_MBX_MAP_RING_TO_VECTOR:
                        ret = hclge_map_unmap_ring_to_vf_vector(vport, true,
index 988db46bff0eec77c37ef58112b4d8950f7a67dd..214a38de3f415012600bccb0af01a20e6f30c9f1 100644 (file)
@@ -467,12 +467,16 @@ static int ixgbe_set_vf_vlan(struct ixgbe_adapter *adapter, int add, int vid,
        return err;
 }
 
-static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
+static int ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 max_frame, u32 vf)
 {
        struct ixgbe_hw *hw = &adapter->hw;
-       int max_frame = msgbuf[1];
        u32 max_frs;
 
+       if (max_frame < ETH_MIN_MTU || max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) {
+               e_err(drv, "VF max_frame %d out of range\n", max_frame);
+               return -EINVAL;
+       }
+
        /*
         * For 82599EB we have to keep all PFs and VFs operating with
         * the same max_frame value in order to avoid sending an oversize
@@ -533,12 +537,6 @@ static s32 ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf, u32 vf)
                }
        }
 
-       /* MTU < 68 is an error and causes problems on some kernels */
-       if (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE) {
-               e_err(drv, "VF max_frame %d out of range\n", max_frame);
-               return -EINVAL;
-       }
-
        /* pull current max frame size from hardware */
        max_frs = IXGBE_READ_REG(hw, IXGBE_MAXFRS);
        max_frs &= IXGBE_MHADD_MFS_MASK;
@@ -1249,7 +1247,7 @@ static int ixgbe_rcv_msg_from_vf(struct ixgbe_adapter *adapter, u32 vf)
                retval = ixgbe_set_vf_vlan_msg(adapter, msgbuf, vf);
                break;
        case IXGBE_VF_SET_LPE:
-               retval = ixgbe_set_vf_lpe(adapter, msgbuf, vf);
+               retval = ixgbe_set_vf_lpe(adapter, msgbuf[1], vf);
                break;
        case IXGBE_VF_SET_MACVLAN:
                retval = ixgbe_set_vf_macvlan_msg(adapter, msgbuf, vf);
index 6f987a7ffcb36e51755972b87f1606d813863af9..b30a45725374b48174fba0b0001644a22e963b54 100644 (file)
@@ -1315,23 +1315,23 @@ static int korina_probe(struct platform_device *pdev)
        lp->tx_irq = platform_get_irq_byname(pdev, "tx");
 
        p = devm_platform_ioremap_resource_byname(pdev, "emac");
-       if (!p) {
+       if (IS_ERR(p)) {
                printk(KERN_ERR DRV_NAME ": cannot remap registers\n");
-               return -ENOMEM;
+               return PTR_ERR(p);
        }
        lp->eth_regs = p;
 
        p = devm_platform_ioremap_resource_byname(pdev, "dma_rx");
-       if (!p) {
+       if (IS_ERR(p)) {
                printk(KERN_ERR DRV_NAME ": cannot remap Rx DMA registers\n");
-               return -ENOMEM;
+               return PTR_ERR(p);
        }
        lp->rx_dma_regs = p;
 
        p = devm_platform_ioremap_resource_byname(pdev, "dma_tx");
-       if (!p) {
+       if (IS_ERR(p)) {
                printk(KERN_ERR DRV_NAME ": cannot remap Tx DMA registers\n");
-               return -ENOMEM;
+               return PTR_ERR(p);
        }
        lp->tx_dma_regs = p;
 
index 41c2ad210bc99c65175dd79f551a77df0c098caf..36dc3e5f621897c50ca477f5311e38f64733a0bb 100644 (file)
@@ -154,6 +154,7 @@ static int xrx200_close(struct net_device *net_dev)
 
 static int xrx200_alloc_skb(struct xrx200_chan *ch)
 {
+       dma_addr_t mapping;
        int ret = 0;
 
        ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev,
@@ -163,16 +164,17 @@ static int xrx200_alloc_skb(struct xrx200_chan *ch)
                goto skip;
        }
 
-       ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(ch->priv->dev,
-                       ch->skb[ch->dma.desc]->data, XRX200_DMA_DATA_LEN,
-                       DMA_FROM_DEVICE);
-       if (unlikely(dma_mapping_error(ch->priv->dev,
-                                      ch->dma.desc_base[ch->dma.desc].addr))) {
+       mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data,
+                                XRX200_DMA_DATA_LEN, DMA_FROM_DEVICE);
+       if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) {
                dev_kfree_skb_any(ch->skb[ch->dma.desc]);
                ret = -ENOMEM;
                goto skip;
        }
 
+       ch->dma.desc_base[ch->dma.desc].addr = mapping;
+       /* Make sure the address is written before we give it to HW */
+       wmb();
 skip:
        ch->dma.desc_base[ch->dma.desc].ctl =
                LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
@@ -196,6 +198,8 @@ static int xrx200_hw_receive(struct xrx200_chan *ch)
        ch->dma.desc %= LTQ_DESC_NUM;
 
        if (ret) {
+               ch->skb[ch->dma.desc] = skb;
+               net_dev->stats.rx_dropped++;
                netdev_err(net_dev, "failed to allocate new rx buffer\n");
                return ret;
        }
index 8edba5ea90f03bac6004a3cc43e119161ce0d1ad..4a61c90003b5ead489bc5147fc068c3d12976b3c 100644 (file)
@@ -993,6 +993,14 @@ enum mvpp22_ptp_packet_format {
 
 #define MVPP2_DESC_DMA_MASK    DMA_BIT_MASK(40)
 
+/* Buffer header info bits */
+#define MVPP2_B_HDR_INFO_MC_ID_MASK    0xfff
+#define MVPP2_B_HDR_INFO_MC_ID(info)   ((info) & MVPP2_B_HDR_INFO_MC_ID_MASK)
+#define MVPP2_B_HDR_INFO_LAST_OFFS     12
+#define MVPP2_B_HDR_INFO_LAST_MASK     BIT(12)
+#define MVPP2_B_HDR_INFO_IS_LAST(info) \
+          (((info) & MVPP2_B_HDR_INFO_LAST_MASK) >> MVPP2_B_HDR_INFO_LAST_OFFS)
+
 struct mvpp2_tai;
 
 /* Definitions */
@@ -1002,6 +1010,20 @@ struct mvpp2_rss_table {
        u32 indir[MVPP22_RSS_TABLE_ENTRIES];
 };
 
+struct mvpp2_buff_hdr {
+       __le32 next_phys_addr;
+       __le32 next_dma_addr;
+       __le16 byte_count;
+       __le16 info;
+       __le16 reserved1;       /* bm_qset (for future use, BM) */
+       u8 next_phys_addr_high;
+       u8 next_dma_addr_high;
+       __le16 reserved2;
+       __le16 reserved3;
+       __le16 reserved4;
+       __le16 reserved5;
+};
+
 /* Shared Packet Processor resources */
 struct mvpp2 {
        /* Shared registers' base addresses */
index ec706d614cacc146221bcaf037f7a46c9162add7..d39c7639cdbab16b5688d294d7e55ac71421853f 100644 (file)
@@ -3839,6 +3839,35 @@ mvpp2_run_xdp(struct mvpp2_port *port, struct mvpp2_rx_queue *rxq,
        return ret;
 }
 
+static void mvpp2_buff_hdr_pool_put(struct mvpp2_port *port, struct mvpp2_rx_desc *rx_desc,
+                                   int pool, u32 rx_status)
+{
+       phys_addr_t phys_addr, phys_addr_next;
+       dma_addr_t dma_addr, dma_addr_next;
+       struct mvpp2_buff_hdr *buff_hdr;
+
+       phys_addr = mvpp2_rxdesc_dma_addr_get(port, rx_desc);
+       dma_addr = mvpp2_rxdesc_cookie_get(port, rx_desc);
+
+       do {
+               buff_hdr = (struct mvpp2_buff_hdr *)phys_to_virt(phys_addr);
+
+               phys_addr_next = le32_to_cpu(buff_hdr->next_phys_addr);
+               dma_addr_next = le32_to_cpu(buff_hdr->next_dma_addr);
+
+               if (port->priv->hw_version >= MVPP22) {
+                       phys_addr_next |= ((u64)buff_hdr->next_phys_addr_high << 32);
+                       dma_addr_next |= ((u64)buff_hdr->next_dma_addr_high << 32);
+               }
+
+               mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
+
+               phys_addr = phys_addr_next;
+               dma_addr = dma_addr_next;
+
+       } while (!MVPP2_B_HDR_INFO_IS_LAST(le16_to_cpu(buff_hdr->info)));
+}
+
 /* Main rx processing */
 static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
                    int rx_todo, struct mvpp2_rx_queue *rxq)
@@ -3885,14 +3914,6 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
                        MVPP2_RXD_BM_POOL_ID_OFFS;
                bm_pool = &port->priv->bm_pools[pool];
 
-               /* In case of an error, release the requested buffer pointer
-                * to the Buffer Manager. This request process is controlled
-                * by the hardware, and the information about the buffer is
-                * comprised by the RX descriptor.
-                */
-               if (rx_status & MVPP2_RXD_ERR_SUMMARY)
-                       goto err_drop_frame;
-
                if (port->priv->percpu_pools) {
                        pp = port->priv->page_pool[pool];
                        dma_dir = page_pool_get_dma_dir(pp);
@@ -3904,6 +3925,18 @@ static int mvpp2_rx(struct mvpp2_port *port, struct napi_struct *napi,
                                        rx_bytes + MVPP2_MH_SIZE,
                                        dma_dir);
 
+               /* Buffer header not supported */
+               if (rx_status & MVPP2_RXD_BUF_HDR)
+                       goto err_drop_frame;
+
+               /* In case of an error, release the requested buffer pointer
+                * to the Buffer Manager. This request process is controlled
+                * by the hardware, and the information about the buffer is
+                * comprised by the RX descriptor.
+                */
+               if (rx_status & MVPP2_RXD_ERR_SUMMARY)
+                       goto err_drop_frame;
+
                /* Prefetch header */
                prefetch(data);
 
@@ -3985,7 +4018,10 @@ err_drop_frame:
                dev->stats.rx_errors++;
                mvpp2_rx_error(port, rx_desc);
                /* Return the buffer to the pool */
-               mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
+               if (rx_status & MVPP2_RXD_BUF_HDR)
+                       mvpp2_buff_hdr_pool_put(port, rx_desc, pool, rx_status);
+               else
+                       mvpp2_bm_pool_put(port, pool, dma_addr, phys_addr);
        }
 
        rcu_read_unlock();
index f4962a97a0757ca5cf6b95f396a8698bfa5f4e3f..9d9a2e438acfcdbb4365918b54eaae3bd757cc6f 100644 (file)
@@ -786,6 +786,10 @@ static int otx2_set_rxfh_context(struct net_device *dev, const u32 *indir,
        if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
                return -EOPNOTSUPP;
 
+       if (*rss_context != ETH_RXFH_CONTEXT_ALLOC &&
+           *rss_context >= MAX_RSS_GROUPS)
+               return -EINVAL;
+
        rss = &pfvf->hw.rss_info;
 
        if (!rss->enable) {
index ed4eacef17cea42a5ab32dbaadab6995face80a5..64adfd24e134d80ec341cf2ed5055e054ecc9b57 100644 (file)
@@ -681,32 +681,53 @@ static int mtk_set_mac_address(struct net_device *dev, void *p)
 void mtk_stats_update_mac(struct mtk_mac *mac)
 {
        struct mtk_hw_stats *hw_stats = mac->hw_stats;
-       unsigned int base = MTK_GDM1_TX_GBCNT;
-       u64 stats;
-
-       base += hw_stats->reg_offset;
+       struct mtk_eth *eth = mac->hw;
 
        u64_stats_update_begin(&hw_stats->syncp);
 
-       hw_stats->rx_bytes += mtk_r32(mac->hw, base);
-       stats =  mtk_r32(mac->hw, base + 0x04);
-       if (stats)
-               hw_stats->rx_bytes += (stats << 32);
-       hw_stats->rx_packets += mtk_r32(mac->hw, base + 0x08);
-       hw_stats->rx_overflow += mtk_r32(mac->hw, base + 0x10);
-       hw_stats->rx_fcs_errors += mtk_r32(mac->hw, base + 0x14);
-       hw_stats->rx_short_errors += mtk_r32(mac->hw, base + 0x18);
-       hw_stats->rx_long_errors += mtk_r32(mac->hw, base + 0x1c);
-       hw_stats->rx_checksum_errors += mtk_r32(mac->hw, base + 0x20);
-       hw_stats->rx_flow_control_packets +=
-                                       mtk_r32(mac->hw, base + 0x24);
-       hw_stats->tx_skip += mtk_r32(mac->hw, base + 0x28);
-       hw_stats->tx_collisions += mtk_r32(mac->hw, base + 0x2c);
-       hw_stats->tx_bytes += mtk_r32(mac->hw, base + 0x30);
-       stats =  mtk_r32(mac->hw, base + 0x34);
-       if (stats)
-               hw_stats->tx_bytes += (stats << 32);
-       hw_stats->tx_packets += mtk_r32(mac->hw, base + 0x38);
+       if (MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628)) {
+               hw_stats->tx_packets += mtk_r32(mac->hw, MT7628_SDM_TPCNT);
+               hw_stats->tx_bytes += mtk_r32(mac->hw, MT7628_SDM_TBCNT);
+               hw_stats->rx_packets += mtk_r32(mac->hw, MT7628_SDM_RPCNT);
+               hw_stats->rx_bytes += mtk_r32(mac->hw, MT7628_SDM_RBCNT);
+               hw_stats->rx_checksum_errors +=
+                       mtk_r32(mac->hw, MT7628_SDM_CS_ERR);
+       } else {
+               unsigned int offs = hw_stats->reg_offset;
+               u64 stats;
+
+               hw_stats->rx_bytes += mtk_r32(mac->hw,
+                                             MTK_GDM1_RX_GBCNT_L + offs);
+               stats = mtk_r32(mac->hw, MTK_GDM1_RX_GBCNT_H + offs);
+               if (stats)
+                       hw_stats->rx_bytes += (stats << 32);
+               hw_stats->rx_packets +=
+                       mtk_r32(mac->hw, MTK_GDM1_RX_GPCNT + offs);
+               hw_stats->rx_overflow +=
+                       mtk_r32(mac->hw, MTK_GDM1_RX_OERCNT + offs);
+               hw_stats->rx_fcs_errors +=
+                       mtk_r32(mac->hw, MTK_GDM1_RX_FERCNT + offs);
+               hw_stats->rx_short_errors +=
+                       mtk_r32(mac->hw, MTK_GDM1_RX_SERCNT + offs);
+               hw_stats->rx_long_errors +=
+                       mtk_r32(mac->hw, MTK_GDM1_RX_LENCNT + offs);
+               hw_stats->rx_checksum_errors +=
+                       mtk_r32(mac->hw, MTK_GDM1_RX_CERCNT + offs);
+               hw_stats->rx_flow_control_packets +=
+                       mtk_r32(mac->hw, MTK_GDM1_RX_FCCNT + offs);
+               hw_stats->tx_skip +=
+                       mtk_r32(mac->hw, MTK_GDM1_TX_SKIPCNT + offs);
+               hw_stats->tx_collisions +=
+                       mtk_r32(mac->hw, MTK_GDM1_TX_COLCNT + offs);
+               hw_stats->tx_bytes +=
+                       mtk_r32(mac->hw, MTK_GDM1_TX_GBCNT_L + offs);
+               stats =  mtk_r32(mac->hw, MTK_GDM1_TX_GBCNT_H + offs);
+               if (stats)
+                       hw_stats->tx_bytes += (stats << 32);
+               hw_stats->tx_packets +=
+                       mtk_r32(mac->hw, MTK_GDM1_TX_GPCNT + offs);
+       }
+
        u64_stats_update_end(&hw_stats->syncp);
 }
 
@@ -2423,7 +2444,8 @@ static void mtk_dim_rx(struct work_struct *work)
        val |= cur << MTK_PDMA_DELAY_RX_PINT_SHIFT;
 
        mtk_w32(eth, val, MTK_PDMA_DELAY_INT);
-       mtk_w32(eth, val, MTK_QDMA_DELAY_INT);
+       if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+               mtk_w32(eth, val, MTK_QDMA_DELAY_INT);
 
        spin_unlock_bh(&eth->dim_lock);
 
@@ -2452,7 +2474,8 @@ static void mtk_dim_tx(struct work_struct *work)
        val |= cur << MTK_PDMA_DELAY_TX_PINT_SHIFT;
 
        mtk_w32(eth, val, MTK_PDMA_DELAY_INT);
-       mtk_w32(eth, val, MTK_QDMA_DELAY_INT);
+       if (MTK_HAS_CAPS(eth->soc->caps, MTK_QDMA))
+               mtk_w32(eth, val, MTK_QDMA_DELAY_INT);
 
        spin_unlock_bh(&eth->dim_lock);
 
@@ -2480,6 +2503,10 @@ static int mtk_hw_init(struct mtk_eth *eth)
                        goto err_disable_pm;
                }
 
+               /* set interrupt delays based on current Net DIM sample */
+               mtk_dim_rx(&eth->rx_dim.work);
+               mtk_dim_tx(&eth->tx_dim.work);
+
                /* disable delay and normal interrupt */
                mtk_tx_irq_disable(eth, ~0);
                mtk_rx_irq_disable(eth, ~0);
index 11331b44ba07966ee3baef60da719c1343dfc4df..5ef70dd8b49c655c8d954f96b0fb9c0228d94489 100644 (file)
 /* QDMA FQ Free Page Buffer Length Register */
 #define MTK_QDMA_FQ_BLEN       0x1B2C
 
-/* GMA1 Received Good Byte Count Register */
-#define MTK_GDM1_TX_GBCNT      0x2400
+/* GMA1 counter / statics register */
+#define MTK_GDM1_RX_GBCNT_L    0x2400
+#define MTK_GDM1_RX_GBCNT_H    0x2404
+#define MTK_GDM1_RX_GPCNT      0x2408
+#define MTK_GDM1_RX_OERCNT     0x2410
+#define MTK_GDM1_RX_FERCNT     0x2414
+#define MTK_GDM1_RX_SERCNT     0x2418
+#define MTK_GDM1_RX_LENCNT     0x241c
+#define MTK_GDM1_RX_CERCNT     0x2420
+#define MTK_GDM1_RX_FCCNT      0x2424
+#define MTK_GDM1_TX_SKIPCNT    0x2428
+#define MTK_GDM1_TX_COLCNT     0x242c
+#define MTK_GDM1_TX_GBCNT_L    0x2430
+#define MTK_GDM1_TX_GBCNT_H    0x2434
+#define MTK_GDM1_TX_GPCNT      0x2438
 #define MTK_STAT_OFFSET                0x40
 
 /* QDMA descriptor txd4 */
 #define MT7628_SDM_MAC_ADRL    (MT7628_SDM_OFFSET + 0x0c)
 #define MT7628_SDM_MAC_ADRH    (MT7628_SDM_OFFSET + 0x10)
 
+/* Counter / stat register */
+#define MT7628_SDM_TPCNT       (MT7628_SDM_OFFSET + 0x100)
+#define MT7628_SDM_TBCNT       (MT7628_SDM_OFFSET + 0x104)
+#define MT7628_SDM_RPCNT       (MT7628_SDM_OFFSET + 0x108)
+#define MT7628_SDM_RBCNT       (MT7628_SDM_OFFSET + 0x10c)
+#define MT7628_SDM_CS_ERR      (MT7628_SDM_OFFSET + 0x110)
+
 struct mtk_rx_dma {
        unsigned int rxd1;
        unsigned int rxd2;
index 1434df66fcf2ee0910d086e44694dfd35d7f1039..3616b77caa0adb407288c51297e580a7f415bb13 100644 (file)
@@ -2027,8 +2027,6 @@ static int mlx4_en_set_tunable(struct net_device *dev,
        return ret;
 }
 
-#define MLX4_EEPROM_PAGE_LEN 256
-
 static int mlx4_en_get_module_info(struct net_device *dev,
                                   struct ethtool_modinfo *modinfo)
 {
@@ -2063,7 +2061,7 @@ static int mlx4_en_get_module_info(struct net_device *dev,
                break;
        case MLX4_MODULE_ID_SFP:
                modinfo->type = ETH_MODULE_SFF_8472;
-               modinfo->eeprom_len = MLX4_EEPROM_PAGE_LEN;
+               modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
                break;
        default:
                return -EINVAL;
index ba6ac31a339dc3c6c84ff30eea9d8126ab2279b9..256a06b3c096b302a0196d71fe02bca3182db580 100644 (file)
@@ -1973,6 +1973,7 @@ EXPORT_SYMBOL(mlx4_get_roce_gid_from_slave);
 #define I2C_ADDR_LOW  0x50
 #define I2C_ADDR_HIGH 0x51
 #define I2C_PAGE_SIZE 256
+#define I2C_HIGH_PAGE_SIZE 128
 
 /* Module Info Data */
 struct mlx4_cable_info {
@@ -2026,6 +2027,88 @@ static inline const char *cable_info_mad_err_str(u16 mad_status)
        return "Unknown Error";
 }
 
+static int mlx4_get_module_id(struct mlx4_dev *dev, u8 port, u8 *module_id)
+{
+       struct mlx4_cmd_mailbox *inbox, *outbox;
+       struct mlx4_mad_ifc *inmad, *outmad;
+       struct mlx4_cable_info *cable_info;
+       int ret;
+
+       inbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(inbox))
+               return PTR_ERR(inbox);
+
+       outbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(outbox)) {
+               mlx4_free_cmd_mailbox(dev, inbox);
+               return PTR_ERR(outbox);
+       }
+
+       inmad = (struct mlx4_mad_ifc *)(inbox->buf);
+       outmad = (struct mlx4_mad_ifc *)(outbox->buf);
+
+       inmad->method = 0x1; /* Get */
+       inmad->class_version = 0x1;
+       inmad->mgmt_class = 0x1;
+       inmad->base_version = 0x1;
+       inmad->attr_id = cpu_to_be16(0xFF60); /* Module Info */
+
+       cable_info = (struct mlx4_cable_info *)inmad->data;
+       cable_info->dev_mem_address = 0;
+       cable_info->page_num = 0;
+       cable_info->i2c_addr = I2C_ADDR_LOW;
+       cable_info->size = cpu_to_be16(1);
+
+       ret = mlx4_cmd_box(dev, inbox->dma, outbox->dma, port, 3,
+                          MLX4_CMD_MAD_IFC, MLX4_CMD_TIME_CLASS_C,
+                          MLX4_CMD_NATIVE);
+       if (ret)
+               goto out;
+
+       if (be16_to_cpu(outmad->status)) {
+               /* Mad returned with bad status */
+               ret = be16_to_cpu(outmad->status);
+               mlx4_warn(dev,
+                         "MLX4_CMD_MAD_IFC Get Module ID attr(%x) port(%d) i2c_addr(%x) offset(%d) size(%d): Response Mad Status(%x) - %s\n",
+                         0xFF60, port, I2C_ADDR_LOW, 0, 1, ret,
+                         cable_info_mad_err_str(ret));
+               ret = -ret;
+               goto out;
+       }
+       cable_info = (struct mlx4_cable_info *)outmad->data;
+       *module_id = cable_info->data[0];
+out:
+       mlx4_free_cmd_mailbox(dev, inbox);
+       mlx4_free_cmd_mailbox(dev, outbox);
+       return ret;
+}
+
+static void mlx4_sfp_eeprom_params_set(u8 *i2c_addr, u8 *page_num, u16 *offset)
+{
+       *i2c_addr = I2C_ADDR_LOW;
+       *page_num = 0;
+
+       if (*offset < I2C_PAGE_SIZE)
+               return;
+
+       *i2c_addr = I2C_ADDR_HIGH;
+       *offset -= I2C_PAGE_SIZE;
+}
+
+static void mlx4_qsfp_eeprom_params_set(u8 *i2c_addr, u8 *page_num, u16 *offset)
+{
+       /* Offsets 0-255 belong to page 0.
+        * Offsets 256-639 belong to pages 01, 02, 03.
+        * For example, offset 400 is page 02: 1 + (400 - 256) / 128 = 2
+        */
+       if (*offset < I2C_PAGE_SIZE)
+               *page_num = 0;
+       else
+               *page_num = 1 + (*offset - I2C_PAGE_SIZE) / I2C_HIGH_PAGE_SIZE;
+       *i2c_addr = I2C_ADDR_LOW;
+       *offset -= *page_num * I2C_HIGH_PAGE_SIZE;
+}
+
 /**
  * mlx4_get_module_info - Read cable module eeprom data
  * @dev: mlx4_dev.
@@ -2045,12 +2128,30 @@ int mlx4_get_module_info(struct mlx4_dev *dev, u8 port,
        struct mlx4_cmd_mailbox *inbox, *outbox;
        struct mlx4_mad_ifc *inmad, *outmad;
        struct mlx4_cable_info *cable_info;
-       u16 i2c_addr;
+       u8 module_id, i2c_addr, page_num;
        int ret;
 
        if (size > MODULE_INFO_MAX_READ)
                size = MODULE_INFO_MAX_READ;
 
+       ret = mlx4_get_module_id(dev, port, &module_id);
+       if (ret)
+               return ret;
+
+       switch (module_id) {
+       case MLX4_MODULE_ID_SFP:
+               mlx4_sfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
+               break;
+       case MLX4_MODULE_ID_QSFP:
+       case MLX4_MODULE_ID_QSFP_PLUS:
+       case MLX4_MODULE_ID_QSFP28:
+               mlx4_qsfp_eeprom_params_set(&i2c_addr, &page_num, &offset);
+               break;
+       default:
+               mlx4_err(dev, "Module ID not recognized: %#x\n", module_id);
+               return -EINVAL;
+       }
+
        inbox = mlx4_alloc_cmd_mailbox(dev);
        if (IS_ERR(inbox))
                return PTR_ERR(inbox);
@@ -2076,11 +2177,9 @@ int mlx4_get_module_info(struct mlx4_dev *dev, u8 port,
                 */
                size -= offset + size - I2C_PAGE_SIZE;
 
-       i2c_addr = I2C_ADDR_LOW;
-
        cable_info = (struct mlx4_cable_info *)inmad->data;
        cable_info->dev_mem_address = cpu_to_be16(offset);
-       cable_info->page_num = 0;
+       cable_info->page_num = page_num;
        cable_info->i2c_addr = i2c_addr;
        cable_info->size = cpu_to_be16(size);
 
index 95f2b26a3ee316c5f73b42a24ebad573f3b0345d..9c076aa20306a7d2bd116b85dfac000bcafaa3f0 100644 (file)
@@ -223,6 +223,8 @@ static void mlx5e_rep_changelowerstate_event(struct net_device *netdev, void *pt
        rpriv = priv->ppriv;
        fwd_vport_num = rpriv->rep->vport;
        lag_dev = netdev_master_upper_dev_get(netdev);
+       if (!lag_dev)
+               return;
 
        netdev_dbg(netdev, "lag_dev(%s)'s slave vport(%d) is txable(%d)\n",
                   lag_dev->name, fwd_vport_num, net_lag_port_dev_txable(netdev));
index 6cdc52d50a488a9a372719f7fb5252fa76f85f97..3113822618402f9854e3c83d0aa6af26ffc9dd93 100644 (file)
@@ -626,7 +626,7 @@ static bool mlx5e_restore_skb(struct sk_buff *skb, u32 chain, u32 reg_c1,
                struct mlx5_eswitch *esw;
                u32 zone_restore_id;
 
-               tc_skb_ext = skb_ext_add(skb, TC_SKB_EXT);
+               tc_skb_ext = tc_skb_ext_alloc(skb);
                if (!tc_skb_ext) {
                        WARN_ON(1);
                        return false;
index 593503bc4d0785a8699edb1b624577ffc2e8403a..f1fb11680d2026b5a7d07add4959c409971994e8 100644 (file)
@@ -1505,7 +1505,7 @@ mlx5e_init_fib_work_ipv4(struct mlx5e_priv *priv,
 
        fen_info = container_of(info, struct fib_entry_notifier_info, info);
        fib_dev = fib_info_nh(fen_info->fi, 0)->fib_nh_dev;
-       if (fib_dev->netdev_ops != &mlx5e_netdev_ops ||
+       if (!fib_dev || fib_dev->netdev_ops != &mlx5e_netdev_ops ||
            fen_info->dst_len != 32)
                return NULL;
 
index 0d571a0c76d90aec5c70e5497292f3de33776d3c..0b75fab41ae8f819737cd31d5178bec847621536 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/ipv6.h>
 #include <linux/tcp.h>
 #include <linux/mlx5/fs.h>
+#include <linux/mlx5/mpfs.h>
 #include "en.h"
 #include "en_rep.h"
 #include "lib/mpfs.h"
index bca832cdc4cbe22bd3a26d9ac847311f32bb9738..ad0f69480b9ca1d3c8609b01da74c4be4acc28b2 100644 (file)
@@ -889,10 +889,13 @@ err_free_rq:
 void mlx5e_activate_rq(struct mlx5e_rq *rq)
 {
        set_bit(MLX5E_RQ_STATE_ENABLED, &rq->state);
-       if (rq->icosq)
+       if (rq->icosq) {
                mlx5e_trigger_irq(rq->icosq);
-       else
+       } else {
+               local_bh_disable();
                napi_schedule(rq->cq.napi);
+               local_bh_enable();
+       }
 }
 
 void mlx5e_deactivate_rq(struct mlx5e_rq *rq)
@@ -2697,7 +2700,7 @@ static int mlx5e_update_netdev_queues(struct mlx5e_priv *priv)
        int err;
 
        old_num_txqs = netdev->real_num_tx_queues;
-       old_ntc = netdev->num_tc;
+       old_ntc = netdev->num_tc ? : 1;
 
        nch = priv->channels.params.num_channels;
        ntc = priv->channels.params.num_tc;
@@ -5229,6 +5232,11 @@ static void mlx5e_update_features(struct net_device *netdev)
        rtnl_unlock();
 }
 
+static void mlx5e_reset_channels(struct net_device *netdev)
+{
+       netdev_reset_tc(netdev);
+}
+
 int mlx5e_attach_netdev(struct mlx5e_priv *priv)
 {
        const bool take_rtnl = priv->netdev->reg_state == NETREG_REGISTERED;
@@ -5283,6 +5291,7 @@ err_cleanup_tx:
        profile->cleanup_tx(priv);
 
 out:
+       mlx5e_reset_channels(priv->netdev);
        set_bit(MLX5E_STATE_DESTROYING, &priv->state);
        cancel_work_sync(&priv->update_stats_work);
        return err;
@@ -5300,6 +5309,7 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv)
 
        profile->cleanup_rx(priv);
        profile->cleanup_tx(priv);
+       mlx5e_reset_channels(priv->netdev);
        cancel_work_sync(&priv->update_stats_work);
 }
 
index 47a9c49b25fd1bc39137e3e803094aa09fd2ee7d..2c776e7a7692a1386848f350d41d77ee577a6e9c 100644 (file)
@@ -1322,10 +1322,10 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
                      struct netlink_ext_ack *extack)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
-       struct net_device *out_dev, *encap_dev = NULL;
        struct mlx5e_tc_flow_parse_attr *parse_attr;
        struct mlx5_flow_attr *attr = flow->attr;
        bool vf_tun = false, encap_valid = true;
+       struct net_device *encap_dev = NULL;
        struct mlx5_esw_flow_attr *esw_attr;
        struct mlx5_fc *counter = NULL;
        struct mlx5e_rep_priv *rpriv;
@@ -1371,16 +1371,22 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
        esw_attr = attr->esw_attr;
 
        for (out_index = 0; out_index < MLX5_MAX_FLOW_FWD_VPORTS; out_index++) {
+               struct net_device *out_dev;
                int mirred_ifindex;
 
                if (!(esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP))
                        continue;
 
                mirred_ifindex = parse_attr->mirred_ifindex[out_index];
-               out_dev = __dev_get_by_index(dev_net(priv->netdev),
-                                            mirred_ifindex);
+               out_dev = dev_get_by_index(dev_net(priv->netdev), mirred_ifindex);
+               if (!out_dev) {
+                       NL_SET_ERR_MSG_MOD(extack, "Requested mirred device not found");
+                       err = -ENODEV;
+                       goto err_out;
+               }
                err = mlx5e_attach_encap(priv, flow, out_dev, out_index,
                                         extack, &encap_dev, &encap_valid);
+               dev_put(out_dev);
                if (err)
                        goto err_out;
 
@@ -1393,6 +1399,12 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
                esw_attr->dests[out_index].mdev = out_priv->mdev;
        }
 
+       if (vf_tun && esw_attr->out_count > 1) {
+               NL_SET_ERR_MSG_MOD(extack, "VF tunnel encap with mirroring is not supported");
+               err = -EOPNOTSUPP;
+               goto err_out;
+       }
+
        err = mlx5_eswitch_add_vlan_action(esw, attr);
        if (err)
                goto err_out;
@@ -3526,8 +3538,12 @@ static int add_vlan_push_action(struct mlx5e_priv *priv,
        if (err)
                return err;
 
-       *out_dev = dev_get_by_index_rcu(dev_net(vlan_dev),
-                                       dev_get_iflink(vlan_dev));
+       rcu_read_lock();
+       *out_dev = dev_get_by_index_rcu(dev_net(vlan_dev), dev_get_iflink(vlan_dev));
+       rcu_read_unlock();
+       if (!*out_dev)
+               return -ENODEV;
+
        if (is_vlan_dev(*out_dev))
                err = add_vlan_push_action(priv, attr, out_dev, action);
 
@@ -5074,7 +5090,7 @@ bool mlx5e_tc_update_skb(struct mlx5_cqe64 *cqe,
 
        if (mapped_obj.type == MLX5_MAPPED_OBJ_CHAIN) {
                chain = mapped_obj.chain;
-               tc_skb_ext = skb_ext_add(skb, TC_SKB_EXT);
+               tc_skb_ext = tc_skb_ext_alloc(skb);
                if (WARN_ON(!tc_skb_ext))
                        return false;
 
index 570f2280823c0671ced01947b67150c41f9db3bc..b88705a3a1a8e515251ca5b3961a2406917d1fd3 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/mlx5/mlx5_ifc.h>
 #include <linux/mlx5/vport.h>
 #include <linux/mlx5/fs.h>
+#include <linux/mlx5/mpfs.h>
 #include "esw/acl/lgcy.h"
 #include "esw/legacy.h"
 #include "mlx5_core.h"
index a81ece94f59910c00cc1123d16f89540ed64d6cf..b459549058450ab890f6093050d484926a5e232a 100644 (file)
@@ -65,7 +65,7 @@ mlx5_eswitch_termtbl_create(struct mlx5_core_dev *dev,
 {
        struct mlx5_flow_table_attr ft_attr = {};
        struct mlx5_flow_namespace *root_ns;
-       int err;
+       int err, err2;
 
        root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB);
        if (!root_ns) {
@@ -76,33 +76,34 @@ mlx5_eswitch_termtbl_create(struct mlx5_core_dev *dev,
        /* As this is the terminating action then the termination table is the
         * same prio as the slow path
         */
-       ft_attr.flags = MLX5_FLOW_TABLE_TERMINATION |
+       ft_attr.flags = MLX5_FLOW_TABLE_TERMINATION | MLX5_FLOW_TABLE_UNMANAGED |
                        MLX5_FLOW_TABLE_TUNNEL_EN_REFORMAT;
-       ft_attr.prio = FDB_SLOW_PATH;
+       ft_attr.prio = FDB_TC_OFFLOAD;
        ft_attr.max_fte = 1;
+       ft_attr.level = 1;
        ft_attr.autogroup.max_num_groups = 1;
        tt->termtbl = mlx5_create_auto_grouped_flow_table(root_ns, &ft_attr);
        if (IS_ERR(tt->termtbl)) {
-               esw_warn(dev, "Failed to create termination table (error %d)\n",
-                        IS_ERR(tt->termtbl));
-               return -EOPNOTSUPP;
+               err = PTR_ERR(tt->termtbl);
+               esw_warn(dev, "Failed to create termination table, err %pe\n", tt->termtbl);
+               return err;
        }
 
        tt->rule = mlx5_add_flow_rules(tt->termtbl, NULL, flow_act,
                                       &tt->dest, 1);
        if (IS_ERR(tt->rule)) {
-               esw_warn(dev, "Failed to create termination table rule (error %d)\n",
-                        IS_ERR(tt->rule));
+               err = PTR_ERR(tt->rule);
+               esw_warn(dev, "Failed to create termination table rule, err %pe\n", tt->rule);
                goto add_flow_err;
        }
        return 0;
 
 add_flow_err:
-       err = mlx5_destroy_flow_table(tt->termtbl);
-       if (err)
-               esw_warn(dev, "Failed to destroy termination table\n");
+       err2 = mlx5_destroy_flow_table(tt->termtbl);
+       if (err2)
+               esw_warn(dev, "Failed to destroy termination table, err %d\n", err2);
 
-       return -EOPNOTSUPP;
+       return err;
 }
 
 static struct mlx5_termtbl_handle *
@@ -172,19 +173,6 @@ mlx5_eswitch_termtbl_put(struct mlx5_eswitch *esw,
        }
 }
 
-static bool mlx5_eswitch_termtbl_is_encap_reformat(struct mlx5_pkt_reformat *rt)
-{
-       switch (rt->reformat_type) {
-       case MLX5_REFORMAT_TYPE_L2_TO_VXLAN:
-       case MLX5_REFORMAT_TYPE_L2_TO_NVGRE:
-       case MLX5_REFORMAT_TYPE_L2_TO_L2_TUNNEL:
-       case MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL:
-               return true;
-       default:
-               return false;
-       }
-}
-
 static void
 mlx5_eswitch_termtbl_actions_move(struct mlx5_flow_act *src,
                                  struct mlx5_flow_act *dst)
@@ -202,14 +190,6 @@ mlx5_eswitch_termtbl_actions_move(struct mlx5_flow_act *src,
                        memset(&src->vlan[1], 0, sizeof(src->vlan[1]));
                }
        }
-
-       if (src->action & MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT &&
-           mlx5_eswitch_termtbl_is_encap_reformat(src->pkt_reformat)) {
-               src->action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
-               dst->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
-               dst->pkt_reformat = src->pkt_reformat;
-               src->pkt_reformat = NULL;
-       }
 }
 
 static bool mlx5_eswitch_offload_is_uplink_port(const struct mlx5_eswitch *esw,
@@ -238,6 +218,7 @@ mlx5_eswitch_termtbl_required(struct mlx5_eswitch *esw,
        int i;
 
        if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, termination_table) ||
+           !MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ignore_flow_level) ||
            attr->flags & MLX5_ESW_ATTR_FLAG_SLOW_PATH ||
            !mlx5_eswitch_offload_is_uplink_port(esw, spec))
                return false;
@@ -279,12 +260,19 @@ mlx5_eswitch_add_termtbl_rule(struct mlx5_eswitch *esw,
                if (dest[i].type != MLX5_FLOW_DESTINATION_TYPE_VPORT)
                        continue;
 
+               if (attr->dests[num_vport_dests].flags & MLX5_ESW_DEST_ENCAP) {
+                       term_tbl_act.action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
+                       term_tbl_act.pkt_reformat = attr->dests[num_vport_dests].pkt_reformat;
+               } else {
+                       term_tbl_act.action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
+                       term_tbl_act.pkt_reformat = NULL;
+               }
+
                /* get the terminating table for the action list */
                tt = mlx5_eswitch_termtbl_get_create(esw, &term_tbl_act,
                                                     &dest[i], attr);
                if (IS_ERR(tt)) {
-                       esw_warn(esw->dev, "Failed to get termination table (error %d)\n",
-                                IS_ERR(tt));
+                       esw_warn(esw->dev, "Failed to get termination table, err %pe\n", tt);
                        goto revert_changes;
                }
                attr->dests[num_vport_dests].termtbl = tt;
@@ -301,6 +289,9 @@ mlx5_eswitch_add_termtbl_rule(struct mlx5_eswitch *esw,
                goto revert_changes;
 
        /* create the FTE */
+       flow_act->action &= ~MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT;
+       flow_act->pkt_reformat = NULL;
+       flow_act->flags |= FLOW_ACT_IGNORE_FLOW_LEVEL;
        rule = mlx5_add_flow_rules(fdb, spec, flow_act, dest, num_dest);
        if (IS_ERR(rule))
                goto revert_changes;
index 2c41a69202642ad62756e06e1a3f3b47203e8c2b..fd6196b5e1630e0fbdb7713ea1a5e686644bfa80 100644 (file)
@@ -307,6 +307,11 @@ int mlx5_lag_mp_init(struct mlx5_lag *ldev)
        struct lag_mp *mp = &ldev->lag_mp;
        int err;
 
+       /* always clear mfi, as it might become stale when a route delete event
+        * has been missed
+        */
+       mp->mfi = NULL;
+
        if (mp->fib_nb.notifier_call)
                return 0;
 
@@ -335,4 +340,5 @@ void mlx5_lag_mp_cleanup(struct mlx5_lag *ldev)
        unregister_fib_notifier(&init_net, &mp->fib_nb);
        destroy_workqueue(mp->wq);
        mp->fib_nb.notifier_call = NULL;
+       mp->mfi = NULL;
 }
index fd8449ff9e176594dbfcc11b06d52b93851ccb1a..839a01da110f34390a00f3e542d26ae8fd0a50c7 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/etherdevice.h>
 #include <linux/mlx5/driver.h>
 #include <linux/mlx5/mlx5_ifc.h>
+#include <linux/mlx5/mpfs.h>
 #include <linux/mlx5/eswitch.h>
 #include "mlx5_core.h"
 #include "lib/mpfs.h"
@@ -175,6 +176,7 @@ out:
        mutex_unlock(&mpfs->lock);
        return err;
 }
+EXPORT_SYMBOL(mlx5_mpfs_add_mac);
 
 int mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac)
 {
@@ -206,3 +208,4 @@ unlock:
        mutex_unlock(&mpfs->lock);
        return err;
 }
+EXPORT_SYMBOL(mlx5_mpfs_del_mac);
index 4a7b2c3203a7e94cbdc328283beefe586d490caa..4a293542a7aa1a0b6f9fa20bc8c2d50e15e7c2c0 100644 (file)
@@ -84,12 +84,9 @@ struct l2addr_node {
 #ifdef CONFIG_MLX5_MPFS
 int  mlx5_mpfs_init(struct mlx5_core_dev *dev);
 void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev);
-int  mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac);
-int  mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac);
 #else /* #ifndef CONFIG_MLX5_MPFS */
 static inline int  mlx5_mpfs_init(struct mlx5_core_dev *dev) { return 0; }
 static inline void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev) {}
-static inline int  mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac) { return 0; }
-static inline int  mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac) { return 0; }
 #endif
+
 #endif
index c114365eb126fd9ef458e6875b2696b5612e1092..a1d67bd7fb43b54ddce183eacd0a879fe1107598 100644 (file)
@@ -503,7 +503,7 @@ static int handle_hca_cap_odp(struct mlx5_core_dev *dev, void *set_ctx)
 
 static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
 {
-       struct mlx5_profile *prof = dev->profile;
+       struct mlx5_profile *prof = &dev->profile;
        void *set_hca_cap;
        int err;
 
@@ -524,11 +524,11 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
                 to_fw_pkey_sz(dev, 128));
 
        /* Check log_max_qp from HCA caps to set in current profile */
-       if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < profile[prof_sel].log_max_qp) {
+       if (MLX5_CAP_GEN_MAX(dev, log_max_qp) < prof->log_max_qp) {
                mlx5_core_warn(dev, "log_max_qp value in current profile is %d, changing it to HCA capability limit (%d)\n",
-                              profile[prof_sel].log_max_qp,
+                              prof->log_max_qp,
                               MLX5_CAP_GEN_MAX(dev, log_max_qp));
-               profile[prof_sel].log_max_qp = MLX5_CAP_GEN_MAX(dev, log_max_qp);
+               prof->log_max_qp = MLX5_CAP_GEN_MAX(dev, log_max_qp);
        }
        if (prof->mask & MLX5_PROF_MASK_QP_SIZE)
                MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_qp,
@@ -1381,8 +1381,7 @@ int mlx5_mdev_init(struct mlx5_core_dev *dev, int profile_idx)
        struct mlx5_priv *priv = &dev->priv;
        int err;
 
-       dev->profile = &profile[profile_idx];
-
+       memcpy(&dev->profile, &profile[profile_idx], sizeof(dev->profile));
        INIT_LIST_HEAD(&priv->ctx_list);
        spin_lock_init(&priv->ctx_lock);
        mutex_init(&dev->intf_state_mutex);
index 1f907df5b3a2b0b3bceceae5c0c7bec9c635c35c..c3373fb1cd7fcd73b131d8ec7eab74828eeb6b8a 100644 (file)
@@ -95,9 +95,10 @@ int mlx5_get_default_msix_vec_count(struct mlx5_core_dev *dev, int num_vfs)
 int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
                            int msix_vec_count)
 {
-       int sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
+       int query_sz = MLX5_ST_SZ_BYTES(query_hca_cap_out);
+       int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
+       void *hca_cap = NULL, *query_cap = NULL, *cap;
        int num_vf_msix, min_msix, max_msix;
-       void *hca_cap, *cap;
        int ret;
 
        num_vf_msix = MLX5_CAP_GEN_MAX(dev, num_total_dynamic_vf_msix);
@@ -116,11 +117,20 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
        if (msix_vec_count > max_msix)
                return -EOVERFLOW;
 
-       hca_cap = kzalloc(sz, GFP_KERNEL);
-       if (!hca_cap)
-               return -ENOMEM;
+       query_cap = kzalloc(query_sz, GFP_KERNEL);
+       hca_cap = kzalloc(set_sz, GFP_KERNEL);
+       if (!hca_cap || !query_cap) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = mlx5_vport_get_other_func_cap(dev, function_id, query_cap);
+       if (ret)
+               goto out;
 
        cap = MLX5_ADDR_OF(set_hca_cap_in, hca_cap, capability);
+       memcpy(cap, MLX5_ADDR_OF(query_hca_cap_out, query_cap, capability),
+              MLX5_UN_SZ_BYTES(hca_cap_union));
        MLX5_SET(cmd_hca_cap, cap, dynamic_msix_table_size, msix_vec_count);
 
        MLX5_SET(set_hca_cap_in, hca_cap, opcode, MLX5_CMD_OP_SET_HCA_CAP);
@@ -130,7 +140,9 @@ int mlx5_set_msix_vec_count(struct mlx5_core_dev *dev, int function_id,
        MLX5_SET(set_hca_cap_in, hca_cap, op_mod,
                 MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE << 1);
        ret = mlx5_cmd_exec_in(dev, set_hca_cap, hca_cap);
+out:
        kfree(hca_cap);
+       kfree(query_cap);
        return ret;
 }
 
index a8e73c9ed1eae11a2e797d117415c2e9edf87bbd..1be0487693094a4ab613005383ba18118e7672bd 100644 (file)
@@ -136,10 +136,10 @@ static enum devlink_port_fn_state mlx5_sf_to_devlink_state(u8 hw_state)
        switch (hw_state) {
        case MLX5_VHCA_STATE_ACTIVE:
        case MLX5_VHCA_STATE_IN_USE:
-       case MLX5_VHCA_STATE_TEARDOWN_REQUEST:
                return DEVLINK_PORT_FN_STATE_ACTIVE;
        case MLX5_VHCA_STATE_INVALID:
        case MLX5_VHCA_STATE_ALLOCATED:
+       case MLX5_VHCA_STATE_TEARDOWN_REQUEST:
        default:
                return DEVLINK_PORT_FN_STATE_INACTIVE;
        }
@@ -192,14 +192,17 @@ sf_err:
        return err;
 }
 
-static int mlx5_sf_activate(struct mlx5_core_dev *dev, struct mlx5_sf *sf)
+static int mlx5_sf_activate(struct mlx5_core_dev *dev, struct mlx5_sf *sf,
+                           struct netlink_ext_ack *extack)
 {
        int err;
 
        if (mlx5_sf_is_active(sf))
                return 0;
-       if (sf->hw_state != MLX5_VHCA_STATE_ALLOCATED)
-               return -EINVAL;
+       if (sf->hw_state != MLX5_VHCA_STATE_ALLOCATED) {
+               NL_SET_ERR_MSG_MOD(extack, "SF is inactivated but it is still attached");
+               return -EBUSY;
+       }
 
        err = mlx5_cmd_sf_enable_hca(dev, sf->hw_fn_id);
        if (err)
@@ -226,7 +229,8 @@ static int mlx5_sf_deactivate(struct mlx5_core_dev *dev, struct mlx5_sf *sf)
 
 static int mlx5_sf_state_set(struct mlx5_core_dev *dev, struct mlx5_sf_table *table,
                             struct mlx5_sf *sf,
-                            enum devlink_port_fn_state state)
+                            enum devlink_port_fn_state state,
+                            struct netlink_ext_ack *extack)
 {
        int err = 0;
 
@@ -234,7 +238,7 @@ static int mlx5_sf_state_set(struct mlx5_core_dev *dev, struct mlx5_sf_table *ta
        if (state == mlx5_sf_to_devlink_state(sf->hw_state))
                goto out;
        if (state == DEVLINK_PORT_FN_STATE_ACTIVE)
-               err = mlx5_sf_activate(dev, sf);
+               err = mlx5_sf_activate(dev, sf, extack);
        else if (state == DEVLINK_PORT_FN_STATE_INACTIVE)
                err = mlx5_sf_deactivate(dev, sf);
        else
@@ -265,7 +269,7 @@ int mlx5_devlink_sf_port_fn_state_set(struct devlink *devlink, struct devlink_po
                goto out;
        }
 
-       err = mlx5_sf_state_set(dev, table, sf, state);
+       err = mlx5_sf_state_set(dev, table, sf, state, extack);
 out:
        mlx5_sf_table_put(table);
        return err;
index 3658c4ae3c37e82c9b89b506439eaca83f77fe2e..ee921a99e439a23f42b27f34cca6a01a64b99957 100644 (file)
@@ -1,5 +1,5 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
-/**
+/*
  * Microchip ENCX24J600 ethernet driver
  *
  * Copyright (C) 2015 Gridpoint
index f604a260ede798b93d9235087cb850250f40de2e..fac61a8fbd0205feef4e1ed3608b733fcad12722 100644 (file)
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-/**
+/*
  * encx24j600_hw.h: Register definitions
  *
  */
index 5f8b0bb3af6e342ee08077279e29764058df20ea..202973a82712ea5a1ed45f9b90d914d1513e0e4b 100644 (file)
@@ -20,6 +20,7 @@ if NET_VENDOR_PENSANDO
 config IONIC
        tristate "Pensando Ethernet IONIC Support"
        depends on 64BIT && PCI
+       depends on PTP_1588_CLOCK || !PTP_1588_CLOCK
        select NET_DEVLINK
        select DIMLIB
        help
index 214e347097a7a952913b9cc0e7752df70257da0b..2376b2729633f9e98c3c2a6238c871339260b655 100644 (file)
@@ -114,7 +114,7 @@ static int ql_sem_spinlock(struct ql3_adapter *qdev,
                value = readl(&port_regs->CommonRegs.semaphoreReg);
                if ((value & (sem_mask >> 16)) == sem_bits)
                        return 0;
-               ssleep(1);
+               mdelay(1000);
        } while (--seconds);
        return -1;
 }
index d8a3ecaed3fc65a458d12c044006fe593a79e154..d8f0863b393425b0dd2c49526e10b679f6062eec 100644 (file)
@@ -1048,7 +1048,7 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
        for (i = 0; i < QLCNIC_NUM_ILB_PKT; i++) {
                skb = netdev_alloc_skb(adapter->netdev, QLCNIC_ILB_PKT_SIZE);
                if (!skb)
-                       break;
+                       goto error;
                qlcnic_create_loopback_buff(skb->data, adapter->mac_addr);
                skb_put(skb, QLCNIC_ILB_PKT_SIZE);
                adapter->ahw->diag_cnt = 0;
@@ -1072,6 +1072,7 @@ int qlcnic_do_lb_test(struct qlcnic_adapter *adapter, u8 mode)
                        cnt++;
        }
        if (cnt != i) {
+error:
                dev_err(&adapter->pdev->dev,
                        "LB Test: failed, TX[%d], RX[%d]\n", i, cnt);
                if (mode != QLCNIC_ILB_MODE)
index d1e908846f5dd9347adae576456dee70caa6820a..22fbb0ae77fba7681bee74ed0726ab6dbb8d7a2c 100644 (file)
@@ -90,6 +90,7 @@ int efx_nic_init_interrupt(struct efx_nic *efx)
                                  efx->pci_dev->irq);
                        goto fail1;
                }
+               efx->irqs_hooked = true;
                return 0;
        }
 
index 527077c98ebce1a49d87c5c3458c2a947143855a..fc3b0acc8f99f0ee2cae3db690eb8fac78436f81 100644 (file)
@@ -30,7 +30,7 @@ struct sunxi_priv_data {
 static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
 {
        struct sunxi_priv_data *gmac = priv;
-       int ret;
+       int ret = 0;
 
        if (gmac->regulator) {
                ret = regulator_enable(gmac->regulator);
@@ -51,11 +51,11 @@ static int sun7i_gmac_init(struct platform_device *pdev, void *priv)
        } else {
                clk_set_rate(gmac->tx_clk, SUN7I_GMAC_MII_RATE);
                ret = clk_prepare(gmac->tx_clk);
-               if (ret)
-                       return ret;
+               if (ret && gmac->regulator)
+                       regulator_disable(gmac->regulator);
        }
 
-       return 0;
+       return ret;
 }
 
 static void sun7i_gmac_exit(struct platform_device *pdev, void *priv)
index 345b4c6d1fd40ad402d9380a121a0dfb3c728941..5d956a5534345da558e4db653310d67be01ff6f1 100644 (file)
@@ -1196,7 +1196,6 @@ static void stmmac_check_pcs_mode(struct stmmac_priv *priv)
  */
 static int stmmac_init_phy(struct net_device *dev)
 {
-       struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
        struct stmmac_priv *priv = netdev_priv(dev);
        struct device_node *node;
        int ret;
@@ -1222,8 +1221,12 @@ static int stmmac_init_phy(struct net_device *dev)
                ret = phylink_connect_phy(priv->phylink, phydev);
        }
 
-       phylink_ethtool_get_wol(priv->phylink, &wol);
-       device_set_wakeup_capable(priv->device, !!wol.supported);
+       if (!priv->plat->pmt) {
+               struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
+
+               phylink_ethtool_get_wol(priv->phylink, &wol);
+               device_set_wakeup_capable(priv->device, !!wol.supported);
+       }
 
        return ret;
 }
@@ -5888,12 +5891,21 @@ static int stmmac_set_mac_address(struct net_device *ndev, void *addr)
        struct stmmac_priv *priv = netdev_priv(ndev);
        int ret = 0;
 
+       ret = pm_runtime_get_sync(priv->device);
+       if (ret < 0) {
+               pm_runtime_put_noidle(priv->device);
+               return ret;
+       }
+
        ret = eth_mac_addr(ndev, addr);
        if (ret)
-               return ret;
+               goto set_mac_error;
 
        stmmac_set_umac_addr(priv, priv->hw, ndev->dev_addr, 0);
 
+set_mac_error:
+       pm_runtime_put(priv->device);
+
        return ret;
 }
 
@@ -6188,12 +6200,6 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
        bool is_double = false;
        int ret;
 
-       ret = pm_runtime_get_sync(priv->device);
-       if (ret < 0) {
-               pm_runtime_put_noidle(priv->device);
-               return ret;
-       }
-
        if (be16_to_cpu(proto) == ETH_P_8021AD)
                is_double = true;
 
@@ -6219,6 +6225,12 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
        bool is_double = false;
        int ret;
 
+       ret = pm_runtime_get_sync(priv->device);
+       if (ret < 0) {
+               pm_runtime_put_noidle(priv->device);
+               return ret;
+       }
+
        if (be16_to_cpu(proto) == ETH_P_8021AD)
                is_double = true;
 
index 707ccdd03b19eea1de7c818bd6ead715a2da7393..74e748662ec017027b1eac053fa7618948c90a36 100644 (file)
@@ -8144,10 +8144,10 @@ static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
                                     "VPD_SCAN: Reading in property [%s] len[%d]\n",
                                     namebuf, prop_len);
                        for (i = 0; i < prop_len; i++) {
-                               err = niu_pci_eeprom_read(np, off + i);
-                               if (err >= 0)
-                                       *prop_buf = err;
-                               ++prop_buf;
+                               err =  niu_pci_eeprom_read(np, off + i);
+                               if (err < 0)
+                                       return err;
+                               *prop_buf++ = err;
                        }
                }
 
@@ -8158,14 +8158,14 @@ static int niu_pci_vpd_scan_props(struct niu *np, u32 start, u32 end)
 }
 
 /* ESPC_PIO_EN_ENABLE must be set */
-static void niu_pci_vpd_fetch(struct niu *np, u32 start)
+static int niu_pci_vpd_fetch(struct niu *np, u32 start)
 {
        u32 offset;
        int err;
 
        err = niu_pci_eeprom_read16_swp(np, start + 1);
        if (err < 0)
-               return;
+               return err;
 
        offset = err + 3;
 
@@ -8174,12 +8174,14 @@ static void niu_pci_vpd_fetch(struct niu *np, u32 start)
                u32 end;
 
                err = niu_pci_eeprom_read(np, here);
+               if (err < 0)
+                       return err;
                if (err != 0x90)
-                       return;
+                       return -EINVAL;
 
                err = niu_pci_eeprom_read16_swp(np, here + 1);
                if (err < 0)
-                       return;
+                       return err;
 
                here = start + offset + 3;
                end = start + offset + err;
@@ -8187,9 +8189,12 @@ static void niu_pci_vpd_fetch(struct niu *np, u32 start)
                offset += err;
 
                err = niu_pci_vpd_scan_props(np, here, end);
-               if (err < 0 || err == 1)
-                       return;
+               if (err < 0)
+                       return err;
+               if (err == 1)
+                       return -EINVAL;
        }
+       return 0;
 }
 
 /* ESPC_PIO_EN_ENABLE must be set */
@@ -9280,8 +9285,11 @@ static int niu_get_invariants(struct niu *np)
                offset = niu_pci_vpd_offset(np);
                netif_printk(np, probe, KERN_DEBUG, np->dev,
                             "%s() VPD offset [%08x]\n", __func__, offset);
-               if (offset)
-                       niu_pci_vpd_fetch(np, offset);
+               if (offset) {
+                       err = niu_pci_vpd_fetch(np, offset);
+                       if (err < 0)
+                               return err;
+               }
                nw64(ESPC_PIO_EN, 0);
 
                if (np->flags & NIU_FLAGS_VPD_VALID) {
index 9030e619e54360fa4f17eb29e8966cdec8306b19..97942b0e3897539b0a63eb491719398cc9ac33a8 100644 (file)
@@ -1350,8 +1350,8 @@ int netcp_txpipe_open(struct netcp_tx_pipe *tx_pipe)
        tx_pipe->dma_queue = knav_queue_open(name, tx_pipe->dma_queue_id,
                                             KNAV_QUEUE_SHARED);
        if (IS_ERR(tx_pipe->dma_queue)) {
-               dev_err(dev, "Could not open DMA queue for channel \"%s\": %d\n",
-                       name, ret);
+               dev_err(dev, "Could not open DMA queue for channel \"%s\": %pe\n",
+                       name, tx_pipe->dma_queue);
                ret = PTR_ERR(tx_pipe->dma_queue);
                goto err;
        }
index e7ff376cb5b7d358661e648e369120dfc06611c0..744406832a774a0cefa2fa1cea844cb4fa396135 100644 (file)
@@ -58,6 +58,7 @@ enum ipa_flag {
  * @mem_virt:          Virtual address of IPA-local memory space
  * @mem_offset:                Offset from @mem_virt used for access to IPA memory
  * @mem_size:          Total size (bytes) of memory at @mem_virt
+ * @mem_count:         Number of entries in the mem array
  * @mem:               Array of IPA-local memory region descriptors
  * @imem_iova:         I/O virtual address of IPA region in IMEM
  * @imem_size:         Size of IMEM region
@@ -103,6 +104,7 @@ struct ipa {
        void *mem_virt;
        u32 mem_offset;
        u32 mem_size;
+       u32 mem_count;
        const struct ipa_mem *mem;
 
        unsigned long imem_iova;
index c5c3b1b7e67d5a13c6122217cedc244aa040bbb4..1624125e7459f145275dc1c14e826f46f0154349 100644 (file)
@@ -180,7 +180,7 @@ int ipa_mem_config(struct ipa *ipa)
         * for the region, write "canary" values in the space prior to
         * the region's base address.
         */
-       for (mem_id = 0; mem_id < IPA_MEM_COUNT; mem_id++) {
+       for (mem_id = 0; mem_id < ipa->mem_count; mem_id++) {
                const struct ipa_mem *mem = &ipa->mem[mem_id];
                u16 canary_count;
                __le32 *canary;
@@ -487,6 +487,7 @@ int ipa_mem_init(struct ipa *ipa, const struct ipa_mem_data *mem_data)
        ipa->mem_size = resource_size(res);
 
        /* The ipa->mem[] array is indexed by enum ipa_mem_id values */
+       ipa->mem_count = mem_data->local_count;
        ipa->mem = mem_data->local;
 
        ret = ipa_imem_init(ipa, mem_data->imem_addr, mem_data->imem_size);
index 8ce99c4888e106d2e7ef6001b5528f6905085bab..e096e68ac667b5a01e418913a9d09c4fb4e9f608 100644 (file)
@@ -71,7 +71,6 @@ static int octeon_mdiobus_probe(struct platform_device *pdev)
 
        return 0;
 fail_register:
-       mdiobus_free(bus->mii_bus);
        smi_en.u64 = 0;
        oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
        return err;
@@ -85,7 +84,6 @@ static int octeon_mdiobus_remove(struct platform_device *pdev)
        bus = platform_get_drvdata(pdev);
 
        mdiobus_unregister(bus->mii_bus);
-       mdiobus_free(bus->mii_bus);
        smi_en.u64 = 0;
        oct_mdio_writeq(smi_en.u64, bus->register_base + SMI_EN);
        return 0;
index cb1761693b690983a7c177f25669148912838eed..822d2cdd2f3599025f3e79d4243337c18114c951 100644 (file)
@@ -126,7 +126,6 @@ static void thunder_mdiobus_pci_remove(struct pci_dev *pdev)
                        continue;
 
                mdiobus_unregister(bus->mii_bus);
-               mdiobus_free(bus->mii_bus);
                oct_mdio_writeq(0, bus->register_base + SMI_EN);
        }
        pci_release_regions(pdev);
index dadf75ff3ab938f9dd0ae7a70ec65f62c9ebef85..6045ad3def1235fe60a550967d39a25aa8446cad 100644 (file)
@@ -607,7 +607,8 @@ void mdiobus_unregister(struct mii_bus *bus)
        struct mdio_device *mdiodev;
        int i;
 
-       BUG_ON(bus->state != MDIOBUS_REGISTERED);
+       if (WARN_ON_ONCE(bus->state != MDIOBUS_REGISTERED))
+               return;
        bus->state = MDIOBUS_UNREGISTERED;
 
        for (i = 0; i < PHY_MAX_ADDR; i++) {
index 0eeec80bec311ca6fd31f1d62c2847e2c7299a6f..2e60bc1b9a6b0a82b504f3b7f00efc6bd75daaae 100644 (file)
@@ -26,7 +26,7 @@
  * for transport over USB using a simpler USB device model than the
  * previous CDC "Ethernet Control Model" (ECM, or "CDC Ethernet").
  *
- * For details, see www.usb.org/developers/devclass_docs/CDC_EEM10.pdf
+ * For details, see https://usb.org/sites/default/files/CDC_EEM10.pdf
  *
  * This version has been tested with GIGAntIC WuaoW SIM Smart Card on 2.6.24,
  * 2.6.27 and 2.6.30rc2 kernel.
index 3ef4b2841402c28c80605a19ce7ff8c973d46f5d..5c779cc0ea1124463808db677337b9d8ea792803 100644 (file)
@@ -1689,7 +1689,7 @@ static int hso_serial_tiocmset(struct tty_struct *tty,
        spin_unlock_irqrestore(&serial->serial_lock, flags);
 
        return usb_control_msg(serial->parent->usb,
-                              usb_rcvctrlpipe(serial->parent->usb, 0), 0x22,
+                              usb_sndctrlpipe(serial->parent->usb, 0), 0x22,
                               0x21, val, if_num, NULL, 0,
                               USB_CTRL_SET_TIMEOUT);
 }
@@ -2436,7 +2436,7 @@ static int hso_rfkill_set_block(void *data, bool blocked)
        if (hso_dev->usb_gone)
                rv = 0;
        else
-               rv = usb_control_msg(hso_dev->usb, usb_rcvctrlpipe(hso_dev->usb, 0),
+               rv = usb_control_msg(hso_dev->usb, usb_sndctrlpipe(hso_dev->usb, 0),
                                       enabled ? 0x82 : 0x81, 0x40, 0, 0, NULL, 0,
                                       USB_CTRL_SET_TIMEOUT);
        mutex_unlock(&hso_dev->mutex);
@@ -2618,32 +2618,31 @@ static struct hso_device *hso_create_bulk_serial_device(
                num_urbs = 2;
                serial->tiocmget = kzalloc(sizeof(struct hso_tiocmget),
                                           GFP_KERNEL);
+               if (!serial->tiocmget)
+                       goto exit;
                serial->tiocmget->serial_state_notification
                        = kzalloc(sizeof(struct hso_serial_state_notification),
                                           GFP_KERNEL);
-               /* it isn't going to break our heart if serial->tiocmget
-                *  allocation fails don't bother checking this.
-                */
-               if (serial->tiocmget && serial->tiocmget->serial_state_notification) {
-                       tiocmget = serial->tiocmget;
-                       tiocmget->endp = hso_get_ep(interface,
-                                                   USB_ENDPOINT_XFER_INT,
-                                                   USB_DIR_IN);
-                       if (!tiocmget->endp) {
-                               dev_err(&interface->dev, "Failed to find INT IN ep\n");
-                               goto exit;
-                       }
-
-                       tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL);
-                       if (tiocmget->urb) {
-                               mutex_init(&tiocmget->mutex);
-                               init_waitqueue_head(&tiocmget->waitq);
-                       } else
-                               hso_free_tiomget(serial);
+               if (!serial->tiocmget->serial_state_notification)
+                       goto exit;
+               tiocmget = serial->tiocmget;
+               tiocmget->endp = hso_get_ep(interface,
+                                           USB_ENDPOINT_XFER_INT,
+                                           USB_DIR_IN);
+               if (!tiocmget->endp) {
+                       dev_err(&interface->dev, "Failed to find INT IN ep\n");
+                       goto exit;
                }
-       }
-       else
+
+               tiocmget->urb = usb_alloc_urb(0, GFP_KERNEL);
+               if (!tiocmget->urb)
+                       goto exit;
+
+               mutex_init(&tiocmget->mutex);
+               init_waitqueue_head(&tiocmget->waitq);
+       } else {
                num_urbs = 1;
+       }
 
        if (hso_serial_common_create(serial, num_urbs, BULK_URB_RX_SIZE,
                                     BULK_URB_TX_SIZE))
index 6acc5e9045181c6cacfd03ff35f94b9e9433b16c..02bce40a67e5ba36018634f9070b890f56ea4630 100644 (file)
@@ -1645,6 +1645,7 @@ static const struct ethtool_ops lan78xx_ethtool_ops = {
        .get_strings    = lan78xx_get_strings,
        .get_wol        = lan78xx_get_wol,
        .set_wol        = lan78xx_set_wol,
+       .get_ts_info    = ethtool_op_get_ts_info,
        .get_eee        = lan78xx_get_eee,
        .set_eee        = lan78xx_set_eee,
        .get_pauseparam = lan78xx_get_pause,
index 136ea06540ff7923578c05152c552a9abb2e7c59..f6abb2fbf9728e5f8e378ef31cba21361a2e14e4 100644 (file)
@@ -8107,6 +8107,37 @@ static void r8156b_init(struct r8152 *tp)
        tp->coalesce = 15000;   /* 15 us */
 }
 
+static bool rtl_check_vendor_ok(struct usb_interface *intf)
+{
+       struct usb_host_interface *alt = intf->cur_altsetting;
+       struct usb_endpoint_descriptor *in, *out, *intr;
+
+       if (usb_find_common_endpoints(alt, &in, &out, &intr, NULL) < 0) {
+               dev_err(&intf->dev, "Expected endpoints are not found\n");
+               return false;
+       }
+
+       /* Check Rx endpoint address */
+       if (usb_endpoint_num(in) != 1) {
+               dev_err(&intf->dev, "Invalid Rx endpoint address\n");
+               return false;
+       }
+
+       /* Check Tx endpoint address */
+       if (usb_endpoint_num(out) != 2) {
+               dev_err(&intf->dev, "Invalid Tx endpoint address\n");
+               return false;
+       }
+
+       /* Check interrupt endpoint address */
+       if (usb_endpoint_num(intr) != 3) {
+               dev_err(&intf->dev, "Invalid interrupt endpoint address\n");
+               return false;
+       }
+
+       return true;
+}
+
 static bool rtl_vendor_mode(struct usb_interface *intf)
 {
        struct usb_host_interface *alt = intf->cur_altsetting;
@@ -8115,12 +8146,15 @@ static bool rtl_vendor_mode(struct usb_interface *intf)
        int i, num_configs;
 
        if (alt->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC)
-               return true;
+               return rtl_check_vendor_ok(intf);
 
        /* The vendor mode is not always config #1, so to find it out. */
        udev = interface_to_usbdev(intf);
        c = udev->config;
        num_configs = udev->descriptor.bNumConfigurations;
+       if (num_configs < 2)
+               return false;
+
        for (i = 0; i < num_configs; (i++, c++)) {
                struct usb_interface_descriptor *desc = NULL;
 
@@ -8135,7 +8169,8 @@ static bool rtl_vendor_mode(struct usb_interface *intf)
                }
        }
 
-       WARN_ON_ONCE(i == num_configs);
+       if (i == num_configs)
+               dev_err(&intf->dev, "Unexpected Device\n");
 
        return false;
 }
@@ -9381,9 +9416,6 @@ static int rtl8152_probe(struct usb_interface *intf,
        if (!rtl_vendor_mode(intf))
                return -ENODEV;
 
-       if (intf->cur_altsetting->desc.bNumEndpoints < 3)
-               return -ENODEV;
-
        usb_reset_device(udev);
        netdev = alloc_etherdev(sizeof(struct r8152));
        if (!netdev) {
index f8cdabb9ef5a4dd181605dc01f47e10b991ee9aa..b286993da67c96c4df24c12aff0f126100422be2 100644 (file)
@@ -1483,7 +1483,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
        ret = smsc75xx_wait_ready(dev, 0);
        if (ret < 0) {
                netdev_warn(dev->net, "device not ready in smsc75xx_bind\n");
-               return ret;
+               goto err;
        }
 
        smsc75xx_init_mac_address(dev);
@@ -1492,7 +1492,7 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
        ret = smsc75xx_reset(dev);
        if (ret < 0) {
                netdev_warn(dev->net, "smsc75xx_reset error %d\n", ret);
-               return ret;
+               goto err;
        }
 
        dev->net->netdev_ops = &smsc75xx_netdev_ops;
@@ -1502,6 +1502,10 @@ static int smsc75xx_bind(struct usbnet *dev, struct usb_interface *intf)
        dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;
        dev->net->max_mtu = MAX_SINGLE_PACKET_SIZE;
        return 0;
+
+err:
+       kfree(pdata);
+       return ret;
 }
 
 static void smsc75xx_unbind(struct usbnet *dev, struct usb_interface *intf)
index 956157946106c3f333426af6e706a48af22fa12f..dbc8aef82a65f3466e57e8ee1ef0aa48284e3f4d 100644 (file)
@@ -845,6 +845,7 @@ enum htt_security_types {
 
 #define ATH10K_HTT_TXRX_PEER_SECURITY_MAX 2
 #define ATH10K_TXRX_NUM_EXT_TIDS 19
+#define ATH10K_TXRX_NON_QOS_TID 16
 
 enum htt_security_flags {
 #define HTT_SECURITY_TYPE_MASK 0x7F
index 1a08156d5011df4464739aef42862277b5f7be74..7ffb5d5b2a70e6f9bbee4d2b3c1a0406a79fc6d0 100644 (file)
@@ -1746,16 +1746,97 @@ static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
        msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
 }
 
+static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb,
+                                 u16 offset,
+                                 enum htt_rx_mpdu_encrypt_type enctype)
+{
+       struct ieee80211_hdr *hdr;
+       u64 pn = 0;
+       u8 *ehdr;
+
+       hdr = (struct ieee80211_hdr *)(skb->data + offset);
+       ehdr = skb->data + offset + ieee80211_hdrlen(hdr->frame_control);
+
+       if (enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) {
+               pn = ehdr[0];
+               pn |= (u64)ehdr[1] << 8;
+               pn |= (u64)ehdr[4] << 16;
+               pn |= (u64)ehdr[5] << 24;
+               pn |= (u64)ehdr[6] << 32;
+               pn |= (u64)ehdr[7] << 40;
+       }
+       return pn;
+}
+
+static bool ath10k_htt_rx_h_frag_multicast_check(struct ath10k *ar,
+                                                struct sk_buff *skb,
+                                                u16 offset)
+{
+       struct ieee80211_hdr *hdr;
+
+       hdr = (struct ieee80211_hdr *)(skb->data + offset);
+       return !is_multicast_ether_addr(hdr->addr1);
+}
+
+static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar,
+                                         struct sk_buff *skb,
+                                         u16 peer_id,
+                                         u16 offset,
+                                         enum htt_rx_mpdu_encrypt_type enctype)
+{
+       struct ath10k_peer *peer;
+       union htt_rx_pn_t *last_pn, new_pn = {0};
+       struct ieee80211_hdr *hdr;
+       bool more_frags;
+       u8 tid, frag_number;
+       u32 seq;
+
+       peer = ath10k_peer_find_by_id(ar, peer_id);
+       if (!peer) {
+               ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid peer for frag pn check\n");
+               return false;
+       }
+
+       hdr = (struct ieee80211_hdr *)(skb->data + offset);
+       if (ieee80211_is_data_qos(hdr->frame_control))
+               tid = ieee80211_get_tid(hdr);
+       else
+               tid = ATH10K_TXRX_NON_QOS_TID;
+
+       last_pn = &peer->frag_tids_last_pn[tid];
+       new_pn.pn48 = ath10k_htt_rx_h_get_pn(ar, skb, offset, enctype);
+       more_frags = ieee80211_has_morefrags(hdr->frame_control);
+       frag_number = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
+       seq = (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+
+       if (frag_number == 0) {
+               last_pn->pn48 = new_pn.pn48;
+               peer->frag_tids_seq[tid] = seq;
+       } else {
+               if (seq != peer->frag_tids_seq[tid])
+                       return false;
+
+               if (new_pn.pn48 != last_pn->pn48 + 1)
+                       return false;
+
+               last_pn->pn48 = new_pn.pn48;
+       }
+
+       return true;
+}
+
 static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
                                 struct sk_buff_head *amsdu,
                                 struct ieee80211_rx_status *status,
                                 bool fill_crypt_header,
                                 u8 *rx_hdr,
-                                enum ath10k_pkt_rx_err *err)
+                                enum ath10k_pkt_rx_err *err,
+                                u16 peer_id,
+                                bool frag)
 {
        struct sk_buff *first;
        struct sk_buff *last;
-       struct sk_buff *msdu;
+       struct sk_buff *msdu, *temp;
        struct htt_rx_desc *rxd;
        struct ieee80211_hdr *hdr;
        enum htt_rx_mpdu_encrypt_type enctype;
@@ -1768,6 +1849,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        bool is_decrypted;
        bool is_mgmt;
        u32 attention;
+       bool frag_pn_check = true, multicast_check = true;
 
        if (skb_queue_empty(amsdu))
                return;
@@ -1866,7 +1948,37 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        }
 
        skb_queue_walk(amsdu, msdu) {
+               if (frag && !fill_crypt_header && is_decrypted &&
+                   enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2)
+                       frag_pn_check = ath10k_htt_rx_h_frag_pn_check(ar,
+                                                                     msdu,
+                                                                     peer_id,
+                                                                     0,
+                                                                     enctype);
+
+               if (frag)
+                       multicast_check = ath10k_htt_rx_h_frag_multicast_check(ar,
+                                                                              msdu,
+                                                                              0);
+
+               if (!frag_pn_check || !multicast_check) {
+                       /* Discard the fragment with invalid PN or multicast DA
+                        */
+                       temp = msdu->prev;
+                       __skb_unlink(msdu, amsdu);
+                       dev_kfree_skb_any(msdu);
+                       msdu = temp;
+                       frag_pn_check = true;
+                       multicast_check = true;
+                       continue;
+               }
+
                ath10k_htt_rx_h_csum_offload(msdu);
+
+               if (frag && !fill_crypt_header &&
+                   enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
+                       status->flag &= ~RX_FLAG_MMIC_STRIPPED;
+
                ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
                                        is_decrypted);
 
@@ -1884,6 +1996,11 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
 
                hdr = (void *)msdu->data;
                hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
+
+               if (frag && !fill_crypt_header &&
+                   enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
+                       status->flag &= ~RX_FLAG_IV_STRIPPED &
+                                       ~RX_FLAG_MMIC_STRIPPED;
        }
 }
 
@@ -1991,14 +2108,62 @@ static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
        ath10k_unchain_msdu(amsdu, unchain_cnt);
 }
 
+static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar,
+                                        struct sk_buff_head *amsdu)
+{
+       u8 *subframe_hdr;
+       struct sk_buff *first;
+       bool is_first, is_last;
+       struct htt_rx_desc *rxd;
+       struct ieee80211_hdr *hdr;
+       size_t hdr_len, crypto_len;
+       enum htt_rx_mpdu_encrypt_type enctype;
+       int bytes_aligned = ar->hw_params.decap_align_bytes;
+
+       first = skb_peek(amsdu);
+
+       rxd = (void *)first->data - sizeof(*rxd);
+       hdr = (void *)rxd->rx_hdr_status;
+
+       is_first = !!(rxd->msdu_end.common.info0 &
+                     __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
+       is_last = !!(rxd->msdu_end.common.info0 &
+                    __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
+
+       /* Return in case of non-aggregated msdu */
+       if (is_first && is_last)
+               return true;
+
+       /* First msdu flag is not set for the first msdu of the list */
+       if (!is_first)
+               return false;
+
+       enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+                    RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+
+       hdr_len = ieee80211_hdrlen(hdr->frame_control);
+       crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
+
+       subframe_hdr = (u8 *)hdr + round_up(hdr_len, bytes_aligned) +
+                      crypto_len;
+
+       /* Validate if the amsdu has a proper first subframe.
+        * There are chances a single msdu can be received as amsdu when
+        * the unauthenticated amsdu flag of a QoS header
+        * gets flipped in non-SPP AMSDU's, in such cases the first
+        * subframe has llc/snap header in place of a valid da.
+        * return false if the da matches rfc1042 pattern
+        */
+       if (ether_addr_equal(subframe_hdr, rfc1042_header))
+               return false;
+
+       return true;
+}
+
 static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
                                        struct sk_buff_head *amsdu,
                                        struct ieee80211_rx_status *rx_status)
 {
-       /* FIXME: It might be a good idea to do some fuzzy-testing to drop
-        * invalid/dangerous frames.
-        */
-
        if (!rx_status->freq) {
                ath10k_dbg(ar, ATH10K_DBG_HTT, "no channel configured; ignoring frame(s)!\n");
                return false;
@@ -2009,6 +2174,11 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
                return false;
        }
 
+       if (!ath10k_htt_rx_validate_amsdu(ar, amsdu)) {
+               ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid amsdu received\n");
+               return false;
+       }
+
        return true;
 }
 
@@ -2071,7 +2241,8 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
                ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt);
 
        ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter);
-       ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err);
+       ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err, 0,
+                            false);
        msdus_to_queue = skb_queue_len(&amsdu);
        ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status);
 
@@ -2204,6 +2375,11 @@ static bool ath10k_htt_rx_proc_rx_ind_hl(struct ath10k_htt *htt,
        fw_desc = &rx->fw_desc;
        rx_desc_len = fw_desc->len;
 
+       if (fw_desc->u.bits.discard) {
+               ath10k_dbg(ar, ATH10K_DBG_HTT, "htt discard mpdu\n");
+               goto err;
+       }
+
        /* I have not yet seen any case where num_mpdu_ranges > 1.
         * qcacld does not seem handle that case either, so we introduce the
         * same limitiation here as well.
@@ -2509,6 +2685,13 @@ static bool ath10k_htt_rx_proc_rx_frag_ind_hl(struct ath10k_htt *htt,
        rx_desc = (struct htt_hl_rx_desc *)(skb->data + tot_hdr_len);
        rx_desc_info = __le32_to_cpu(rx_desc->info);
 
+       hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);
+
+       if (is_multicast_ether_addr(hdr->addr1)) {
+               /* Discard the fragment with multicast DA */
+               goto err;
+       }
+
        if (!MS(rx_desc_info, HTT_RX_DESC_HL_INFO_ENCRYPTED)) {
                spin_unlock_bh(&ar->data_lock);
                return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb,
@@ -2516,8 +2699,6 @@ static bool ath10k_htt_rx_proc_rx_frag_ind_hl(struct ath10k_htt *htt,
                                                    HTT_RX_NON_TKIP_MIC);
        }
 
-       hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);
-
        if (ieee80211_has_retry(hdr->frame_control))
                goto err;
 
@@ -3027,7 +3208,7 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
                        ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
                        ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL);
                        ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL,
-                                            NULL);
+                                            NULL, peer_id, frag);
                        ath10k_htt_rx_h_enqueue(ar, &amsdu, status);
                        break;
                case -EAGAIN:
index f2b6bf8f0d60db404fa4987116817fd25267d141..705b6295e4663bc65dbf5df3a7a752d15f70a51e 100644 (file)
@@ -1282,7 +1282,19 @@ struct fw_rx_desc_base {
 #define FW_RX_DESC_UDP              (1 << 6)
 
 struct fw_rx_desc_hl {
-       u8 info0;
+       union {
+               struct {
+               u8 discard:1,
+                  forward:1,
+                  any_err:1,
+                  dup_err:1,
+                  reserved:1,
+                  inspect:1,
+                  extension:2;
+               } bits;
+               u8 info0;
+       } u;
+
        u8 version;
        u8 len;
        u8 flags;
index 1d9aa1bb6b6e994a97ce6e471972795dac8d5209..603d2f93ac18f73fcf74e9eebdc04053ed1ac172 100644 (file)
@@ -260,6 +260,16 @@ static void ath11k_dp_rxdesc_set_msdu_len(struct ath11k_base *ab,
        ab->hw_params.hw_ops->rx_desc_set_msdu_len(desc, len);
 }
 
+static bool ath11k_dp_rx_h_attn_is_mcbc(struct ath11k_base *ab,
+                                       struct hal_rx_desc *desc)
+{
+       struct rx_attention *attn = ath11k_dp_rx_get_attention(ab, desc);
+
+       return ath11k_dp_rx_h_msdu_end_first_msdu(ab, desc) &&
+               (!!FIELD_GET(RX_ATTENTION_INFO1_MCAST_BCAST,
+                __le32_to_cpu(attn->info1)));
+}
+
 static void ath11k_dp_service_mon_ring(struct timer_list *t)
 {
        struct ath11k_base *ab = from_timer(ab, t, mon_reap_timer);
@@ -852,6 +862,24 @@ static void ath11k_dp_rx_frags_cleanup(struct dp_rx_tid *rx_tid, bool rel_link_d
        __skb_queue_purge(&rx_tid->rx_frags);
 }
 
+void ath11k_peer_frags_flush(struct ath11k *ar, struct ath11k_peer *peer)
+{
+       struct dp_rx_tid *rx_tid;
+       int i;
+
+       lockdep_assert_held(&ar->ab->base_lock);
+
+       for (i = 0; i <= IEEE80211_NUM_TIDS; i++) {
+               rx_tid = &peer->rx_tid[i];
+
+               spin_unlock_bh(&ar->ab->base_lock);
+               del_timer_sync(&rx_tid->frag_timer);
+               spin_lock_bh(&ar->ab->base_lock);
+
+               ath11k_dp_rx_frags_cleanup(rx_tid, true);
+       }
+}
+
 void ath11k_peer_rx_tid_cleanup(struct ath11k *ar, struct ath11k_peer *peer)
 {
        struct dp_rx_tid *rx_tid;
@@ -3450,6 +3478,7 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar,
        u8 tid;
        int ret = 0;
        bool more_frags;
+       bool is_mcbc;
 
        rx_desc = (struct hal_rx_desc *)msdu->data;
        peer_id = ath11k_dp_rx_h_mpdu_start_peer_id(ar->ab, rx_desc);
@@ -3457,6 +3486,11 @@ static int ath11k_dp_rx_frag_h_mpdu(struct ath11k *ar,
        seqno = ath11k_dp_rx_h_mpdu_start_seq_no(ar->ab, rx_desc);
        frag_no = ath11k_dp_rx_h_mpdu_start_frag_no(ar->ab, msdu);
        more_frags = ath11k_dp_rx_h_mpdu_start_more_frags(ar->ab, msdu);
+       is_mcbc = ath11k_dp_rx_h_attn_is_mcbc(ar->ab, rx_desc);
+
+       /* Multicast/Broadcast fragments are not expected */
+       if (is_mcbc)
+               return -EINVAL;
 
        if (!ath11k_dp_rx_h_mpdu_start_seq_ctrl_valid(ar->ab, rx_desc) ||
            !ath11k_dp_rx_h_mpdu_start_fc_valid(ar->ab, rx_desc) ||
index bf399312b5ff5c26a3823b29fa7a9ca09b14c3a5..623da3bf9dc81035ed7ce5db3258515c172b6f08 100644 (file)
@@ -49,6 +49,7 @@ int ath11k_dp_peer_rx_pn_replay_config(struct ath11k_vif *arvif,
                                       const u8 *peer_addr,
                                       enum set_key_cmd key_cmd,
                                       struct ieee80211_key_conf *key);
+void ath11k_peer_frags_flush(struct ath11k *ar, struct ath11k_peer *peer);
 void ath11k_peer_rx_tid_cleanup(struct ath11k *ar, struct ath11k_peer *peer);
 void ath11k_peer_rx_tid_delete(struct ath11k *ar,
                               struct ath11k_peer *peer, u8 tid);
index 4df425dd31a2661bf9ec2715f4cf6d75fc60cf5a..9d0ff150ec30f17304ecf435e9009035b790868a 100644 (file)
@@ -2779,6 +2779,12 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
         */
        spin_lock_bh(&ab->base_lock);
        peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
+
+       /* flush the fragments cache during key (re)install to
+        * ensure all frags in the new frag list belong to the same key.
+        */
+       if (peer && cmd == SET_KEY)
+               ath11k_peer_frags_flush(ar, peer);
        spin_unlock_bh(&ab->base_lock);
 
        if (!peer) {
index 7506cea46f58918207255eaf3e9a01fb07076abf..433a047f3747bc01e3c3b604bc42a94a4cecc47c 100644 (file)
@@ -1027,14 +1027,17 @@ static ssize_t ath6kl_lrssi_roam_write(struct file *file,
 {
        struct ath6kl *ar = file->private_data;
        unsigned long lrssi_roam_threshold;
+       int ret;
 
        if (kstrtoul_from_user(user_buf, count, 0, &lrssi_roam_threshold))
                return -EINVAL;
 
        ar->lrssi_roam_threshold = lrssi_roam_threshold;
 
-       ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold);
+       ret = ath6kl_wmi_set_roam_lrssi_cmd(ar->wmi, ar->lrssi_roam_threshold);
 
+       if (ret)
+               return ret;
        return count;
 }
 
index ce8c102df7b3e820b6a4db9e030427fdbe0bf5fd..633d0ab190314bfb84178d9f4a37fdeed19feb05 100644 (file)
@@ -1217,13 +1217,9 @@ static struct sdio_driver brcmf_sdmmc_driver = {
        },
 };
 
-void brcmf_sdio_register(void)
+int brcmf_sdio_register(void)
 {
-       int ret;
-
-       ret = sdio_register_driver(&brcmf_sdmmc_driver);
-       if (ret)
-               brcmf_err("sdio_register_driver failed: %d\n", ret);
+       return sdio_register_driver(&brcmf_sdmmc_driver);
 }
 
 void brcmf_sdio_exit(void)
index 08f9d47f2e5ca68b9e9e01e2e39b85d455222930..3f5da3bb6aa5930b026bdbb0d2737a3e30cd9f0f 100644 (file)
@@ -275,11 +275,26 @@ void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
 
 #ifdef CONFIG_BRCMFMAC_SDIO
 void brcmf_sdio_exit(void);
-void brcmf_sdio_register(void);
+int brcmf_sdio_register(void);
+#else
+static inline void brcmf_sdio_exit(void) { }
+static inline int brcmf_sdio_register(void) { return 0; }
 #endif
+
 #ifdef CONFIG_BRCMFMAC_USB
 void brcmf_usb_exit(void);
-void brcmf_usb_register(void);
+int brcmf_usb_register(void);
+#else
+static inline void brcmf_usb_exit(void) { }
+static inline int brcmf_usb_register(void) { return 0; }
+#endif
+
+#ifdef CONFIG_BRCMFMAC_PCIE
+void brcmf_pcie_exit(void);
+int brcmf_pcie_register(void);
+#else
+static inline void brcmf_pcie_exit(void) { }
+static inline int brcmf_pcie_register(void) { return 0; }
 #endif
 
 #endif /* BRCMFMAC_BUS_H */
index 838b09b23abff49da1e4e45817741a309ab4123c..cee1682d2333599666080df6c8e5ee16ab021552 100644 (file)
@@ -1518,40 +1518,34 @@ void brcmf_bus_change_state(struct brcmf_bus *bus, enum brcmf_bus_state state)
        }
 }
 
-static void brcmf_driver_register(struct work_struct *work)
-{
-#ifdef CONFIG_BRCMFMAC_SDIO
-       brcmf_sdio_register();
-#endif
-#ifdef CONFIG_BRCMFMAC_USB
-       brcmf_usb_register();
-#endif
-#ifdef CONFIG_BRCMFMAC_PCIE
-       brcmf_pcie_register();
-#endif
-}
-static DECLARE_WORK(brcmf_driver_work, brcmf_driver_register);
-
 int __init brcmf_core_init(void)
 {
-       if (!schedule_work(&brcmf_driver_work))
-               return -EBUSY;
+       int err;
 
+       err = brcmf_sdio_register();
+       if (err)
+               return err;
+
+       err = brcmf_usb_register();
+       if (err)
+               goto error_usb_register;
+
+       err = brcmf_pcie_register();
+       if (err)
+               goto error_pcie_register;
        return 0;
+
+error_pcie_register:
+       brcmf_usb_exit();
+error_usb_register:
+       brcmf_sdio_exit();
+       return err;
 }
 
 void __exit brcmf_core_exit(void)
 {
-       cancel_work_sync(&brcmf_driver_work);
-
-#ifdef CONFIG_BRCMFMAC_SDIO
        brcmf_sdio_exit();
-#endif
-#ifdef CONFIG_BRCMFMAC_USB
        brcmf_usb_exit();
-#endif
-#ifdef CONFIG_BRCMFMAC_PCIE
        brcmf_pcie_exit();
-#endif
 }
 
index ad79e3b7e74a350845494534e88d23679b2e8a00..143a705b5cb3a44fe3fddf491596162979edb05d 100644 (file)
@@ -2140,15 +2140,10 @@ static struct pci_driver brcmf_pciedrvr = {
 };
 
 
-void brcmf_pcie_register(void)
+int brcmf_pcie_register(void)
 {
-       int err;
-
        brcmf_dbg(PCIE, "Enter\n");
-       err = pci_register_driver(&brcmf_pciedrvr);
-       if (err)
-               brcmf_err(NULL, "PCIE driver registration failed, err=%d\n",
-                         err);
+       return pci_register_driver(&brcmf_pciedrvr);
 }
 
 
index d026401d200109bcd0cb7d3ef0b035c47d3cd785..8e6c227e8315c8372720ae5df9c7dca121ca1ae3 100644 (file)
@@ -11,9 +11,4 @@ struct brcmf_pciedev {
        struct brcmf_pciedev_info *devinfo;
 };
 
-
-void brcmf_pcie_exit(void);
-void brcmf_pcie_register(void);
-
-
 #endif /* BRCMFMAC_PCIE_H */
index 586f4dfc638b9ecd69f53898f95896af9ea689ce..9fb68c2dc7e39cec6d1ef547115b5d89aa4dfddd 100644 (file)
@@ -1584,12 +1584,8 @@ void brcmf_usb_exit(void)
        usb_deregister(&brcmf_usbdrvr);
 }
 
-void brcmf_usb_register(void)
+int brcmf_usb_register(void)
 {
-       int ret;
-
        brcmf_dbg(USB, "Enter\n");
-       ret = usb_register(&brcmf_usbdrvr);
-       if (ret)
-               brcmf_err("usb_register failed %d\n", ret);
+       return usb_register(&brcmf_usbdrvr);
 }
index f5b78257d551858692af2488b15236c0cdf7016b..c68814841583f562ce3495ee3dec82f7e72a8c21 100644 (file)
@@ -801,24 +801,6 @@ static const struct attribute_group mesh_ie_group = {
        .attrs = mesh_ie_attrs,
 };
 
-static void lbs_persist_config_init(struct net_device *dev)
-{
-       int ret;
-       ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
-       if (ret)
-               pr_err("failed to create boot_opts_group.\n");
-
-       ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
-       if (ret)
-               pr_err("failed to create mesh_ie_group.\n");
-}
-
-static void lbs_persist_config_remove(struct net_device *dev)
-{
-       sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
-       sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
-}
-
 
 /***************************************************************************
  * Initializing and starting, stopping mesh
@@ -1014,6 +996,10 @@ static int lbs_add_mesh(struct lbs_private *priv)
        SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
 
        mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+       mesh_dev->sysfs_groups[0] = &lbs_mesh_attr_group;
+       mesh_dev->sysfs_groups[1] = &boot_opts_group;
+       mesh_dev->sysfs_groups[2] = &mesh_ie_group;
+
        /* Register virtual mesh interface */
        ret = register_netdev(mesh_dev);
        if (ret) {
@@ -1021,19 +1007,10 @@ static int lbs_add_mesh(struct lbs_private *priv)
                goto err_free_netdev;
        }
 
-       ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-       if (ret)
-               goto err_unregister;
-
-       lbs_persist_config_init(mesh_dev);
-
        /* Everything successful */
        ret = 0;
        goto done;
 
-err_unregister:
-       unregister_netdev(mesh_dev);
-
 err_free_netdev:
        free_netdev(mesh_dev);
 
@@ -1054,8 +1031,6 @@ void lbs_remove_mesh(struct lbs_private *priv)
 
        netif_stop_queue(mesh_dev);
        netif_carrier_off(mesh_dev);
-       sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
-       lbs_persist_config_remove(mesh_dev);
        unregister_netdev(mesh_dev);
        priv->mesh_dev = NULL;
        kfree(mesh_dev->ieee80211_ptr);
index 2a7ee90a3f549c1c3a2f2c46b92582be01831676..ffd150ec181fab2ccc9d67606abd29c495800831 100644 (file)
@@ -440,9 +440,14 @@ static void rtl_watchdog_wq_callback(struct work_struct *work);
 static void rtl_fwevt_wq_callback(struct work_struct *work);
 static void rtl_c2hcmd_wq_callback(struct work_struct *work);
 
-static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
+static int _rtl_init_deferred_work(struct ieee80211_hw *hw)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
+       struct workqueue_struct *wq;
+
+       wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
+       if (!wq)
+               return -ENOMEM;
 
        /* <1> timer */
        timer_setup(&rtlpriv->works.watchdog_timer,
@@ -451,11 +456,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
                    rtl_easy_concurrent_retrytimer_callback, 0);
        /* <2> work queue */
        rtlpriv->works.hw = hw;
-       rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
-       if (unlikely(!rtlpriv->works.rtl_wq)) {
-               pr_err("Failed to allocate work queue\n");
-               return;
-       }
+       rtlpriv->works.rtl_wq = wq;
 
        INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
                          rtl_watchdog_wq_callback);
@@ -466,6 +467,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw)
                          rtl_swlps_rfon_wq_callback);
        INIT_DELAYED_WORK(&rtlpriv->works.fwevt_wq, rtl_fwevt_wq_callback);
        INIT_DELAYED_WORK(&rtlpriv->works.c2hcmd_wq, rtl_c2hcmd_wq_callback);
+       return 0;
 }
 
 void rtl_deinit_deferred_work(struct ieee80211_hw *hw, bool ips_wq)
@@ -564,9 +566,7 @@ int rtl_init_core(struct ieee80211_hw *hw)
        rtlmac->link_state = MAC80211_NOLINK;
 
        /* <6> init deferred work */
-       _rtl_init_deferred_work(hw);
-
-       return 0;
+       return _rtl_init_deferred_work(hw);
 }
 EXPORT_SYMBOL_GPL(rtl_init_core);
 
index ee4a339c05fd0bd2e20ed063652c8076acc3e878..058ce77b3cbce2b367962ed797d646d679f69a23 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Marvell NFC driver: Firmware downloader
  *
  * Copyright (C) 2015, Marvell International Ltd.
index 18cd96284b77a3b6827473b56f94dcc3fefdb5c3..c5420616b7bca508eeed80a09f66264673e572a5 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Marvell NFC-over-I2C driver: I2C interface related functions
  *
  * Copyright (C) 2015, Marvell International Ltd.
index de68ff45e49a4e7c228cb15f5e46c1e378736943..e84ee18c73aeb43c5063612e5fe0c3b477ac8fb6 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Marvell NFC driver
  *
  * Copyright (C) 2014-2015, Marvell International Ltd.
index 8e0ddb43477042dfa035c1ebb05b175b39d13796..dec0d3eb3648a5299ea822bbb56d63fdf699af72 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Marvell NFC-over-SPI driver: SPI interface related functions
  *
  * Copyright (C) 2015, Marvell International Ltd.
index e5a622ce4b9517d299170f20d35bde2bd5e003da..7194dd7ef0f1f47dea7382c3b6d45f9e5209ab3c 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Marvell NFC-over-UART driver
  *
  * Copyright (C) 2015, Marvell International Ltd.
index 888e298f610b8ed7140c85c5d0355d55007b6cfc..bcd563cb556ce1199382c689dc235b40f662b80c 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * Marvell NFC-over-USB driver: USB interface related functions
  *
  * Copyright (C) 2014, Marvell International Ltd.
index a44d49d63968a45a4c29f89ac9c7dadcb8890961..494675aeaaad7957e5df634fdb5911762a92328e 100644 (file)
@@ -71,7 +71,8 @@ config NVME_FC
 config NVME_TCP
        tristate "NVM Express over Fabrics TCP host driver"
        depends on INET
-       depends on BLK_DEV_NVME
+       depends on BLOCK
+       select NVME_CORE
        select NVME_FABRICS
        select CRYPTO
        select CRYPTO_CRC32C
index 762125f2905f7021f331c719e2ba127f56f52a32..66973bb5630551911c358e859266dab2da59638e 100644 (file)
@@ -3485,8 +3485,10 @@ int nvme_cdev_add(struct cdev *cdev, struct device *cdev_device,
        cdev_init(cdev, fops);
        cdev->owner = owner;
        ret = cdev_device_add(cdev, cdev_device);
-       if (ret)
+       if (ret) {
+               put_device(cdev_device);
                ida_simple_remove(&nvme_ns_chr_minor_ida, minor);
+       }
        return ret;
 }
 
index a2bb7fc63a735d07f0a3e4b7e84629b68bf3eed2..34a84d2086c74f7726b0b7312401f714b4fe0741 100644 (file)
@@ -336,6 +336,11 @@ static void nvmf_log_connect_error(struct nvme_ctrl *ctrl,
                        cmd->connect.recfmt);
                break;
 
+       case NVME_SC_HOST_PATH_ERROR:
+               dev_err(ctrl->device,
+                       "Connect command failed: host path error\n");
+               break;
+
        default:
                dev_err(ctrl->device,
                        "Connect command failed, error wo/DNR bit: %d\n",
index d9ab9e7871d0f7dc4b52e18e4c96091cfeac8733..f183f9fa03d0e18223c2e02e4eade52f13401d26 100644 (file)
@@ -2461,6 +2461,18 @@ nvme_fc_terminate_exchange(struct request *req, void *data, bool reserved)
 static void
 __nvme_fc_abort_outstanding_ios(struct nvme_fc_ctrl *ctrl, bool start_queues)
 {
+       int q;
+
+       /*
+        * if aborting io, the queues are no longer good, mark them
+        * all as not live.
+        */
+       if (ctrl->ctrl.queue_count > 1) {
+               for (q = 1; q < ctrl->ctrl.queue_count; q++)
+                       clear_bit(NVME_FC_Q_LIVE, &ctrl->queues[q].flags);
+       }
+       clear_bit(NVME_FC_Q_LIVE, &ctrl->queues[0].flags);
+
        /*
         * If io queues are present, stop them and terminate all outstanding
         * ios on them. As FC allocates FC exchange for each io, the
@@ -3095,6 +3107,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        if (ctrl->ctrl.icdoff) {
                dev_err(ctrl->ctrl.device, "icdoff %d is not supported!\n",
                                ctrl->ctrl.icdoff);
+               ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
                goto out_disconnect_admin_queue;
        }
 
@@ -3102,6 +3115,7 @@ nvme_fc_create_association(struct nvme_fc_ctrl *ctrl)
        if (!(ctrl->ctrl.sgls & ((1 << 0) | (1 << 1)))) {
                dev_err(ctrl->ctrl.device,
                        "Mandatory sgls are not supported!\n");
+               ret = NVME_SC_INVALID_FIELD | NVME_SC_DNR;
                goto out_disconnect_admin_queue;
        }
 
@@ -3268,11 +3282,13 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
        if (ctrl->ctrl.state != NVME_CTRL_CONNECTING)
                return;
 
-       if (portptr->port_state == FC_OBJSTATE_ONLINE)
+       if (portptr->port_state == FC_OBJSTATE_ONLINE) {
                dev_info(ctrl->ctrl.device,
                        "NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n",
                        ctrl->cnum, status);
-       else if (time_after_eq(jiffies, rport->dev_loss_end))
+               if (status > 0 && (status & NVME_SC_DNR))
+                       recon = false;
+       } else if (time_after_eq(jiffies, rport->dev_loss_end))
                recon = false;
 
        if (recon && nvmf_should_reconnect(&ctrl->ctrl)) {
@@ -3286,12 +3302,17 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)
 
                queue_delayed_work(nvme_wq, &ctrl->connect_work, recon_delay);
        } else {
-               if (portptr->port_state == FC_OBJSTATE_ONLINE)
-                       dev_warn(ctrl->ctrl.device,
-                               "NVME-FC{%d}: Max reconnect attempts (%d) "
-                               "reached.\n",
-                               ctrl->cnum, ctrl->ctrl.nr_reconnects);
-               else
+               if (portptr->port_state == FC_OBJSTATE_ONLINE) {
+                       if (status > 0 && (status & NVME_SC_DNR))
+                               dev_warn(ctrl->ctrl.device,
+                                        "NVME-FC{%d}: reconnect failure\n",
+                                        ctrl->cnum);
+                       else
+                               dev_warn(ctrl->ctrl.device,
+                                        "NVME-FC{%d}: Max reconnect attempts "
+                                        "(%d) reached.\n",
+                                        ctrl->cnum, ctrl->ctrl.nr_reconnects);
+               } else
                        dev_warn(ctrl->ctrl.device,
                                "NVME-FC{%d}: dev_loss_tmo (%d) expired "
                                "while waiting for remoteport connectivity.\n",
index 0222e23f5936da8032c75d5045efb368aa5fe74d..34f4b3402f7c1961a52cda389f14cca5e543a0d7 100644 (file)
@@ -943,7 +943,6 @@ static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)
                if (ret <= 0)
                        return ret;
 
-               nvme_tcp_advance_req(req, ret);
                if (queue->data_digest)
                        nvme_tcp_ddgst_update(queue->snd_hash, page,
                                        offset, ret);
@@ -960,6 +959,7 @@ static int nvme_tcp_try_send_data(struct nvme_tcp_request *req)
                        }
                        return 1;
                }
+               nvme_tcp_advance_req(req, ret);
        }
        return -EAGAIN;
 }
@@ -1140,7 +1140,8 @@ static void nvme_tcp_io_work(struct work_struct *w)
                                pending = true;
                        else if (unlikely(result < 0))
                                break;
-               }
+               } else
+                       pending = !llist_empty(&queue->req_list);
 
                result = nvme_tcp_try_recv(queue);
                if (result > 0)
index 25cc2ee8de3f10aa3658b6a769bbb024d965c280..4b29a5bac89697395f015dada7b4122265e8ab8d 100644 (file)
@@ -388,10 +388,10 @@ static void nvmet_keep_alive_timer(struct work_struct *work)
 {
        struct nvmet_ctrl *ctrl = container_of(to_delayed_work(work),
                        struct nvmet_ctrl, ka_work);
-       bool cmd_seen = ctrl->cmd_seen;
+       bool reset_tbkas = ctrl->reset_tbkas;
 
-       ctrl->cmd_seen = false;
-       if (cmd_seen) {
+       ctrl->reset_tbkas = false;
+       if (reset_tbkas) {
                pr_debug("ctrl %d reschedule traffic based keep-alive timer\n",
                        ctrl->cntlid);
                schedule_delayed_work(&ctrl->ka_work, ctrl->kato * HZ);
@@ -804,6 +804,13 @@ void nvmet_sq_destroy(struct nvmet_sq *sq)
        percpu_ref_exit(&sq->ref);
 
        if (ctrl) {
+               /*
+                * The teardown flow may take some time, and the host may not
+                * send us keep-alive during this period, hence reset the
+                * traffic based keep-alive timer so we don't trigger a
+                * controller teardown as a result of a keep-alive expiration.
+                */
+               ctrl->reset_tbkas = true;
                nvmet_ctrl_put(ctrl);
                sq->ctrl = NULL; /* allows reusing the queue later */
        }
@@ -952,7 +959,7 @@ bool nvmet_req_init(struct nvmet_req *req, struct nvmet_cq *cq,
        }
 
        if (sq->ctrl)
-               sq->ctrl->cmd_seen = true;
+               sq->ctrl->reset_tbkas = true;
 
        return true;
 
@@ -1372,7 +1379,7 @@ u16 nvmet_alloc_ctrl(const char *subsysnqn, const char *hostnqn,
                goto out_free_changed_ns_list;
 
        if (subsys->cntlid_min > subsys->cntlid_max)
-               goto out_free_changed_ns_list;
+               goto out_free_sqs;
 
        ret = ida_simple_get(&cntlid_ida,
                             subsys->cntlid_min, subsys->cntlid_max,
index 74b3b150e1a57f9cc836275316b1b22e2a38c201..cb30cb942e1d187802960f0d0262bbb232a7a18c 100644 (file)
@@ -590,8 +590,10 @@ static struct nvme_ctrl *nvme_loop_create_ctrl(struct device *dev,
 
        ret = nvme_init_ctrl(&ctrl->ctrl, dev, &nvme_loop_ctrl_ops,
                                0 /* no quirks, we're perfect! */);
-       if (ret)
+       if (ret) {
+               kfree(ctrl);
                goto out;
+       }
 
        if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))
                WARN_ON_ONCE(1);
index d69a409515d6509ed41910defa206b6ad1547720..53aea9a8056e73d1bff57a3c516e47370c90ff10 100644 (file)
@@ -167,7 +167,7 @@ struct nvmet_ctrl {
        struct nvmet_subsys     *subsys;
        struct nvmet_sq         **sqs;
 
-       bool                    cmd_seen;
+       bool                    reset_tbkas;
 
        struct mutex            lock;
        u64                     cap;
index f9f34f6caf5e8c4d7f7bfa9a2af8687bb464f221..d8aceef83284680fbfeae752154eeea37b6f2960 100644 (file)
@@ -550,7 +550,7 @@ static void nvmet_tcp_queue_response(struct nvmet_req *req)
                 * nvmet_req_init is completed.
                 */
                if (queue->rcv_state == NVMET_TCP_RECV_PDU &&
-                   len && len < cmd->req.port->inline_data_size &&
+                   len && len <= cmd->req.port->inline_data_size &&
                    nvme_is_write(cmd->req.cmd))
                        return;
        }
index bbc4e71a16ff8372f69977a74e5dd7899beabba7..38800e86ed8ad47371abe6f4459b259137a85c0f 100644 (file)
@@ -294,6 +294,9 @@ mlxbf_tmfifo_get_next_desc(struct mlxbf_tmfifo_vring *vring)
        if (vring->next_avail == virtio16_to_cpu(vdev, vr->avail->idx))
                return NULL;
 
+       /* Make sure 'avail->idx' is visible already. */
+       virtio_rmb(false);
+
        idx = vring->next_avail % vr->num;
        head = virtio16_to_cpu(vdev, vr->avail->ring[idx]);
        if (WARN_ON(head >= vr->num))
@@ -322,7 +325,7 @@ static void mlxbf_tmfifo_release_desc(struct mlxbf_tmfifo_vring *vring,
         * done or not. Add a memory barrier here to make sure the update above
         * completes before updating the idx.
         */
-       mb();
+       virtio_mb(false);
        vr->used->idx = cpu_to_virtio16(vdev, vr_idx + 1);
 }
 
@@ -733,6 +736,12 @@ static bool mlxbf_tmfifo_rxtx_one_desc(struct mlxbf_tmfifo_vring *vring,
                desc = NULL;
                fifo->vring[is_rx] = NULL;
 
+               /*
+                * Make sure the load/store are in order before
+                * returning back to virtio.
+                */
+               virtio_mb(false);
+
                /* Notify upper layer that packet is done. */
                spin_lock_irqsave(&fifo->spin_lock[is_rx], flags);
                vring_interrupt(0, vring->vq);
index 69e86cd599d38dce783d91b061ab5d3d6dbdf10b..8a70df60142c2d10ef095533f34429f7231677da 100644 (file)
@@ -2483,8 +2483,7 @@ int ssam_irq_setup(struct ssam_controller *ctrl)
         * interrupt, and let the SAM resume callback during the controller
         * resume process clear it.
         */
-       const int irqf = IRQF_SHARED | IRQF_ONESHOT |
-                        IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN;
+       const int irqf = IRQF_ONESHOT | IRQF_TRIGGER_RISING | IRQF_NO_AUTOEN;
 
        gpiod = gpiod_get(dev, "ssam_wakeup-int", GPIOD_ASIS);
        if (IS_ERR(gpiod))
index 63ce587e79e3ba2470778b2dfc5386dfcb0d8ea4..5d9b758a99bbc8c8a2616406ece312db8d3f615b 100644 (file)
@@ -527,20 +527,14 @@ static __poll_t surface_dtx_poll(struct file *file, struct poll_table_struct *pt
        struct sdtx_client *client = file->private_data;
        __poll_t events = 0;
 
-       if (down_read_killable(&client->ddev->lock))
-               return -ERESTARTSYS;
-
-       if (test_bit(SDTX_DEVICE_SHUTDOWN_BIT, &client->ddev->flags)) {
-               up_read(&client->ddev->lock);
+       if (test_bit(SDTX_DEVICE_SHUTDOWN_BIT, &client->ddev->flags))
                return EPOLLHUP | EPOLLERR;
-       }
 
        poll_wait(file, &client->ddev->waitq, pt);
 
        if (!kfifo_is_empty(&client->buffer))
                events |= EPOLLIN | EPOLLRDNORM;
 
-       up_read(&client->ddev->lock);
        return events;
 }
 
index 2714f7c3843e3d3ea34117b95a2cab422bd95076..60592fb88e7a0a347d718fb9ae66ec2525bde198 100644 (file)
@@ -711,7 +711,7 @@ config INTEL_HID_EVENT
 
 config INTEL_INT0002_VGPIO
        tristate "Intel ACPI INT0002 Virtual GPIO driver"
-       depends on GPIOLIB && ACPI
+       depends on GPIOLIB && ACPI && PM_SLEEP
        select GPIOLIB_IRQCHIP
        help
          Some peripherals on Bay Trail and Cherry Trail platforms signal a
index a1753485159ca6164206665fbb7d1e53a08eb442..33f823772733568a4f0aa59ab60efc102129bbbf 100644 (file)
@@ -270,7 +270,8 @@ int init_dell_smbios_wmi(void)
 
 void exit_dell_smbios_wmi(void)
 {
-       wmi_driver_unregister(&dell_smbios_wmi_driver);
+       if (wmi_supported)
+               wmi_driver_unregister(&dell_smbios_wmi_driver);
 }
 
 MODULE_DEVICE_TABLE(wmi, dell_smbios_wmi_id_table);
index 13d57434e60f26ee1686bd6286964301faee8ee6..5529d7b0abea353b3148510e10f0ed5c1bd063d2 100644 (file)
@@ -133,31 +133,21 @@ static u8 gigabyte_wmi_detect_sensor_usability(struct wmi_device *wdev)
        return r;
 }
 
+#define DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME(name) \
+       { .matches = { \
+               DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), \
+               DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
+       }}
+
 static const struct dmi_system_id gigabyte_wmi_known_working_platforms[] = {
-       { .matches = {
-               DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
-               DMI_EXACT_MATCH(DMI_BOARD_NAME, "B550 GAMING X V2"),
-       }},
-       { .matches = {
-               DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
-               DMI_EXACT_MATCH(DMI_BOARD_NAME, "B550M AORUS PRO-P"),
-       }},
-       { .matches = {
-               DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
-               DMI_EXACT_MATCH(DMI_BOARD_NAME, "B550M DS3H"),
-       }},
-       { .matches = {
-               DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
-               DMI_EXACT_MATCH(DMI_BOARD_NAME, "Z390 I AORUS PRO WIFI-CF"),
-       }},
-       { .matches = {
-               DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
-               DMI_EXACT_MATCH(DMI_BOARD_NAME, "X570 AORUS ELITE"),
-       }},
-       { .matches = {
-               DMI_EXACT_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
-               DMI_EXACT_MATCH(DMI_BOARD_NAME, "X570 I AORUS PRO WIFI"),
-       }},
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 AORUS ELITE"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550 GAMING X V2"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M AORUS PRO-P"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("B550M DS3H"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("Z390 I AORUS PRO WIFI-CF"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 AORUS ELITE"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 I AORUS PRO WIFI"),
+       DMI_EXACT_MATCH_GIGABYTE_BOARD_NAME("X570 UD"),
        { }
 };
 
index 12c31fd5d5ae25e25416a5ba1ca587f377c3100c..0753ef18e7211c6274f2bb41e2390a5ad3df99b5 100644 (file)
@@ -17,12 +17,14 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alex Hung");
 MODULE_ALIAS("acpi*:HPQ6001:*");
 MODULE_ALIAS("acpi*:WSTADEF:*");
+MODULE_ALIAS("acpi*:AMDI0051:*");
 
 static struct input_dev *hpwl_input_dev;
 
 static const struct acpi_device_id hpwl_ids[] = {
        {"HPQ6001", 0},
        {"WSTADEF", 0},
+       {"AMDI0051", 0},
        {"", 0},
 };
 
index 799cbe2ffcf36fe6d9ac3ab7094964bfb2a412bd..8c0867bda8280e3340f28f1ff821db03db0f3937 100644 (file)
@@ -88,6 +88,9 @@ MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
 static int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
 {
        struct acpi_device *dev = lis3->bus_priv;
+       if (!lis3->init_required)
+               return 0;
+
        if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
                                 NULL, NULL) != AE_OK)
                return -EINVAL;
@@ -356,6 +359,7 @@ static int lis3lv02d_add(struct acpi_device *device)
        }
 
        /* call the core layer do its init */
+       lis3_dev.init_required = true;
        ret = lis3lv02d_init_device(&lis3_dev);
        if (ret)
                return ret;
@@ -403,11 +407,27 @@ static int lis3lv02d_suspend(struct device *dev)
 
 static int lis3lv02d_resume(struct device *dev)
 {
+       lis3_dev.init_required = false;
+       lis3lv02d_poweron(&lis3_dev);
+       return 0;
+}
+
+static int lis3lv02d_restore(struct device *dev)
+{
+       lis3_dev.init_required = true;
        lis3lv02d_poweron(&lis3_dev);
        return 0;
 }
 
-static SIMPLE_DEV_PM_OPS(hp_accel_pm, lis3lv02d_suspend, lis3lv02d_resume);
+static const struct dev_pm_ops hp_accel_pm = {
+       .suspend = lis3lv02d_suspend,
+       .resume = lis3lv02d_resume,
+       .freeze = lis3lv02d_suspend,
+       .thaw = lis3lv02d_resume,
+       .poweroff = lis3lv02d_suspend,
+       .restore = lis3lv02d_restore,
+};
+
 #define HP_ACCEL_PM (&hp_accel_pm)
 #else
 #define HP_ACCEL_PM NULL
index 6cb5ad4be231d387385b32b648aa4aa152eb6ca5..3878172909219043b4f9e341cd2e9ad6ff2cd07a 100644 (file)
@@ -57,8 +57,8 @@ enum {
 };
 
 enum {
-       SMBC_CONSERVATION_ON  = 3,
-       SMBC_CONSERVATION_OFF = 5,
+       SBMC_CONSERVATION_ON  = 3,
+       SBMC_CONSERVATION_OFF = 5,
 };
 
 enum {
@@ -182,9 +182,9 @@ static int eval_gbmd(acpi_handle handle, unsigned long *res)
        return eval_int(handle, "GBMD", res);
 }
 
-static int exec_smbc(acpi_handle handle, unsigned long arg)
+static int exec_sbmc(acpi_handle handle, unsigned long arg)
 {
-       return exec_simple_method(handle, "SMBC", arg);
+       return exec_simple_method(handle, "SBMC", arg);
 }
 
 static int eval_hals(acpi_handle handle, unsigned long *res)
@@ -477,7 +477,7 @@ static ssize_t conservation_mode_store(struct device *dev,
        if (err)
                return err;
 
-       err = exec_smbc(priv->adev->handle, state ? SMBC_CONSERVATION_ON : SMBC_CONSERVATION_OFF);
+       err = exec_sbmc(priv->adev->handle, state ? SBMC_CONSERVATION_ON : SBMC_CONSERVATION_OFF);
        if (err)
                return err;
 
@@ -809,6 +809,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
 {
        struct ideapad_dytc_priv *dytc = container_of(pprof, struct ideapad_dytc_priv, pprof);
        struct ideapad_private *priv = dytc->priv;
+       unsigned long output;
        int err;
 
        err = mutex_lock_interruptible(&dytc->mutex);
@@ -829,7 +830,7 @@ static int dytc_profile_set(struct platform_profile_handler *pprof,
 
                /* Determine if we are in CQL mode. This alters the commands we do */
                err = dytc_cql_command(priv, DYTC_SET_COMMAND(DYTC_FUNCTION_MMC, perfmode, 1),
-                                      NULL);
+                                      &output);
                if (err)
                        goto unlock;
        }
index 289c6655d425d4a549cbe294212289777a697e27..569342aa8926eef258bd624f4f446b1faaceca82 100644 (file)
 #define GPE0A_STS_PORT                 0x420
 #define GPE0A_EN_PORT                  0x428
 
+struct int0002_data {
+       struct gpio_chip chip;
+       int parent_irq;
+       int wake_enable_count;
+};
+
 /*
  * As this is not a real GPIO at all, but just a hack to model an event in
  * ACPI the get / set functions are dummy functions.
@@ -98,14 +104,16 @@ static void int0002_irq_mask(struct irq_data *data)
 static int int0002_irq_set_wake(struct irq_data *data, unsigned int on)
 {
        struct gpio_chip *chip = irq_data_get_irq_chip_data(data);
-       struct platform_device *pdev = to_platform_device(chip->parent);
-       int irq = platform_get_irq(pdev, 0);
+       struct int0002_data *int0002 = container_of(chip, struct int0002_data, chip);
 
-       /* Propagate to parent irq */
+       /*
+        * Applying of the wakeup flag to our parent IRQ is delayed till system
+        * suspend, because we only want to do this when using s2idle.
+        */
        if (on)
-               enable_irq_wake(irq);
+               int0002->wake_enable_count++;
        else
-               disable_irq_wake(irq);
+               int0002->wake_enable_count--;
 
        return 0;
 }
@@ -135,7 +143,7 @@ static bool int0002_check_wake(void *data)
        return (gpe_sts_reg & GPE0A_PME_B0_STS_BIT);
 }
 
-static struct irq_chip int0002_byt_irqchip = {
+static struct irq_chip int0002_irqchip = {
        .name                   = DRV_NAME,
        .irq_ack                = int0002_irq_ack,
        .irq_mask               = int0002_irq_mask,
@@ -143,21 +151,9 @@ static struct irq_chip int0002_byt_irqchip = {
        .irq_set_wake           = int0002_irq_set_wake,
 };
 
-static struct irq_chip int0002_cht_irqchip = {
-       .name                   = DRV_NAME,
-       .irq_ack                = int0002_irq_ack,
-       .irq_mask               = int0002_irq_mask,
-       .irq_unmask             = int0002_irq_unmask,
-       /*
-        * No set_wake, on CHT the IRQ is typically shared with the ACPI SCI
-        * and we don't want to mess with the ACPI SCI irq settings.
-        */
-       .flags                  = IRQCHIP_SKIP_SET_WAKE,
-};
-
 static const struct x86_cpu_id int0002_cpu_ids[] = {
-       X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT,     &int0002_byt_irqchip),
-       X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT,        &int0002_cht_irqchip),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, NULL),
+       X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, NULL),
        {}
 };
 
@@ -172,8 +168,9 @@ static int int0002_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        const struct x86_cpu_id *cpu_id;
-       struct gpio_chip *chip;
+       struct int0002_data *int0002;
        struct gpio_irq_chip *girq;
+       struct gpio_chip *chip;
        int irq, ret;
 
        /* Menlow has a different INT0002 device? <sigh> */
@@ -185,10 +182,13 @@ static int int0002_probe(struct platform_device *pdev)
        if (irq < 0)
                return irq;
 
-       chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
-       if (!chip)
+       int0002 = devm_kzalloc(dev, sizeof(*int0002), GFP_KERNEL);
+       if (!int0002)
                return -ENOMEM;
 
+       int0002->parent_irq = irq;
+
+       chip = &int0002->chip;
        chip->label = DRV_NAME;
        chip->parent = dev;
        chip->owner = THIS_MODULE;
@@ -214,7 +214,7 @@ static int int0002_probe(struct platform_device *pdev)
        }
 
        girq = &chip->irq;
-       girq->chip = (struct irq_chip *)cpu_id->driver_data;
+       girq->chip = &int0002_irqchip;
        /* This let us handle the parent IRQ in the driver */
        girq->parent_handler = NULL;
        girq->num_parents = 0;
@@ -230,6 +230,7 @@ static int int0002_probe(struct platform_device *pdev)
 
        acpi_register_wakeup_handler(irq, int0002_check_wake, NULL);
        device_init_wakeup(dev, true);
+       dev_set_drvdata(dev, int0002);
        return 0;
 }
 
@@ -240,6 +241,36 @@ static int int0002_remove(struct platform_device *pdev)
        return 0;
 }
 
+static int int0002_suspend(struct device *dev)
+{
+       struct int0002_data *int0002 = dev_get_drvdata(dev);
+
+       /*
+        * The INT0002 parent IRQ is often shared with the ACPI GPE IRQ, don't
+        * muck with it when firmware based suspend is used, otherwise we may
+        * cause spurious wakeups from firmware managed suspend.
+        */
+       if (!pm_suspend_via_firmware() && int0002->wake_enable_count)
+               enable_irq_wake(int0002->parent_irq);
+
+       return 0;
+}
+
+static int int0002_resume(struct device *dev)
+{
+       struct int0002_data *int0002 = dev_get_drvdata(dev);
+
+       if (!pm_suspend_via_firmware() && int0002->wake_enable_count)
+               disable_irq_wake(int0002->parent_irq);
+
+       return 0;
+}
+
+static const struct dev_pm_ops int0002_pm_ops = {
+       .suspend = int0002_suspend,
+       .resume = int0002_resume,
+};
+
 static const struct acpi_device_id int0002_acpi_ids[] = {
        { "INT0002", 0 },
        { },
@@ -250,6 +281,7 @@ static struct platform_driver int0002_driver = {
        .driver = {
                .name                   = DRV_NAME,
                .acpi_match_table       = int0002_acpi_ids,
+               .pm                     = &int0002_pm_ops,
        },
        .probe  = int0002_probe,
        .remove = int0002_remove,
index 05cced59e251a98bfbf4c58f9f5541726f310184..f58b8543f6ac576243bc1734f3a0ba52a7107dac 100644 (file)
@@ -312,6 +312,7 @@ static const struct acpi_device_id punit_ipc_acpi_ids[] = {
        { "INT34D4", 0 },
        { }
 };
+MODULE_DEVICE_TABLE(acpi, punit_ipc_acpi_ids);
 
 static struct platform_driver intel_punit_ipc_driver = {
        .probe = intel_punit_ipc_probe,
index 90fe4f8f3c2c796b8257bf3733d6b65c84d4c955..bde740d6120e1e36c2929a5fe7626a6ea2f45bb1 100644 (file)
@@ -115,6 +115,32 @@ static const struct ts_dmi_data chuwi_hi10_plus_data = {
        .properties     = chuwi_hi10_plus_props,
 };
 
+static const struct property_entry chuwi_hi10_pro_props[] = {
+       PROPERTY_ENTRY_U32("touchscreen-min-x", 8),
+       PROPERTY_ENTRY_U32("touchscreen-min-y", 8),
+       PROPERTY_ENTRY_U32("touchscreen-size-x", 1912),
+       PROPERTY_ENTRY_U32("touchscreen-size-y", 1272),
+       PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+       PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-chuwi-hi10-pro.fw"),
+       PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+       PROPERTY_ENTRY_BOOL("silead,home-button"),
+       { }
+};
+
+static const struct ts_dmi_data chuwi_hi10_pro_data = {
+       .embedded_fw = {
+               .name   = "silead/gsl1680-chuwi-hi10-pro.fw",
+               .prefix = { 0xf0, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00 },
+               .length = 42504,
+               .sha256 = { 0xdb, 0x92, 0x68, 0xa8, 0xdb, 0x81, 0x31, 0x00,
+                           0x1f, 0x58, 0x89, 0xdb, 0x19, 0x1b, 0x15, 0x8c,
+                           0x05, 0x14, 0xf4, 0x95, 0xba, 0x15, 0x45, 0x98,
+                           0x42, 0xa3, 0xbb, 0x65, 0xe3, 0x30, 0xa5, 0x93 },
+       },
+       .acpi_name      = "MSSL1680:00",
+       .properties     = chuwi_hi10_pro_props,
+};
+
 static const struct property_entry chuwi_vi8_props[] = {
        PROPERTY_ENTRY_U32("touchscreen-min-x", 4),
        PROPERTY_ENTRY_U32("touchscreen-min-y", 6),
@@ -915,6 +941,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
                },
        },
+       {
+               /* Chuwi Hi10 Prus (CWI597) */
+               .driver_data = (void *)&chuwi_hi10_pro_data,
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "Hi10 pro tablet"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Cherry Trail CR"),
+               },
+       },
        {
                /* Chuwi Vi8 (CWI506) */
                .driver_data = (void *)&chuwi_vi8_data,
@@ -1096,6 +1131,14 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
                        DMI_MATCH(DMI_BIOS_VERSION, "jumperx.T87.KFBNEEA"),
                },
        },
+       {
+               /* Mediacom WinPad 7.0 W700 (same hw as Wintron surftab 7") */
+               .driver_data = (void *)&trekstor_surftab_wintron70_data,
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "WinPad 7 W10 - WPW700"),
+               },
+       },
        {
                /* Mediacom Flexbook Edge 11 (same hw as TS Primebook C11) */
                .driver_data = (void *)&trekstor_primebook_c11_data,
index 530e5f90095e6cf2d879376744d531254a02dc3b..0d1034e3ed0f2d2ef9c0adf83a7fa232e1b4d91c 100644 (file)
@@ -324,7 +324,7 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!bp->base) {
                dev_err(&pdev->dev, "io_remap bar0\n");
                err = -ENOMEM;
-               goto out;
+               goto out_release_regions;
        }
        bp->reg = bp->base + OCP_REGISTER_OFFSET;
        bp->tod = bp->base + TOD_REGISTER_OFFSET;
@@ -347,6 +347,8 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        return 0;
 
 out:
+       pci_iounmap(pdev, bp->base);
+out_release_regions:
        pci_release_regions(pdev);
 out_disable:
        pci_disable_device(pdev);
index 50ec53d67a4c0ed3e78a261647538d01ada3cd60..db4c265287ae6e1fdaadb62e291157cacbcb5251 100644 (file)
@@ -2127,6 +2127,14 @@ static int riocm_add_mport(struct device *dev,
                return -ENODEV;
        }
 
+       cm->rx_wq = create_workqueue(DRV_NAME "/rxq");
+       if (!cm->rx_wq) {
+               rio_release_inb_mbox(mport, cmbox);
+               rio_release_outb_mbox(mport, cmbox);
+               kfree(cm);
+               return -ENOMEM;
+       }
+
        /*
         * Allocate and register inbound messaging buffers to be ready
         * to receive channel and system management requests
@@ -2137,15 +2145,6 @@ static int riocm_add_mport(struct device *dev,
        cm->rx_slots = RIOCM_RX_RING_SIZE;
        mutex_init(&cm->rx_lock);
        riocm_rx_fill(cm, RIOCM_RX_RING_SIZE);
-       cm->rx_wq = create_workqueue(DRV_NAME "/rxq");
-       if (!cm->rx_wq) {
-               riocm_error("failed to allocate IBMBOX_%d on %s",
-                           cmbox, mport->name);
-               rio_release_outb_mbox(mport, cmbox);
-               kfree(cm);
-               return -ENOMEM;
-       }
-
        INIT_WORK(&cm->rx_work, rio_ibmsg_handler);
 
        cm->tx_slot = 0;
index 1b9e1442e6a50f003efabc4977bdae8899399cf3..fd42a5fffaed1bc2c8e76918f397820a1a93e394 100644 (file)
@@ -642,12 +642,18 @@ static void dasd_diag_setup_blk_queue(struct dasd_block *block)
        blk_queue_segment_boundary(q, PAGE_SIZE - 1);
 }
 
+static int dasd_diag_pe_handler(struct dasd_device *device,
+                               __u8 tbvpm, __u8 fcsecpm)
+{
+       return dasd_generic_verify_path(device, tbvpm);
+}
+
 static struct dasd_discipline dasd_diag_discipline = {
        .owner = THIS_MODULE,
        .name = "DIAG",
        .ebcname = "DIAG",
        .check_device = dasd_diag_check_device,
-       .verify_path = dasd_generic_verify_path,
+       .pe_handler = dasd_diag_pe_handler,
        .fill_geometry = dasd_diag_fill_geometry,
        .setup_blk_queue = dasd_diag_setup_blk_queue,
        .start_IO = dasd_start_diag,
index 4789410885e4fba8b8d9e6acf7f1a14d70a6a7bb..3ad319aee51edb470b970ce8dad903ab30cb954c 100644 (file)
@@ -794,13 +794,19 @@ static void dasd_fba_setup_blk_queue(struct dasd_block *block)
        blk_queue_flag_set(QUEUE_FLAG_DISCARD, q);
 }
 
+static int dasd_fba_pe_handler(struct dasd_device *device,
+                              __u8 tbvpm, __u8 fcsecpm)
+{
+       return dasd_generic_verify_path(device, tbvpm);
+}
+
 static struct dasd_discipline dasd_fba_discipline = {
        .owner = THIS_MODULE,
        .name = "FBA ",
        .ebcname = "FBA ",
        .check_device = dasd_fba_check_characteristics,
        .do_analysis = dasd_fba_do_analysis,
-       .verify_path = dasd_generic_verify_path,
+       .pe_handler = dasd_fba_pe_handler,
        .setup_blk_queue = dasd_fba_setup_blk_queue,
        .fill_geometry = dasd_fba_fill_geometry,
        .start_IO = dasd_start_IO,
index 1c59b0e86a9f073a82831c68cd4259f2a988de20..155428bfed8ac12b3c4d9b7da1af6752c827173b 100644 (file)
@@ -297,7 +297,6 @@ struct dasd_discipline {
         * e.g. verify that new path is compatible with the current
         * configuration.
         */
-       int (*verify_path)(struct dasd_device *, __u8);
        int (*pe_handler)(struct dasd_device *, __u8, __u8);
 
        /*
index b9febc581b1f4cf82a8013ef09b75d619847b834..8d1b2771c1aa0252df0196e08189691a474c7066 100644 (file)
@@ -638,6 +638,10 @@ int cp_init(struct channel_program *cp, struct device *mdev, union orb *orb)
        static DEFINE_RATELIMIT_STATE(ratelimit_state, 5 * HZ, 1);
        int ret;
 
+       /* this is an error in the caller */
+       if (cp->initialized)
+               return -EBUSY;
+
        /*
         * We only support prefetching the channel program. We assume all channel
         * programs executed by supported guests likewise support prefetching.
index 8c625b530035f536248ba2ad0260c82342144630..9b61e9b131ade02da6be5f87be69068353881272 100644 (file)
@@ -86,6 +86,7 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
        struct vfio_ccw_private *private;
        struct irb *irb;
        bool is_final;
+       bool cp_is_finished = false;
 
        private = container_of(work, struct vfio_ccw_private, io_work);
        irb = &private->irb;
@@ -94,14 +95,21 @@ static void vfio_ccw_sch_io_todo(struct work_struct *work)
                     (SCSW_ACTL_DEVACT | SCSW_ACTL_SCHACT));
        if (scsw_is_solicited(&irb->scsw)) {
                cp_update_scsw(&private->cp, &irb->scsw);
-               if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING)
+               if (is_final && private->state == VFIO_CCW_STATE_CP_PENDING) {
                        cp_free(&private->cp);
+                       cp_is_finished = true;
+               }
        }
        mutex_lock(&private->io_mutex);
        memcpy(private->io_region->irb_area, irb, sizeof(*irb));
        mutex_unlock(&private->io_mutex);
 
-       if (private->mdev && is_final)
+       /*
+        * Reset to IDLE only if processing of a channel program
+        * has finished. Do not overwrite a possible processing
+        * state if the final interrupt was for HSCH or CSCH.
+        */
+       if (private->mdev && cp_is_finished)
                private->state = VFIO_CCW_STATE_IDLE;
 
        if (private->io_trigger)
index 23e61aa638e4eb3048ee6fb84584c6591afa7d48..e435a9cd92dacf2b14fd30013e4fa1e839c2a180 100644 (file)
@@ -318,6 +318,7 @@ static void fsm_io_request(struct vfio_ccw_private *private,
        }
 
 err_out:
+       private->state = VFIO_CCW_STATE_IDLE;
        trace_vfio_ccw_fsm_io_request(scsw->cmd.fctl, schid,
                                      io_region->ret_code, errstr);
 }
index 491a64c61fff1a6b350a949b6988b46270e16b2b..c57d2a7f0919759a661bf01021d7746c4058fea3 100644 (file)
@@ -279,8 +279,6 @@ static ssize_t vfio_ccw_mdev_write_io_region(struct vfio_ccw_private *private,
        }
 
        vfio_ccw_fsm_event(private, VFIO_CCW_EVENT_IO_REQ);
-       if (region->ret_code != 0)
-               private->state = VFIO_CCW_STATE_IDLE;
        ret = (region->ret_code != 0) ? region->ret_code : count;
 
 out_unlock:
index 3ee46a843cb5f2d36e2d35707402fa2fbddb6773..adddcd5899416c5704efb7b957290846d894f386 100644 (file)
@@ -2926,11 +2926,11 @@ static int blogic_qcmd_lck(struct scsi_cmnd *command,
                ccb->opcode = BLOGIC_INITIATOR_CCB_SG;
                ccb->datalen = count * sizeof(struct blogic_sg_seg);
                if (blogic_multimaster_type(adapter))
-                       ccb->data = (void *)((unsigned int) ccb->dma_handle +
+                       ccb->data = (unsigned int) ccb->dma_handle +
                                        ((unsigned long) &ccb->sglist -
-                                       (unsigned long) ccb));
+                                       (unsigned long) ccb);
                else
-                       ccb->data = ccb->sglist;
+                       ccb->data = virt_to_32bit_virt(ccb->sglist);
 
                scsi_for_each_sg(command, sg, count, i) {
                        ccb->sglist[i].segbytes = sg_dma_len(sg);
index a8e4a19788a77641778e16e994aa6d234da86f8c..7d1ec10f243052023f6de6512815451b6f88fc21 100644 (file)
@@ -806,7 +806,7 @@ struct blogic_ccb {
        unsigned char cdblen;                           /* Byte 2 */
        unsigned char sense_datalen;                    /* Byte 3 */
        u32 datalen;                                    /* Bytes 4-7 */
-       void *data;                                     /* Bytes 8-11 */
+       u32 data;                                       /* Bytes 8-11 */
        unsigned char:8;                                /* Byte 12 */
        unsigned char:8;                                /* Byte 13 */
        enum blogic_adapter_status adapter_status;      /* Byte 14 */
index 924d55a8acbfced66e23f8851f182b8e2c3c7439..65182ad9cdf82adcdda3a85b213da22117ddf806 100644 (file)
@@ -58,7 +58,6 @@
 #include "aicasm_symbol.h"
 #include "aicasm_insformat.h"
 
-int yylineno;
 char *yyfilename;
 char stock_prefix[] = "aic_";
 char *prefix = stock_prefix;
index 7bf7fd5953ac97aeb767fa87249abed6e246d975..ed3bdd43c29763c2f4160fddb1880fffc9e26dd0 100644 (file)
@@ -108,7 +108,7 @@ struct macro_arg {
        regex_t arg_regex;
        char   *replacement_text;
 };
-STAILQ_HEAD(macro_arg_list, macro_arg) args;
+STAILQ_HEAD(macro_arg_list, macro_arg);
 
 struct macro_info {
        struct macro_arg_list args;
index a7515c3039edb672d718f285914d01064fa3bb3f..53343a6d8ae19a8c13202763fed3ec79863117a4 100644 (file)
@@ -3,6 +3,17 @@
  * $FreeBSD: src/sys/cam/scsi/scsi_message.h,v 1.2 2000/05/01 20:21:29 peter Exp $
  */
 
+/* Messages (1 byte) */                     /* I/T (M)andatory or (O)ptional */
+#define MSG_SAVEDATAPOINTER    0x02 /* O/O */
+#define MSG_RESTOREPOINTERS    0x03 /* O/O */
+#define MSG_DISCONNECT         0x04 /* O/O */
+#define MSG_MESSAGE_REJECT     0x07 /* M/M */
+#define MSG_NOOP               0x08 /* M/M */
+
+/* Messages (2 byte) */
+#define MSG_SIMPLE_Q_TAG       0x20 /* O/O */
+#define MSG_IGN_WIDE_RESIDUE   0x23 /* O/O */
+
 /* Identify message */              /* M/M */  
 #define MSG_IDENTIFYFLAG       0x80 
 #define MSG_IDENTIFY_DISCFLAG  0x40 
index 1a0dc18d6915567d3be040a7fbe8212e6cc85990..ed300a279a387f16d669fdee54d712eee21e6c14 100644 (file)
@@ -1220,6 +1220,7 @@ int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
                   was a result from the ABTS request rather than the CLEANUP
                   request */
                set_bit(BNX2FC_FLAG_IO_CLEANUP, &io_req->req_flags);
+               rc = FAILED;
                goto done;
        }
 
index 499c770d405c78fcc13d0dfb1f64b7b53f37190e..e954083140786dfae2be7e1c02122da8f1a22a57 100644 (file)
@@ -4811,14 +4811,14 @@ hisi_sas_v3_destroy_irqs(struct pci_dev *pdev, struct hisi_hba *hisi_hba)
 {
        int i;
 
-       free_irq(pci_irq_vector(pdev, 1), hisi_hba);
-       free_irq(pci_irq_vector(pdev, 2), hisi_hba);
-       free_irq(pci_irq_vector(pdev, 11), hisi_hba);
+       devm_free_irq(&pdev->dev, pci_irq_vector(pdev, 1), hisi_hba);
+       devm_free_irq(&pdev->dev, pci_irq_vector(pdev, 2), hisi_hba);
+       devm_free_irq(&pdev->dev, pci_irq_vector(pdev, 11), hisi_hba);
        for (i = 0; i < hisi_hba->cq_nvecs; i++) {
                struct hisi_sas_cq *cq = &hisi_hba->cq[i];
                int nr = hisi_sas_intr_conv ? 16 : 16 + i;
 
-               free_irq(pci_irq_vector(pdev, nr), cq);
+               devm_free_irq(&pdev->dev, pci_irq_vector(pdev, nr), cq);
        }
        pci_free_irq_vectors(pdev);
 }
index 19cf418928faae07fb58a6e911c9297c153a79fe..e3d03d744713d126966f635be71adee28a32741a 100644 (file)
@@ -25,7 +25,7 @@ static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy
 
 static void sas_resume_port(struct asd_sas_phy *phy)
 {
-       struct domain_device *dev;
+       struct domain_device *dev, *n;
        struct asd_sas_port *port = phy->port;
        struct sas_ha_struct *sas_ha = phy->ha;
        struct sas_internal *si = to_sas_internal(sas_ha->core.shost->transportt);
@@ -44,7 +44,7 @@ static void sas_resume_port(struct asd_sas_phy *phy)
         * 1/ presume every device came back
         * 2/ force the next revalidation to check all expander phys
         */
-       list_for_each_entry(dev, &port->dev_list, dev_list_node) {
+       list_for_each_entry_safe(dev, n, &port->dev_list, dev_list_node) {
                int i, rc;
 
                rc = sas_notify_lldd_dev_found(dev);
index ecd06d2d7e81624553b67f4da111d7603dca6341..71aa6af08340612e28454018d98d274b1bf31e69 100644 (file)
@@ -3765,11 +3765,13 @@ static int mpi_hw_event(struct pm8001_hba_info *pm8001_ha, void *piomb)
        case HW_EVENT_PHY_START_STATUS:
                pm8001_dbg(pm8001_ha, MSG, "HW_EVENT_PHY_START_STATUS status = %x\n",
                           status);
-               if (status == 0) {
+               if (status == 0)
                        phy->phy_state = 1;
-                       if (pm8001_ha->flags == PM8001F_RUN_TIME &&
-                                       phy->enable_completion != NULL)
-                               complete(phy->enable_completion);
+
+               if (pm8001_ha->flags == PM8001F_RUN_TIME &&
+                               phy->enable_completion != NULL) {
+                       complete(phy->enable_completion);
+                       phy->enable_completion = NULL;
                }
                break;
        case HW_EVENT_SAS_PHY_UP:
index 390c33df03578e7bc876e266ef9d3ad98a4ab57d..af09bd282cb94d80861c37a297d7b1ac2c38767a 100644 (file)
@@ -1151,8 +1151,8 @@ static int pm8001_pci_probe(struct pci_dev *pdev,
                goto err_out_shost;
        }
        list_add_tail(&pm8001_ha->list, &hba_list);
-       scsi_scan_host(pm8001_ha->shost);
        pm8001_ha->flags = PM8001F_RUN_TIME;
+       scsi_scan_host(pm8001_ha->shost);
        return 0;
 
 err_out_shost:
index d28af413b93a227014e529addec26d2ff54ee68b..335cf37e6cb94053f6cade51993afebb1ded3e22 100644 (file)
@@ -264,12 +264,17 @@ void pm8001_scan_start(struct Scsi_Host *shost)
        int i;
        struct pm8001_hba_info *pm8001_ha;
        struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
+       DECLARE_COMPLETION_ONSTACK(completion);
        pm8001_ha = sha->lldd_ha;
        /* SAS_RE_INITIALIZATION not available in SPCv/ve */
        if (pm8001_ha->chip_id == chip_8001)
                PM8001_CHIP_DISP->sas_re_init_req(pm8001_ha);
-       for (i = 0; i < pm8001_ha->chip->n_phy; ++i)
+       for (i = 0; i < pm8001_ha->chip->n_phy; ++i) {
+               pm8001_ha->phy[i].enable_completion = &completion;
                PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i);
+               wait_for_completion(&completion);
+               msleep(300);
+       }
 }
 
 int pm8001_scan_finished(struct Scsi_Host *shost, unsigned long time)
index 4e980830f9f59f137f1a80cefaba49199ee6894c..700530e969ac0d125170a3a038b692d8928cdcd0 100644 (file)
@@ -3487,13 +3487,13 @@ static int mpi_phy_start_resp(struct pm8001_hba_info *pm8001_ha, void *piomb)
        pm8001_dbg(pm8001_ha, INIT,
                   "phy start resp status:0x%x, phyid:0x%x\n",
                   status, phy_id);
-       if (status == 0) {
+       if (status == 0)
                phy->phy_state = PHY_LINK_DOWN;
-               if (pm8001_ha->flags == PM8001F_RUN_TIME &&
-                               phy->enable_completion != NULL) {
-                       complete(phy->enable_completion);
-                       phy->enable_completion = NULL;
-               }
+
+       if (pm8001_ha->flags == PM8001F_RUN_TIME &&
+                       phy->enable_completion != NULL) {
+               complete(phy->enable_completion);
+               phy->enable_completion = NULL;
        }
        return 0;
 
index 69f7784233f938ce9d6ebda1b0262da86fe49a02..756231151882478e0e225599bed69502e0b02a92 100644 (file)
@@ -536,7 +536,9 @@ static void qedf_update_link_speed(struct qedf_ctx *qedf,
        if (linkmode_intersects(link->supported_caps, sup_caps))
                lport->link_supported_speeds |= FC_PORTSPEED_20GBIT;
 
-       fc_host_supported_speeds(lport->host) = lport->link_supported_speeds;
+       if (lport->host && lport->host->shost_data)
+               fc_host_supported_speeds(lport->host) =
+                       lport->link_supported_speeds;
 }
 
 static void qedf_bw_update(void *dev)
index 0677295957bc5cb8cf89ea765011e7c6e106faaa..615e44af1ca604309fd845ea4b5b0405d1b25d6d 100644 (file)
@@ -1063,7 +1063,8 @@ qla82xx_write_flash_dword(struct qla_hw_data *ha, uint32_t flashaddr,
                return ret;
        }
 
-       if (qla82xx_flash_set_write_enable(ha))
+       ret = qla82xx_flash_set_write_enable(ha);
+       if (ret < 0)
                goto done_write;
 
        qla82xx_wr_32(ha, QLA82XX_ROMUSB_ROM_WDATA, data);
index b2008fb1dd386a103598739b17c04577c69e9445..12a6848ade435eaa1407fa2a238e9444bd4bf773 100644 (file)
@@ -1563,10 +1563,12 @@ void qlt_stop_phase2(struct qla_tgt *tgt)
                return;
        }
 
+       mutex_lock(&tgt->ha->optrom_mutex);
        mutex_lock(&vha->vha_tgt.tgt_mutex);
        tgt->tgt_stop = 0;
        tgt->tgt_stopped = 1;
        mutex_unlock(&vha->vha_tgt.tgt_mutex);
+       mutex_unlock(&tgt->ha->optrom_mutex);
 
        ql_dbg(ql_dbg_tgt_mgt, vha, 0xf00c, "Stop of tgt %p finished\n",
            tgt);
index 0aa58131e7915add4d8bc3fca57c8290817de7ac..d0626773eb3863a1194509db2d98fc125ba26900 100644 (file)
@@ -467,21 +467,24 @@ static int ufs_hisi_init_common(struct ufs_hba *hba)
        host->hba = hba;
        ufshcd_set_variant(hba, host);
 
-       host->rst  = devm_reset_control_get(dev, "rst");
+       host->rst = devm_reset_control_get(dev, "rst");
        if (IS_ERR(host->rst)) {
                dev_err(dev, "%s: failed to get reset control\n", __func__);
-               return PTR_ERR(host->rst);
+               err = PTR_ERR(host->rst);
+               goto error;
        }
 
        ufs_hisi_set_pm_lvl(hba);
 
        err = ufs_hisi_get_resource(host);
-       if (err) {
-               ufshcd_set_variant(hba, NULL);
-               return err;
-       }
+       if (err)
+               goto error;
 
        return 0;
+
+error:
+       ufshcd_set_variant(hba, NULL);
+       return err;
 }
 
 static int ufs_hi3660_init(struct ufs_hba *hba)
index a981f261b3043cae5861ce82e8d56c4003c50fab..aee3cfc7142a4213fc95731fed7be780978b3157 100644 (file)
@@ -922,6 +922,7 @@ static void ufs_mtk_vreg_set_lpm(struct ufs_hba *hba, bool lpm)
 static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
 {
        int err;
+       struct arm_smccc_res res;
 
        if (ufshcd_is_link_hibern8(hba)) {
                err = ufs_mtk_link_set_lpm(hba);
@@ -941,6 +942,9 @@ static int ufs_mtk_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op)
                        goto fail;
        }
 
+       if (ufshcd_is_link_off(hba))
+               ufs_mtk_device_reset_ctrl(0, res);
+
        return 0;
 fail:
        /*
index 3eb54937f1d8a7057d393e51ff8c50aca3b9afad..72fd41bfbd54bf38983953cc5f6059a93ff69c3e 100644 (file)
@@ -2842,7 +2842,7 @@ static int ufshcd_wait_for_dev_cmd(struct ufs_hba *hba,
  * ufshcd_exec_dev_cmd - API for sending device management requests
  * @hba: UFS hba
  * @cmd_type: specifies the type (NOP, Query...)
- * @timeout: time in seconds
+ * @timeout: timeout in milliseconds
  *
  * NOTE: Since there is only one available tag for device management commands,
  * it is expected you hold the hba->dev_cmd.lock mutex.
@@ -2872,6 +2872,9 @@ static int ufshcd_exec_dev_cmd(struct ufs_hba *hba,
        }
        tag = req->tag;
        WARN_ON_ONCE(!ufshcd_valid_tag(hba, tag));
+       /* Set the timeout such that the SCSI error handler is not activated. */
+       req->timeout = msecs_to_jiffies(2 * timeout);
+       blk_mq_start_request(req);
 
        init_completion(&wait);
        lrbp = &hba->lrb[tag];
index 8a79605d9652150b9433c81b8cfd811eb06f13b1..b9969fce6b4d14d0f9cd933cefe145da558b718b 100644 (file)
@@ -585,7 +585,13 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter,
                case BTSTAT_SUCCESS:
                case BTSTAT_LINKED_COMMAND_COMPLETED:
                case BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG:
-                       /* If everything went fine, let's move on..  */
+                       /*
+                        * Commands like INQUIRY may transfer less data than
+                        * requested by the initiator via bufflen. Set residual
+                        * count to make upper layer aware of the actual amount
+                        * of data returned.
+                        */
+                       scsi_set_resid(cmd, scsi_bufflen(cmd) - e->dataLen);
                        cmd->result = (DID_OK << 16);
                        break;
 
index 2827085a323b85078641c055019ea2346c89c203..0ef79d60e88e6dedded0db63be62b90f8f49f80e 100644 (file)
@@ -1150,8 +1150,16 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
 
        ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
                                        bp_mode, nports);
-       if (ret)
-               return ret;
+       if (ret) {
+               u32 version;
+
+               ctrl->reg_read(ctrl, SWRM_COMP_HW_VERSION, &version);
+
+               if (version <= 0x01030000)
+                       memset(bp_mode, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
+               else
+                       return ret;
+       }
 
        memset(hstart, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
        of_property_read_u8_array(np, "qcom,ports-hstart", hstart, nports);
index 8b161ec4943bfe05d4b406c7eb96bd04c6273100..f4481fe48bf0698fbf5d371353060316473e48b4 100644 (file)
@@ -65,7 +65,7 @@ config SPI_ALTERA
          This is the driver for the Altera SPI Controller.
 
 config SPI_ALTERA_CORE
-       tristate "Altera SPI Controller core code"
+       tristate "Altera SPI Controller core code" if COMPILE_TEST
        select REGMAP
        help
          "The core code for the Altera SPI Controller"
index 0287366874882de8bd941b8617b9625288088772..fb45e6af6638136ed071c282c74572697a32d198 100644 (file)
@@ -1375,11 +1375,13 @@ poll_mode:
        ret = spi_register_controller(ctlr);
        if (ret != 0) {
                dev_err(&pdev->dev, "Problem registering DSPI ctlr\n");
-               goto out_free_irq;
+               goto out_release_dma;
        }
 
        return ret;
 
+out_release_dma:
+       dspi_release_dma(dspi);
 out_free_irq:
        if (dspi->irq)
                free_irq(dspi->irq, dspi);
index 297c512069a5780f3d130563363eb7fa3577a33f..5d27ee4822376b9ac9702930420e525c3b20ae6b 100644 (file)
@@ -174,7 +174,7 @@ static int sc18is602_setup_transfer(struct sc18is602 *hw, u32 hz, u8 mode)
 static int sc18is602_check_transfer(struct spi_device *spi,
                                    struct spi_transfer *t, int tlen)
 {
-       if (t && t->len + tlen > SC18IS602_BUFSIZ)
+       if (t && t->len + tlen > SC18IS602_BUFSIZ + 1)
                return -EINVAL;
 
        return 0;
@@ -219,6 +219,11 @@ static int sc18is602_transfer_one(struct spi_master *master,
        return status;
 }
 
+static size_t sc18is602_max_transfer_size(struct spi_device *spi)
+{
+       return SC18IS602_BUFSIZ;
+}
+
 static int sc18is602_setup(struct spi_device *spi)
 {
        struct sc18is602 *hw = spi_master_get_devdata(spi->master);
@@ -293,6 +298,8 @@ static int sc18is602_probe(struct i2c_client *client,
        master->bits_per_word_mask = SPI_BPW_MASK(8);
        master->setup = sc18is602_setup;
        master->transfer_one_message = sc18is602_transfer_one;
+       master->max_transfer_size = sc18is602_max_transfer_size;
+       master->max_message_size = sc18is602_max_transfer_size;
        master->dev.of_node = np;
        master->min_speed_hz = hw->freq / 128;
        master->max_speed_hz = hw->freq / 4;
index b41a75749b498ed36d1361c5d2da1e4f857cb584..28e70db9bbba852d40ab53d211aada4353cf93a2 100644 (file)
@@ -1068,6 +1068,7 @@ static const struct of_device_id sprd_spi_of_match[] = {
        { .compatible = "sprd,sc9860-spi", },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, sprd_spi_of_match);
 
 static struct platform_driver sprd_spi_driver = {
        .driver = {
index 5d8a5ee62fa236bbf207f24d778209f089cb077d..5a3d81c31d0407aef1a8a898a165ecab2af9baa2 100644 (file)
@@ -367,7 +367,7 @@ static int zynq_qspi_config_op(struct zynq_qspi *xqspi, struct spi_device *spi)
 }
 
 /**
- * zynq_qspi_setup - Configure the QSPI controller
+ * zynq_qspi_setup_op - Configure the QSPI controller
  * @spi:       Pointer to the spi_device structure
  *
  * Sets the operational mode of QSPI controller for the next QSPI transfer, baud
@@ -528,18 +528,17 @@ static int zynq_qspi_exec_mem_op(struct spi_mem *mem,
        struct zynq_qspi *xqspi = spi_controller_get_devdata(mem->spi->master);
        int err = 0, i;
        u8 *tmpbuf;
-       u8 opcode = op->cmd.opcode;
 
        dev_dbg(xqspi->dev, "cmd:%#x mode:%d.%d.%d.%d\n",
-               opcode, op->cmd.buswidth, op->addr.buswidth,
+               op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth,
                op->dummy.buswidth, op->data.buswidth);
 
        zynq_qspi_chipselect(mem->spi, true);
        zynq_qspi_config_op(xqspi, mem->spi);
 
-       if (op->cmd.nbytes) {
+       if (op->cmd.opcode) {
                reinit_completion(&xqspi->data_completion);
-               xqspi->txbuf = &opcode;
+               xqspi->txbuf = (u8 *)&op->cmd.opcode;
                xqspi->rxbuf = NULL;
                xqspi->tx_bytes = op->cmd.nbytes;
                xqspi->rx_bytes = op->cmd.nbytes;
index ba425b9c77007ab9989d70c5be143ffebf69caa3..e353b7a9e54ebad4f5aa3d3262f474c289e3dc57 100644 (file)
@@ -47,10 +47,6 @@ static void spidev_release(struct device *dev)
 {
        struct spi_device       *spi = to_spi_device(dev);
 
-       /* spi controllers may cleanup for released devices */
-       if (spi->controller->cleanup)
-               spi->controller->cleanup(spi);
-
        spi_controller_put(spi->controller);
        kfree(spi->driver_override);
        kfree(spi);
@@ -558,6 +554,12 @@ static int spi_dev_check(struct device *dev, void *data)
        return 0;
 }
 
+static void spi_cleanup(struct spi_device *spi)
+{
+       if (spi->controller->cleanup)
+               spi->controller->cleanup(spi);
+}
+
 /**
  * spi_add_device - Add spi_device allocated with spi_alloc_device
  * @spi: spi_device to register
@@ -622,11 +624,13 @@ int spi_add_device(struct spi_device *spi)
 
        /* Device may be bound to an active driver when this returns */
        status = device_add(&spi->dev);
-       if (status < 0)
+       if (status < 0) {
                dev_err(dev, "can't add %s, status %d\n",
                                dev_name(&spi->dev), status);
-       else
+               spi_cleanup(spi);
+       } else {
                dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
+       }
 
 done:
        mutex_unlock(&spi_add_lock);
@@ -717,7 +721,9 @@ void spi_unregister_device(struct spi_device *spi)
        if (ACPI_COMPANION(&spi->dev))
                acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev));
        device_remove_software_node(&spi->dev);
-       device_unregister(&spi->dev);
+       device_del(&spi->dev);
+       spi_cleanup(spi);
+       put_device(&spi->dev);
 }
 EXPORT_SYMBOL_GPL(spi_unregister_device);
 
@@ -814,15 +820,29 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force)
 
        if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio)) {
                if (!(spi->mode & SPI_NO_CS)) {
-                       if (spi->cs_gpiod)
-                               /* polarity handled by gpiolib */
-                               gpiod_set_value_cansleep(spi->cs_gpiod, activate);
-                       else
+                       if (spi->cs_gpiod) {
+                               /*
+                                * Historically ACPI has no means of the GPIO polarity and
+                                * thus the SPISerialBus() resource defines it on the per-chip
+                                * basis. In order to avoid a chain of negations, the GPIO
+                                * polarity is considered being Active High. Even for the cases
+                                * when _DSD() is involved (in the updated versions of ACPI)
+                                * the GPIO CS polarity must be defined Active High to avoid
+                                * ambiguity. That's why we use enable, that takes SPI_CS_HIGH
+                                * into account.
+                                */
+                               if (has_acpi_companion(&spi->dev))
+                                       gpiod_set_value_cansleep(spi->cs_gpiod, !enable);
+                               else
+                                       /* Polarity handled by GPIO library */
+                                       gpiod_set_value_cansleep(spi->cs_gpiod, activate);
+                       } else {
                                /*
                                 * invert the enable line, as active low is
                                 * default for SPI.
                                 */
                                gpio_set_value_cansleep(spi->cs_gpio, !enable);
+                       }
                }
                /* Some SPI masters need both GPIO CS & slave_select */
                if ((spi->controller->flags & SPI_MASTER_GPIO_SS) &&
@@ -3451,9 +3471,12 @@ int spi_set_cs_timing(struct spi_device *spi, struct spi_delay *setup,
 
        if (spi->controller->set_cs_timing &&
            !(spi->cs_gpiod || gpio_is_valid(spi->cs_gpio))) {
+               mutex_lock(&spi->controller->io_mutex);
+
                if (spi->controller->auto_runtime_pm) {
                        status = pm_runtime_get_sync(parent);
                        if (status < 0) {
+                               mutex_unlock(&spi->controller->io_mutex);
                                pm_runtime_put_noidle(parent);
                                dev_err(&spi->controller->dev, "Failed to power device: %d\n",
                                        status);
@@ -3464,11 +3487,13 @@ int spi_set_cs_timing(struct spi_device *spi, struct spi_delay *setup,
                                                                hold, inactive);
                        pm_runtime_mark_last_busy(parent);
                        pm_runtime_put_autosuspend(parent);
-                       return status;
                } else {
-                       return spi->controller->set_cs_timing(spi, setup, hold,
+                       status = spi->controller->set_cs_timing(spi, setup, hold,
                                                              inactive);
                }
+
+               mutex_unlock(&spi->controller->io_mutex);
+               return status;
        }
 
        if ((setup && setup->unit == SPI_DELAY_UNIT_SCK) ||
index 741147a4f0fe4ee262eb38e0d144ddd914e91a7f..ecc5c9da902704a5a13bd91493df9a97d6d6e64e 100644 (file)
@@ -2064,7 +2064,7 @@ static int _nbu2ss_nuke(struct nbu2ss_udc *udc,
                        struct nbu2ss_ep *ep,
                        int status)
 {
-       struct nbu2ss_req *req;
+       struct nbu2ss_req *req, *n;
 
        /* Endpoint Disable */
        _nbu2ss_epn_exit(udc, ep);
@@ -2076,7 +2076,7 @@ static int _nbu2ss_nuke(struct nbu2ss_udc *udc,
                return 0;
 
        /* called with irqs blocked */
-       list_for_each_entry(req, &ep->queue, queue) {
+       list_for_each_entry_safe(req, n, &ep->queue, queue) {
                _nbu2ss_ep_done(ep, req, status);
        }
 
index dfd71e99e872ed27c089496a1b9826b9a0fe6a62..eab534dc4bcc0dbfad60de19bcc43000d3791aa3 100644 (file)
@@ -700,7 +700,6 @@ static int ad7746_probe(struct i2c_client *client,
                indio_dev->num_channels = ARRAY_SIZE(ad7746_channels);
        else
                indio_dev->num_channels =  ARRAY_SIZE(ad7746_channels) - 2;
-       indio_dev->num_channels = ARRAY_SIZE(ad7746_channels);
        indio_dev->modes = INDIO_DIRECT_MODE;
 
        if (pdata) {
index d6fdd1c61f90374957a2bdff0abb26b94f894abf..a526f9678c34bde71d001f3896d2ff201861ea50 100644 (file)
@@ -204,11 +204,11 @@ static struct se_dev_plug *iblock_plug_device(struct se_device *se_dev)
        struct iblock_dev_plug *ib_dev_plug;
 
        /*
-        * Each se_device has a per cpu work this can be run from. Wwe
+        * Each se_device has a per cpu work this can be run from. We
         * shouldn't have multiple threads on the same cpu calling this
         * at the same time.
         */
-       ib_dev_plug = &ib_dev->ibd_plug[smp_processor_id()];
+       ib_dev_plug = &ib_dev->ibd_plug[raw_smp_processor_id()];
        if (test_and_set_bit(IBD_PLUGF_PLUGGED, &ib_dev_plug->flags))
                return NULL;
 
index 8fbfe75c5744a8164efd9a9a24650131c29b6b8b..05d7ffd59df658f6387ab403bdcccf52f6f0b38e 100644 (file)
@@ -1416,7 +1416,7 @@ void __target_init_cmd(
        cmd->orig_fe_lun = unpacked_lun;
 
        if (!(cmd->se_cmd_flags & SCF_USE_CPUID))
-               cmd->cpuid = smp_processor_id();
+               cmd->cpuid = raw_smp_processor_id();
 
        cmd->state_active = false;
 }
index 198d25ae482ab6fcd83a675b6b73c1ac4ab956e3..4bba10e7755aa726282a7eec30efc70026474447 100644 (file)
@@ -516,8 +516,10 @@ static inline int tcmu_get_empty_block(struct tcmu_dev *udev,
        dpi = dbi * udev->data_pages_per_blk;
        /* Count the number of already allocated pages */
        xas_set(&xas, dpi);
+       rcu_read_lock();
        for (cnt = 0; xas_next(&xas) && cnt < page_cnt;)
                cnt++;
+       rcu_read_unlock();
 
        for (i = cnt; i < page_cnt; i++) {
                /* try to get new page from the mm */
@@ -699,11 +701,10 @@ static inline void tcmu_copy_data(struct tcmu_dev *udev,
                                  struct scatterlist *sg, unsigned int sg_nents,
                                  struct iovec **iov, size_t data_len)
 {
-       XA_STATE(xas, &udev->data_pages, 0);
        /* start value of dbi + 1 must not be a valid dbi */
        int dbi = -2;
        size_t page_remaining, cp_len;
-       int page_cnt, page_inx;
+       int page_cnt, page_inx, dpi;
        struct sg_mapping_iter sg_iter;
        unsigned int sg_flags;
        struct page *page;
@@ -726,9 +727,10 @@ static inline void tcmu_copy_data(struct tcmu_dev *udev,
                if (page_cnt > udev->data_pages_per_blk)
                        page_cnt = udev->data_pages_per_blk;
 
-               xas_set(&xas, dbi * udev->data_pages_per_blk);
-               for (page_inx = 0; page_inx < page_cnt && data_len; page_inx++) {
-                       page = xas_next(&xas);
+               dpi = dbi * udev->data_pages_per_blk;
+               for (page_inx = 0; page_inx < page_cnt && data_len;
+                    page_inx++, dpi++) {
+                       page = xa_load(&udev->data_pages, dpi);
 
                        if (direction == TCMU_DATA_AREA_TO_SG)
                                flush_dcache_page(page);
index 337c8d82f74ebfcc0f90e1d080a4a04456fa8156..6d0f7062bb870749e3a5117cf6dd98fe9d944a4b 100644 (file)
@@ -21,6 +21,7 @@
 #define TEEC_SUCCESS                   0x00000000
 #define TEEC_ERROR_GENERIC             0xFFFF0000
 #define TEEC_ERROR_BAD_PARAMETERS      0xFFFF0006
+#define TEEC_ERROR_OUT_OF_MEMORY       0xFFFF000C
 #define TEEC_ERROR_COMMUNICATION       0xFFFF000E
 
 #define TEEC_ORIGIN_COMMS              0x00000002
@@ -93,6 +94,18 @@ struct amdtee_shm_data {
        u32     buf_id;
 };
 
+/**
+ * struct amdtee_ta_data - Keeps track of all TAs loaded in AMD Secure
+ *                        Processor
+ * @ta_handle: Handle to TA loaded in TEE
+ * @refcount:  Reference count for the loaded TA
+ */
+struct amdtee_ta_data {
+       struct list_head list_node;
+       u32 ta_handle;
+       u32 refcount;
+};
+
 #define LOWER_TWO_BYTE_MASK    0x0000FFFF
 
 /**
index 096dd4d92d39ceac19a85a8dc504ddc2cd280c78..07f36ac834c888a428683b4df7def47684cfb27f 100644 (file)
@@ -121,15 +121,69 @@ static int amd_params_to_tee_params(struct tee_param *tee, u32 count,
        return ret;
 }
 
+static DEFINE_MUTEX(ta_refcount_mutex);
+static struct list_head ta_list = LIST_HEAD_INIT(ta_list);
+
+static u32 get_ta_refcount(u32 ta_handle)
+{
+       struct amdtee_ta_data *ta_data;
+       u32 count = 0;
+
+       /* Caller must hold a mutex */
+       list_for_each_entry(ta_data, &ta_list, list_node)
+               if (ta_data->ta_handle == ta_handle)
+                       return ++ta_data->refcount;
+
+       ta_data = kzalloc(sizeof(*ta_data), GFP_KERNEL);
+       if (ta_data) {
+               ta_data->ta_handle = ta_handle;
+               ta_data->refcount = 1;
+               count = ta_data->refcount;
+               list_add(&ta_data->list_node, &ta_list);
+       }
+
+       return count;
+}
+
+static u32 put_ta_refcount(u32 ta_handle)
+{
+       struct amdtee_ta_data *ta_data;
+       u32 count = 0;
+
+       /* Caller must hold a mutex */
+       list_for_each_entry(ta_data, &ta_list, list_node)
+               if (ta_data->ta_handle == ta_handle) {
+                       count = --ta_data->refcount;
+                       if (count == 0) {
+                               list_del(&ta_data->list_node);
+                               kfree(ta_data);
+                               break;
+                       }
+               }
+
+       return count;
+}
+
 int handle_unload_ta(u32 ta_handle)
 {
        struct tee_cmd_unload_ta cmd = {0};
-       u32 status;
+       u32 status, count;
        int ret;
 
        if (!ta_handle)
                return -EINVAL;
 
+       mutex_lock(&ta_refcount_mutex);
+
+       count = put_ta_refcount(ta_handle);
+
+       if (count) {
+               pr_debug("unload ta: not unloading %u count %u\n",
+                        ta_handle, count);
+               ret = -EBUSY;
+               goto unlock;
+       }
+
        cmd.ta_handle = ta_handle;
 
        ret = psp_tee_process_cmd(TEE_CMD_ID_UNLOAD_TA, (void *)&cmd,
@@ -137,8 +191,12 @@ int handle_unload_ta(u32 ta_handle)
        if (!ret && status != 0) {
                pr_err("unload ta: status = 0x%x\n", status);
                ret = -EBUSY;
+       } else {
+               pr_debug("unloaded ta handle %u\n", ta_handle);
        }
 
+unlock:
+       mutex_unlock(&ta_refcount_mutex);
        return ret;
 }
 
@@ -340,7 +398,8 @@ int handle_open_session(struct tee_ioctl_open_session_arg *arg, u32 *info,
 
 int handle_load_ta(void *data, u32 size, struct tee_ioctl_open_session_arg *arg)
 {
-       struct tee_cmd_load_ta cmd = {0};
+       struct tee_cmd_unload_ta unload_cmd = {};
+       struct tee_cmd_load_ta load_cmd = {};
        phys_addr_t blob;
        int ret;
 
@@ -353,21 +412,36 @@ int handle_load_ta(void *data, u32 size, struct tee_ioctl_open_session_arg *arg)
                return -EINVAL;
        }
 
-       cmd.hi_addr = upper_32_bits(blob);
-       cmd.low_addr = lower_32_bits(blob);
-       cmd.size = size;
+       load_cmd.hi_addr = upper_32_bits(blob);
+       load_cmd.low_addr = lower_32_bits(blob);
+       load_cmd.size = size;
 
-       ret = psp_tee_process_cmd(TEE_CMD_ID_LOAD_TA, (void *)&cmd,
-                                 sizeof(cmd), &arg->ret);
+       mutex_lock(&ta_refcount_mutex);
+
+       ret = psp_tee_process_cmd(TEE_CMD_ID_LOAD_TA, (void *)&load_cmd,
+                                 sizeof(load_cmd), &arg->ret);
        if (ret) {
                arg->ret_origin = TEEC_ORIGIN_COMMS;
                arg->ret = TEEC_ERROR_COMMUNICATION;
-       } else {
-               set_session_id(cmd.ta_handle, 0, &arg->session);
+       } else if (arg->ret == TEEC_SUCCESS) {
+               ret = get_ta_refcount(load_cmd.ta_handle);
+               if (!ret) {
+                       arg->ret_origin = TEEC_ORIGIN_COMMS;
+                       arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
+
+                       /* Unload the TA on error */
+                       unload_cmd.ta_handle = load_cmd.ta_handle;
+                       psp_tee_process_cmd(TEE_CMD_ID_UNLOAD_TA,
+                                           (void *)&unload_cmd,
+                                           sizeof(unload_cmd), &ret);
+               } else {
+                       set_session_id(load_cmd.ta_handle, 0, &arg->session);
+               }
        }
+       mutex_unlock(&ta_refcount_mutex);
 
        pr_debug("load TA: TA handle = 0x%x, RO = 0x%x, ret = 0x%x\n",
-                cmd.ta_handle, arg->ret_origin, arg->ret);
+                load_cmd.ta_handle, arg->ret_origin, arg->ret);
 
        return 0;
 }
index 8a6a8f30bb427ab060b4a132c1cbd0af06f1184a..da6b88e80dc07e0afd1fc1d7eb9235c27a53a60b 100644 (file)
@@ -59,10 +59,9 @@ static void release_session(struct amdtee_session *sess)
                        continue;
 
                handle_close_session(sess->ta_handle, sess->session_info[i]);
+               handle_unload_ta(sess->ta_handle);
        }
 
-       /* Unload Trusted Application once all sessions are closed */
-       handle_unload_ta(sess->ta_handle);
        kfree(sess);
 }
 
@@ -224,8 +223,6 @@ static void destroy_session(struct kref *ref)
        struct amdtee_session *sess = container_of(ref, struct amdtee_session,
                                                   refcount);
 
-       /* Unload the TA from TEE */
-       handle_unload_ta(sess->ta_handle);
        mutex_lock(&session_list_mutex);
        list_del(&sess->list_node);
        mutex_unlock(&session_list_mutex);
@@ -238,7 +235,7 @@ int amdtee_open_session(struct tee_context *ctx,
 {
        struct amdtee_context_data *ctxdata = ctx->data;
        struct amdtee_session *sess = NULL;
-       u32 session_info;
+       u32 session_info, ta_handle;
        size_t ta_size;
        int rc, i;
        void *ta;
@@ -259,11 +256,14 @@ int amdtee_open_session(struct tee_context *ctx,
        if (arg->ret != TEEC_SUCCESS)
                goto out;
 
+       ta_handle = get_ta_handle(arg->session);
+
        mutex_lock(&session_list_mutex);
        sess = alloc_session(ctxdata, arg->session);
        mutex_unlock(&session_list_mutex);
 
        if (!sess) {
+               handle_unload_ta(ta_handle);
                rc = -ENOMEM;
                goto out;
        }
@@ -277,6 +277,7 @@ int amdtee_open_session(struct tee_context *ctx,
 
        if (i >= TEE_NUM_SESSIONS) {
                pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
+               handle_unload_ta(ta_handle);
                kref_put(&sess->refcount, destroy_session);
                rc = -ENOMEM;
                goto out;
@@ -289,12 +290,13 @@ int amdtee_open_session(struct tee_context *ctx,
                spin_lock(&sess->lock);
                clear_bit(i, sess->sess_mask);
                spin_unlock(&sess->lock);
+               handle_unload_ta(ta_handle);
                kref_put(&sess->refcount, destroy_session);
                goto out;
        }
 
        sess->session_info[i] = session_info;
-       set_session_id(sess->ta_handle, i, &arg->session);
+       set_session_id(ta_handle, i, &arg->session);
 out:
        free_pages((u64)ta, get_order(ta_size));
        return rc;
@@ -329,6 +331,7 @@ int amdtee_close_session(struct tee_context *ctx, u32 session)
 
        /* Close the session */
        handle_close_session(ta_handle, session_info);
+       handle_unload_ta(ta_handle);
 
        kref_put(&sess->refcount, destroy_session);
 
index d1248ba943a4eb07660633a529eae0550c4e5675..62c0aa5d0783770baac479928c3a31a922b1c117 100644 (file)
@@ -237,6 +237,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
        if (ACPI_FAILURE(status))
                trip_cnt = 0;
        else {
+               int i;
+
                int34x_thermal_zone->aux_trips =
                        kcalloc(trip_cnt,
                                sizeof(*int34x_thermal_zone->aux_trips),
@@ -247,6 +249,8 @@ struct int34x_thermal_zone *int340x_thermal_zone_add(struct acpi_device *adev,
                }
                trip_mask = BIT(trip_cnt) - 1;
                int34x_thermal_zone->aux_trip_nr = trip_cnt;
+               for (i = 0; i < trip_cnt; ++i)
+                       int34x_thermal_zone->aux_trips[i] = THERMAL_TEMP_INVALID;
        }
 
        trip_cnt = int340x_thermal_read_trips(int34x_thermal_zone);
index 295742e839602f3d030affc4578b8c943e91e642..4d8edc61a78b22ac24ded8cff26a90d05d481a07 100644 (file)
@@ -166,7 +166,7 @@ static int sys_get_trip_temp(struct thermal_zone_device *tzd,
        if (thres_reg_value)
                *temp = zonedev->tj_max - thres_reg_value * 1000;
        else
-               *temp = 0;
+               *temp = THERMAL_TEMP_INVALID;
        pr_debug("sys_get_trip_temp %d\n", *temp);
 
        return 0;
index b460b56e981cc673ebd92fecbf6f9886f540d69e..232fd0b333251c3c7b4bfecf7289c82585002970 100644 (file)
@@ -441,7 +441,7 @@ static int adc_tm5_get_dt_channel_data(struct adc_tm5_chip *adc_tm,
 
        if (args.args_count != 1 || args.args[0] >= ADC5_MAX_CHANNEL) {
                dev_err(dev, "%s: invalid ADC channel number %d\n", name, chan);
-               return ret;
+               return -EINVAL;
        }
        channel->adc_channel = args.args[0];
 
index ebe7cb70bfb6334990f3306411949f04b5f5a783..ea0603b59309f5f0b0218d6e8398006cb41e6bbf 100644 (file)
@@ -770,7 +770,7 @@ static int ti_bandgap_tshut_init(struct ti_bandgap *bgp,
 }
 
 /**
- * ti_bandgap_alert_init() - setup and initialize talert handling
+ * ti_bandgap_talert_init() - setup and initialize talert handling
  * @bgp: pointer to struct ti_bandgap
  * @pdev: pointer to device struct platform_device
  *
index 7288aaf01ae6a494148ecb11df8b01f3b3d663d9..5631319f7b205676382166bcce2568aa7119b3ce 100644 (file)
@@ -366,15 +366,15 @@ int dma_port_flash_read(struct tb_dma_port *dma, unsigned int address,
                        void *buf, size_t size)
 {
        unsigned int retries = DMA_PORT_RETRIES;
-       unsigned int offset;
-
-       offset = address & 3;
-       address = address & ~3;
 
        do {
-               u32 nbytes = min_t(u32, size, MAIL_DATA_DWORDS * 4);
+               unsigned int offset;
+               size_t nbytes;
                int ret;
 
+               offset = address & 3;
+               nbytes = min_t(size_t, size + offset, MAIL_DATA_DWORDS * 4);
+
                ret = dma_port_flash_read_block(dma, address, dma->buf,
                                                ALIGN(nbytes, 4));
                if (ret) {
@@ -386,6 +386,7 @@ int dma_port_flash_read(struct tb_dma_port *dma, unsigned int address,
                        return ret;
                }
 
+               nbytes -= offset;
                memcpy(buf, dma->buf + offset, nbytes);
 
                size -= nbytes;
index 680bc738dd66dbaed41a67d0cf144426329da61c..671d72af8ba13b62fcbd04c46ec3bf67a266140f 100644 (file)
@@ -68,15 +68,15 @@ static int usb4_do_read_data(u16 address, void *buf, size_t size,
        unsigned int retries = USB4_DATA_RETRIES;
        unsigned int offset;
 
-       offset = address & 3;
-       address = address & ~3;
-
        do {
-               size_t nbytes = min_t(size_t, size, USB4_DATA_DWORDS * 4);
                unsigned int dwaddress, dwords;
                u8 data[USB4_DATA_DWORDS * 4];
+               size_t nbytes;
                int ret;
 
+               offset = address & 3;
+               nbytes = min_t(size_t, size + offset, USB4_DATA_DWORDS * 4);
+
                dwaddress = address / 4;
                dwords = ALIGN(nbytes, 4) / 4;
 
@@ -87,6 +87,7 @@ static int usb4_do_read_data(u16 address, void *buf, size_t size,
                        return ret;
                }
 
+               nbytes -= offset;
                memcpy(buf, data + offset, nbytes);
 
                size -= nbytes;
index 52bb21205bb682555ba6f22ce89b2ef388f0cc79..6473361525d1f792868db6117bd7c4555845a319 100644 (file)
@@ -7,6 +7,7 @@
  *  Copyright (C) 2001 Russell King.
  */
 
+#include <linux/bits.h>
 #include <linux/serial_8250.h>
 #include <linux/serial_reg.h>
 #include <linux/dmaengine.h>
@@ -70,24 +71,25 @@ struct serial8250_config {
        unsigned int    flags;
 };
 
-#define UART_CAP_FIFO  (1 << 8)        /* UART has FIFO */
-#define UART_CAP_EFR   (1 << 9)        /* UART has EFR */
-#define UART_CAP_SLEEP (1 << 10)       /* UART has IER sleep */
-#define UART_CAP_AFE   (1 << 11)       /* MCR-based hw flow control */
-#define UART_CAP_UUE   (1 << 12)       /* UART needs IER bit 6 set (Xscale) */
-#define UART_CAP_RTOIE (1 << 13)       /* UART needs IER bit 4 set (Xscale, Tegra) */
-#define UART_CAP_HFIFO (1 << 14)       /* UART has a "hidden" FIFO */
-#define UART_CAP_RPM   (1 << 15)       /* Runtime PM is active while idle */
-#define UART_CAP_IRDA  (1 << 16)       /* UART supports IrDA line discipline */
-#define UART_CAP_MINI  (1 << 17)       /* Mini UART on BCM283X family lacks:
+#define UART_CAP_FIFO  BIT(8)  /* UART has FIFO */
+#define UART_CAP_EFR   BIT(9)  /* UART has EFR */
+#define UART_CAP_SLEEP BIT(10) /* UART has IER sleep */
+#define UART_CAP_AFE   BIT(11) /* MCR-based hw flow control */
+#define UART_CAP_UUE   BIT(12) /* UART needs IER bit 6 set (Xscale) */
+#define UART_CAP_RTOIE BIT(13) /* UART needs IER bit 4 set (Xscale, Tegra) */
+#define UART_CAP_HFIFO BIT(14) /* UART has a "hidden" FIFO */
+#define UART_CAP_RPM   BIT(15) /* Runtime PM is active while idle */
+#define UART_CAP_IRDA  BIT(16) /* UART supports IrDA line discipline */
+#define UART_CAP_MINI  BIT(17) /* Mini UART on BCM283X family lacks:
                                         * STOP PARITY EPAR SPAR WLEN5 WLEN6
                                         */
 
-#define UART_BUG_QUOT  (1 << 0)        /* UART has buggy quot LSB */
-#define UART_BUG_TXEN  (1 << 1)        /* UART has buggy TX IIR status */
-#define UART_BUG_NOMSR (1 << 2)        /* UART has buggy MSR status bits (Au1x00) */
-#define UART_BUG_THRE  (1 << 3)        /* UART has buggy THRE reassertion */
-#define UART_BUG_PARITY        (1 << 4)        /* UART mishandles parity if FIFO enabled */
+#define UART_BUG_QUOT  BIT(0)  /* UART has buggy quot LSB */
+#define UART_BUG_TXEN  BIT(1)  /* UART has buggy TX IIR status */
+#define UART_BUG_NOMSR BIT(2)  /* UART has buggy MSR status bits (Au1x00) */
+#define UART_BUG_THRE  BIT(3)  /* UART has buggy THRE reassertion */
+#define UART_BUG_PARITY        BIT(4)  /* UART mishandles parity if FIFO enabled */
+#define UART_BUG_TXRACE        BIT(5)  /* UART Tx fails to set remote DR */
 
 
 #ifdef CONFIG_SERIAL_8250_SHARE_IRQ
index 61550f24a2d377e45e0a2a718c659b43eab9384c..d035d08cb98714186c0143458dc90814e6b91fc2 100644 (file)
@@ -437,6 +437,7 @@ static int aspeed_vuart_probe(struct platform_device *pdev)
        port.port.status = UPSTAT_SYNC_FIFO;
        port.port.dev = &pdev->dev;
        port.port.has_sysrq = IS_ENABLED(CONFIG_SERIAL_8250_CONSOLE);
+       port.bugs |= UART_BUG_TXRACE;
 
        rc = sysfs_create_group(&vuart->dev->kobj, &aspeed_vuart_attr_group);
        if (rc < 0)
index 9e204f9b799a1c868a21086e32ea5f4cd272c3f2..a3a0154da567da4a37fb9cc7a8fb1ba631b64bc8 100644 (file)
@@ -714,6 +714,7 @@ static const struct acpi_device_id dw8250_acpi_match[] = {
        { "APMC0D08", 0},
        { "AMD0020", 0 },
        { "AMDI0020", 0 },
+       { "AMDI0022", 0 },
        { "BRCM2032", 0 },
        { "HISI0031", 0 },
        { },
index 689d8227f95f7dfbc04a27fa39a63f6b85eae2b7..780cc99732b6239e980072756d17c17699bfc8fa 100644 (file)
@@ -56,6 +56,8 @@ struct serial_private {
        int                     line[];
 };
 
+#define PCI_DEVICE_ID_HPE_PCI_SERIAL   0x37e
+
 static const struct pci_device_id pci_use_msi[] = {
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9900,
                         0xA000, 0x1000) },
@@ -63,6 +65,8 @@ static const struct pci_device_id pci_use_msi[] = {
                         0xA000, 0x1000) },
        { PCI_DEVICE_SUB(PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9922,
                         0xA000, 0x1000) },
+       { PCI_DEVICE_SUB(PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL,
+                        PCI_ANY_ID, PCI_ANY_ID) },
        { }
 };
 
@@ -1997,6 +2001,16 @@ static struct pci_serial_quirk pci_serial_quirks[] = {
                .init           = pci_hp_diva_init,
                .setup          = pci_hp_diva_setup,
        },
+       /*
+        * HPE PCI serial device
+        */
+       {
+               .vendor         = PCI_VENDOR_ID_HP_3PAR,
+               .device         = PCI_DEVICE_ID_HPE_PCI_SERIAL,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_hp_diva_setup,
+       },
        /*
         * Intel
         */
@@ -3944,21 +3958,26 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
        uart.port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_SHARE_IRQ;
        uart.port.uartclk = board->base_baud * 16;
 
-       if (pci_match_id(pci_use_msi, dev)) {
-               dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n");
-               pci_set_master(dev);
-               rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES);
+       if (board->flags & FL_NOIRQ) {
+               uart.port.irq = 0;
        } else {
-               dev_dbg(&dev->dev, "Using legacy interrupts\n");
-               rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY);
-       }
-       if (rc < 0) {
-               kfree(priv);
-               priv = ERR_PTR(rc);
-               goto err_deinit;
+               if (pci_match_id(pci_use_msi, dev)) {
+                       dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n");
+                       pci_set_master(dev);
+                       rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES);
+               } else {
+                       dev_dbg(&dev->dev, "Using legacy interrupts\n");
+                       rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY);
+               }
+               if (rc < 0) {
+                       kfree(priv);
+                       priv = ERR_PTR(rc);
+                       goto err_deinit;
+               }
+
+               uart.port.irq = pci_irq_vector(dev, 0);
        }
 
-       uart.port.irq = pci_irq_vector(dev, 0);
        uart.port.dev = &dev->dev;
 
        for (i = 0; i < nr_ports; i++) {
@@ -4973,6 +4992,10 @@ static const struct pci_device_id serial_pci_tbl[] = {
        {       PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_DIVA_AUX,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
                pbn_b2_1_115200 },
+       /* HPE PCI serial device */
+       {       PCI_VENDOR_ID_HP_3PAR, PCI_DEVICE_ID_HPE_PCI_SERIAL,
+               PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+               pbn_b1_1_115200 },
 
        {       PCI_VENDOR_ID_DCI, PCI_DEVICE_ID_DCI_PCCOM2,
                PCI_ANY_ID, PCI_ANY_ID, 0, 0,
index d45dab1ab316473d9e9af8138db33a4ec02b2316..fc5ab203228213c4b0524d59f9478db813d3f687 100644 (file)
@@ -1809,6 +1809,18 @@ void serial8250_tx_chars(struct uart_8250_port *up)
        count = up->tx_loadsz;
        do {
                serial_out(up, UART_TX, xmit->buf[xmit->tail]);
+               if (up->bugs & UART_BUG_TXRACE) {
+                       /*
+                        * The Aspeed BMC virtual UARTs have a bug where data
+                        * may get stuck in the BMC's Tx FIFO from bursts of
+                        * writes on the APB interface.
+                        *
+                        * Delay back-to-back writes by a read cycle to avoid
+                        * stalling the VUART. Read a register that won't have
+                        * side-effects and discard the result.
+                        */
+                       serial_in(up, UART_SCR);
+               }
                xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
                port->icount.tx++;
                if (uart_circ_empty(xmit))
index 8534d6e45a1d7b65c149a130526aa5314203b66b..3cbc757d7be76cdc6ebb105da44916069226874f 100644 (file)
@@ -1519,6 +1519,8 @@ static int __init max310x_uart_init(void)
 
 #ifdef CONFIG_SPI_MASTER
        ret = spi_register_driver(&max310x_spi_driver);
+       if (ret)
+               uart_unregister_driver(&max310x_uart);
 #endif
 
        return ret;
index e0c00a1b07639b5a12a583059af4150c3f8d44aa..51b0ecabf2ec963ffefcd33999b08f1d9830931e 100644 (file)
@@ -818,9 +818,6 @@ static int mvebu_uart_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       if (!match)
-               return -ENODEV;
-
        /* Assume that all UART ports have a DT alias or none has */
        id = of_alias_get_id(pdev->dev.of_node, "serial");
        if (!pdev->dev.of_node || id < 0)
index d60abffab70eca80e450174378c50a25d8fe0861..6689d8add8f7aa66926f80cd9d316e5a4a5882e2 100644 (file)
@@ -195,7 +195,6 @@ struct rp2_card {
        void __iomem                    *bar0;
        void __iomem                    *bar1;
        spinlock_t                      card_lock;
-       struct completion               fw_loaded;
 };
 
 #define RP_ID(prod) PCI_VDEVICE(RP, (prod))
@@ -662,17 +661,10 @@ static void rp2_remove_ports(struct rp2_card *card)
        card->initialized_ports = 0;
 }
 
-static void rp2_fw_cb(const struct firmware *fw, void *context)
+static int rp2_load_firmware(struct rp2_card *card, const struct firmware *fw)
 {
-       struct rp2_card *card = context;
        resource_size_t phys_base;
-       int i, rc = -ENOENT;
-
-       if (!fw) {
-               dev_err(&card->pdev->dev, "cannot find '%s' firmware image\n",
-                       RP2_FW_NAME);
-               goto no_fw;
-       }
+       int i, rc = 0;
 
        phys_base = pci_resource_start(card->pdev, 1);
 
@@ -718,23 +710,13 @@ static void rp2_fw_cb(const struct firmware *fw, void *context)
                card->initialized_ports++;
        }
 
-       release_firmware(fw);
-no_fw:
-       /*
-        * rp2_fw_cb() is called from a workqueue long after rp2_probe()
-        * has already returned success.  So if something failed here,
-        * we'll just leave the now-dormant device in place until somebody
-        * unbinds it.
-        */
-       if (rc)
-               dev_warn(&card->pdev->dev, "driver initialization failed\n");
-
-       complete(&card->fw_loaded);
+       return rc;
 }
 
 static int rp2_probe(struct pci_dev *pdev,
                                   const struct pci_device_id *id)
 {
+       const struct firmware *fw;
        struct rp2_card *card;
        struct rp2_uart_port *ports;
        void __iomem * const *bars;
@@ -745,7 +727,6 @@ static int rp2_probe(struct pci_dev *pdev,
                return -ENOMEM;
        pci_set_drvdata(pdev, card);
        spin_lock_init(&card->card_lock);
-       init_completion(&card->fw_loaded);
 
        rc = pcim_enable_device(pdev);
        if (rc)
@@ -778,21 +759,23 @@ static int rp2_probe(struct pci_dev *pdev,
                return -ENOMEM;
        card->ports = ports;
 
-       rc = devm_request_irq(&pdev->dev, pdev->irq, rp2_uart_interrupt,
-                             IRQF_SHARED, DRV_NAME, card);
-       if (rc)
+       rc = request_firmware(&fw, RP2_FW_NAME, &pdev->dev);
+       if (rc < 0) {
+               dev_err(&pdev->dev, "cannot find '%s' firmware image\n",
+                       RP2_FW_NAME);
                return rc;
+       }
 
-       /*
-        * Only catastrophic errors (e.g. ENOMEM) are reported here.
-        * If the FW image is missing, we'll find out in rp2_fw_cb()
-        * and print an error message.
-        */
-       rc = request_firmware_nowait(THIS_MODULE, 1, RP2_FW_NAME, &pdev->dev,
-                                    GFP_KERNEL, card, rp2_fw_cb);
+       rc = rp2_load_firmware(card, fw);
+
+       release_firmware(fw);
+       if (rc < 0)
+               return rc;
+
+       rc = devm_request_irq(&pdev->dev, pdev->irq, rp2_uart_interrupt,
+                             IRQF_SHARED, DRV_NAME, card);
        if (rc)
                return rc;
-       dev_dbg(&pdev->dev, "waiting for firmware blob...\n");
 
        return 0;
 }
@@ -801,7 +784,6 @@ static void rp2_remove(struct pci_dev *pdev)
 {
        struct rp2_card *card = pci_get_drvdata(pdev);
 
-       wait_for_completion(&card->fw_loaded);
        rp2_remove_ports(card);
 }
 
index bbae072a125db880e87c19db1432017455e8fedf..222032792d6c29633904d91feaad89a90a82243f 100644 (file)
@@ -338,7 +338,7 @@ static void tegra_uart_fifo_reset(struct tegra_uart_port *tup, u8 fcr_bits)
 
        do {
                lsr = tegra_uart_read(tup, UART_LSR);
-               if ((lsr | UART_LSR_TEMT) && !(lsr & UART_LSR_DR))
+               if ((lsr & UART_LSR_TEMT) && !(lsr & UART_LSR_DR))
                        break;
                udelay(1);
        } while (--tmout);
index 87f7127b57e6b1ca5d64414ab76bab5bb3ed9c15..18ff85a83f8067bcff0b8d3fb56acf839b19b0e6 100644 (file)
@@ -863,9 +863,11 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
                goto check_and_exit;
        }
 
-       retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
-       if (retval && (change_irq || change_port))
-               goto exit;
+       if (change_irq || change_port) {
+               retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
+               if (retval)
+                       goto exit;
+       }
 
        /*
         * Ask the low level driver to verify the settings.
index ef37fdf37612f82f1ce280d885775f3178820fe1..4baf1316ea729931eb8675e433144103eabd6c19 100644 (file)
@@ -1023,10 +1023,10 @@ static int scif_set_rtrg(struct uart_port *port, int rx_trig)
 {
        unsigned int bits;
 
+       if (rx_trig >= port->fifosize)
+               rx_trig = port->fifosize - 1;
        if (rx_trig < 1)
                rx_trig = 1;
-       if (rx_trig >= port->fifosize)
-               rx_trig = port->fifosize;
 
        /* HSCIF can be set to an arbitrary level. */
        if (sci_getreg(port, HSRTRGR)->size) {
index 0330ba99730e2b2a21054c52b72cdf14bebfea9d..652fe2547587888d38d1b66c561ea7701586dcd8 100644 (file)
@@ -291,13 +291,15 @@ hv_uio_probe(struct hv_device *dev,
        pdata->recv_buf = vzalloc(RECV_BUFFER_SIZE);
        if (pdata->recv_buf == NULL) {
                ret = -ENOMEM;
-               goto fail_close;
+               goto fail_free_ring;
        }
 
        ret = vmbus_establish_gpadl(channel, pdata->recv_buf,
                                    RECV_BUFFER_SIZE, &pdata->recv_gpadl);
-       if (ret)
+       if (ret) {
+               vfree(pdata->recv_buf);
                goto fail_close;
+       }
 
        /* put Global Physical Address Label in name */
        snprintf(pdata->recv_name, sizeof(pdata->recv_name),
@@ -316,8 +318,10 @@ hv_uio_probe(struct hv_device *dev,
 
        ret = vmbus_establish_gpadl(channel, pdata->send_buf,
                                    SEND_BUFFER_SIZE, &pdata->send_gpadl);
-       if (ret)
+       if (ret) {
+               vfree(pdata->send_buf);
                goto fail_close;
+       }
 
        snprintf(pdata->send_name, sizeof(pdata->send_name),
                 "send:%u", pdata->send_gpadl);
@@ -347,6 +351,8 @@ hv_uio_probe(struct hv_device *dev,
 
 fail_close:
        hv_uio_cleanup(dev, pdata);
+fail_free_ring:
+       vmbus_free_ring(dev->channel);
 
        return ret;
 }
index c7d681fef198d6735dcbe0d2afcdaaed611a4b99..3bb0b0075467931c3b4d2e56fd915a1d56cf7efc 100644 (file)
@@ -82,7 +82,7 @@ static int probe(struct pci_dev *pdev,
        }
 
        if (pdev->irq && !pci_intx_mask_supported(pdev))
-               return -ENOMEM;
+               return -ENODEV;
 
        gdev = devm_kzalloc(&pdev->dev, sizeof(struct uio_pci_generic_dev), GFP_KERNEL);
        if (!gdev)
index 9b1bd417cec0393c1097f96800abd9e8f5ad8f28..a8b7b50abf6451cb5ff8c91aaf505676c7b17a0d 100644 (file)
@@ -3268,8 +3268,10 @@ static int __cdns3_gadget_init(struct cdns *cdns)
        pm_runtime_get_sync(cdns->dev);
 
        ret = cdns3_gadget_start(cdns);
-       if (ret)
+       if (ret) {
+               pm_runtime_put_sync(cdns->dev);
                return ret;
+       }
 
        /*
         * Because interrupt line can be shared with other components in
index 56707b6b0f57ca2c5ac6ebff23e62fe5459aeb56..c083985e387b2db123309fb5ce1e6846b6a2b6bb 100644 (file)
@@ -422,17 +422,17 @@ unmap:
 int cdnsp_ep_dequeue(struct cdnsp_ep *pep, struct cdnsp_request *preq)
 {
        struct cdnsp_device *pdev = pep->pdev;
-       int ret;
+       int ret_stop = 0;
+       int ret_rem;
 
        trace_cdnsp_request_dequeue(preq);
 
-       if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_RUNNING) {
-               ret = cdnsp_cmd_stop_ep(pdev, pep);
-               if (ret)
-                       return ret;
-       }
+       if (GET_EP_CTX_STATE(pep->out_ctx) == EP_STATE_RUNNING)
+               ret_stop = cdnsp_cmd_stop_ep(pdev, pep);
+
+       ret_rem = cdnsp_remove_request(pdev, preq, pep);
 
-       return cdnsp_remove_request(pdev, preq, pep);
+       return ret_rem ? ret_rem : ret_stop;
 }
 
 static void cdnsp_zero_in_ctx(struct cdnsp_device *pdev)
index c16d900cdaee3ce88bc33f605362561f86850fb5..393f216b916153c832b6f95eec764ac681c23171 100644 (file)
@@ -2061,6 +2061,7 @@ static int udc_start(struct ci_hdrc *ci)
        ci->gadget.name         = ci->platdata->name;
        ci->gadget.otg_caps     = otg_caps;
        ci->gadget.sg_supported = 1;
+       ci->gadget.irq          = ci->irq;
 
        if (ci->platdata->flags & CI_HDRC_REQUIRES_ALIGNED_DMA)
                ci->gadget.quirk_avoids_skb_reserve = 1;
index 533236366a03b8d35b8c6a724946dff6d9fe44b3..2218941d35a3fb1df5d3541951f4b64e28bb7c0d 100644 (file)
@@ -1218,7 +1218,12 @@ static int do_proc_bulk(struct usb_dev_state *ps,
        ret = usbfs_increase_memory_usage(len1 + sizeof(struct urb));
        if (ret)
                return ret;
-       tbuf = kmalloc(len1, GFP_KERNEL);
+
+       /*
+        * len1 can be almost arbitrarily large.  Don't WARN if it's
+        * too big, just fail the request.
+        */
+       tbuf = kmalloc(len1, GFP_KERNEL | __GFP_NOWARN);
        if (!tbuf) {
                ret = -ENOMEM;
                goto done;
@@ -1696,7 +1701,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
        if (num_sgs) {
                as->urb->sg = kmalloc_array(num_sgs,
                                            sizeof(struct scatterlist),
-                                           GFP_KERNEL);
+                                           GFP_KERNEL | __GFP_NOWARN);
                if (!as->urb->sg) {
                        ret = -ENOMEM;
                        goto error;
@@ -1731,7 +1736,7 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb
                                        (uurb_start - as->usbm->vm_start);
                } else {
                        as->urb->transfer_buffer = kmalloc(uurb->buffer_length,
-                                       GFP_KERNEL);
+                                       GFP_KERNEL | __GFP_NOWARN);
                        if (!as->urb->transfer_buffer) {
                                ret = -ENOMEM;
                                goto error;
index 49ca5da5e2794866148b66b93570797e661a163b..612825a39f8214d3fbd600ef0e18125ab712679b 100644 (file)
@@ -1244,6 +1244,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
                        req->start_sg = sg_next(s);
 
                req->num_queued_sgs++;
+               req->num_pending_sgs--;
 
                /*
                 * The number of pending SG entries may not correspond to the
@@ -1251,7 +1252,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
                 * don't include unused SG entries.
                 */
                if (length == 0) {
-                       req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs;
+                       req->num_pending_sgs = 0;
                        break;
                }
 
@@ -2873,15 +2874,15 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
        struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue];
        struct scatterlist *sg = req->sg;
        struct scatterlist *s;
-       unsigned int pending = req->num_pending_sgs;
+       unsigned int num_queued = req->num_queued_sgs;
        unsigned int i;
        int ret = 0;
 
-       for_each_sg(sg, s, pending, i) {
+       for_each_sg(sg, s, num_queued, i) {
                trb = &dep->trb_pool[dep->trb_dequeue];
 
                req->sg = sg_next(s);
-               req->num_pending_sgs--;
+               req->num_queued_sgs--;
 
                ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req,
                                trb, event, status, true);
@@ -2904,7 +2905,7 @@ static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep,
 
 static bool dwc3_gadget_ep_request_completed(struct dwc3_request *req)
 {
-       return req->num_pending_sgs == 0;
+       return req->num_pending_sgs == 0 && req->num_queued_sgs == 0;
 }
 
 static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
@@ -2913,7 +2914,7 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
 {
        int ret;
 
-       if (req->num_pending_sgs)
+       if (req->request.num_mapped_sgs)
                ret = dwc3_gadget_ep_reclaim_trb_sg(dep, req, event,
                                status);
        else
index 0c418ce50ba0f41a804d6b9000d0bcf9f3caaaea..f1b35a39d1ba8712daf42c7c754cd465e93179eb 100644 (file)
@@ -1488,7 +1488,7 @@ static void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep,
                             struct renesas_usb3_request *usb3_req)
 {
        struct renesas_usb3 *usb3 = usb3_ep_to_usb3(usb3_ep);
-       struct renesas_usb3_request *usb3_req_first = usb3_get_request(usb3_ep);
+       struct renesas_usb3_request *usb3_req_first;
        unsigned long flags;
        int ret = -EAGAIN;
        u32 enable_bits = 0;
@@ -1496,7 +1496,8 @@ static void usb3_start_pipen(struct renesas_usb3_ep *usb3_ep,
        spin_lock_irqsave(&usb3->lock, flags);
        if (usb3_ep->halt || usb3_ep->started)
                goto out;
-       if (usb3_req != usb3_req_first)
+       usb3_req_first = __usb3_get_request(usb3_ep);
+       if (!usb3_req_first || usb3_req != usb3_req_first)
                goto out;
 
        if (usb3_pn_change(usb3, usb3_ep->num) < 0)
index a8e4189277da875995467b04b5754d6412290386..6acd2329e08d49d6301fd62d7f82f7f9217fff11 100644 (file)
@@ -828,14 +828,10 @@ static void xhci_giveback_invalidated_tds(struct xhci_virt_ep *ep)
        list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list,
                                 cancelled_td_list) {
 
-               /*
-                * Doesn't matter what we pass for status, since the core will
-                * just overwrite it (because the URB has been unlinked).
-                */
                ring = xhci_urb_to_transfer_ring(ep->xhci, td->urb);
 
                if (td->cancel_status == TD_CLEARED)
-                       xhci_td_cleanup(ep->xhci, td, ring, 0);
+                       xhci_td_cleanup(ep->xhci, td, ring, td->status);
 
                if (ep->xhci->xhc_state & XHCI_STATE_DYING)
                        return;
@@ -937,14 +933,18 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
                        continue;
                }
                /*
-                * If ring stopped on the TD we need to cancel, then we have to
+                * If a ring stopped on the TD we need to cancel then we have to
                 * move the xHC endpoint ring dequeue pointer past this TD.
+                * Rings halted due to STALL may show hw_deq is past the stalled
+                * TD, but still require a set TR Deq command to flush xHC cache.
                 */
                hw_deq = xhci_get_hw_deq(xhci, ep->vdev, ep->ep_index,
                                         td->urb->stream_id);
                hw_deq &= ~0xf;
 
-               if (trb_in_td(xhci, td->start_seg, td->first_trb,
+               if (td->cancel_status == TD_HALTED) {
+                       cached_td = td;
+               } else if (trb_in_td(xhci, td->start_seg, td->first_trb,
                              td->last_trb, hw_deq, false)) {
                        switch (td->cancel_status) {
                        case TD_CLEARED: /* TD is already no-op */
index a3dfc77578ea1200129d69e693740900b8721109..26baba3ab7d733d35aa1d46443da0a187a519685 100644 (file)
@@ -61,9 +61,9 @@ static ssize_t speed_store(struct device *dev, struct device_attribute *attr,
        /* Set speed */
        retval = usb_control_msg(tv->udev, usb_sndctrlpipe(tv->udev, 0),
                                 0x01, /* vendor request: set speed */
-                                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
+                                USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
                                 tv->speed, /* speed value */
-                                0, NULL, 0, USB_CTRL_GET_TIMEOUT);
+                                0, NULL, 0, USB_CTRL_SET_TIMEOUT);
        if (retval) {
                tv->speed = old;
                dev_dbg(&tv->udev->dev, "retval = %d\n", retval);
index b5d6616442635b8bf4c814bfd629a9ec18e927a3..748139d262633cb1a8bec5c3a5843a2346c6614b 100644 (file)
@@ -736,6 +736,7 @@ static int uss720_probe(struct usb_interface *intf,
        parport_announce_port(pp);
 
        usb_set_intfdata(intf, pp);
+       usb_put_dev(usbdev);
        return 0;
 
 probe_abort:
index 6f2659e59b2ee7bdfc7c16da88d3d20e25acd696..369ef140df78aab9caf3c5a92ed1db998c67cd72 100644 (file)
@@ -1034,6 +1034,9 @@ static const struct usb_device_id id_table_combined[] = {
        /* Sienna devices */
        { USB_DEVICE(FTDI_VID, FTDI_SIENNA_PID) },
        { USB_DEVICE(ECHELON_VID, ECHELON_U20_PID) },
+       /* IDS GmbH devices */
+       { USB_DEVICE(IDS_VID, IDS_SI31A_PID) },
+       { USB_DEVICE(IDS_VID, IDS_CM31A_PID) },
        /* U-Blox devices */
        { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ZED_PID) },
        { USB_DEVICE(UBLOX_VID, UBLOX_C099F9P_ODIN_PID) },
index 3d47c6d72256e383afad8d42cd2e5b5d1ccb01e5..d854e04a4286e2e8d17f39e59ae395d212fe134b 100644 (file)
 #define UNJO_VID                       0x22B7
 #define UNJO_ISODEBUG_V1_PID           0x150D
 
+/*
+ * IDS GmbH
+ */
+#define IDS_VID                                0x2CAF
+#define IDS_SI31A_PID                  0x13A2
+#define IDS_CM31A_PID                  0x13A3
+
 /*
  * U-Blox products (http://www.u-blox.com).
  */
index 3e79a543d3e771d515bdd502c7df5035becbe617..7608584ef4fe78f1394fc74dcce169efc2dc38ec 100644 (file)
@@ -1240,6 +1240,10 @@ static const struct usb_device_id option_ids[] = {
          .driver_info = NCTRL(0) | RSVD(1) },
        { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff),    /* Telit LN940 (MBIM) */
          .driver_info = NCTRL(0) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7010, 0xff),    /* Telit LE910-S1 (RNDIS) */
+         .driver_info = NCTRL(2) },
+       { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x7011, 0xff),    /* Telit LE910-S1 (ECM) */
+         .driver_info = NCTRL(2) },
        { USB_DEVICE(TELIT_VENDOR_ID, 0x9010),                          /* Telit SBL FN980 flashing device */
          .driver_info = NCTRL(0) | ZLP },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */
index fd773d252691b86a42d4b17da31a2e1a6bc68217..940050c314822539260a99361dcc723e6490d1a6 100644 (file)
@@ -113,6 +113,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) },
        { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) },
        { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) },
+       { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530GC_PRODUCT_ID) },
        { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) },
        { USB_DEVICE(AT_VENDOR_ID, AT_VTKIT3_PRODUCT_ID) },
        { }                                     /* Terminating entry */
index 0f681ddbfd288de75af32f8e6453fb4f27844ee0..6097ee8fccb25cdbf6feaa28d49f784c913ca492 100644 (file)
 /* ADLINK ND-6530 RS232,RS485 and RS422 adapter */
 #define ADLINK_VENDOR_ID               0x0b63
 #define ADLINK_ND6530_PRODUCT_ID       0x6530
+#define ADLINK_ND6530GC_PRODUCT_ID     0x653a
 
 /* SMART USB Serial Adapter */
 #define SMART_VENDOR_ID        0x0b8c
index caa46ac23db90e8ab953c773aa16453604d9050a..310db5abea9d81267a1a66ab0c44749bf231e76d 100644 (file)
@@ -37,6 +37,7 @@
 /* Vendor and product ids */
 #define TI_VENDOR_ID                   0x0451
 #define IBM_VENDOR_ID                  0x04b3
+#define STARTECH_VENDOR_ID             0x14b0
 #define TI_3410_PRODUCT_ID             0x3410
 #define IBM_4543_PRODUCT_ID            0x4543
 #define IBM_454B_PRODUCT_ID            0x454b
@@ -370,6 +371,7 @@ static const struct usb_device_id ti_id_table_3410[] = {
        { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) },
        { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) },
        { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) },
+       { USB_DEVICE(STARTECH_VENDOR_ID, TI_3410_PRODUCT_ID) },
        { }     /* terminator */
 };
 
@@ -408,6 +410,7 @@ static const struct usb_device_id ti_id_table_combined[] = {
        { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1131_PRODUCT_ID) },
        { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1150_PRODUCT_ID) },
        { USB_DEVICE(MXU1_VENDOR_ID, MXU1_1151_PRODUCT_ID) },
+       { USB_DEVICE(STARTECH_VENDOR_ID, TI_3410_PRODUCT_ID) },
        { }     /* terminator */
 };
 
index 9da22ae3006c970011624262084f4a97a954fc41..8514bec7e1b89282aa70034e33f7ddb17536d3ff 100644 (file)
@@ -191,6 +191,7 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id,
        bool match;
        int nval;
        u16 *val;
+       int ret;
        int i;
 
        /*
@@ -218,10 +219,10 @@ static void *typec_mux_match(struct fwnode_handle *fwnode, const char *id,
        if (!val)
                return ERR_PTR(-ENOMEM);
 
-       nval = fwnode_property_read_u16_array(fwnode, "svid", val, nval);
-       if (nval < 0) {
+       ret = fwnode_property_read_u16_array(fwnode, "svid", val, nval);
+       if (ret < 0) {
                kfree(val);
-               return ERR_PTR(nval);
+               return ERR_PTR(ret);
        }
 
        for (i = 0; i < nval; i++) {
index 64133e586c644e7ccf0c0bd4a2c899eab9f76884..9ce8c9af4da5805b205b68c5ded86445f67694b0 100644 (file)
@@ -1550,6 +1550,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
                        if (PD_VDO_SVDM_VER(p[0]) < svdm_version)
                                typec_partner_set_svdm_version(port->partner,
                                                               PD_VDO_SVDM_VER(p[0]));
+
+                       tcpm_ams_start(port, DISCOVER_IDENTITY);
                        /* 6.4.4.3.1: Only respond as UFP (device) */
                        if (port->data_role == TYPEC_DEVICE &&
                            port->nr_snk_vdo) {
@@ -1568,14 +1570,19 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
                        }
                        break;
                case CMD_DISCOVER_SVID:
+                       tcpm_ams_start(port, DISCOVER_SVIDS);
                        break;
                case CMD_DISCOVER_MODES:
+                       tcpm_ams_start(port, DISCOVER_MODES);
                        break;
                case CMD_ENTER_MODE:
+                       tcpm_ams_start(port, DFP_TO_UFP_ENTER_MODE);
                        break;
                case CMD_EXIT_MODE:
+                       tcpm_ams_start(port, DFP_TO_UFP_EXIT_MODE);
                        break;
                case CMD_ATTENTION:
+                       tcpm_ams_start(port, ATTENTION);
                        /* Attention command does not have response */
                        *adev_action = ADEV_ATTENTION;
                        return 0;
@@ -2287,6 +2294,12 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
        bool frs_enable;
        int ret;
 
+       if (tcpm_vdm_ams(port) && type != PD_DATA_VENDOR_DEF) {
+               port->vdm_state = VDM_STATE_ERR_BUSY;
+               tcpm_ams_finish(port);
+               mod_vdm_delayed_work(port, 0);
+       }
+
        switch (type) {
        case PD_DATA_SOURCE_CAP:
                for (i = 0; i < cnt; i++)
@@ -2417,7 +2430,10 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
                                           NONE_AMS);
                break;
        case PD_DATA_VENDOR_DEF:
-               tcpm_handle_vdm_request(port, msg->payload, cnt);
+               if (tcpm_vdm_ams(port) || port->nr_snk_vdo)
+                       tcpm_handle_vdm_request(port, msg->payload, cnt);
+               else if (port->negotiated_rev > PD_REV20)
+                       tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
                break;
        case PD_DATA_BIST:
                port->bist_request = le32_to_cpu(msg->payload[0]);
@@ -2459,6 +2475,16 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
        enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
        enum tcpm_state next_state;
 
+       /*
+        * Stop VDM state machine if interrupted by other Messages while NOT_SUPP is allowed in
+        * VDM AMS if waiting for VDM responses and will be handled later.
+        */
+       if (tcpm_vdm_ams(port) && type != PD_CTRL_NOT_SUPP && type != PD_CTRL_GOOD_CRC) {
+               port->vdm_state = VDM_STATE_ERR_BUSY;
+               tcpm_ams_finish(port);
+               mod_vdm_delayed_work(port, 0);
+       }
+
        switch (type) {
        case PD_CTRL_GOOD_CRC:
        case PD_CTRL_PING:
@@ -2717,7 +2743,14 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port,
        enum pd_ext_msg_type type = pd_header_type_le(msg->header);
        unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header);
 
-       if (!(msg->ext_msg.header & PD_EXT_HDR_CHUNKED)) {
+       /* stopping VDM state machine if interrupted by other Messages */
+       if (tcpm_vdm_ams(port)) {
+               port->vdm_state = VDM_STATE_ERR_BUSY;
+               tcpm_ams_finish(port);
+               mod_vdm_delayed_work(port, 0);
+       }
+
+       if (!(le16_to_cpu(msg->ext_msg.header) & PD_EXT_HDR_CHUNKED)) {
                tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
                tcpm_log(port, "Unchunked extended messages unsupported");
                return;
@@ -2811,7 +2844,7 @@ static void tcpm_pd_rx_handler(struct kthread_work *work)
                                 "Data role mismatch, initiating error recovery");
                        tcpm_set_state(port, ERROR_RECOVERY, 0);
                } else {
-                       if (msg->header & PD_HEADER_EXT_HDR)
+                       if (le16_to_cpu(msg->header) & PD_HEADER_EXT_HDR)
                                tcpm_pd_ext_msg_request(port, msg);
                        else if (cnt)
                                tcpm_pd_data_request(port, msg);
index 1d8b7df59ff49a61de17a8f7f2055adefbfe9460..b433169ef6fa4cf105ef018a98d0adc10905a7d1 100644 (file)
@@ -717,8 +717,8 @@ static void ucsi_handle_connector_change(struct work_struct *work)
        ucsi_send_command(con->ucsi, command, NULL, 0);
 
        /* 3. ACK connector change */
-       clear_bit(EVENT_PENDING, &ucsi->flags);
        ret = ucsi_acknowledge_connector_change(ucsi);
+       clear_bit(EVENT_PENDING, &ucsi->flags);
        if (ret) {
                dev_err(ucsi->dev, "%s: ACK failed (%d)", __func__, ret);
                goto out_unlock;
index 189e4385df403337f626e3081364cf056ae54563..dda5dc6f7737897c580a388c33ac5ade3b8de73c 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/mlx5/vport.h>
 #include <linux/mlx5/fs.h>
 #include <linux/mlx5/mlx5_ifc_vdpa.h>
+#include <linux/mlx5/mpfs.h>
 #include "mlx5_vdpa.h"
 
 MODULE_AUTHOR("Eli Cohen <eli@mellanox.com>");
@@ -1859,11 +1860,16 @@ static int mlx5_vdpa_set_map(struct vdpa_device *vdev, struct vhost_iotlb *iotlb
 static void mlx5_vdpa_free(struct vdpa_device *vdev)
 {
        struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev);
+       struct mlx5_core_dev *pfmdev;
        struct mlx5_vdpa_net *ndev;
 
        ndev = to_mlx5_vdpa_ndev(mvdev);
 
        free_resources(ndev);
+       if (!is_zero_ether_addr(ndev->config.mac)) {
+               pfmdev = pci_get_drvdata(pci_physfn(mvdev->mdev->pdev));
+               mlx5_mpfs_del_mac(pfmdev, ndev->config.mac);
+       }
        mlx5_vdpa_free_resources(&ndev->mvdev);
        mutex_destroy(&ndev->reslock);
 }
@@ -1990,6 +1996,7 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name)
 {
        struct mlx5_vdpa_mgmtdev *mgtdev = container_of(v_mdev, struct mlx5_vdpa_mgmtdev, mgtdev);
        struct virtio_net_config *config;
+       struct mlx5_core_dev *pfmdev;
        struct mlx5_vdpa_dev *mvdev;
        struct mlx5_vdpa_net *ndev;
        struct mlx5_core_dev *mdev;
@@ -2023,10 +2030,17 @@ static int mlx5_vdpa_dev_add(struct vdpa_mgmt_dev *v_mdev, const char *name)
        if (err)
                goto err_mtu;
 
+       if (!is_zero_ether_addr(config->mac)) {
+               pfmdev = pci_get_drvdata(pci_physfn(mdev->pdev));
+               err = mlx5_mpfs_add_mac(pfmdev, config->mac);
+               if (err)
+                       goto err_mtu;
+       }
+
        mvdev->vdev.dma_dev = mdev->device;
        err = mlx5_vdpa_alloc_resources(&ndev->mvdev);
        if (err)
-               goto err_mtu;
+               goto err_mpfs;
 
        err = alloc_resources(ndev);
        if (err)
@@ -2044,6 +2058,9 @@ err_reg:
        free_resources(ndev);
 err_res:
        mlx5_vdpa_free_resources(&ndev->mvdev);
+err_mpfs:
+       if (!is_zero_ether_addr(config->mac))
+               mlx5_mpfs_del_mac(pfmdev, config->mac);
 err_mtu:
        mutex_destroy(&ndev->reslock);
        put_device(&mvdev->vdev.dev);
index 8bbac7182ad32a7e32f62142ba48612e83586834..bd3d07aa4f0ec48340a1373266f2231a34e07313 100644 (file)
@@ -286,7 +286,7 @@ static int hga_card_detect(void)
 
        hga_vram = ioremap(0xb0000, hga_vram_len);
        if (!hga_vram)
-               goto error;
+               return -ENOMEM;
 
        if (request_region(0x3b0, 12, "hgafb"))
                release_io_ports = 1;
@@ -346,13 +346,18 @@ static int hga_card_detect(void)
                        hga_type_name = "Hercules";
                        break;
        }
-       return 1;
+       return 0;
 error:
        if (release_io_ports)
                release_region(0x3b0, 12);
        if (release_io_port)
                release_region(0x3bf, 1);
-       return 0;
+
+       iounmap(hga_vram);
+
+       pr_err("hgafb: HGA card not detected.\n");
+
+       return -EINVAL;
 }
 
 /**
@@ -550,13 +555,11 @@ static const struct fb_ops hgafb_ops = {
 static int hgafb_probe(struct platform_device *pdev)
 {
        struct fb_info *info;
+       int ret;
 
-       if (! hga_card_detect()) {
-               printk(KERN_INFO "hgafb: HGA card not detected.\n");
-               if (hga_vram)
-                       iounmap(hga_vram);
-               return -EINVAL;
-       }
+       ret = hga_card_detect();
+       if (ret)
+               return ret;
 
        printk(KERN_INFO "hgafb: %s with %ldK of memory detected.\n",
                hga_type_name, hga_vram_len/1024);
index 3ac053b884958e040f8b77587518e993b941c585..16f272a508112c91a6381f2d08081ced787de643 100644 (file)
@@ -1469,6 +1469,7 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        struct imstt_par *par;
        struct fb_info *info;
        struct device_node *dp;
+       int ret = -ENOMEM;
        
        dp = pci_device_to_OF_node(pdev);
        if(dp)
@@ -1504,28 +1505,37 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
                default:
                        printk(KERN_INFO "imsttfb: Device 0x%x unknown, "
                                         "contact maintainer.\n", pdev->device);
-                       release_mem_region(addr, size);
-                       framebuffer_release(info);
-                       return -ENODEV;
+                       ret = -ENODEV;
+                       goto error;
        }
 
        info->fix.smem_start = addr;
        info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ?
                                            0x400000 : 0x800000);
-       if (!info->screen_base) {
-               release_mem_region(addr, size);
-               framebuffer_release(info);
-               return -ENOMEM;
-       }
+       if (!info->screen_base)
+               goto error;
        info->fix.mmio_start = addr + 0x800000;
        par->dc_regs = ioremap(addr + 0x800000, 0x1000);
+       if (!par->dc_regs)
+               goto error;
        par->cmap_regs_phys = addr + 0x840000;
        par->cmap_regs = (__u8 *)ioremap(addr + 0x840000, 0x1000);
+       if (!par->cmap_regs)
+               goto error;
        info->pseudo_palette = par->palette;
        init_imstt(info);
 
        pci_set_drvdata(pdev, info);
        return 0;
+
+error:
+       if (par->dc_regs)
+               iounmap(par->dc_regs);
+       if (info->screen_base)
+               iounmap(info->screen_base);
+       release_mem_region(addr, size);
+       framebuffer_release(info);
+       return ret;
 }
 
 static void imsttfb_remove(struct pci_dev *pdev)
index 4162d0e7e00d7ed5334d20c2ad2ac226fe27837f..cc7450f2b2a93eda90da1602725b18f4e44b8028 100644 (file)
@@ -70,7 +70,7 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
                                   struct pci_dev *dev, int devid,
                                   publish_pci_dev_cb publish_cb)
 {
-       int err = 0, slot, func = -1;
+       int err = 0, slot, func = PCI_FUNC(dev->devfn);
        struct pci_dev_entry *t, *dev_entry;
        struct vpci_dev_data *vpci_dev = pdev->pci_dev_data;
 
@@ -95,22 +95,25 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
 
        /*
         * Keep multi-function devices together on the virtual PCI bus, except
-        * virtual functions.
+        * that we want to keep virtual functions at func 0 on their own. They
+        * aren't multi-function devices and hence their presence at func 0
+        * may cause guests to not scan the other functions.
         */
-       if (!dev->is_virtfn) {
+       if (!dev->is_virtfn || func) {
                for (slot = 0; slot < PCI_SLOT_MAX; slot++) {
                        if (list_empty(&vpci_dev->dev_list[slot]))
                                continue;
 
                        t = list_entry(list_first(&vpci_dev->dev_list[slot]),
                                       struct pci_dev_entry, list);
+                       if (t->dev->is_virtfn && !PCI_FUNC(t->dev->devfn))
+                               continue;
 
                        if (match_slot(dev, t->dev)) {
                                dev_info(&dev->dev, "vpci: assign to virtual slot %d func %d\n",
-                                        slot, PCI_FUNC(dev->devfn));
+                                        slot, func);
                                list_add_tail(&dev_entry->list,
                                              &vpci_dev->dev_list[slot]);
-                               func = PCI_FUNC(dev->devfn);
                                goto unlock;
                        }
                }
@@ -123,7 +126,6 @@ static int __xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev,
                                 slot);
                        list_add_tail(&dev_entry->list,
                                      &vpci_dev->dev_list[slot]);
-                       func = dev->is_virtfn ? 0 : PCI_FUNC(dev->devfn);
                        goto unlock;
                }
        }
index 5188f02e75fb3202d27f9f57dd42cb5aa0232627..c09c7ebd6968d03cf115ccf7af9a4a8d477cd8a9 100644 (file)
@@ -359,7 +359,8 @@ out:
        return err;
 }
 
-static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev)
+static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev,
+                                enum xenbus_state state)
 {
        int err = 0;
        int num_devs;
@@ -373,9 +374,7 @@ static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev)
        dev_dbg(&pdev->xdev->dev, "Reconfiguring device ...\n");
 
        mutex_lock(&pdev->dev_lock);
-       /* Make sure we only reconfigure once */
-       if (xenbus_read_driver_state(pdev->xdev->nodename) !=
-           XenbusStateReconfiguring)
+       if (xenbus_read_driver_state(pdev->xdev->nodename) != state)
                goto out;
 
        err = xenbus_scanf(XBT_NIL, pdev->xdev->nodename, "num_devs", "%d",
@@ -500,6 +499,10 @@ static int xen_pcibk_reconfigure(struct xen_pcibk_device *pdev)
                }
        }
 
+       if (state != XenbusStateReconfiguring)
+               /* Make sure we only reconfigure once. */
+               goto out;
+
        err = xenbus_switch_state(pdev->xdev, XenbusStateReconfigured);
        if (err) {
                xenbus_dev_fatal(pdev->xdev, err,
@@ -525,7 +528,7 @@ static void xen_pcibk_frontend_changed(struct xenbus_device *xdev,
                break;
 
        case XenbusStateReconfiguring:
-               xen_pcibk_reconfigure(pdev);
+               xen_pcibk_reconfigure(pdev, XenbusStateReconfiguring);
                break;
 
        case XenbusStateConnected:
@@ -664,6 +667,15 @@ static void xen_pcibk_be_watch(struct xenbus_watch *watch,
                xen_pcibk_setup_backend(pdev);
                break;
 
+       case XenbusStateInitialised:
+               /*
+                * We typically move to Initialised when the first device was
+                * added. Hence subsequent devices getting added may need
+                * reconfiguring.
+                */
+               xen_pcibk_reconfigure(pdev, XenbusStateInitialised);
+               break;
+
        default:
                break;
        }
index a4e9e6e07e9397321f61567a047f3fafb574fa62..d3c6bb22c5f4890081c2e5bf06af1d34fc63cc86 100644 (file)
@@ -322,6 +322,8 @@ static int afs_deliver_cb_callback(struct afs_call *call)
                        return ret;
 
                call->unmarshall++;
+               fallthrough;
+
        case 5:
                break;
        }
@@ -418,6 +420,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
                        r->node[loop] = ntohl(b[loop + 5]);
 
                call->unmarshall++;
+               fallthrough;
 
        case 2:
                break;
@@ -530,6 +533,7 @@ static int afs_deliver_cb_probe_uuid(struct afs_call *call)
                        r->node[loop] = ntohl(b[loop + 5]);
 
                call->unmarshall++;
+               fallthrough;
 
        case 2:
                break;
@@ -663,6 +667,7 @@ static int afs_deliver_yfs_cb_callback(struct afs_call *call)
 
                afs_extract_to_tmp(call);
                call->unmarshall++;
+               fallthrough;
 
        case 3:
                break;
index 9fbe5a5ec9bd493e35394c84e4c4ce6f8fd1b541..78719f2f567e9fbce41a927f012f0dffa45329a4 100644 (file)
@@ -1919,7 +1919,9 @@ static void afs_rename_edit_dir(struct afs_operation *op)
        new_inode = d_inode(new_dentry);
        if (new_inode) {
                spin_lock(&new_inode->i_lock);
-               if (new_inode->i_nlink > 0)
+               if (S_ISDIR(new_inode->i_mode))
+                       clear_nlink(new_inode);
+               else if (new_inode->i_nlink > 0)
                        drop_nlink(new_inode);
                spin_unlock(&new_inode->i_lock);
        }
index 2f695a260442553dffd102e4cef79a25c91b0c90..dd3f45d906d23cf9ea8926b876a51099fd525cae 100644 (file)
@@ -388,6 +388,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
                req->file_size = vp->scb.status.size;
 
                call->unmarshall++;
+               fallthrough;
 
        case 5:
                break;
@@ -1408,6 +1409,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call)
                _debug("motd '%s'", p);
 
                call->unmarshall++;
+               fallthrough;
 
        case 8:
                break;
@@ -1845,6 +1847,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
                xdr_decode_AFSVolSync(&bp, &op->volsync);
 
                call->unmarshall++;
+               fallthrough;
 
        case 6:
                break;
@@ -1979,6 +1982,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call)
                xdr_decode_AFSVolSync(&bp, &op->volsync);
 
                call->unmarshall++;
+               fallthrough;
 
        case 4:
                break;
index dc9327332f069067fe1204cab325916054e060bf..00fca3c66ba616331d748f3280ae4564206efa98 100644 (file)
@@ -593,6 +593,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call)
                if (ret < 0)
                        return ret;
                call->unmarshall = 6;
+               fallthrough;
 
        case 6:
                break;
index b8abccd03e5d55efd2abf8392420fdf1856c3479..6cc4d4cfe0c286dd3268969e834b59e2e9a284d7 100644 (file)
@@ -1244,6 +1244,9 @@ int bdev_disk_changed(struct block_device *bdev, bool invalidate)
 
        lockdep_assert_held(&bdev->bd_mutex);
 
+       if (!(disk->flags & GENHD_FL_UP))
+               return -ENXIO;
+
 rescan:
        if (bdev->bd_part_count)
                return -EBUSY;
@@ -1298,6 +1301,9 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode)
        struct gendisk *disk = bdev->bd_disk;
        int ret = 0;
 
+       if (!(disk->flags & GENHD_FL_UP))
+               return -ENXIO;
+
        if (!bdev->bd_openers) {
                if (!bdev_is_partition(bdev)) {
                        ret = 0;
@@ -1332,8 +1338,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode)
                        whole->bd_part_count++;
                        mutex_unlock(&whole->bd_mutex);
 
-                       if (!(disk->flags & GENHD_FL_UP) ||
-                           !bdev_nr_sectors(bdev)) {
+                       if (!bdev_nr_sectors(bdev)) {
                                __blkdev_put(whole, mode, 1);
                                bdput(whole);
                                return -ENXIO;
@@ -1364,16 +1369,12 @@ struct block_device *blkdev_get_no_open(dev_t dev)
        struct block_device *bdev;
        struct gendisk *disk;
 
-       down_read(&bdev_lookup_sem);
        bdev = bdget(dev);
        if (!bdev) {
-               up_read(&bdev_lookup_sem);
                blk_request_module(dev);
-               down_read(&bdev_lookup_sem);
-
                bdev = bdget(dev);
                if (!bdev)
-                       goto unlock;
+                       return NULL;
        }
 
        disk = bdev->bd_disk;
@@ -1383,14 +1384,11 @@ struct block_device *blkdev_get_no_open(dev_t dev)
                goto put_disk;
        if (!try_module_get(bdev->bd_disk->fops->owner))
                goto put_disk;
-       up_read(&bdev_lookup_sem);
        return bdev;
 put_disk:
        put_disk(disk);
 bdput:
        bdput(bdev);
-unlock:
-       up_read(&bdev_lookup_sem);
        return NULL;
 }
 
index 2bea01d23a5b57352cb659bbd5a20aa06017fc89..d17ac301032e42d643663ceecae7e98a350f76a6 100644 (file)
@@ -28,6 +28,7 @@
 #include "compression.h"
 #include "extent_io.h"
 #include "extent_map.h"
+#include "zoned.h"
 
 static const char* const btrfs_compress_types[] = { "", "zlib", "lzo", "zstd" };
 
@@ -349,6 +350,7 @@ static void end_compressed_bio_write(struct bio *bio)
         */
        inode = cb->inode;
        cb->compressed_pages[0]->mapping = cb->inode->i_mapping;
+       btrfs_record_physical_zoned(inode, cb->start, bio);
        btrfs_writepage_endio_finish_ordered(cb->compressed_pages[0],
                        cb->start, cb->start + cb->len - 1,
                        bio->bi_status == BLK_STS_OK);
@@ -401,6 +403,8 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
        u64 first_byte = disk_start;
        blk_status_t ret;
        int skip_sum = inode->flags & BTRFS_INODE_NODATASUM;
+       const bool use_append = btrfs_use_zone_append(inode, disk_start);
+       const unsigned int bio_op = use_append ? REQ_OP_ZONE_APPEND : REQ_OP_WRITE;
 
        WARN_ON(!PAGE_ALIGNED(start));
        cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS);
@@ -418,10 +422,31 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
        cb->nr_pages = nr_pages;
 
        bio = btrfs_bio_alloc(first_byte);
-       bio->bi_opf = REQ_OP_WRITE | write_flags;
+       bio->bi_opf = bio_op | write_flags;
        bio->bi_private = cb;
        bio->bi_end_io = end_compressed_bio_write;
 
+       if (use_append) {
+               struct extent_map *em;
+               struct map_lookup *map;
+               struct block_device *bdev;
+
+               em = btrfs_get_chunk_map(fs_info, disk_start, PAGE_SIZE);
+               if (IS_ERR(em)) {
+                       kfree(cb);
+                       bio_put(bio);
+                       return BLK_STS_NOTSUPP;
+               }
+
+               map = em->map_lookup;
+               /* We only support single profile for now */
+               ASSERT(map->num_stripes == 1);
+               bdev = map->stripes[0].dev->bdev;
+
+               bio_set_dev(bio, bdev);
+               free_extent_map(em);
+       }
+
        if (blkcg_css) {
                bio->bi_opf |= REQ_CGROUP_PUNT;
                kthread_associate_blkcg(blkcg_css);
@@ -432,6 +457,7 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
        bytes_left = compressed_len;
        for (pg_index = 0; pg_index < cb->nr_pages; pg_index++) {
                int submit = 0;
+               int len;
 
                page = compressed_pages[pg_index];
                page->mapping = inode->vfs_inode.i_mapping;
@@ -439,9 +465,13 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
                        submit = btrfs_bio_fits_in_stripe(page, PAGE_SIZE, bio,
                                                          0);
 
+               if (pg_index == 0 && use_append)
+                       len = bio_add_zone_append_page(bio, page, PAGE_SIZE, 0);
+               else
+                       len = bio_add_page(bio, page, PAGE_SIZE, 0);
+
                page->mapping = NULL;
-               if (submit || bio_add_page(bio, page, PAGE_SIZE, 0) <
-                   PAGE_SIZE) {
+               if (submit || len < PAGE_SIZE) {
                        /*
                         * inc the count before we submit the bio so
                         * we know the end IO handler won't happen before
@@ -465,11 +495,15 @@ blk_status_t btrfs_submit_compressed_write(struct btrfs_inode *inode, u64 start,
                        }
 
                        bio = btrfs_bio_alloc(first_byte);
-                       bio->bi_opf = REQ_OP_WRITE | write_flags;
+                       bio->bi_opf = bio_op | write_flags;
                        bio->bi_private = cb;
                        bio->bi_end_io = end_compressed_bio_write;
                        if (blkcg_css)
                                bio->bi_opf |= REQ_CGROUP_PUNT;
+                       /*
+                        * Use bio_add_page() to ensure the bio has at least one
+                        * page.
+                        */
                        bio_add_page(bio, page, PAGE_SIZE, 0);
                }
                if (bytes_left < PAGE_SIZE) {
index 074a78a202b8363b5aee1a74d33cf200b0b164e4..dee2dafbc872f379aa2fc861a822104aea7768f0 100644 (file)
@@ -3753,7 +3753,7 @@ static noinline_for_stack int __extent_writepage_io(struct btrfs_inode *inode,
                /* Note that em_end from extent_map_end() is exclusive */
                iosize = min(em_end, end + 1) - cur;
 
-               if (btrfs_use_zone_append(inode, em))
+               if (btrfs_use_zone_append(inode, em->block_start))
                        opf = REQ_OP_ZONE_APPEND;
 
                free_extent_map(em);
@@ -5196,7 +5196,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
                  u64 start, u64 len)
 {
        int ret = 0;
-       u64 off = start;
+       u64 off;
        u64 max = start + len;
        u32 flags = 0;
        u32 found_type;
@@ -5231,6 +5231,11 @@ int extent_fiemap(struct btrfs_inode *inode, struct fiemap_extent_info *fieinfo,
                goto out_free_ulist;
        }
 
+       /*
+        * We can't initialize that to 'start' as this could miss extents due
+        * to extent item merging
+        */
+       off = 0;
        start = round_down(start, btrfs_inode_sectorsize(inode));
        len = round_up(max, btrfs_inode_sectorsize(inode)) - start;
 
index eb6fddf40841c7c43adf67f92e51067c3abba365..33f14573f2ecd8fbf1e3d15619786842786abfce 100644 (file)
@@ -3241,6 +3241,7 @@ void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info)
                inode = list_first_entry(&fs_info->delayed_iputs,
                                struct btrfs_inode, delayed_iput);
                run_delayed_iput_locked(fs_info, inode);
+               cond_resched_lock(&fs_info->delayed_iput_lock);
        }
        spin_unlock(&fs_info->delayed_iput_lock);
 }
@@ -7785,7 +7786,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
        iomap->bdev = fs_info->fs_devices->latest_bdev;
        iomap->length = len;
 
-       if (write && btrfs_use_zone_append(BTRFS_I(inode), em))
+       if (write && btrfs_use_zone_append(BTRFS_I(inode), em->block_start))
                iomap->flags |= IOMAP_F_ZONE_APPEND;
 
        free_extent_map(em);
index 3928ecc40d7b07d831e342ce61f51165c20d2f1d..d434dc78dadf5ccf37d32cf0be97d9b17d19b8c5 100644 (file)
@@ -281,6 +281,11 @@ copy_inline_extent:
        ret = btrfs_inode_set_file_extent_range(BTRFS_I(dst), 0, aligned_end);
 out:
        if (!ret && !trans) {
+               /*
+                * Release path before starting a new transaction so we don't
+                * hold locks that would confuse lockdep.
+                */
+               btrfs_release_path(path);
                /*
                 * No transaction here means we copied the inline extent into a
                 * page of the destination inode.
index 95a600034d61283752969105450e57e954f2ac99..326be57f282816dabc8766af26d0722940531aef 100644 (file)
@@ -1858,8 +1858,6 @@ static noinline int link_to_fixup_dir(struct btrfs_trans_handle *trans,
                ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
        } else if (ret == -EEXIST) {
                ret = 0;
-       } else {
-               BUG(); /* Logic Error */
        }
        iput(inode);
 
@@ -6463,6 +6461,24 @@ void btrfs_log_new_name(struct btrfs_trans_handle *trans,
            (!old_dir || old_dir->logged_trans < trans->transid))
                return;
 
+       /*
+        * If we are doing a rename (old_dir is not NULL) from a directory that
+        * was previously logged, make sure the next log attempt on the directory
+        * is not skipped and logs the inode again. This is because the log may
+        * not currently be authoritative for a range including the old
+        * BTRFS_DIR_ITEM_KEY and BTRFS_DIR_INDEX_KEY keys, so we want to make
+        * sure after a log replay we do not end up with both the new and old
+        * dentries around (in case the inode is a directory we would have a
+        * directory with two hard links and 2 inode references for different
+        * parents). The next log attempt of old_dir will happen at
+        * btrfs_log_all_parents(), called through btrfs_log_inode_parent()
+        * below, because we have previously set inode->last_unlink_trans to the
+        * current transaction ID, either here or at btrfs_record_unlink_dir() in
+        * case inode is a directory.
+        */
+       if (old_dir)
+               old_dir->logged_trans = 0;
+
        btrfs_init_log_ctx(&ctx, &inode->vfs_inode);
        ctx.logging_new_name = true;
        /*
index 9a1ead0c4a3113b24b0a7a658cf20cd84778e7af..47d27059d06411a78d8cc1d2fff1675ee7656a0d 100644 (file)
@@ -1459,7 +1459,7 @@ static bool dev_extent_hole_check_zoned(struct btrfs_device *device,
                /* Given hole range was invalid (outside of device) */
                if (ret == -ERANGE) {
                        *hole_start += *hole_size;
-                       *hole_size = false;
+                       *hole_size = 0;
                        return true;
                }
 
index 304ce64c70a44957a51b3b632d98de8ca72bcb78..1bb8ee97aae095c4479cfd7b0ff486a87f23c1cf 100644 (file)
@@ -1278,7 +1278,7 @@ void btrfs_free_redirty_list(struct btrfs_transaction *trans)
        spin_unlock(&trans->releasing_ebs_lock);
 }
 
-bool btrfs_use_zone_append(struct btrfs_inode *inode, struct extent_map *em)
+bool btrfs_use_zone_append(struct btrfs_inode *inode, u64 start)
 {
        struct btrfs_fs_info *fs_info = inode->root->fs_info;
        struct btrfs_block_group *cache;
@@ -1293,7 +1293,7 @@ bool btrfs_use_zone_append(struct btrfs_inode *inode, struct extent_map *em)
        if (!is_data_inode(&inode->vfs_inode))
                return false;
 
-       cache = btrfs_lookup_block_group(fs_info, em->block_start);
+       cache = btrfs_lookup_block_group(fs_info, start);
        ASSERT(cache);
        if (!cache)
                return false;
index 5e41a74a9cb24d22c30f92f2b21e1d87467dceee..e55d32595c2c03705441404acc324f03052e8dfe 100644 (file)
@@ -53,7 +53,7 @@ void btrfs_calc_zone_unusable(struct btrfs_block_group *cache);
 void btrfs_redirty_list_add(struct btrfs_transaction *trans,
                            struct extent_buffer *eb);
 void btrfs_free_redirty_list(struct btrfs_transaction *trans);
-bool btrfs_use_zone_append(struct btrfs_inode *inode, struct extent_map *em);
+bool btrfs_use_zone_append(struct btrfs_inode *inode, u64 start);
 void btrfs_record_physical_zoned(struct inode *inode, u64 file_offset,
                                 struct bio *bio);
 void btrfs_rewrite_logical_zoned(struct btrfs_ordered_extent *ordered);
@@ -152,8 +152,7 @@ static inline void btrfs_redirty_list_add(struct btrfs_transaction *trans,
                                          struct extent_buffer *eb) { }
 static inline void btrfs_free_redirty_list(struct btrfs_transaction *trans) { }
 
-static inline bool btrfs_use_zone_append(struct btrfs_inode *inode,
-                                        struct extent_map *em)
+static inline bool btrfs_use_zone_append(struct btrfs_inode *inode, u64 start)
 {
        return false;
 }
index 4a97fe12006b7f9e78aff30c38cdbd77cae809da..37fc7d6ac457adf3c356c8a1061a49f500081635 100644 (file)
@@ -72,15 +72,28 @@ struct smb3_key_debug_info {
 } __packed;
 
 /*
- * Dump full key (32 byte encrypt/decrypt keys instead of 16 bytes)
- * is needed if GCM256 (stronger encryption) negotiated
+ * Dump variable-sized keys
  */
 struct smb3_full_key_debug_info {
-       __u64   Suid;
+       /* INPUT: size of userspace buffer */
+       __u32   in_size;
+
+       /*
+        * INPUT: 0 for current user, otherwise session to dump
+        * OUTPUT: session id that was dumped
+        */
+       __u64   session_id;
        __u16   cipher_type;
-       __u8    auth_key[16]; /* SMB2_NTLMV2_SESSKEY_SIZE */
-       __u8    smb3encryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
-       __u8    smb3decryptionkey[32]; /* SMB3_ENC_DEC_KEY_SIZE */
+       __u8    session_key_length;
+       __u8    server_in_key_length;
+       __u8    server_out_key_length;
+       __u8    data[];
+       /*
+        * return this struct with the keys appended at the end:
+        * __u8 session_key[session_key_length];
+        * __u8 server_in_key[server_in_key_length];
+        * __u8 server_out_key[server_out_key_length];
+        */
 } __packed;
 
 struct smb3_notify {
index d7ea9c5fe0f84948ce6fcdcf1fbb6ec0806fb614..2ffcb29d5c8f40440fe3a40dbd95fb0ecad5f028 100644 (file)
@@ -133,7 +133,7 @@ struct workqueue_struct     *cifsiod_wq;
 struct workqueue_struct        *decrypt_wq;
 struct workqueue_struct        *fileinfo_put_wq;
 struct workqueue_struct        *cifsoplockd_wq;
-struct workqueue_struct *deferredclose_wq;
+struct workqueue_struct        *deferredclose_wq;
 __u32 cifs_lock_secret;
 
 /*
index d88b4b523dcc4c74d5f9a49ecb8a504f2399ae3e..8488d70244620b40e5c37eb73ab60de99f061a24 100644 (file)
@@ -1257,8 +1257,7 @@ struct cifsFileInfo {
        struct work_struct oplock_break; /* work for oplock breaks */
        struct work_struct put; /* work for the final part of _put */
        struct delayed_work deferred;
-       bool oplock_break_received; /* Flag to indicate oplock break */
-       bool deferred_scheduled;
+       bool deferred_close_scheduled; /* Flag to indicate close is scheduled */
 };
 
 struct cifs_io_parms {
@@ -1418,6 +1417,7 @@ struct cifsInodeInfo {
        struct inode vfs_inode;
        struct list_head deferred_closes; /* list of deferred closes */
        spinlock_t deferred_lock; /* protection on deferred list */
+       bool lease_granted; /* Flag to indicate whether lease or oplock is granted. */
 };
 
 static inline struct cifsInodeInfo *
index b53a87db282f928f28757b4aee53808573af11c4..554d64fe171e039e7b0a5a21cbec65f5b14300ec 100644 (file)
 #define SMB3_SIGN_KEY_SIZE (16)
 
 /*
- * Size of the smb3 encryption/decryption keys
+ * Size of the smb3 encryption/decryption key storage.
+ * This size is big enough to store any cipher key types.
  */
 #define SMB3_ENC_DEC_KEY_SIZE (32)
 
index 6caad100c3f36b78e94c387c5f3c6b6feeab9dd8..379a427f3c2f1ccedc9515b61cce91e8d81e5587 100644 (file)
@@ -323,8 +323,7 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        cfile->dentry = dget(dentry);
        cfile->f_flags = file->f_flags;
        cfile->invalidHandle = false;
-       cfile->oplock_break_received = false;
-       cfile->deferred_scheduled = false;
+       cfile->deferred_close_scheduled = false;
        cfile->tlink = cifs_get_tlink(tlink);
        INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
        INIT_WORK(&cfile->put, cifsFileInfo_put_work);
@@ -574,21 +573,18 @@ int cifs_open(struct inode *inode, struct file *file)
                        file->f_op = &cifs_file_direct_ops;
        }
 
-       spin_lock(&CIFS_I(inode)->deferred_lock);
        /* Get the cached handle as SMB2 close is deferred */
        rc = cifs_get_readable_path(tcon, full_path, &cfile);
        if (rc == 0) {
                if (file->f_flags == cfile->f_flags) {
                        file->private_data = cfile;
+                       spin_lock(&CIFS_I(inode)->deferred_lock);
                        cifs_del_deferred_close(cfile);
                        spin_unlock(&CIFS_I(inode)->deferred_lock);
                        goto out;
                } else {
-                       spin_unlock(&CIFS_I(inode)->deferred_lock);
                        _cifsFileInfo_put(cfile, true, false);
                }
-       } else {
-               spin_unlock(&CIFS_I(inode)->deferred_lock);
        }
 
        if (server->oplocks)
@@ -878,12 +874,8 @@ void smb2_deferred_work_close(struct work_struct *work)
                        struct cifsFileInfo, deferred.work);
 
        spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
-       if (!cfile->deferred_scheduled) {
-               spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
-               return;
-       }
        cifs_del_deferred_close(cfile);
-       cfile->deferred_scheduled = false;
+       cfile->deferred_close_scheduled = false;
        spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
        _cifsFileInfo_put(cfile, true, false);
 }
@@ -900,19 +892,26 @@ int cifs_close(struct inode *inode, struct file *file)
                file->private_data = NULL;
                dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
                if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
+                   cinode->lease_granted &&
                    dclose) {
                        if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags))
                                inode->i_ctime = inode->i_mtime = current_time(inode);
                        spin_lock(&cinode->deferred_lock);
                        cifs_add_deferred_close(cfile, dclose);
-                       if (cfile->deferred_scheduled) {
-                               mod_delayed_work(deferredclose_wq,
-                                               &cfile->deferred, cifs_sb->ctx->acregmax);
+                       if (cfile->deferred_close_scheduled &&
+                           delayed_work_pending(&cfile->deferred)) {
+                               /*
+                                * If there is no pending work, mod_delayed_work queues new work.
+                                * So, Increase the ref count to avoid use-after-free.
+                                */
+                               if (!mod_delayed_work(deferredclose_wq,
+                                               &cfile->deferred, cifs_sb->ctx->acregmax))
+                                       cifsFileInfo_get(cfile);
                        } else {
                                /* Deferred close for files */
                                queue_delayed_work(deferredclose_wq,
                                                &cfile->deferred, cifs_sb->ctx->acregmax);
-                               cfile->deferred_scheduled = true;
+                               cfile->deferred_close_scheduled = true;
                                spin_unlock(&cinode->deferred_lock);
                                return 0;
                        }
@@ -2020,8 +2019,7 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode,
                if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
                        continue;
                if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
-                       if ((!open_file->invalidHandle) &&
-                               (!open_file->oplock_break_received)) {
+                       if ((!open_file->invalidHandle)) {
                                /* found a good file */
                                /* lock it so it will not be closed on us */
                                cifsFileInfo_get(open_file);
@@ -4874,14 +4872,20 @@ oplock_break_ack:
        }
        /*
         * When oplock break is received and there are no active
-        * file handles but cached, then set the flag oplock_break_received.
+        * file handles but cached, then schedule deferred close immediately.
         * So, new open will not use cached handle.
         */
        spin_lock(&CIFS_I(inode)->deferred_lock);
        is_deferred = cifs_is_deferred_close(cfile, &dclose);
-       if (is_deferred && cfile->deferred_scheduled) {
-               cfile->oplock_break_received = true;
-               mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
+       if (is_deferred &&
+           cfile->deferred_close_scheduled &&
+           delayed_work_pending(&cfile->deferred)) {
+               /*
+                * If there is no pending work, mod_delayed_work queues new work.
+                * So, Increase the ref count to avoid use-after-free.
+                */
+               if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
+                       cifsFileInfo_get(cfile);
        }
        spin_unlock(&CIFS_I(inode)->deferred_lock);
        _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
index 5d21cd905315d4dca90ca5001d064f2bfae05e5c..92d4ab029c917dde84e575706559545f409c97ec 100644 (file)
@@ -1145,7 +1145,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
                /* if iocharset not set then load_nls_default
                 * is used by caller
                 */
-                cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
+               cifs_dbg(FYI, "iocharset set to %s\n", ctx->iocharset);
                break;
        case Opt_netbiosname:
                memset(ctx->source_rfc1001_name, 0x20,
index 28ec8d7c521a978c744a228ff59c676740093077..d67d281ab86320750081114ff8bebd935d39d289 100644 (file)
@@ -33,6 +33,7 @@
 #include "cifsfs.h"
 #include "cifs_ioctl.h"
 #include "smb2proto.h"
+#include "smb2glob.h"
 #include <linux/btrfs.h>
 
 static long cifs_ioctl_query_info(unsigned int xid, struct file *filep,
@@ -214,48 +215,112 @@ static int cifs_shutdown(struct super_block *sb, unsigned long arg)
        return 0;
 }
 
-static int cifs_dump_full_key(struct cifs_tcon *tcon, unsigned long arg)
+static int cifs_dump_full_key(struct cifs_tcon *tcon, struct smb3_full_key_debug_info __user *in)
 {
-       struct smb3_full_key_debug_info pfull_key_inf;
-       __u64 suid;
-       struct list_head *tmp;
+       struct smb3_full_key_debug_info out;
        struct cifs_ses *ses;
+       int rc = 0;
        bool found = false;
+       u8 __user *end;
 
-       if (!smb3_encryption_required(tcon))
-               return -EOPNOTSUPP;
+       if (!smb3_encryption_required(tcon)) {
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
+       /* copy user input into our output buffer */
+       if (copy_from_user(&out, in, sizeof(out))) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+       if (!out.session_id) {
+               /* if ses id is 0, use current user session */
+               ses = tcon->ses;
+       } else {
+               /* otherwise if a session id is given, look for it in all our sessions */
+               struct cifs_ses *ses_it = NULL;
+               struct TCP_Server_Info *server_it = NULL;
 
-       ses = tcon->ses; /* default to user id for current user */
-       if (get_user(suid, (__u64 __user *)arg))
-               suid = 0;
-       if (suid) {
-               /* search to see if there is a session with a matching SMB UID */
                spin_lock(&cifs_tcp_ses_lock);
-               list_for_each(tmp, &tcon->ses->server->smb_ses_list) {
-                       ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
-                       if (ses->Suid == suid) {
-                               found = true;
-                               break;
+               list_for_each_entry(server_it, &cifs_tcp_ses_list, tcp_ses_list) {
+                       list_for_each_entry(ses_it, &server_it->smb_ses_list, smb_ses_list) {
+                               if (ses_it->Suid == out.session_id) {
+                                       ses = ses_it;
+                                       /*
+                                        * since we are using the session outside the crit
+                                        * section, we need to make sure it won't be released
+                                        * so increment its refcount
+                                        */
+                                       ses->ses_count++;
+                                       found = true;
+                                       goto search_end;
+                               }
                        }
                }
+search_end:
                spin_unlock(&cifs_tcp_ses_lock);
-               if (found == false)
-                       return -EINVAL;
-       } /* else uses default user's SMB UID (ie current user) */
-
-       pfull_key_inf.cipher_type = le16_to_cpu(ses->server->cipher_type);
-       pfull_key_inf.Suid = ses->Suid;
-       memcpy(pfull_key_inf.auth_key, ses->auth_key.response,
-              16 /* SMB2_NTLMV2_SESSKEY_SIZE */);
-       memcpy(pfull_key_inf.smb3decryptionkey, ses->smb3decryptionkey,
-              32 /* SMB3_ENC_DEC_KEY_SIZE */);
-       memcpy(pfull_key_inf.smb3encryptionkey,
-              ses->smb3encryptionkey, 32 /* SMB3_ENC_DEC_KEY_SIZE */);
-       if (copy_to_user((void __user *)arg, &pfull_key_inf,
-                        sizeof(struct smb3_full_key_debug_info)))
-               return -EFAULT;
+               if (!found) {
+                       rc = -ENOENT;
+                       goto out;
+               }
+       }
 
-       return 0;
+       switch (ses->server->cipher_type) {
+       case SMB2_ENCRYPTION_AES128_CCM:
+       case SMB2_ENCRYPTION_AES128_GCM:
+               out.session_key_length = CIFS_SESS_KEY_SIZE;
+               out.server_in_key_length = out.server_out_key_length = SMB3_GCM128_CRYPTKEY_SIZE;
+               break;
+       case SMB2_ENCRYPTION_AES256_CCM:
+       case SMB2_ENCRYPTION_AES256_GCM:
+               out.session_key_length = CIFS_SESS_KEY_SIZE;
+               out.server_in_key_length = out.server_out_key_length = SMB3_GCM256_CRYPTKEY_SIZE;
+               break;
+       default:
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
+       /* check if user buffer is big enough to store all the keys */
+       if (out.in_size < sizeof(out) + out.session_key_length + out.server_in_key_length
+           + out.server_out_key_length) {
+               rc = -ENOBUFS;
+               goto out;
+       }
+
+       out.session_id = ses->Suid;
+       out.cipher_type = le16_to_cpu(ses->server->cipher_type);
+
+       /* overwrite user input with our output */
+       if (copy_to_user(in, &out, sizeof(out))) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+       /* append all the keys at the end of the user buffer */
+       end = in->data;
+       if (copy_to_user(end, ses->auth_key.response, out.session_key_length)) {
+               rc = -EINVAL;
+               goto out;
+       }
+       end += out.session_key_length;
+
+       if (copy_to_user(end, ses->smb3encryptionkey, out.server_in_key_length)) {
+               rc = -EINVAL;
+               goto out;
+       }
+       end += out.server_in_key_length;
+
+       if (copy_to_user(end, ses->smb3decryptionkey, out.server_out_key_length)) {
+               rc = -EINVAL;
+               goto out;
+       }
+
+out:
+       if (found)
+               cifs_put_smb_ses(ses);
+       return rc;
 }
 
 long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
@@ -371,6 +436,10 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                                rc = -EOPNOTSUPP;
                        break;
                case CIFS_DUMP_KEY:
+                       /*
+                        * Dump encryption keys. This is an old ioctl that only
+                        * handles AES-128-{CCM,GCM}.
+                        */
                        if (pSMBFile == NULL)
                                break;
                        if (!capable(CAP_SYS_ADMIN)) {
@@ -398,11 +467,10 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                        else
                                rc = 0;
                        break;
-               /*
-                * Dump full key (32 bytes instead of 16 bytes) is
-                * needed if GCM256 (stronger encryption) negotiated
-                */
                case CIFS_DUMP_FULL_KEY:
+                       /*
+                        * Dump encryption keys (handles any key sizes)
+                        */
                        if (pSMBFile == NULL)
                                break;
                        if (!capable(CAP_SYS_ADMIN)) {
@@ -410,8 +478,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
                                break;
                        }
                        tcon = tlink_tcon(pSMBFile->tlink);
-                       rc = cifs_dump_full_key(tcon, arg);
-
+                       rc = cifs_dump_full_key(tcon, (void __user *)arg);
                        break;
                case CIFS_IOC_NOTIFY:
                        if (!S_ISDIR(inode->i_mode)) {
index 524dbdfb7184d964b6e6fe7d0462d3cef0f1056c..7207a63819cbf271e1c53c0a4e8c9323c13f40d1 100644 (file)
@@ -672,6 +672,11 @@ cifs_add_pending_open(struct cifs_fid *fid, struct tcon_link *tlink,
        spin_unlock(&tlink_tcon(open->tlink)->open_file_lock);
 }
 
+/*
+ * Critical section which runs after acquiring deferred_lock.
+ * As there is no reference count on cifs_deferred_close, pdclose
+ * should not be used outside deferred_lock.
+ */
 bool
 cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **pdclose)
 {
@@ -688,6 +693,9 @@ cifs_is_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close **
        return false;
 }
 
+/*
+ * Critical section which runs after acquiring deferred_lock.
+ */
 void
 cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *dclose)
 {
@@ -707,6 +715,9 @@ cifs_add_deferred_close(struct cifsFileInfo *cfile, struct cifs_deferred_close *
        list_add_tail(&dclose->dlist, &CIFS_I(d_inode(cfile->dentry))->deferred_closes);
 }
 
+/*
+ * Critical section which runs after acquiring deferred_lock.
+ */
 void
 cifs_del_deferred_close(struct cifsFileInfo *cfile)
 {
@@ -738,15 +749,19 @@ void
 cifs_close_all_deferred_files(struct cifs_tcon *tcon)
 {
        struct cifsFileInfo *cfile;
-       struct cifsInodeInfo *cinode;
        struct list_head *tmp;
 
        spin_lock(&tcon->open_file_lock);
        list_for_each(tmp, &tcon->openFileList) {
                cfile = list_entry(tmp, struct cifsFileInfo, tlist);
-               cinode = CIFS_I(d_inode(cfile->dentry));
-               if (delayed_work_pending(&cfile->deferred))
-                       mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
+               if (delayed_work_pending(&cfile->deferred)) {
+                       /*
+                        * If there is no pending work, mod_delayed_work queues new work.
+                        * So, Increase the ref count to avoid use-after-free.
+                        */
+                       if (!mod_delayed_work(deferredclose_wq, &cfile->deferred, 0))
+                               cifsFileInfo_get(cfile);
+               }
        }
        spin_unlock(&tcon->open_file_lock);
 }
index dd0eb665b680c86549418e9044b130ea25ec3261..21ef51d338e0ca333e21a81610ab0cec1d6567b6 100644 (file)
@@ -1861,6 +1861,8 @@ smb2_copychunk_range(const unsigned int xid,
                        cpu_to_le32(min_t(u32, len, tcon->max_bytes_chunk));
 
                /* Request server copy to target from src identified by key */
+               kfree(retbuf);
+               retbuf = NULL;
                rc = SMB2_ioctl(xid, tcon, trgtfile->fid.persistent_fid,
                        trgtfile->fid.volatile_fid, FSCTL_SRV_COPYCHUNK_WRITE,
                        true /* is_fsctl */, (char *)pcchunk,
@@ -3981,6 +3983,7 @@ smb2_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
                      unsigned int epoch, bool *purge_cache)
 {
        oplock &= 0xFF;
+       cinode->lease_granted = false;
        if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
                return;
        if (oplock == SMB2_OPLOCK_LEVEL_BATCH) {
@@ -4007,6 +4010,7 @@ smb21_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock,
        unsigned int new_oplock = 0;
 
        oplock &= 0xFF;
+       cinode->lease_granted = true;
        if (oplock == SMB2_OPLOCK_LEVEL_NOCHANGE)
                return;
 
index a8bf431847730298c4da9f3a311d612337d1ee28..c205f93e0a10ff595fa04afdc9005dda6214309c 100644 (file)
@@ -958,6 +958,13 @@ SMB2_negotiate(const unsigned int xid, struct cifs_ses *ses)
        /* Internal types */
        server->capabilities |= SMB2_NT_FIND | SMB2_LARGE_FILES;
 
+       /*
+        * SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
+        * Set the cipher type manually.
+        */
+       if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
+               server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
+
        security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
                                               (struct smb2_sync_hdr *)rsp);
        /*
@@ -3900,10 +3907,10 @@ smb2_new_read_req(void **buf, unsigned int *total_len,
                         * Related requests use info from previous read request
                         * in chain.
                         */
-                       shdr->SessionId = 0xFFFFFFFF;
+                       shdr->SessionId = 0xFFFFFFFFFFFFFFFF;
                        shdr->TreeId = 0xFFFFFFFF;
-                       req->PersistentFileId = 0xFFFFFFFF;
-                       req->VolatileFileId = 0xFFFFFFFF;
+                       req->PersistentFileId = 0xFFFFFFFFFFFFFFFF;
+                       req->VolatileFileId = 0xFFFFFFFFFFFFFFFF;
                }
        }
        if (remaining_bytes > io_parms->length)
index d6df908dccade5b68eb877e0f45e6aab5e0ed5ee..dafcb6ab050dd9218d824b4808af3267b5c0e316 100644 (file)
 
 #include <linux/tracepoint.h>
 
+/*
+ * Please use this 3-part article as a reference for writing new tracepoints:
+ * https://lwn.net/Articles/379903/
+ */
+
 /* For logging errors in read or write */
 DECLARE_EVENT_CLASS(smb3_rw_err_class,
        TP_PROTO(unsigned int xid,
@@ -529,16 +534,16 @@ DECLARE_EVENT_CLASS(smb3_exit_err_class,
        TP_ARGS(xid, func_name, rc),
        TP_STRUCT__entry(
                __field(unsigned int, xid)
-               __field(const char *, func_name)
+               __string(func_name, func_name)
                __field(int, rc)
        ),
        TP_fast_assign(
                __entry->xid = xid;
-               __entry->func_name = func_name;
+               __assign_str(func_name, func_name);
                __entry->rc = rc;
        ),
        TP_printk("\t%s: xid=%u rc=%d",
-               __entry->func_name, __entry->xid, __entry->rc)
+               __get_str(func_name), __entry->xid, __entry->rc)
 )
 
 #define DEFINE_SMB3_EXIT_ERR_EVENT(name)          \
@@ -583,14 +588,14 @@ DECLARE_EVENT_CLASS(smb3_enter_exit_class,
        TP_ARGS(xid, func_name),
        TP_STRUCT__entry(
                __field(unsigned int, xid)
-               __field(const char *, func_name)
+               __string(func_name, func_name)
        ),
        TP_fast_assign(
                __entry->xid = xid;
-               __entry->func_name = func_name;
+               __assign_str(func_name, func_name);
        ),
        TP_printk("\t%s: xid=%u",
-               __entry->func_name, __entry->xid)
+               __get_str(func_name), __entry->xid)
 )
 
 #define DEFINE_SMB3_ENTER_EXIT_EVENT(name)        \
@@ -857,16 +862,16 @@ DECLARE_EVENT_CLASS(smb3_reconnect_class,
        TP_STRUCT__entry(
                __field(__u64, currmid)
                __field(__u64, conn_id)
-               __field(char *, hostname)
+               __string(hostname, hostname)
        ),
        TP_fast_assign(
                __entry->currmid = currmid;
                __entry->conn_id = conn_id;
-               __entry->hostname = hostname;
+               __assign_str(hostname, hostname);
        ),
        TP_printk("conn_id=0x%llx server=%s current_mid=%llu",
                __entry->conn_id,
-               __entry->hostname,
+               __get_str(hostname),
                __entry->currmid)
 )
 
@@ -891,7 +896,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class,
        TP_STRUCT__entry(
                __field(__u64, currmid)
                __field(__u64, conn_id)
-               __field(char *, hostname)
+               __string(hostname, hostname)
                __field(int, credits)
                __field(int, credits_to_add)
                __field(int, in_flight)
@@ -899,7 +904,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class,
        TP_fast_assign(
                __entry->currmid = currmid;
                __entry->conn_id = conn_id;
-               __entry->hostname = hostname;
+               __assign_str(hostname, hostname);
                __entry->credits = credits;
                __entry->credits_to_add = credits_to_add;
                __entry->in_flight = in_flight;
@@ -907,7 +912,7 @@ DECLARE_EVENT_CLASS(smb3_credit_class,
        TP_printk("conn_id=0x%llx server=%s current_mid=%llu "
                        "credits=%d credit_change=%d in_flight=%d",
                __entry->conn_id,
-               __entry->hostname,
+               __get_str(hostname),
                __entry->currmid,
                __entry->credits,
                __entry->credits_to_add,
index 1d252164d97b6f989f1836dc27e69e3dc698abdf..8129a430d789d92865a5ad71c0d5d9af43a87509 100644 (file)
@@ -45,10 +45,13 @@ static unsigned int debugfs_allow __ro_after_init = DEFAULT_DEBUGFS_ALLOW_BITS;
 static int debugfs_setattr(struct user_namespace *mnt_userns,
                           struct dentry *dentry, struct iattr *ia)
 {
-       int ret = security_locked_down(LOCKDOWN_DEBUGFS);
+       int ret;
 
-       if (ret && (ia->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)))
-               return ret;
+       if (ia->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID)) {
+               ret = security_locked_down(LOCKDOWN_DEBUGFS);
+               if (ret)
+                       return ret;
+       }
        return simple_setattr(&init_user_ns, dentry, ia);
 }
 
index 345f8061e3b4abf424ea4079e2d01ac620ac13d3..e3f5d7f3c8a0ad12eb04be0c89b1b63910b31d6d 100644 (file)
@@ -296,10 +296,6 @@ static int crypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat,
        struct extent_crypt_result ecr;
        int rc = 0;
 
-       if (!crypt_stat || !crypt_stat->tfm
-              || !(crypt_stat->flags & ECRYPTFS_STRUCT_INITIALIZED))
-               return -EINVAL;
-
        if (unlikely(ecryptfs_verbosity > 0)) {
                ecryptfs_printk(KERN_DEBUG, "Key size [%zd]; key:\n",
                                crypt_stat->key_size);
index 9d9e0097c1d3864ff62399a7111e63af92725acb..55efd3dd04f621643f928b9292f81b8ac6331284 100644 (file)
@@ -529,7 +529,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                         * the subpool and global reserve usage count can need
                         * to be adjusted.
                         */
-                       VM_BUG_ON(PagePrivate(page));
+                       VM_BUG_ON(HPageRestoreReserve(page));
                        remove_huge_page(page);
                        freed++;
                        if (!truncate_op) {
index 5361a9b4b47b5f25904f0dbaa8112b79ec6611a8..b3e8624a37d0904c73151fc00a4b3bb64b60dc70 100644 (file)
@@ -979,13 +979,16 @@ static bool io_task_work_match(struct callback_head *cb, void *data)
        return cwd->wqe->wq == data;
 }
 
+void io_wq_exit_start(struct io_wq *wq)
+{
+       set_bit(IO_WQ_BIT_EXIT, &wq->state);
+}
+
 static void io_wq_exit_workers(struct io_wq *wq)
 {
        struct callback_head *cb;
        int node;
 
-       set_bit(IO_WQ_BIT_EXIT, &wq->state);
-
        if (!wq->task)
                return;
 
@@ -1003,13 +1006,16 @@ static void io_wq_exit_workers(struct io_wq *wq)
                struct io_wqe *wqe = wq->wqes[node];
 
                io_wq_for_each_worker(wqe, io_wq_worker_wake, NULL);
-               spin_lock_irq(&wq->hash->wait.lock);
-               list_del_init(&wq->wqes[node]->wait.entry);
-               spin_unlock_irq(&wq->hash->wait.lock);
        }
        rcu_read_unlock();
        io_worker_ref_put(wq);
        wait_for_completion(&wq->worker_done);
+
+       for_each_node(node) {
+               spin_lock_irq(&wq->hash->wait.lock);
+               list_del_init(&wq->wqes[node]->wait.entry);
+               spin_unlock_irq(&wq->hash->wait.lock);
+       }
        put_task_struct(wq->task);
        wq->task = NULL;
 }
@@ -1020,8 +1026,6 @@ static void io_wq_destroy(struct io_wq *wq)
 
        cpuhp_state_remove_instance_nocalls(io_wq_online, &wq->cpuhp_node);
 
-       io_wq_exit_workers(wq);
-
        for_each_node(node) {
                struct io_wqe *wqe = wq->wqes[node];
                struct io_cb_cancel_data match = {
@@ -1036,16 +1040,13 @@ static void io_wq_destroy(struct io_wq *wq)
        kfree(wq);
 }
 
-void io_wq_put(struct io_wq *wq)
-{
-       if (refcount_dec_and_test(&wq->refs))
-               io_wq_destroy(wq);
-}
-
 void io_wq_put_and_exit(struct io_wq *wq)
 {
+       WARN_ON_ONCE(!test_bit(IO_WQ_BIT_EXIT, &wq->state));
+
        io_wq_exit_workers(wq);
-       io_wq_put(wq);
+       if (refcount_dec_and_test(&wq->refs))
+               io_wq_destroy(wq);
 }
 
 static bool io_wq_worker_affinity(struct io_worker *worker, void *data)
index 0e6d310999e899a9d416459138be22a23f02bf56..af2df0680ee22b2d6363df48ee0016d439f96056 100644 (file)
@@ -122,7 +122,7 @@ struct io_wq_data {
 };
 
 struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data);
-void io_wq_put(struct io_wq *wq);
+void io_wq_exit_start(struct io_wq *wq);
 void io_wq_put_and_exit(struct io_wq *wq);
 
 void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work);
index e481ac8a757ad66769e0cf482ec8ec756842bc97..903458afd56c17de177e29e58974aac45b7dbcba 100644 (file)
@@ -5019,10 +5019,10 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt,
                 * Can't handle multishot for double wait for now, turn it
                 * into one-shot mode.
                 */
-               if (!(req->poll.events & EPOLLONESHOT))
-                       req->poll.events |= EPOLLONESHOT;
+               if (!(poll_one->events & EPOLLONESHOT))
+                       poll_one->events |= EPOLLONESHOT;
                /* double add on the same waitqueue head, ignore */
-               if (poll->head == head)
+               if (poll_one->head == head)
                        return;
                poll = kmalloc(sizeof(*poll), GFP_ATOMIC);
                if (!poll) {
@@ -9035,14 +9035,19 @@ static void io_uring_del_task_file(unsigned long index)
 
 static void io_uring_clean_tctx(struct io_uring_task *tctx)
 {
+       struct io_wq *wq = tctx->io_wq;
        struct io_tctx_node *node;
        unsigned long index;
 
        xa_for_each(&tctx->xa, index, node)
                io_uring_del_task_file(index);
-       if (tctx->io_wq) {
-               io_wq_put_and_exit(tctx->io_wq);
+       if (wq) {
+               /*
+                * Must be after io_uring_del_task_file() (removes nodes under
+                * uring_lock) to avoid race with io_uring_try_cancel_iowq().
+                */
                tctx->io_wq = NULL;
+               io_wq_put_and_exit(wq);
        }
 }
 
@@ -9078,6 +9083,9 @@ static void io_uring_cancel_sqpoll(struct io_sq_data *sqd)
 
        if (!current->io_uring)
                return;
+       if (tctx->io_wq)
+               io_wq_exit_start(tctx->io_wq);
+
        WARN_ON_ONCE(!sqd || sqd->thread != current);
 
        atomic_inc(&tctx->in_idle);
@@ -9112,6 +9120,9 @@ void __io_uring_cancel(struct files_struct *files)
        DEFINE_WAIT(wait);
        s64 inflight;
 
+       if (tctx->io_wq)
+               io_wq_exit_start(tctx->io_wq);
+
        /* make sure overflow events are dropped */
        atomic_inc(&tctx->in_idle);
        do {
index f63337828e1c474daa4ac8f13ebb99fc180e5eae..c3f1a78ba36977054f1acaf79889af664d664588 100644 (file)
@@ -3855,8 +3855,12 @@ static int can_idmap_mount(const struct mount_kattr *kattr, struct mount *mnt)
        if (!(m->mnt_sb->s_type->fs_flags & FS_ALLOW_IDMAP))
                return -EINVAL;
 
+       /* Don't yet support filesystem mountable in user namespaces. */
+       if (m->mnt_sb->s_user_ns != &init_user_ns)
+               return -EINVAL;
+
        /* We're not controlling the superblock. */
-       if (!ns_capable(m->mnt_sb->s_user_ns, CAP_SYS_ADMIN))
+       if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
        /* Mount has already been visible in the filesystem hierarchy. */
index 578112713703b92b7cbfe578bdac9c4a374ec4ed..b4db21022cb43f3b371e31687a89ec309f5b3726 100644 (file)
@@ -1,7 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0-only
 
 config NETFS_SUPPORT
-       tristate "Support for network filesystem high-level I/O"
+       tristate
        help
          This option enables support for network filesystems, including
          helpers for high-level buffered I/O, abstracting out read
index 193841d03de09b515b821ab67b50fcfc1b0b89a6..725614625ed4864cf6695aad85e2611b7946b5ed 100644 (file)
@@ -1068,7 +1068,7 @@ int netfs_write_begin(struct file *file, struct address_space *mapping,
        DEFINE_READAHEAD(ractl, file, NULL, mapping, index);
 
 retry:
-       page = grab_cache_page_write_begin(mapping, index, 0);
+       page = grab_cache_page_write_begin(mapping, index, flags);
        if (!page)
                return -ENOMEM;
 
index d158a500c25c65d048f7fd45809dabb0f3012467..d2103852475fa0f82cbf09fbefea870e46a8474d 100644 (file)
@@ -718,7 +718,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo,
                if (unlikely(!p))
                        goto out_err;
                fl->fh_array[i]->size = be32_to_cpup(p++);
-               if (sizeof(struct nfs_fh) < fl->fh_array[i]->size) {
+               if (fl->fh_array[i]->size > NFS_MAXFHSIZE) {
                        printk(KERN_ERR "NFS: Too big fh %d received %d\n",
                               i, fl->fh_array[i]->size);
                        goto out_err;
index 93e60e921f9261866d3ff6bfdf2c2c2a5472a0a4..bc0c698f3350814d9411886e216a5ca7db8f1db7 100644 (file)
@@ -362,7 +362,7 @@ static const struct kernel_param_ops param_ops_nfs_timeout = {
        .set = param_set_nfs_timeout,
        .get = param_get_nfs_timeout,
 };
-#define param_check_nfs_timeout(name, p) __param_check(name, p, int);
+#define param_check_nfs_timeout(name, p) __param_check(name, p, int)
 
 module_param(nfs_mountpoint_expiry_timeout, nfs_timeout, 0644);
 MODULE_PARM_DESC(nfs_mountpoint_expiry_timeout,
index 57b3821d975a35962e6eabafc27e9e461fe02b2b..a1e5c6b85dedc5836b5ecbc407bc02a29dad3e72 100644 (file)
@@ -211,7 +211,7 @@ static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
        case SEEK_HOLE:
        case SEEK_DATA:
                ret = nfs42_proc_llseek(filep, offset, whence);
-               if (ret != -ENOTSUPP)
+               if (ret != -EOPNOTSUPP)
                        return ret;
                fallthrough;
        default:
index 87d04f2c93852b28a8f7ce9c34d1ef627715ba56..0cd9658822329a97a04b716f8a61e000c273d459 100644 (file)
@@ -1706,7 +1706,7 @@ static void nfs_set_open_stateid_locked(struct nfs4_state *state,
                rcu_read_unlock();
                trace_nfs4_open_stateid_update_wait(state->inode, stateid, 0);
 
-               if (!signal_pending(current)) {
+               if (!fatal_signal_pending(current)) {
                        if (schedule_timeout(5*HZ) == 0)
                                status = -EAGAIN;
                        else
@@ -3487,7 +3487,7 @@ static bool nfs4_refresh_open_old_stateid(nfs4_stateid *dst,
                write_sequnlock(&state->seqlock);
                trace_nfs4_close_stateid_update_wait(state->inode, dst, 0);
 
-               if (signal_pending(current))
+               if (fatal_signal_pending(current))
                        status = -EINTR;
                else
                        if (schedule_timeout(5*HZ) != 0)
index 6c20b28d9d7c1a9032e89f83a8e751b625469cb2..cf9cc62ec48ec32a29aa3ebc8f79a86fe24a8c29 100644 (file)
@@ -1094,15 +1094,16 @@ nfs_pageio_do_add_request(struct nfs_pageio_descriptor *desc,
        struct nfs_page *prev = NULL;
        unsigned int size;
 
-       if (mirror->pg_count != 0) {
-               prev = nfs_list_entry(mirror->pg_list.prev);
-       } else {
+       if (list_empty(&mirror->pg_list)) {
                if (desc->pg_ops->pg_init)
                        desc->pg_ops->pg_init(desc, req);
                if (desc->pg_error < 0)
                        return 0;
                mirror->pg_base = req->wb_pgbase;
-       }
+               mirror->pg_count = 0;
+               mirror->pg_recoalesce = 0;
+       } else
+               prev = nfs_list_entry(mirror->pg_list.prev);
 
        if (desc->pg_maxretrans && req->wb_nio > desc->pg_maxretrans) {
                if (NFS_SERVER(desc->pg_inode)->flags & NFS_MOUNT_SOFTERR)
@@ -1127,18 +1128,13 @@ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
 {
        struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(desc);
 
-
        if (!list_empty(&mirror->pg_list)) {
                int error = desc->pg_ops->pg_doio(desc);
                if (error < 0)
                        desc->pg_error = error;
-               else
+               if (list_empty(&mirror->pg_list))
                        mirror->pg_bytes_written += mirror->pg_count;
        }
-       if (list_empty(&mirror->pg_list)) {
-               mirror->pg_count = 0;
-               mirror->pg_base = 0;
-       }
 }
 
 static void
@@ -1227,10 +1223,6 @@ static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc)
 
        do {
                list_splice_init(&mirror->pg_list, &head);
-               mirror->pg_bytes_written -= mirror->pg_count;
-               mirror->pg_count = 0;
-               mirror->pg_base = 0;
-               mirror->pg_recoalesce = 0;
 
                while (!list_empty(&head)) {
                        struct nfs_page *req;
index 03e0b34c4a64cc7a7299866ed13c99b417ade0aa..2c01ee805306c4e88067dcf84c719f9828046b7d 100644 (file)
@@ -1317,6 +1317,11 @@ _pnfs_return_layout(struct inode *ino)
 {
        struct pnfs_layout_hdr *lo = NULL;
        struct nfs_inode *nfsi = NFS_I(ino);
+       struct pnfs_layout_range range = {
+               .iomode         = IOMODE_ANY,
+               .offset         = 0,
+               .length         = NFS4_MAX_UINT64,
+       };
        LIST_HEAD(tmp_list);
        const struct cred *cred;
        nfs4_stateid stateid;
@@ -1344,16 +1349,10 @@ _pnfs_return_layout(struct inode *ino)
        }
        valid_layout = pnfs_layout_is_valid(lo);
        pnfs_clear_layoutcommit(ino, &tmp_list);
-       pnfs_mark_matching_lsegs_return(lo, &tmp_list, NULL, 0);
+       pnfs_mark_matching_lsegs_return(lo, &tmp_list, &range, 0);
 
-       if (NFS_SERVER(ino)->pnfs_curr_ld->return_range) {
-               struct pnfs_layout_range range = {
-                       .iomode         = IOMODE_ANY,
-                       .offset         = 0,
-                       .length         = NFS4_MAX_UINT64,
-               };
+       if (NFS_SERVER(ino)->pnfs_curr_ld->return_range)
                NFS_SERVER(ino)->pnfs_curr_ld->return_range(lo, &range);
-       }
 
        /* Don't send a LAYOUTRETURN if list was initially empty */
        if (!test_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags) ||
@@ -2678,7 +2677,7 @@ EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_range);
 void
 pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
-       u64 rd_size = req->wb_bytes;
+       u64 rd_size;
 
        pnfs_generic_pg_check_layout(pgio);
        pnfs_generic_pg_check_range(pgio, req);
index 19a212f9725de4999ee983a2b31fb62842d7c06a..fe58525cfed48388364bc04ea97119d79b6409bb 100644 (file)
@@ -1379,7 +1379,7 @@ static const struct kernel_param_ops param_ops_portnr = {
        .set = param_set_portnr,
        .get = param_get_uint,
 };
-#define param_check_portnr(name, p) __param_check(name, p, unsigned int);
+#define param_check_portnr(name, p) __param_check(name, p, unsigned int)
 
 module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
 module_param_named(callback_nr_threads, nfs_callback_nr_threads, ushort, 0644);
index 3851bfcdba56ef929411e99a70bb8895bc609e85..58bbf334265b733f23f3d652931ef8b0e30fc2cb 100644 (file)
@@ -2703,6 +2703,10 @@ static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
        void *page;
        int rv;
 
+       /* A task may only write when it was the opener. */
+       if (file->f_cred != current_real_cred())
+               return -EPERM;
+
        rcu_read_lock();
        task = pid_task(proc_pid(inode), PIDTYPE_PID);
        if (!task) {
index 4f13734637660056e299d4ed04ceb38fb04cb580..22d904bde6ab9158702e4d4d83a42ebb4056770d 100644 (file)
@@ -288,14 +288,12 @@ static inline void remove_dquot_hash(struct dquot *dquot)
 static struct dquot *find_dquot(unsigned int hashent, struct super_block *sb,
                                struct kqid qid)
 {
-       struct hlist_node *node;
        struct dquot *dquot;
 
-       hlist_for_each (node, dquot_hash+hashent) {
-               dquot = hlist_entry(node, struct dquot, dq_hash);
+       hlist_for_each_entry(dquot, dquot_hash+hashent, dq_hash)
                if (dquot->dq_sb == sb && qid_eq(dquot->dq_id, qid))
                        return dquot;
-       }
+
        return NULL;
 }
 
index 040a1142915fcd494dfb39c6ba036279c7492de1..167b5889db4bbc2df27b09401bade062d0ba140a 100644 (file)
@@ -114,29 +114,24 @@ static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
                break;
        case SIL_FAULT_BNDERR:
        case SIL_FAULT_PKUERR:
+       case SIL_PERF_EVENT:
                /*
-                * Fall through to the SIL_FAULT case.  Both SIL_FAULT_BNDERR
-                * and SIL_FAULT_PKUERR are only generated by faults that
-                * deliver them synchronously to userspace.  In case someone
-                * injects one of these signals and signalfd catches it treat
-                * it as SIL_FAULT.
+                * Fall through to the SIL_FAULT case.  SIL_FAULT_BNDERR,
+                * SIL_FAULT_PKUERR, and SIL_PERF_EVENT are only
+                * generated by faults that deliver them synchronously to
+                * userspace.  In case someone injects one of these signals
+                * and signalfd catches it treat it as SIL_FAULT.
                 */
        case SIL_FAULT:
                new.ssi_addr = (long) kinfo->si_addr;
-#ifdef __ARCH_SI_TRAPNO
-               new.ssi_trapno = kinfo->si_trapno;
-#endif
                break;
-       case SIL_FAULT_MCEERR:
+       case SIL_FAULT_TRAPNO:
                new.ssi_addr = (long) kinfo->si_addr;
-#ifdef __ARCH_SI_TRAPNO
                new.ssi_trapno = kinfo->si_trapno;
-#endif
-               new.ssi_addr_lsb = (short) kinfo->si_addr_lsb;
                break;
-       case SIL_PERF_EVENT:
+       case SIL_FAULT_MCEERR:
                new.ssi_addr = (long) kinfo->si_addr;
-               new.ssi_perf = kinfo->si_perf;
+               new.ssi_addr_lsb = (short) kinfo->si_addr_lsb;
                break;
        case SIL_CHLD:
                new.ssi_pid    = kinfo->si_pid;
index e32a1833d5231e2a971b939d453eef1ca6c72fa5..bbfea8022a3b96c5bc25bb012b07a90f9241032b 100644 (file)
@@ -325,10 +325,22 @@ out:
                error2 = xfs_alloc_pagf_init(mp, tp, pag->pag_agno, 0);
                if (error2)
                        return error2;
-               ASSERT(xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved +
-                      xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved <=
-                      pag->pagf_freeblks + pag->pagf_flcount);
+
+               /*
+                * If there isn't enough space in the AG to satisfy the
+                * reservation, let the caller know that there wasn't enough
+                * space.  Callers are responsible for deciding what to do
+                * next, since (in theory) we can stumble along with
+                * insufficient reservation if data blocks are being freed to
+                * replenish the AG's free space.
+                */
+               if (!error &&
+                   xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved +
+                   xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved >
+                   pag->pagf_freeblks + pag->pagf_flcount)
+                       error = -ENOSPC;
        }
+
        return error;
 }
 
index 7e3b9b01431e573a92db759a1025d58e5a7f84ea..a3e0e6f672d63ad29ec04e0704eb036cb8a12172 100644 (file)
@@ -605,7 +605,6 @@ xfs_bmap_btree_to_extents(
 
        ASSERT(cur);
        ASSERT(whichfork != XFS_COW_FORK);
-       ASSERT(!xfs_need_iread_extents(ifp));
        ASSERT(ifp->if_format == XFS_DINODE_FMT_BTREE);
        ASSERT(be16_to_cpu(rblock->bb_level) == 1);
        ASSERT(be16_to_cpu(rblock->bb_numrecs) == 1);
@@ -5350,7 +5349,6 @@ __xfs_bunmapi(
        xfs_fsblock_t           sum;
        xfs_filblks_t           len = *rlen;    /* length to unmap in file */
        xfs_fileoff_t           max_len;
-       xfs_agnumber_t          prev_agno = NULLAGNUMBER, agno;
        xfs_fileoff_t           end;
        struct xfs_iext_cursor  icur;
        bool                    done = false;
@@ -5442,16 +5440,6 @@ __xfs_bunmapi(
                del = got;
                wasdel = isnullstartblock(del.br_startblock);
 
-               /*
-                * Make sure we don't touch multiple AGF headers out of order
-                * in a single transaction, as that could cause AB-BA deadlocks.
-                */
-               if (!wasdel && !isrt) {
-                       agno = XFS_FSB_TO_AGNO(mp, del.br_startblock);
-                       if (prev_agno != NULLAGNUMBER && prev_agno > agno)
-                               break;
-                       prev_agno = agno;
-               }
                if (got.br_startoff < start) {
                        del.br_startoff = start;
                        del.br_blockcount -= start - got.br_startoff;
index a83bdd0c47a846e2fa387818be20c6c2b6017521..bde2b4c64dbe30d13eef44f32005c35fe349ae1e 100644 (file)
@@ -770,6 +770,8 @@ struct xfs_scrub_metadata {
 /*
  * ioctl commands that are used by Linux filesystems
  */
+#define XFS_IOC_GETXFLAGS      FS_IOC_GETFLAGS
+#define XFS_IOC_SETXFLAGS      FS_IOC_SETFLAGS
 #define XFS_IOC_GETVERSION     FS_IOC_GETVERSION
 
 /*
@@ -780,6 +782,8 @@ struct xfs_scrub_metadata {
 #define XFS_IOC_ALLOCSP                _IOW ('X', 10, struct xfs_flock64)
 #define XFS_IOC_FREESP         _IOW ('X', 11, struct xfs_flock64)
 #define XFS_IOC_DIOINFO                _IOR ('X', 30, struct dioattr)
+#define XFS_IOC_FSGETXATTR     FS_IOC_FSGETXATTR
+#define XFS_IOC_FSSETXATTR     FS_IOC_FSSETXATTR
 #define XFS_IOC_ALLOCSP64      _IOW ('X', 36, struct xfs_flock64)
 #define XFS_IOC_FREESP64       _IOW ('X', 37, struct xfs_flock64)
 #define XFS_IOC_GETBMAP                _IOWR('X', 38, struct getbmap)
index 5c9a7440d9e4ed5eae62debe0242e152f7c182f3..f3254a4f4cb4bf5ea7417bb1a0364143890f98d3 100644 (file)
@@ -559,8 +559,17 @@ xfs_dinode_calc_crc(
 /*
  * Validate di_extsize hint.
  *
- * The rules are documented at xfs_ioctl_setattr_check_extsize().
- * These functions must be kept in sync with each other.
+ * 1. Extent size hint is only valid for directories and regular files.
+ * 2. FS_XFLAG_EXTSIZE is only valid for regular files.
+ * 3. FS_XFLAG_EXTSZINHERIT is only valid for directories.
+ * 4. Hint cannot be larger than MAXTEXTLEN.
+ * 5. Can be changed on directories at any time.
+ * 6. Hint value of 0 turns off hints, clears inode flags.
+ * 7. Extent size must be a multiple of the appropriate block size.
+ *    For realtime files, this is the rt extent size.
+ * 8. For non-realtime files, the extent size hint must be limited
+ *    to half the AG size to avoid alignment extending the extent beyond the
+ *    limits of the AG.
  */
 xfs_failaddr_t
 xfs_inode_validate_extsize(
@@ -580,6 +589,28 @@ xfs_inode_validate_extsize(
        inherit_flag = (flags & XFS_DIFLAG_EXTSZINHERIT);
        extsize_bytes = XFS_FSB_TO_B(mp, extsize);
 
+       /*
+        * This comment describes a historic gap in this verifier function.
+        *
+        * On older kernels, the extent size hint verifier doesn't check that
+        * the extent size hint is an integer multiple of the realtime extent
+        * size on a directory with both RTINHERIT and EXTSZINHERIT flags set.
+        * The verifier has always enforced the alignment rule for regular
+        * files with the REALTIME flag set.
+        *
+        * If a directory with a misaligned extent size hint is allowed to
+        * propagate that hint into a new regular realtime file, the result
+        * is that the inode cluster buffer verifier will trigger a corruption
+        * shutdown the next time it is run.
+        *
+        * Unfortunately, there could be filesystems with these misconfigured
+        * directories in the wild, so we cannot add a check to this verifier
+        * at this time because that will result a new source of directory
+        * corruption errors when reading an existing filesystem.  Instead, we
+        * permit the misconfiguration to pass through the verifiers so that
+        * callers of this function can correct and mitigate externally.
+        */
+
        if (rt_flag)
                blocksize_bytes = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
        else
@@ -616,8 +647,15 @@ xfs_inode_validate_extsize(
 /*
  * Validate di_cowextsize hint.
  *
- * The rules are documented at xfs_ioctl_setattr_check_cowextsize().
- * These functions must be kept in sync with each other.
+ * 1. CoW extent size hint can only be set if reflink is enabled on the fs.
+ *    The inode does not have to have any shared blocks, but it must be a v3.
+ * 2. FS_XFLAG_COWEXTSIZE is only valid for directories and regular files;
+ *    for a directory, the hint is propagated to new files.
+ * 3. Can be changed on files & directories at any time.
+ * 4. Hint value of 0 turns off hints, clears inode flags.
+ * 5. Extent size must be a multiple of the appropriate block size.
+ * 6. The extent size hint must be limited to half the AG size to avoid
+ *    alignment extending the extent beyond the limits of the AG.
  */
 xfs_failaddr_t
 xfs_inode_validate_cowextsize(
index 78324e043e257224b802c8e666e43b4df246f5d8..8d595a5c4abd1d85a6efc442f090337b2fc76b3a 100644 (file)
@@ -142,6 +142,23 @@ xfs_trans_log_inode(
                flags |= XFS_ILOG_CORE;
        }
 
+       /*
+        * Inode verifiers on older kernels don't check that the extent size
+        * hint is an integer multiple of the rt extent size on a directory
+        * with both rtinherit and extszinherit flags set.  If we're logging a
+        * directory that is misconfigured in this way, clear the hint.
+        */
+       if ((ip->i_diflags & XFS_DIFLAG_RTINHERIT) &&
+           (ip->i_diflags & XFS_DIFLAG_EXTSZINHERIT) &&
+           (ip->i_extsize % ip->i_mount->m_sb.sb_rextsize) > 0) {
+               xfs_info_once(ip->i_mount,
+       "Correcting misaligned extent size hint in inode 0x%llx.", ip->i_ino);
+               ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
+                                  XFS_DIFLAG_EXTSZINHERIT);
+               ip->i_extsize = 0;
+               flags |= XFS_ILOG_CORE;
+       }
+
        /*
         * Record the specific change for fdatasync optimisation. This allows
         * fdatasync to skip log forces for inodes that are only timestamp
index aa874607618a22e0dbc763f5e540994619231057..be38c960da85863ca6f530b2db3e52fc4f22cc80 100644 (file)
@@ -74,7 +74,9 @@ __xchk_process_error(
                return true;
        case -EDEADLOCK:
                /* Used to restart an op with deadlock avoidance. */
-               trace_xchk_deadlock_retry(sc->ip, sc->sm, *error);
+               trace_xchk_deadlock_retry(
+                               sc->ip ? sc->ip : XFS_I(file_inode(sc->file)),
+                               sc->sm, *error);
                break;
        case -EFSBADCRC:
        case -EFSCORRUPTED:
index a5e9d7d34023f21643a4ca4fd1c9a903abafdb2b..0936f3a96fe6e845007e444bad9a33fa0e8fa12a 100644 (file)
@@ -71,18 +71,24 @@ xfs_zero_extent(
 #ifdef CONFIG_XFS_RT
 int
 xfs_bmap_rtalloc(
-       struct xfs_bmalloca     *ap)    /* bmap alloc argument struct */
+       struct xfs_bmalloca     *ap)
 {
-       int             error;          /* error return value */
-       xfs_mount_t     *mp;            /* mount point structure */
-       xfs_extlen_t    prod = 0;       /* product factor for allocators */
-       xfs_extlen_t    mod = 0;        /* product factor for allocators */
-       xfs_extlen_t    ralen = 0;      /* realtime allocation length */
-       xfs_extlen_t    align;          /* minimum allocation alignment */
-       xfs_rtblock_t   rtb;
-
-       mp = ap->ip->i_mount;
+       struct xfs_mount        *mp = ap->ip->i_mount;
+       xfs_fileoff_t           orig_offset = ap->offset;
+       xfs_rtblock_t           rtb;
+       xfs_extlen_t            prod = 0;  /* product factor for allocators */
+       xfs_extlen_t            mod = 0;   /* product factor for allocators */
+       xfs_extlen_t            ralen = 0; /* realtime allocation length */
+       xfs_extlen_t            align;     /* minimum allocation alignment */
+       xfs_extlen_t            orig_length = ap->length;
+       xfs_extlen_t            minlen = mp->m_sb.sb_rextsize;
+       xfs_extlen_t            raminlen;
+       bool                    rtlocked = false;
+       bool                    ignore_locality = false;
+       int                     error;
+
        align = xfs_get_extsz_hint(ap->ip);
+retry:
        prod = align / mp->m_sb.sb_rextsize;
        error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
                                        align, 1, ap->eof, 0,
@@ -92,6 +98,15 @@ xfs_bmap_rtalloc(
        ASSERT(ap->length);
        ASSERT(ap->length % mp->m_sb.sb_rextsize == 0);
 
+       /*
+        * If we shifted the file offset downward to satisfy an extent size
+        * hint, increase minlen by that amount so that the allocator won't
+        * give us an allocation that's too short to cover at least one of the
+        * blocks that the caller asked for.
+        */
+       if (ap->offset != orig_offset)
+               minlen += orig_offset - ap->offset;
+
        /*
         * If the offset & length are not perfectly aligned
         * then kill prod, it will just get us in trouble.
@@ -116,10 +131,13 @@ xfs_bmap_rtalloc(
        /*
         * Lock out modifications to both the RT bitmap and summary inodes
         */
-       xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL|XFS_ILOCK_RTBITMAP);
-       xfs_trans_ijoin(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL);
-       xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL|XFS_ILOCK_RTSUM);
-       xfs_trans_ijoin(ap->tp, mp->m_rsumip, XFS_ILOCK_EXCL);
+       if (!rtlocked) {
+               xfs_ilock(mp->m_rbmip, XFS_ILOCK_EXCL|XFS_ILOCK_RTBITMAP);
+               xfs_trans_ijoin(ap->tp, mp->m_rbmip, XFS_ILOCK_EXCL);
+               xfs_ilock(mp->m_rsumip, XFS_ILOCK_EXCL|XFS_ILOCK_RTSUM);
+               xfs_trans_ijoin(ap->tp, mp->m_rsumip, XFS_ILOCK_EXCL);
+               rtlocked = true;
+       }
 
        /*
         * If it's an allocation to an empty file at offset 0,
@@ -141,33 +159,59 @@ xfs_bmap_rtalloc(
        /*
         * Realtime allocation, done through xfs_rtallocate_extent.
         */
-       do_div(ap->blkno, mp->m_sb.sb_rextsize);
+       if (ignore_locality)
+               ap->blkno = 0;
+       else
+               do_div(ap->blkno, mp->m_sb.sb_rextsize);
        rtb = ap->blkno;
        ap->length = ralen;
-       error = xfs_rtallocate_extent(ap->tp, ap->blkno, 1, ap->length,
-                               &ralen, ap->wasdel, prod, &rtb);
+       raminlen = max_t(xfs_extlen_t, 1, minlen / mp->m_sb.sb_rextsize);
+       error = xfs_rtallocate_extent(ap->tp, ap->blkno, raminlen, ap->length,
+                       &ralen, ap->wasdel, prod, &rtb);
        if (error)
                return error;
 
-       ap->blkno = rtb;
-       if (ap->blkno != NULLFSBLOCK) {
-               ap->blkno *= mp->m_sb.sb_rextsize;
-               ralen *= mp->m_sb.sb_rextsize;
-               ap->length = ralen;
-               ap->ip->i_nblocks += ralen;
+       if (rtb != NULLRTBLOCK) {
+               ap->blkno = rtb * mp->m_sb.sb_rextsize;
+               ap->length = ralen * mp->m_sb.sb_rextsize;
+               ap->ip->i_nblocks += ap->length;
                xfs_trans_log_inode(ap->tp, ap->ip, XFS_ILOG_CORE);
                if (ap->wasdel)
-                       ap->ip->i_delayed_blks -= ralen;
+                       ap->ip->i_delayed_blks -= ap->length;
                /*
                 * Adjust the disk quota also. This was reserved
                 * earlier.
                 */
                xfs_trans_mod_dquot_byino(ap->tp, ap->ip,
                        ap->wasdel ? XFS_TRANS_DQ_DELRTBCOUNT :
-                                       XFS_TRANS_DQ_RTBCOUNT, (long) ralen);
-       } else {
-               ap->length = 0;
+                                       XFS_TRANS_DQ_RTBCOUNT, ap->length);
+               return 0;
        }
+
+       if (align > mp->m_sb.sb_rextsize) {
+               /*
+                * We previously enlarged the request length to try to satisfy
+                * an extent size hint.  The allocator didn't return anything,
+                * so reset the parameters to the original values and try again
+                * without alignment criteria.
+                */
+               ap->offset = orig_offset;
+               ap->length = orig_length;
+               minlen = align = mp->m_sb.sb_rextsize;
+               goto retry;
+       }
+
+       if (!ignore_locality && ap->blkno != 0) {
+               /*
+                * If we can't allocate near a specific rt extent, try again
+                * without locality criteria.
+                */
+               ignore_locality = true;
+               goto retry;
+       }
+
+       ap->blkno = NULLFSBLOCK;
+       ap->length = 0;
        return 0;
 }
 #endif /* CONFIG_XFS_RT */
index 0369eb22c1bb0fd04e8b97f99703494a23bf69b5..e4c2da4566f13f1748de5c8c5e54c683dd7be866 100644 (file)
@@ -690,6 +690,7 @@ xfs_inode_inherit_flags(
        const struct xfs_inode  *pip)
 {
        unsigned int            di_flags = 0;
+       xfs_failaddr_t          failaddr;
        umode_t                 mode = VFS_I(ip)->i_mode;
 
        if (S_ISDIR(mode)) {
@@ -729,6 +730,24 @@ xfs_inode_inherit_flags(
                di_flags |= XFS_DIFLAG_FILESTREAM;
 
        ip->i_diflags |= di_flags;
+
+       /*
+        * Inode verifiers on older kernels only check that the extent size
+        * hint is an integer multiple of the rt extent size on realtime files.
+        * They did not check the hint alignment on a directory with both
+        * rtinherit and extszinherit flags set.  If the misaligned hint is
+        * propagated from a directory into a new realtime file, new file
+        * allocations will fail due to math errors in the rt allocator and/or
+        * trip the verifiers.  Validate the hint settings in the new file so
+        * that we don't let broken hints propagate.
+        */
+       failaddr = xfs_inode_validate_extsize(ip->i_mount, ip->i_extsize,
+                       VFS_I(ip)->i_mode, ip->i_diflags);
+       if (failaddr) {
+               ip->i_diflags &= ~(XFS_DIFLAG_EXTSIZE |
+                                  XFS_DIFLAG_EXTSZINHERIT);
+               ip->i_extsize = 0;
+       }
 }
 
 /* Propagate di_flags2 from a parent inode to a child inode. */
@@ -737,12 +756,22 @@ xfs_inode_inherit_flags2(
        struct xfs_inode        *ip,
        const struct xfs_inode  *pip)
 {
+       xfs_failaddr_t          failaddr;
+
        if (pip->i_diflags2 & XFS_DIFLAG2_COWEXTSIZE) {
                ip->i_diflags2 |= XFS_DIFLAG2_COWEXTSIZE;
                ip->i_cowextsize = pip->i_cowextsize;
        }
        if (pip->i_diflags2 & XFS_DIFLAG2_DAX)
                ip->i_diflags2 |= XFS_DIFLAG2_DAX;
+
+       /* Don't let invalid cowextsize hints propagate. */
+       failaddr = xfs_inode_validate_cowextsize(ip->i_mount, ip->i_cowextsize,
+                       VFS_I(ip)->i_mode, ip->i_diflags, ip->i_diflags2);
+       if (failaddr) {
+               ip->i_diflags2 &= ~XFS_DIFLAG2_COWEXTSIZE;
+               ip->i_cowextsize = 0;
+       }
 }
 
 /*
index 3925bfcb236570bf75241e466b15d2aa70f30461..1fe4c1fc0aeaeeebe05c6391625dbfb48f85323f 100644 (file)
@@ -1267,20 +1267,8 @@ out_error:
 }
 
 /*
- * extent size hint validation is somewhat cumbersome. Rules are:
- *
- * 1. extent size hint is only valid for directories and regular files
- * 2. FS_XFLAG_EXTSIZE is only valid for regular files
- * 3. FS_XFLAG_EXTSZINHERIT is only valid for directories.
- * 4. can only be changed on regular files if no extents are allocated
- * 5. can be changed on directories at any time
- * 6. extsize hint of 0 turns off hints, clears inode flags.
- * 7. Extent size must be a multiple of the appropriate block size.
- * 8. for non-realtime files, the extent size hint must be limited
- *    to half the AG size to avoid alignment extending the extent beyond the
- *    limits of the AG.
- *
- * Please keep this function in sync with xfs_scrub_inode_extsize.
+ * Validate a proposed extent size hint.  For regular files, the hint can only
+ * be changed if no extents are allocated.
  */
 static int
 xfs_ioctl_setattr_check_extsize(
@@ -1288,86 +1276,65 @@ xfs_ioctl_setattr_check_extsize(
        struct fileattr         *fa)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       xfs_extlen_t            size;
-       xfs_fsblock_t           extsize_fsb;
+       xfs_failaddr_t          failaddr;
+       uint16_t                new_diflags;
 
        if (!fa->fsx_valid)
                return 0;
 
        if (S_ISREG(VFS_I(ip)->i_mode) && ip->i_df.if_nextents &&
-           ((ip->i_extsize << mp->m_sb.sb_blocklog) != fa->fsx_extsize))
+           XFS_FSB_TO_B(mp, ip->i_extsize) != fa->fsx_extsize)
                return -EINVAL;
 
-       if (fa->fsx_extsize == 0)
-               return 0;
-
-       extsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_extsize);
-       if (extsize_fsb > MAXEXTLEN)
+       if (fa->fsx_extsize & mp->m_blockmask)
                return -EINVAL;
 
-       if (XFS_IS_REALTIME_INODE(ip) ||
-           (fa->fsx_xflags & FS_XFLAG_REALTIME)) {
-               size = mp->m_sb.sb_rextsize << mp->m_sb.sb_blocklog;
-       } else {
-               size = mp->m_sb.sb_blocksize;
-               if (extsize_fsb > mp->m_sb.sb_agblocks / 2)
+       new_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);
+
+       /*
+        * Inode verifiers on older kernels don't check that the extent size
+        * hint is an integer multiple of the rt extent size on a directory
+        * with both rtinherit and extszinherit flags set.  Don't let sysadmins
+        * misconfigure directories.
+        */
+       if ((new_diflags & XFS_DIFLAG_RTINHERIT) &&
+           (new_diflags & XFS_DIFLAG_EXTSZINHERIT)) {
+               unsigned int    rtextsize_bytes;
+
+               rtextsize_bytes = XFS_FSB_TO_B(mp, mp->m_sb.sb_rextsize);
+               if (fa->fsx_extsize % rtextsize_bytes)
                        return -EINVAL;
        }
 
-       if (fa->fsx_extsize % size)
-               return -EINVAL;
-
-       return 0;
+       failaddr = xfs_inode_validate_extsize(ip->i_mount,
+                       XFS_B_TO_FSB(mp, fa->fsx_extsize),
+                       VFS_I(ip)->i_mode, new_diflags);
+       return failaddr != NULL ? -EINVAL : 0;
 }
 
-/*
- * CoW extent size hint validation rules are:
- *
- * 1. CoW extent size hint can only be set if reflink is enabled on the fs.
- *    The inode does not have to have any shared blocks, but it must be a v3.
- * 2. FS_XFLAG_COWEXTSIZE is only valid for directories and regular files;
- *    for a directory, the hint is propagated to new files.
- * 3. Can be changed on files & directories at any time.
- * 4. CoW extsize hint of 0 turns off hints, clears inode flags.
- * 5. Extent size must be a multiple of the appropriate block size.
- * 6. The extent size hint must be limited to half the AG size to avoid
- *    alignment extending the extent beyond the limits of the AG.
- *
- * Please keep this function in sync with xfs_scrub_inode_cowextsize.
- */
 static int
 xfs_ioctl_setattr_check_cowextsize(
        struct xfs_inode        *ip,
        struct fileattr         *fa)
 {
        struct xfs_mount        *mp = ip->i_mount;
-       xfs_extlen_t            size;
-       xfs_fsblock_t           cowextsize_fsb;
+       xfs_failaddr_t          failaddr;
+       uint64_t                new_diflags2;
+       uint16_t                new_diflags;
 
        if (!fa->fsx_valid)
                return 0;
 
-       if (!(fa->fsx_xflags & FS_XFLAG_COWEXTSIZE))
-               return 0;
-
-       if (!xfs_sb_version_hasreflink(&ip->i_mount->m_sb))
+       if (fa->fsx_cowextsize & mp->m_blockmask)
                return -EINVAL;
 
-       if (fa->fsx_cowextsize == 0)
-               return 0;
+       new_diflags = xfs_flags2diflags(ip, fa->fsx_xflags);
+       new_diflags2 = xfs_flags2diflags2(ip, fa->fsx_xflags);
 
-       cowextsize_fsb = XFS_B_TO_FSB(mp, fa->fsx_cowextsize);
-       if (cowextsize_fsb > MAXEXTLEN)
-               return -EINVAL;
-
-       size = mp->m_sb.sb_blocksize;
-       if (cowextsize_fsb > mp->m_sb.sb_agblocks / 2)
-               return -EINVAL;
-
-       if (fa->fsx_cowextsize % size)
-               return -EINVAL;
-
-       return 0;
+       failaddr = xfs_inode_validate_cowextsize(ip->i_mount,
+                       XFS_B_TO_FSB(mp, fa->fsx_cowextsize),
+                       VFS_I(ip)->i_mode, new_diflags, new_diflags2);
+       return failaddr != NULL ? -EINVAL : 0;
 }
 
 static int
index 3c392b1512ac04e2810ced581c2f0f300bc89616..7ec1a9207517f85a0b99af23fd238c59615d9e18 100644 (file)
@@ -73,6 +73,8 @@ do {                                                                  \
        xfs_printk_once(xfs_warn, dev, fmt, ##__VA_ARGS__)
 #define xfs_notice_once(dev, fmt, ...)                         \
        xfs_printk_once(xfs_notice, dev, fmt, ##__VA_ARGS__)
+#define xfs_info_once(dev, fmt, ...)                           \
+       xfs_printk_once(xfs_info, dev, fmt, ##__VA_ARGS__)
 
 void assfail(struct xfs_mount *mp, char *expr, char *f, int l);
 void asswarn(struct xfs_mount *mp, char *expr, char *f, int l);
index ec621180ef094c24d9a87b169d6531dcdf066987..e602d848fc1ab7291fe04dc56745bc41e28b8b1c 100644 (file)
@@ -72,6 +72,9 @@ struct vgic_global {
        bool                    has_gicv4;
        bool                    has_gicv4_1;
 
+       /* Pseudo GICv3 from outer space */
+       bool                    no_hw_deactivation;
+
        /* GIC system register CPU interface */
        struct static_key_false gicv3_cpuif;
 
@@ -89,6 +92,26 @@ enum vgic_irq_config {
        VGIC_CONFIG_LEVEL
 };
 
+/*
+ * Per-irq ops overriding some common behavious.
+ *
+ * Always called in non-preemptible section and the functions can use
+ * kvm_arm_get_running_vcpu() to get the vcpu pointer for private IRQs.
+ */
+struct irq_ops {
+       /* Per interrupt flags for special-cased interrupts */
+       unsigned long flags;
+
+#define VGIC_IRQ_SW_RESAMPLE   BIT(0)  /* Clear the active state for resampling */
+
+       /*
+        * Callback function pointer to in-kernel devices that can tell us the
+        * state of the input level of mapped level-triggered IRQ faster than
+        * peaking into the physical GIC.
+        */
+       bool (*get_input_level)(int vintid);
+};
+
 struct vgic_irq {
        raw_spinlock_t irq_lock;        /* Protects the content of the struct */
        struct list_head lpi_list;      /* Used to link all LPIs together */
@@ -126,21 +149,17 @@ struct vgic_irq {
        u8 group;                       /* 0 == group 0, 1 == group 1 */
        enum vgic_irq_config config;    /* Level or edge */
 
-       /*
-        * Callback function pointer to in-kernel devices that can tell us the
-        * state of the input level of mapped level-triggered IRQ faster than
-        * peaking into the physical GIC.
-        *
-        * Always called in non-preemptible section and the functions can use
-        * kvm_arm_get_running_vcpu() to get the vcpu pointer for private
-        * IRQs.
-        */
-       bool (*get_input_level)(int vintid);
+       struct irq_ops *ops;
 
        void *owner;                    /* Opaque pointer to reserve an interrupt
                                           for in-kernel devices. */
 };
 
+static inline bool vgic_irq_needs_resampling(struct vgic_irq *irq)
+{
+       return irq->ops && (irq->ops->flags & VGIC_IRQ_SW_RESAMPLE);
+}
+
 struct vgic_register_region;
 struct vgic_its;
 
@@ -352,7 +371,7 @@ void kvm_vgic_init_cpu_hardware(void);
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
                        bool level, void *owner);
 int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
-                         u32 vintid, bool (*get_input_level)(int vindid));
+                         u32 vintid, struct irq_ops *ops);
 int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid);
 bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid);
 
index 7f475d59a0974f17d7a9765c643b798a1dc6ee83..87d112650dfbb0ec9ac6825ae2746c61b2659960 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/build_bug.h>
 #define GENMASK_INPUT_CHECK(h, l) \
        (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
-               __builtin_constant_p((l) > (h)), (l) > (h), 0)))
+               __is_constexpr((l) > (h)), (l) > (h), 0)))
 #else
 /*
  * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
index 559ee05f86b2ecde788a5748a5d015f0ce233cc0..fb8f6d2cd1042067511867b96bac3305df827cd9 100644 (file)
@@ -232,7 +232,7 @@ struct css_set {
        struct list_head task_iters;
 
        /*
-        * On the default hierarhcy, ->subsys[ssid] may point to a css
+        * On the default hierarchy, ->subsys[ssid] may point to a css
         * attached to an ancestor instead of the cgroup this css_set is
         * associated with.  The following node is anchored at
         * ->subsys[ssid]->cgroup->e_csets[ssid] and provides a way to
@@ -668,7 +668,7 @@ struct cgroup_subsys {
         */
        bool threaded:1;
 
-       /* the following two fields are initialized automtically during boot */
+       /* the following two fields are initialized automatically during boot */
        int id;
        const char *name;
 
@@ -757,7 +757,7 @@ static inline void cgroup_threadgroup_change_end(struct task_struct *tsk) {}
  * sock_cgroup_data overloads (prioidx, classid) and the cgroup pointer.
  * On boot, sock_cgroup_data records the cgroup that the sock was created
  * in so that cgroup2 matches can be made; however, once either net_prio or
- * net_cls starts being used, the area is overriden to carry prioidx and/or
+ * net_cls starts being used, the area is overridden to carry prioidx and/or
  * classid.  The two modes are distinguished by whether the lowest bit is
  * set.  Clear bit indicates cgroup pointer while set bit prioidx and
  * classid.
index 4f2f79de083e213b53967d2808af15636f9eb222..6bc9c76680b228819fb9577aa5bfcd360d512959 100644 (file)
@@ -32,7 +32,7 @@ struct kernel_clone_args;
 #ifdef CONFIG_CGROUPS
 
 /*
- * All weight knobs on the default hierarhcy should use the following min,
+ * All weight knobs on the default hierarchy should use the following min,
  * default and max values.  The default value is the logarithmic center of
  * MIN and MAX and allows 100x to be expressed in both directions.
  */
index 98dd7b324c35074a98a9e3fca68bdd4c01154d45..8855b1b702b2a7e84ec0d8c75491f4347040d0d1 100644 (file)
@@ -213,12 +213,11 @@ typedef struct compat_siginfo {
                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT */
                struct {
                        compat_uptr_t _addr;    /* faulting insn/memory ref. */
-#ifdef __ARCH_SI_TRAPNO
-                       int _trapno;    /* TRAP # which caused the signal */
-#endif
 #define __COMPAT_ADDR_BND_PKEY_PAD  (__alignof__(compat_uptr_t) < sizeof(short) ? \
                                     sizeof(short) : __alignof__(compat_uptr_t))
                        union {
+                               /* used on alpha and sparc */
+                               int _trapno;    /* TRAP # which caused the signal */
                                /*
                                 * used when si_code=BUS_MCEERR_AR or
                                 * used when si_code=BUS_MCEERR_AO
@@ -236,7 +235,10 @@ typedef struct compat_siginfo {
                                        u32 _pkey;
                                } _addr_pkey;
                                /* used when si_code=TRAP_PERF */
-                               compat_ulong_t _perf;
+                               struct {
+                                       compat_ulong_t _data;
+                                       u32 _type;
+                               } _perf;
                        };
                } _sigfault;
 
index 81b8aae5a8559c9fabf0665c48d8e8659db4f239..435ddd72d2c464fdedd33889190009dde0a3bda9 100644 (file)
@@ -3,4 +3,12 @@
 
 #include <vdso/const.h>
 
+/*
+ * This returns a constant expression while determining if an argument is
+ * a constant expression, most importantly without evaluating the argument.
+ * Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
+ */
+#define __is_constexpr(x) \
+       (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
+
 #endif /* _LINUX_CONST_H */
index 38a2071cf77685a3b8c520f4d4eafb50ee080669..f1a00040fa5349beb2e650376b4c56ddeb6cc46a 100644 (file)
@@ -570,7 +570,7 @@ struct device {
  * @flags: Link flags.
  * @rpm_active: Whether or not the consumer device is runtime-PM-active.
  * @kref: Count repeated addition of the same link.
- * @rcu_head: An RCU head to use for deferred execution of SRCU callbacks.
+ * @rm_work: Work structure used for removing the link.
  * @supplier_preactivated: Supplier has been made active before consumer probe.
  */
 struct device_link {
@@ -583,9 +583,7 @@ struct device_link {
        u32 flags;
        refcount_t rpm_active;
        struct kref kref;
-#ifdef CONFIG_SRCU
-       struct rcu_head rcu_head;
-#endif
+       struct work_struct rm_work;
        bool supplier_preactivated; /* Owned by consumer probe. */
 };
 
index a57ee75342cf801e5d50b5d44702aa6c052a1be4..dce631e678dd6ce0bfd5c9985c0520b3bee78e7c 100644 (file)
@@ -32,6 +32,11 @@ struct _ddebug {
 #define _DPRINTK_FLAGS_INCL_FUNCNAME   (1<<2)
 #define _DPRINTK_FLAGS_INCL_LINENO     (1<<3)
 #define _DPRINTK_FLAGS_INCL_TID                (1<<4)
+
+#define _DPRINTK_FLAGS_INCL_ANY                \
+       (_DPRINTK_FLAGS_INCL_MODNAME | _DPRINTK_FLAGS_INCL_FUNCNAME |\
+        _DPRINTK_FLAGS_INCL_LINENO  | _DPRINTK_FLAGS_INCL_TID)
+
 #if defined DEBUG
 #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT
 #else
index 7e9660ea967d59c422d5ed6a9b6d557a66f86e04..6fc26f7bdf71ea48a7ca1693217f8be150d2d5d7 100644 (file)
@@ -306,8 +306,6 @@ static inline void bd_unlink_disk_holder(struct block_device *bdev,
 }
 #endif /* CONFIG_SYSFS */
 
-extern struct rw_semaphore bdev_lookup_sem;
-
 dev_t blk_lookup_devt(const char *name, int partno);
 void blk_request_module(dev_t devt);
 #ifdef CONFIG_BLOCK
index 045ad1650ed16dacf28f3894ef2414f279e20fe1..d82b4b2e1d25d69839ccd92292c2d9ae5d4736ed 100644 (file)
@@ -242,7 +242,8 @@ extern bool initcall_debug;
        asm(".section   \"" __sec "\", \"a\"            \n"     \
            __stringify(__name) ":                      \n"     \
            ".long      " __stringify(__stub) " - .     \n"     \
-           ".previous                                  \n");
+           ".previous                                  \n");   \
+       static_assert(__same_type(initcall_t, &fn));
 #else
 #define ____define_initcall(fn, __unused, __name, __sec)       \
        static initcall_t __name __used                         \
index fa8c0455c3523316e00a6eaaaed4bf4347ccdb42..1177f3a1aed5dd0da3339974b01568ada7f25079 100644 (file)
@@ -7,8 +7,7 @@
 #ifndef __LINUX_IRQCHIP_ARM_GIC_COMMON_H
 #define __LINUX_IRQCHIP_ARM_GIC_COMMON_H
 
-#include <linux/types.h>
-#include <linux/ioport.h>
+#include <linux/irqchip/arm-vgic-info.h>
 
 #define GICD_INT_DEF_PRI               0xa0
 #define GICD_INT_DEF_PRI_X4            ((GICD_INT_DEF_PRI << 24) |\
                                        (GICD_INT_DEF_PRI << 8) |\
                                        GICD_INT_DEF_PRI)
 
-enum gic_type {
-       GIC_V2,
-       GIC_V3,
-};
-
-struct gic_kvm_info {
-       /* GIC type */
-       enum gic_type   type;
-       /* Virtual CPU interface */
-       struct resource vcpu;
-       /* Interrupt number */
-       unsigned int    maint_irq;
-       /* Virtual control interface */
-       struct resource vctrl;
-       /* vlpi support */
-       bool            has_v4;
-       /* rvpeid support */
-       bool            has_v4_1;
-};
-
-const struct gic_kvm_info *gic_get_kvm_info(void);
-
 struct irq_domain;
 struct fwnode_handle;
 int gicv2m_init(struct fwnode_handle *parent_handle,
diff --git a/include/linux/irqchip/arm-vgic-info.h b/include/linux/irqchip/arm-vgic-info.h
new file mode 100644 (file)
index 0000000..a75b2c7
--- /dev/null
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * include/linux/irqchip/arm-vgic-info.h
+ *
+ * Copyright (C) 2016 ARM Limited, All Rights Reserved.
+ */
+#ifndef __LINUX_IRQCHIP_ARM_VGIC_INFO_H
+#define __LINUX_IRQCHIP_ARM_VGIC_INFO_H
+
+#include <linux/types.h>
+#include <linux/ioport.h>
+
+enum gic_type {
+       /* Full GICv2 */
+       GIC_V2,
+       /* Full GICv3, optionally with v2 compat */
+       GIC_V3,
+};
+
+struct gic_kvm_info {
+       /* GIC type */
+       enum gic_type   type;
+       /* Virtual CPU interface */
+       struct resource vcpu;
+       /* Interrupt number */
+       unsigned int    maint_irq;
+       /* No interrupt mask, no need to use the above field */
+       bool            no_maint_irq_mask;
+       /* Virtual control interface */
+       struct resource vctrl;
+       /* vlpi support */
+       bool            has_v4;
+       /* rvpeid support */
+       bool            has_v4_1;
+       /* Deactivation impared, subpar stuff */
+       bool            no_hw_deactivation;
+};
+
+#ifdef CONFIG_KVM
+void vgic_set_kvm_info(const struct gic_kvm_info *info);
+#else
+static inline void vgic_set_kvm_info(const struct gic_kvm_info *info) {}
+#endif
+
+#endif
index c0f57b0c64d908b0ee298981031d14d6d3cb0de7..5433c08fcc685856798e833202c74b44330ce479 100644 (file)
@@ -2,6 +2,8 @@
 #ifndef _LINUX_MINMAX_H
 #define _LINUX_MINMAX_H
 
+#include <linux/const.h>
+
 /*
  * min()/max()/clamp() macros must accomplish three things:
  *
 #define __typecheck(x, y) \
        (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1)))
 
-/*
- * This returns a constant expression while determining if an argument is
- * a constant expression, most importantly without evaluating the argument.
- * Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
- */
-#define __is_constexpr(x) \
-       (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
-
 #define __no_side_effects(x, y) \
                (__is_constexpr(x) && __is_constexpr(y))
 
index f8e8d7e9061608cd915c60ce293db7bd40e86ca8..020a8f7fdbdd43e3215d0ad9a8dcb6b9d228f9ea 100644 (file)
@@ -703,6 +703,27 @@ struct mlx5_hv_vhca;
 #define MLX5_LOG_SW_ICM_BLOCK_SIZE(dev) (MLX5_CAP_DEV_MEM(dev, log_sw_icm_alloc_granularity))
 #define MLX5_SW_ICM_BLOCK_SIZE(dev) (1 << MLX5_LOG_SW_ICM_BLOCK_SIZE(dev))
 
+enum {
+       MLX5_PROF_MASK_QP_SIZE          = (u64)1 << 0,
+       MLX5_PROF_MASK_MR_CACHE         = (u64)1 << 1,
+};
+
+enum {
+       MR_CACHE_LAST_STD_ENTRY = 20,
+       MLX5_IMR_MTT_CACHE_ENTRY,
+       MLX5_IMR_KSM_CACHE_ENTRY,
+       MAX_MR_CACHE_ENTRIES
+};
+
+struct mlx5_profile {
+       u64     mask;
+       u8      log_max_qp;
+       struct {
+               int     size;
+               int     limit;
+       } mr_cache[MAX_MR_CACHE_ENTRIES];
+};
+
 struct mlx5_core_dev {
        struct device *device;
        enum mlx5_coredev_type coredev_type;
@@ -731,7 +752,7 @@ struct mlx5_core_dev {
        struct mutex            intf_state_mutex;
        unsigned long           intf_state;
        struct mlx5_priv        priv;
-       struct mlx5_profile     *profile;
+       struct mlx5_profile     profile;
        u32                     issi;
        struct mlx5e_resources  mlx5e_res;
        struct mlx5_dm          *dm;
@@ -1083,18 +1104,6 @@ static inline u8 mlx5_mkey_variant(u32 mkey)
        return mkey & 0xff;
 }
 
-enum {
-       MLX5_PROF_MASK_QP_SIZE          = (u64)1 << 0,
-       MLX5_PROF_MASK_MR_CACHE         = (u64)1 << 1,
-};
-
-enum {
-       MR_CACHE_LAST_STD_ENTRY = 20,
-       MLX5_IMR_MTT_CACHE_ENTRY,
-       MLX5_IMR_KSM_CACHE_ENTRY,
-       MAX_MR_CACHE_ENTRIES
-};
-
 /* Async-atomic event notifier used by mlx5 core to forward FW
  * evetns recived from event queue to mlx5 consumers.
  * Optimise event queue dipatching.
@@ -1148,15 +1157,6 @@ int mlx5_rdma_rn_get_params(struct mlx5_core_dev *mdev,
                            struct ib_device *device,
                            struct rdma_netdev_alloc_params *params);
 
-struct mlx5_profile {
-       u64     mask;
-       u8      log_max_qp;
-       struct {
-               int     size;
-               int     limit;
-       } mr_cache[MAX_MR_CACHE_ENTRIES];
-};
-
 enum {
        MLX5_PCI_DEV_IS_VF              = 1 << 0,
 };
diff --git a/include/linux/mlx5/mpfs.h b/include/linux/mlx5/mpfs.h
new file mode 100644 (file)
index 0000000..bf700c8
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+ * Copyright (c) 2021 Mellanox Technologies Ltd.
+ */
+
+#ifndef _MLX5_MPFS_
+#define _MLX5_MPFS_
+
+struct mlx5_core_dev;
+
+#ifdef CONFIG_MLX5_MPFS
+int  mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac);
+int  mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac);
+#else /* #ifndef CONFIG_MLX5_MPFS */
+static inline int  mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac) { return 0; }
+static inline int  mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac) { return 0; }
+#endif
+
+#endif
index 60d2b26026a2dfd142f29ed5f6e9827b1361a8fe..852743f07e3e639f9ffae0b0b8dc00adda17f0c3 100644 (file)
@@ -496,6 +496,11 @@ struct macsec_ops;
  * @mac_managed_pm: Set true if MAC driver takes of suspending/resuming PHY
  * @state: State of the PHY for management purposes
  * @dev_flags: Device-specific flags used by the PHY driver.
+ *             Bits [15:0] are free to use by the PHY driver to communicate
+ *                         driver specific behavior.
+ *             Bits [23:16] are currently reserved for future use.
+ *             Bits [31:24] are reserved for defining generic
+ *                          PHY driver behavior.
  * @irq: IRQ number of the PHY's interrupt (-1 if none)
  * @phy_timer: The timer for handling the state machine
  * @phylink: Pointer to phylink instance for this PHY
index 3f6a0fcaa10cf47050a79f366a1371613178c8df..7f4278fa21fef7e2de8d832ed46461f1de9aba7d 100644 (file)
@@ -326,6 +326,7 @@ int send_sig_mceerr(int code, void __user *, short, struct task_struct *);
 
 int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper);
 int force_sig_pkuerr(void __user *addr, u32 pkey);
+int force_sig_perf(void __user *addr, u32 type, u64 sig_data);
 
 int force_sig_ptrace_errno_trap(int errno, void __user *addr);
 
index 0dbfda8d99d0e9e4290036a3b9fc9864a8a7254a..201f88e3738b2e641370a62ff18a564d6dbdd070 100644 (file)
@@ -40,6 +40,7 @@ enum siginfo_layout {
        SIL_TIMER,
        SIL_POLL,
        SIL_FAULT,
+       SIL_FAULT_TRAPNO,
        SIL_FAULT_MCEERR,
        SIL_FAULT_BNDERR,
        SIL_FAULT_PKUERR,
index 360a3bc767ca0442dd71f7bbfab7174eb942d4df..74239d65c7fd132143c921d822ed4a39e1ecf52c 100644 (file)
@@ -644,8 +644,8 @@ struct spi_controller {
        int                     *cs_gpios;
        struct gpio_desc        **cs_gpiods;
        bool                    use_gpio_descriptors;
-       u8                      unused_native_cs;
-       u8                      max_native_cs;
+       s8                      unused_native_cs;
+       s8                      max_native_cs;
 
        /* statistics */
        struct spi_statistics   statistics;
index d81fe8b364d004ba60cfcfa2139f4175d6569d82..61b622e334ee5fec2fc065efcb4e9c46002f6cf5 100644 (file)
@@ -368,6 +368,8 @@ struct rpc_xprt *   xprt_alloc(struct net *net, size_t size,
                                unsigned int num_prealloc,
                                unsigned int max_req);
 void                   xprt_free(struct rpc_xprt *);
+void                   xprt_add_backlog(struct rpc_xprt *xprt, struct rpc_task *task);
+bool                   xprt_wake_up_backlog(struct rpc_xprt *xprt, struct rpc_rqst *req);
 
 static inline int
 xprt_enable_swap(struct rpc_xprt *xprt)
index 4441ad667c3f9426200d7f56fee2f9d9693f6fb2..6ff9c58b3e17f31900104375de0fe784c212fc46 100644 (file)
@@ -98,9 +98,9 @@ struct ssam_device_uid {
                     | (((fun) != SSAM_ANY_FUN) ? SSAM_MATCH_FUNCTION : 0),     \
        .domain   = d,                                                          \
        .category = cat,                                                        \
-       .target   = ((tid) != SSAM_ANY_TID) ? (tid) : 0,                        \
-       .instance = ((iid) != SSAM_ANY_IID) ? (iid) : 0,                        \
-       .function = ((fun) != SSAM_ANY_FUN) ? (fun) : 0                         \
+       .target   = __builtin_choose_expr((tid) != SSAM_ANY_TID, (tid), 0),     \
+       .instance = __builtin_choose_expr((iid) != SSAM_ANY_IID, (iid), 0),     \
+       .function = __builtin_choose_expr((fun) != SSAM_ANY_FUN, (fun), 0)
 
 /**
  * SSAM_VDEV() - Initialize a &struct ssam_device_id as virtual device with
index 5224f885a99a129856f486249d9a77390ce87d9c..58c2cd417e89ae469a7f46b0e93ce4b1a17c822a 100644 (file)
@@ -5760,7 +5760,7 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr);
  */
 int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
                                  const u8 *addr, enum nl80211_iftype iftype,
-                                 u8 data_offset);
+                                 u8 data_offset, bool is_amsdu);
 
 /**
  * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
@@ -5772,7 +5772,7 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
 static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                                         enum nl80211_iftype iftype)
 {
-       return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0);
+       return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0, false);
 }
 
 /**
index 51d8eb99764dcbcccdd5eca9323ba199cdc9a9c2..48ef7460ff3043e20a1adc02e8e7c657ca0db0e0 100644 (file)
@@ -157,7 +157,6 @@ enum nf_flow_flags {
        NF_FLOW_HW,
        NF_FLOW_HW_DYING,
        NF_FLOW_HW_DEAD,
-       NF_FLOW_HW_REFRESH,
        NF_FLOW_HW_PENDING,
 };
 
index bd76e8e082c0179b3c27b7393ff678909d62de07..1df0f8074c9d3c3b44c0e31699628b73fd1caf3b 100644 (file)
@@ -298,6 +298,7 @@ int nci_nfcc_loopback(struct nci_dev *ndev, void *data, size_t data_len,
                      struct sk_buff **resp);
 
 struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev);
+void nci_hci_deallocate(struct nci_dev *ndev);
 int nci_hci_send_event(struct nci_dev *ndev, u8 gate, u8 event,
                       const u8 *param, size_t param_len);
 int nci_hci_send_cmd(struct nci_dev *ndev, u8 gate,
index 255e4f4b521f4095f2ab1e60e3b262366b5ff95f..ec7823921bd26ec7e33bfef5b849c347414228fa 100644 (file)
@@ -709,6 +709,17 @@ tc_cls_common_offload_init(struct flow_cls_common_offload *cls_common,
                cls_common->extack = extack;
 }
 
+#if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
+static inline struct tc_skb_ext *tc_skb_ext_alloc(struct sk_buff *skb)
+{
+       struct tc_skb_ext *tc_skb_ext = skb_ext_add(skb, TC_SKB_EXT);
+
+       if (tc_skb_ext)
+               memset(tc_skb_ext, 0, sizeof(*tc_skb_ext));
+       return tc_skb_ext;
+}
+#endif
+
 enum tc_matchall_command {
        TC_CLSMATCHALL_REPLACE,
        TC_CLSMATCHALL_DESTROY,
index f5c1bee0cd6ac94440f4b62fe066a065b8c2d70f..6d7b12cba0158f9a954949b1fc42ee418d4b56a7 100644 (file)
@@ -128,12 +128,7 @@ void __qdisc_run(struct Qdisc *q);
 static inline void qdisc_run(struct Qdisc *q)
 {
        if (qdisc_run_begin(q)) {
-               /* NOLOCK qdisc must check 'state' under the qdisc seqlock
-                * to avoid racing with dev_qdisc_reset()
-                */
-               if (!(q->flags & TCQ_F_NOLOCK) ||
-                   likely(!test_bit(__QDISC_STATE_DEACTIVATED, &q->state)))
-                       __qdisc_run(q);
+               __qdisc_run(q);
                qdisc_run_end(q);
        }
 }
index f7a6e14491fb6b0fe347a213e0295a11b263e0f2..1e625519ae9687608c087ceee6b30aac82513fca 100644 (file)
@@ -36,6 +36,7 @@ struct qdisc_rate_table {
 enum qdisc_state_t {
        __QDISC_STATE_SCHED,
        __QDISC_STATE_DEACTIVATED,
+       __QDISC_STATE_MISSED,
 };
 
 struct qdisc_size_table {
@@ -159,8 +160,33 @@ static inline bool qdisc_is_empty(const struct Qdisc *qdisc)
 static inline bool qdisc_run_begin(struct Qdisc *qdisc)
 {
        if (qdisc->flags & TCQ_F_NOLOCK) {
+               if (spin_trylock(&qdisc->seqlock))
+                       goto nolock_empty;
+
+               /* If the MISSED flag is set, it means other thread has
+                * set the MISSED flag before second spin_trylock(), so
+                * we can return false here to avoid multi cpus doing
+                * the set_bit() and second spin_trylock() concurrently.
+                */
+               if (test_bit(__QDISC_STATE_MISSED, &qdisc->state))
+                       return false;
+
+               /* Set the MISSED flag before the second spin_trylock(),
+                * if the second spin_trylock() return false, it means
+                * other cpu holding the lock will do dequeuing for us
+                * or it will see the MISSED flag set after releasing
+                * lock and reschedule the net_tx_action() to do the
+                * dequeuing.
+                */
+               set_bit(__QDISC_STATE_MISSED, &qdisc->state);
+
+               /* Retry again in case other CPU may not see the new flag
+                * after it releases the lock at the end of qdisc_run_end().
+                */
                if (!spin_trylock(&qdisc->seqlock))
                        return false;
+
+nolock_empty:
                WRITE_ONCE(qdisc->empty, false);
        } else if (qdisc_is_running(qdisc)) {
                return false;
@@ -176,8 +202,15 @@ static inline bool qdisc_run_begin(struct Qdisc *qdisc)
 static inline void qdisc_run_end(struct Qdisc *qdisc)
 {
        write_seqcount_end(&qdisc->running);
-       if (qdisc->flags & TCQ_F_NOLOCK)
+       if (qdisc->flags & TCQ_F_NOLOCK) {
                spin_unlock(&qdisc->seqlock);
+
+               if (unlikely(test_bit(__QDISC_STATE_MISSED,
+                                     &qdisc->state))) {
+                       clear_bit(__QDISC_STATE_MISSED, &qdisc->state);
+                       __netif_schedule(qdisc);
+               }
+       }
 }
 
 static inline bool qdisc_may_bulk(const struct Qdisc *qdisc)
index 42bc5e1a627f49a647a7d553f08aca9daa1f0be1..0e962d8bc73b1ce5a38ca1f64c6489f94ab587e4 100644 (file)
@@ -2231,13 +2231,15 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
        sk_mem_charge(sk, skb->truesize);
 }
 
-static inline void skb_set_owner_sk_safe(struct sk_buff *skb, struct sock *sk)
+static inline __must_check bool skb_set_owner_sk_safe(struct sk_buff *skb, struct sock *sk)
 {
        if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) {
                skb_orphan(skb);
                skb->destructor = sock_efree;
                skb->sk = sk;
+               return true;
        }
+       return false;
 }
 
 void sk_reset_timer(struct sock *sk, struct timer_list *timer,
index 1358a0ceb4d01c4bf32ebcf26f3806ec00d4cadc..0bc29c4516e7614c6b15868756cd01621a2b8306 100644 (file)
@@ -81,7 +81,7 @@ struct snd_compr_stream;
 #define SND_SOC_DAIFMT_CBP_CFP         (1 << 12) /* codec clk provider & frame provider */
 #define SND_SOC_DAIFMT_CBC_CFP         (2 << 12) /* codec clk consumer & frame provider */
 #define SND_SOC_DAIFMT_CBP_CFC         (3 << 12) /* codec clk provider & frame consumer */
-#define SND_SOC_DAIFMT_CBC_CFC         (4 << 12) /* codec clk consumer & frame follower */
+#define SND_SOC_DAIFMT_CBC_CFC         (4 << 12) /* codec clk consumer & frame consumer */
 
 /* previous definitions kept for backwards-compatibility, do not use in new contributions */
 #define SND_SOC_DAIFMT_CBM_CFM         SND_SOC_DAIFMT_CBP_CFP
index 03d6f6d2c1fe8298ec164513a7358a541d101c24..5a3c221f4c9d3837692a390fc2da301afadb04df 100644 (file)
@@ -63,9 +63,6 @@ union __sifields {
        /* SIGILL, SIGFPE, SIGSEGV, SIGBUS, SIGTRAP, SIGEMT */
        struct {
                void __user *_addr; /* faulting insn/memory ref. */
-#ifdef __ARCH_SI_TRAPNO
-               int _trapno;    /* TRAP # which caused the signal */
-#endif
 #ifdef __ia64__
                int _imm;               /* immediate value for "break" */
                unsigned int _flags;    /* see ia64 si_flags */
@@ -75,6 +72,8 @@ union __sifields {
 #define __ADDR_BND_PKEY_PAD  (__alignof__(void *) < sizeof(short) ? \
                              sizeof(short) : __alignof__(void *))
                union {
+                       /* used on alpha and sparc */
+                       int _trapno;    /* TRAP # which caused the signal */
                        /*
                         * used when si_code=BUS_MCEERR_AR or
                         * used when si_code=BUS_MCEERR_AO
@@ -92,7 +91,10 @@ union __sifields {
                                __u32 _pkey;
                        } _addr_pkey;
                        /* used when si_code=TRAP_PERF */
-                       unsigned long _perf;
+                       struct {
+                               unsigned long _data;
+                               __u32 _type;
+                       } _perf;
                };
        } _sigfault;
 
@@ -150,14 +152,13 @@ typedef struct siginfo {
 #define si_int         _sifields._rt._sigval.sival_int
 #define si_ptr         _sifields._rt._sigval.sival_ptr
 #define si_addr                _sifields._sigfault._addr
-#ifdef __ARCH_SI_TRAPNO
 #define si_trapno      _sifields._sigfault._trapno
-#endif
 #define si_addr_lsb    _sifields._sigfault._addr_lsb
 #define si_lower       _sifields._sigfault._addr_bnd._lower
 #define si_upper       _sifields._sigfault._addr_bnd._upper
 #define si_pkey                _sifields._sigfault._addr_pkey._pkey
-#define si_perf                _sifields._sigfault._perf
+#define si_perf_data   _sifields._sigfault._perf._data
+#define si_perf_type   _sifields._sigfault._perf._type
 #define si_band                _sifields._sigpoll._band
 #define si_fd          _sifields._sigpoll._fd
 #define si_call_addr   _sifields._sigsys._call_addr
index 68c9e6d8bbda2881bebdf56d9e2574b2434aced7..d9e4aabcb31abaf7f8cc12b5c00a87fd234bd4c8 100644 (file)
@@ -1111,6 +1111,7 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_PPC_RPT_INVALIDATE 202
 #define KVM_CAP_BINARY_STATS_FD 203
 #define KVM_CAP_EXIT_ON_EMULATION_FAILURE 204
+#define KVM_CAP_ARM_MTE 205
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1456,6 +1457,7 @@ struct kvm_s390_ucas_mapping {
 /* Available with KVM_CAP_PMU_EVENT_FILTER */
 #define KVM_SET_PMU_EVENT_FILTER  _IOW(KVMIO,  0xb2, struct kvm_pmu_event_filter)
 #define KVM_PPC_SVM_OFF                  _IO(KVMIO,  0xb3)
+#define KVM_ARM_MTE_COPY_TAGS    _IOR(KVMIO,  0xb4, struct kvm_arm_copy_mte_tags)
 
 /* ioctl for vm fd */
 #define KVM_CREATE_DEVICE        _IOWR(KVMIO,  0xe0, struct kvm_create_device)
index bf8143505c49d033c697653121ec0a2054810e89..f92880a15645a4177406eca6e153665ea1ce0ea0 100644 (file)
@@ -464,7 +464,7 @@ struct perf_event_attr {
 
        /*
         * User provided data if sigtrap=1, passed back to user via
-        * siginfo_t::si_perf, e.g. to permit user to identify the event.
+        * siginfo_t::si_perf_data, e.g. to permit user to identify the event.
         */
        __u64   sig_data;
 };
index 7e333042c7e3a1e2522f7146c4eb7021fbe7c288..83429a05b698e32fcc9be74827577058a5aec974 100644 (file)
@@ -39,8 +39,6 @@ struct signalfd_siginfo {
        __s32 ssi_syscall;
        __u64 ssi_call_addr;
        __u32 ssi_arch;
-       __u32 __pad3;
-       __u64 ssi_perf;
 
        /*
         * Pad strcture to 128 bytes. Remember to update the
@@ -51,7 +49,7 @@ struct signalfd_siginfo {
         * comes out of a read(2) and we really don't want to have
         * a compat on read(2).
         */
-       __u8 __pad[16];
+       __u8 __pad[28];
 };
 
 
index d3e017b5f0dba52cd767160b34fef7fde7bbf2e6..6d2d34c9f375fb4e3169995d4585f0fec812efb7 100644 (file)
@@ -239,6 +239,39 @@ enum gaudi_engine_id {
        GAUDI_ENGINE_ID_SIZE
 };
 
+/*
+ * ASIC specific PLL index
+ *
+ * Used to retrieve in frequency info of different IPs via
+ * HL_INFO_PLL_FREQUENCY under HL_IOCTL_INFO IOCTL. The enums need to be
+ * used as an index in struct hl_pll_frequency_info
+ */
+
+enum hl_goya_pll_index {
+       HL_GOYA_CPU_PLL = 0,
+       HL_GOYA_IC_PLL,
+       HL_GOYA_MC_PLL,
+       HL_GOYA_MME_PLL,
+       HL_GOYA_PCI_PLL,
+       HL_GOYA_EMMC_PLL,
+       HL_GOYA_TPC_PLL,
+       HL_GOYA_PLL_MAX
+};
+
+enum hl_gaudi_pll_index {
+       HL_GAUDI_CPU_PLL = 0,
+       HL_GAUDI_PCI_PLL,
+       HL_GAUDI_SRAM_PLL,
+       HL_GAUDI_HBM_PLL,
+       HL_GAUDI_NIC_PLL,
+       HL_GAUDI_DMA_PLL,
+       HL_GAUDI_MESH_PLL,
+       HL_GAUDI_MME_PLL,
+       HL_GAUDI_TPC_PLL,
+       HL_GAUDI_IF_PLL,
+       HL_GAUDI_PLL_MAX
+};
+
 enum hl_device_status {
        HL_DEVICE_STATUS_OPERATIONAL,
        HL_DEVICE_STATUS_IN_RESET,
index 1ea12c64e4c9f3662bc8b76bd8760295ec735dc8..a61c92066c2e41aaadaed9df78c8a9be35dace32 100644 (file)
@@ -442,6 +442,7 @@ config AUDITSYSCALL
 
 source "kernel/irq/Kconfig"
 source "kernel/time/Kconfig"
+source "kernel/bpf/Kconfig"
 source "kernel/Kconfig.preempt"
 
 menu "CPU/Task time and stats accounting"
@@ -1713,46 +1714,6 @@ config KALLSYMS_BASE_RELATIVE
 
 # syscall, maps, verifier
 
-config BPF_LSM
-       bool "LSM Instrumentation with BPF"
-       depends on BPF_EVENTS
-       depends on BPF_SYSCALL
-       depends on SECURITY
-       depends on BPF_JIT
-       help
-         Enables instrumentation of the security hooks with eBPF programs for
-         implementing dynamic MAC and Audit Policies.
-
-         If you are unsure how to answer this question, answer N.
-
-config BPF_SYSCALL
-       bool "Enable bpf() system call"
-       select BPF
-       select IRQ_WORK
-       select TASKS_TRACE_RCU
-       select BINARY_PRINTF
-       select NET_SOCK_MSG if INET
-       default n
-       help
-         Enable the bpf() system call that allows to manipulate eBPF
-         programs and maps via file descriptors.
-
-config ARCH_WANT_DEFAULT_BPF_JIT
-       bool
-
-config BPF_JIT_ALWAYS_ON
-       bool "Permanently enable BPF JIT and remove BPF interpreter"
-       depends on BPF_SYSCALL && HAVE_EBPF_JIT && BPF_JIT
-       help
-         Enables BPF JIT and removes BPF interpreter to avoid
-         speculative execution of BPF instructions by the interpreter
-
-config BPF_JIT_DEFAULT_ON
-       def_bool ARCH_WANT_DEFAULT_BPF_JIT || BPF_JIT_ALWAYS_ON
-       depends on HAVE_EBPF_JIT && BPF_JIT
-
-source "kernel/bpf/preload/Kconfig"
-
 config USERFAULTFD
        bool "Enable userfaultfd() system call"
        depends on MMU
index 8031464ed4ae24e2611876a520d8232d0c0eacd8..4e4e61111500ca2d0a66d9013f7a57e3f3d5c1aa 100644 (file)
@@ -1004,12 +1004,14 @@ static inline void __pipelined_op(struct wake_q_head *wake_q,
                                  struct mqueue_inode_info *info,
                                  struct ext_wait_queue *this)
 {
+       struct task_struct *task;
+
        list_del(&this->list);
-       get_task_struct(this->task);
+       task = get_task_struct(this->task);
 
        /* see MQ_BARRIER for purpose/pairing */
        smp_store_release(&this->state, STATE_READY);
-       wake_q_add_safe(wake_q, this->task);
+       wake_q_add_safe(wake_q, task);
 }
 
 /* pipelined_send() - send a message directly to the task waiting in
index acd1bc7af55a26b7d680348ef576e0e5ed51a83d..6e6c8e0c9380e346efed7dbe7b88aad215560201 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -251,11 +251,13 @@ static void expunge_all(struct msg_queue *msq, int res,
        struct msg_receiver *msr, *t;
 
        list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) {
-               get_task_struct(msr->r_tsk);
+               struct task_struct *r_tsk;
+
+               r_tsk = get_task_struct(msr->r_tsk);
 
                /* see MSG_BARRIER for purpose/pairing */
                smp_store_release(&msr->r_msg, ERR_PTR(res));
-               wake_q_add_safe(wake_q, msr->r_tsk);
+               wake_q_add_safe(wake_q, r_tsk);
        }
 }
 
index e0ec239680cbd40f79895c260867438f8863e4d7..bf534c74293e1acf4bfdc9fdc12da007486940af 100644 (file)
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -784,12 +784,14 @@ would_block:
 static inline void wake_up_sem_queue_prepare(struct sem_queue *q, int error,
                                             struct wake_q_head *wake_q)
 {
-       get_task_struct(q->sleeper);
+       struct task_struct *sleeper;
+
+       sleeper = get_task_struct(q->sleeper);
 
        /* see SEM_BARRIER_2 for purpose/pairing */
        smp_store_release(&q->status, error);
 
-       wake_q_add_safe(wake_q, q->sleeper);
+       wake_q_add_safe(wake_q, sleeper);
 }
 
 static void unlink_queue(struct sem_array *sma, struct sem_queue *q)
diff --git a/kernel/bpf/Kconfig b/kernel/bpf/Kconfig
new file mode 100644 (file)
index 0000000..bd04f4a
--- /dev/null
@@ -0,0 +1,89 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+# BPF interpreter that, for example, classic socket filters depend on.
+config BPF
+       bool
+
+# Used by archs to tell that they support BPF JIT compiler plus which
+# flavour. Only one of the two can be selected for a specific arch since
+# eBPF JIT supersedes the cBPF JIT.
+
+# Classic BPF JIT (cBPF)
+config HAVE_CBPF_JIT
+       bool
+
+# Extended BPF JIT (eBPF)
+config HAVE_EBPF_JIT
+       bool
+
+# Used by archs to tell that they want the BPF JIT compiler enabled by
+# default for kernels that were compiled with BPF JIT support.
+config ARCH_WANT_DEFAULT_BPF_JIT
+       bool
+
+menu "BPF subsystem"
+
+config BPF_SYSCALL
+       bool "Enable bpf() system call"
+       select BPF
+       select IRQ_WORK
+       select TASKS_TRACE_RCU
+       select BINARY_PRINTF
+       select NET_SOCK_MSG if INET
+       default n
+       help
+         Enable the bpf() system call that allows to manipulate BPF programs
+         and maps via file descriptors.
+
+config BPF_JIT
+       bool "Enable BPF Just In Time compiler"
+       depends on BPF
+       depends on HAVE_CBPF_JIT || HAVE_EBPF_JIT
+       depends on MODULES
+       help
+         BPF programs are normally handled by a BPF interpreter. This option
+         allows the kernel to generate native code when a program is loaded
+         into the kernel. This will significantly speed-up processing of BPF
+         programs.
+
+         Note, an admin should enable this feature changing:
+         /proc/sys/net/core/bpf_jit_enable
+         /proc/sys/net/core/bpf_jit_harden   (optional)
+         /proc/sys/net/core/bpf_jit_kallsyms (optional)
+
+config BPF_JIT_ALWAYS_ON
+       bool "Permanently enable BPF JIT and remove BPF interpreter"
+       depends on BPF_SYSCALL && HAVE_EBPF_JIT && BPF_JIT
+       help
+         Enables BPF JIT and removes BPF interpreter to avoid speculative
+         execution of BPF instructions by the interpreter.
+
+config BPF_JIT_DEFAULT_ON
+       def_bool ARCH_WANT_DEFAULT_BPF_JIT || BPF_JIT_ALWAYS_ON
+       depends on HAVE_EBPF_JIT && BPF_JIT
+
+config BPF_UNPRIV_DEFAULT_OFF
+       bool "Disable unprivileged BPF by default"
+       depends on BPF_SYSCALL
+       help
+         Disables unprivileged BPF by default by setting the corresponding
+         /proc/sys/kernel/unprivileged_bpf_disabled knob to 2. An admin can
+         still reenable it by setting it to 0 later on, or permanently
+         disable it by setting it to 1 (from which no other transition to
+         0 is possible anymore).
+
+source "kernel/bpf/preload/Kconfig"
+
+config BPF_LSM
+       bool "Enable BPF LSM Instrumentation"
+       depends on BPF_EVENTS
+       depends on BPF_SYSCALL
+       depends on SECURITY
+       depends on BPF_JIT
+       help
+         Enables instrumentation of the security hooks with BPF programs for
+         implementing dynamic MAC and Audit Policies.
+
+         If you are unsure how to answer this question, answer N.
+
+endmenu # "BPF subsystem"
index 5efb2b24012c90af20cf955a6abc951557c35d2f..da471bf01b977fbc5952930c866ed5df8bb05543 100644 (file)
@@ -107,10 +107,12 @@ bpf_lsm_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
                return &bpf_inode_storage_get_proto;
        case BPF_FUNC_inode_storage_delete:
                return &bpf_inode_storage_delete_proto;
+#ifdef CONFIG_NET
        case BPF_FUNC_sk_storage_get:
                return &bpf_sk_storage_get_proto;
        case BPF_FUNC_sk_storage_delete:
                return &bpf_sk_storage_delete_proto;
+#endif /* CONFIG_NET */
        case BPF_FUNC_spin_lock:
                return &bpf_spin_lock_proto;
        case BPF_FUNC_spin_unlock:
index 0600ed325fa0b72160cf5fb3c15890d993235cb3..f982a9f0dbc46135b1ae0feef6eb233daeaf92d9 100644 (file)
@@ -5206,6 +5206,12 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
        m->ret_size = ret;
 
        for (i = 0; i < nargs; i++) {
+               if (i == nargs - 1 && args[i].type == 0) {
+                       bpf_log(log,
+                               "The function %s with variable args is unsupported.\n",
+                               tname);
+                       return -EINVAL;
+               }
                ret = __get_type_size(btf, args[i].type, &t);
                if (ret < 0) {
                        bpf_log(log,
@@ -5213,6 +5219,12 @@ int btf_distill_func_proto(struct bpf_verifier_log *log,
                                tname, i, btf_kind_str[BTF_INFO_KIND(t->info)]);
                        return -EINVAL;
                }
+               if (ret == 0) {
+                       bpf_log(log,
+                               "The function %s has malformed void argument.\n",
+                               tname);
+                       return -EINVAL;
+               }
                m->arg_size[i] = ret;
        }
        m->nr_args = nargs;
index 544773970dbc6e7eb8dcd494371c30341124c416..73443498d88fc905be355987e76ffb10af482af8 100644 (file)
@@ -692,38 +692,41 @@ static int bpf_trace_copy_string(char *buf, void *unsafe_ptr, char fmt_ptype,
        return -EINVAL;
 }
 
-/* Per-cpu temp buffers which can be used by printf-like helpers for %s or %p
+/* Per-cpu temp buffers used by printf-like helpers to store the bprintf binary
+ * arguments representation.
  */
-#define MAX_PRINTF_BUF_LEN     512
+#define MAX_BPRINTF_BUF_LEN    512
 
-struct bpf_printf_buf {
-       char tmp_buf[MAX_PRINTF_BUF_LEN];
+/* Support executing three nested bprintf helper calls on a given CPU */
+#define MAX_BPRINTF_NEST_LEVEL 3
+struct bpf_bprintf_buffers {
+       char tmp_bufs[MAX_BPRINTF_NEST_LEVEL][MAX_BPRINTF_BUF_LEN];
 };
-static DEFINE_PER_CPU(struct bpf_printf_buf, bpf_printf_buf);
-static DEFINE_PER_CPU(int, bpf_printf_buf_used);
+static DEFINE_PER_CPU(struct bpf_bprintf_buffers, bpf_bprintf_bufs);
+static DEFINE_PER_CPU(int, bpf_bprintf_nest_level);
 
 static int try_get_fmt_tmp_buf(char **tmp_buf)
 {
-       struct bpf_printf_buf *bufs;
-       int used;
+       struct bpf_bprintf_buffers *bufs;
+       int nest_level;
 
        preempt_disable();
-       used = this_cpu_inc_return(bpf_printf_buf_used);
-       if (WARN_ON_ONCE(used > 1)) {
-               this_cpu_dec(bpf_printf_buf_used);
+       nest_level = this_cpu_inc_return(bpf_bprintf_nest_level);
+       if (WARN_ON_ONCE(nest_level > MAX_BPRINTF_NEST_LEVEL)) {
+               this_cpu_dec(bpf_bprintf_nest_level);
                preempt_enable();
                return -EBUSY;
        }
-       bufs = this_cpu_ptr(&bpf_printf_buf);
-       *tmp_buf = bufs->tmp_buf;
+       bufs = this_cpu_ptr(&bpf_bprintf_bufs);
+       *tmp_buf = bufs->tmp_bufs[nest_level - 1];
 
        return 0;
 }
 
 void bpf_bprintf_cleanup(void)
 {
-       if (this_cpu_read(bpf_printf_buf_used)) {
-               this_cpu_dec(bpf_printf_buf_used);
+       if (this_cpu_read(bpf_bprintf_nest_level)) {
+               this_cpu_dec(bpf_bprintf_nest_level);
                preempt_enable();
        }
 }
@@ -760,7 +763,7 @@ int bpf_bprintf_prepare(char *fmt, u32 fmt_size, const u64 *raw_args,
                if (num_args && try_get_fmt_tmp_buf(&tmp_buf))
                        return -EBUSY;
 
-               tmp_buf_end = tmp_buf + MAX_PRINTF_BUF_LEN;
+               tmp_buf_end = tmp_buf + MAX_BPRINTF_BUF_LEN;
                *bin_args = (u32 *)tmp_buf;
        }
 
index f25b719ac786811c8d1f06b849e42422ccfba70e..84b3b35fc0d05067e9bd3b53d2711404a8fe4eb1 100644 (file)
@@ -221,25 +221,20 @@ static int ringbuf_map_get_next_key(struct bpf_map *map, void *key,
        return -ENOTSUPP;
 }
 
-static size_t bpf_ringbuf_mmap_page_cnt(const struct bpf_ringbuf *rb)
-{
-       size_t data_pages = (rb->mask + 1) >> PAGE_SHIFT;
-
-       /* consumer page + producer page + 2 x data pages */
-       return RINGBUF_POS_PAGES + 2 * data_pages;
-}
-
 static int ringbuf_map_mmap(struct bpf_map *map, struct vm_area_struct *vma)
 {
        struct bpf_ringbuf_map *rb_map;
-       size_t mmap_sz;
 
        rb_map = container_of(map, struct bpf_ringbuf_map, map);
-       mmap_sz = bpf_ringbuf_mmap_page_cnt(rb_map->rb) << PAGE_SHIFT;
-
-       if (vma->vm_pgoff * PAGE_SIZE + (vma->vm_end - vma->vm_start) > mmap_sz)
-               return -EINVAL;
 
+       if (vma->vm_flags & VM_WRITE) {
+               /* allow writable mapping for the consumer_pos only */
+               if (vma->vm_pgoff != 0 || vma->vm_end - vma->vm_start != PAGE_SIZE)
+                       return -EPERM;
+       } else {
+               vma->vm_flags &= ~VM_MAYWRITE;
+       }
+       /* remap_vmalloc_range() checks size and offset constraints */
        return remap_vmalloc_range(vma, rb_map->rb,
                                   vma->vm_pgoff + RINGBUF_PGOFF);
 }
@@ -315,6 +310,9 @@ static void *__bpf_ringbuf_reserve(struct bpf_ringbuf *rb, u64 size)
                return NULL;
 
        len = round_up(size + BPF_RINGBUF_HDR_SZ, 8);
+       if (len > rb->mask + 1)
+               return NULL;
+
        cons_pos = smp_load_acquire(&rb->consumer_pos);
 
        if (in_nmi()) {
index 941ca06d9dfa1714439f6d13ddfbc1ea607b4d2a..ea04b0deb5ce4467c5ef94b3928b8e5da7c640b0 100644 (file)
@@ -50,7 +50,8 @@ static DEFINE_SPINLOCK(map_idr_lock);
 static DEFINE_IDR(link_idr);
 static DEFINE_SPINLOCK(link_idr_lock);
 
-int sysctl_unprivileged_bpf_disabled __read_mostly;
+int sysctl_unprivileged_bpf_disabled __read_mostly =
+       IS_BUILTIN(CONFIG_BPF_UNPRIV_DEFAULT_OFF) ? 2 : 0;
 
 static const struct bpf_map_ops * const bpf_map_types[] = {
 #define BPF_PROG_TYPE(_id, _name, prog_ctx_type, kern_ctx_type)
index 757476c91c98414e83e926a9b14fe874bad284a7..94ba5163d4c540b8a5f19b92e60835831432e13a 100644 (file)
@@ -6409,18 +6409,10 @@ enum {
 };
 
 static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
-                             const struct bpf_reg_state *off_reg,
-                             u32 *alu_limit, u8 opcode)
+                             u32 *alu_limit, bool mask_to_left)
 {
-       bool off_is_neg = off_reg->smin_value < 0;
-       bool mask_to_left = (opcode == BPF_ADD &&  off_is_neg) ||
-                           (opcode == BPF_SUB && !off_is_neg);
        u32 max = 0, ptr_limit = 0;
 
-       if (!tnum_is_const(off_reg->var_off) &&
-           (off_reg->smin_value < 0) != (off_reg->smax_value < 0))
-               return REASON_BOUNDS;
-
        switch (ptr_reg->type) {
        case PTR_TO_STACK:
                /* Offset 0 is out-of-bounds, but acceptable start for the
@@ -6486,15 +6478,20 @@ static bool sanitize_needed(u8 opcode)
        return opcode == BPF_ADD || opcode == BPF_SUB;
 }
 
+struct bpf_sanitize_info {
+       struct bpf_insn_aux_data aux;
+       bool mask_to_left;
+};
+
 static int sanitize_ptr_alu(struct bpf_verifier_env *env,
                            struct bpf_insn *insn,
                            const struct bpf_reg_state *ptr_reg,
                            const struct bpf_reg_state *off_reg,
                            struct bpf_reg_state *dst_reg,
-                           struct bpf_insn_aux_data *tmp_aux,
+                           struct bpf_sanitize_info *info,
                            const bool commit_window)
 {
-       struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : tmp_aux;
+       struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : &info->aux;
        struct bpf_verifier_state *vstate = env->cur_state;
        bool off_is_imm = tnum_is_const(off_reg->var_off);
        bool off_is_neg = off_reg->smin_value < 0;
@@ -6515,7 +6512,16 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
        if (vstate->speculative)
                goto do_sim;
 
-       err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode);
+       if (!commit_window) {
+               if (!tnum_is_const(off_reg->var_off) &&
+                   (off_reg->smin_value < 0) != (off_reg->smax_value < 0))
+                       return REASON_BOUNDS;
+
+               info->mask_to_left = (opcode == BPF_ADD &&  off_is_neg) ||
+                                    (opcode == BPF_SUB && !off_is_neg);
+       }
+
+       err = retrieve_ptr_limit(ptr_reg, &alu_limit, info->mask_to_left);
        if (err < 0)
                return err;
 
@@ -6523,8 +6529,8 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
                /* In commit phase we narrow the masking window based on
                 * the observed pointer move after the simulated operation.
                 */
-               alu_state = tmp_aux->alu_state;
-               alu_limit = abs(tmp_aux->alu_limit - alu_limit);
+               alu_state = info->aux.alu_state;
+               alu_limit = abs(info->aux.alu_limit - alu_limit);
        } else {
                alu_state  = off_is_neg ? BPF_ALU_NEG_VALUE : 0;
                alu_state |= off_is_imm ? BPF_ALU_IMMEDIATE : 0;
@@ -6539,8 +6545,12 @@ do_sim:
        /* If we're in commit phase, we're done here given we already
         * pushed the truncated dst_reg into the speculative verification
         * stack.
+        *
+        * Also, when register is a known constant, we rewrite register-based
+        * operation to immediate-based, and thus do not need masking (and as
+        * a consequence, do not need to simulate the zero-truncation either).
         */
-       if (commit_window)
+       if (commit_window || off_is_imm)
                return 0;
 
        /* Simulate and find potential out-of-bounds access under
@@ -6685,7 +6695,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
            smin_ptr = ptr_reg->smin_value, smax_ptr = ptr_reg->smax_value;
        u64 umin_val = off_reg->umin_value, umax_val = off_reg->umax_value,
            umin_ptr = ptr_reg->umin_value, umax_ptr = ptr_reg->umax_value;
-       struct bpf_insn_aux_data tmp_aux = {};
+       struct bpf_sanitize_info info = {};
        u8 opcode = BPF_OP(insn->code);
        u32 dst = insn->dst_reg;
        int ret;
@@ -6754,7 +6764,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
 
        if (sanitize_needed(opcode)) {
                ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg,
-                                      &tmp_aux, false);
+                                      &info, false);
                if (ret < 0)
                        return sanitize_err(env, insn, ret, off_reg, dst_reg);
        }
@@ -6895,7 +6905,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
                return -EACCES;
        if (sanitize_needed(opcode)) {
                ret = sanitize_ptr_alu(env, insn, dst_reg, off_reg, dst_reg,
-                                      &tmp_aux, true);
+                                      &info, true);
                if (ret < 0)
                        return sanitize_err(env, insn, ret, off_reg, dst_reg);
        }
@@ -7084,11 +7094,10 @@ static void scalar32_min_max_and(struct bpf_reg_state *dst_reg,
        s32 smin_val = src_reg->s32_min_value;
        u32 umax_val = src_reg->u32_max_value;
 
-       /* Assuming scalar64_min_max_and will be called so its safe
-        * to skip updating register for known 32-bit case.
-        */
-       if (src_known && dst_known)
+       if (src_known && dst_known) {
+               __mark_reg32_known(dst_reg, var32_off.value);
                return;
+       }
 
        /* We get our minimum from the var_off, since that's inherently
         * bitwise.  Our maximum is the minimum of the operands' maxima.
@@ -7108,7 +7117,6 @@ static void scalar32_min_max_and(struct bpf_reg_state *dst_reg,
                dst_reg->s32_min_value = dst_reg->u32_min_value;
                dst_reg->s32_max_value = dst_reg->u32_max_value;
        }
-
 }
 
 static void scalar_min_max_and(struct bpf_reg_state *dst_reg,
@@ -7155,11 +7163,10 @@ static void scalar32_min_max_or(struct bpf_reg_state *dst_reg,
        s32 smin_val = src_reg->s32_min_value;
        u32 umin_val = src_reg->u32_min_value;
 
-       /* Assuming scalar64_min_max_or will be called so it is safe
-        * to skip updating register for known case.
-        */
-       if (src_known && dst_known)
+       if (src_known && dst_known) {
+               __mark_reg32_known(dst_reg, var32_off.value);
                return;
+       }
 
        /* We get our maximum from the var_off, and our minimum is the
         * maximum of the operands' minima
@@ -7224,11 +7231,10 @@ static void scalar32_min_max_xor(struct bpf_reg_state *dst_reg,
        struct tnum var32_off = tnum_subreg(dst_reg->var_off);
        s32 smin_val = src_reg->s32_min_value;
 
-       /* Assuming scalar64_min_max_xor will be called so it is safe
-        * to skip updating register for known case.
-        */
-       if (src_known && dst_known)
+       if (src_known && dst_known) {
+               __mark_reg32_known(dst_reg, var32_off.value);
                return;
+       }
 
        /* We get both minimum and maximum from the var32_off. */
        dst_reg->u32_min_value = var32_off.value;
@@ -13200,6 +13206,17 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
        return 0;
 }
 
+BTF_SET_START(btf_id_deny)
+BTF_ID_UNUSED
+#ifdef CONFIG_SMP
+BTF_ID(func, migrate_disable)
+BTF_ID(func, migrate_enable)
+#endif
+#if !defined CONFIG_PREEMPT_RCU && !defined CONFIG_TINY_RCU
+BTF_ID(func, rcu_read_unlock_strict)
+#endif
+BTF_SET_END(btf_id_deny)
+
 static int check_attach_btf_id(struct bpf_verifier_env *env)
 {
        struct bpf_prog *prog = env->prog;
@@ -13259,6 +13276,9 @@ static int check_attach_btf_id(struct bpf_verifier_env *env)
                ret = bpf_lsm_verify_prog(&env->log, prog);
                if (ret < 0)
                        return ret;
+       } else if (prog->type == BPF_PROG_TYPE_TRACING &&
+                  btf_id_set_contains(&btf_id_deny, btf_id)) {
+               return -EINVAL;
        }
 
        key = bpf_trampoline_compute_key(tgt_prog, prog->aux->attach_btf, btf_id);
@@ -13358,12 +13378,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
        if (is_priv)
                env->test_state_freq = attr->prog_flags & BPF_F_TEST_STATE_FREQ;
 
-       if (bpf_prog_is_dev_bound(env->prog->aux)) {
-               ret = bpf_prog_offload_verifier_prep(env->prog);
-               if (ret)
-                       goto skip_full_check;
-       }
-
        env->explored_states = kvcalloc(state_htab_size(env),
                                       sizeof(struct bpf_verifier_state_list *),
                                       GFP_USER);
@@ -13391,6 +13405,12 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr,
        if (ret < 0)
                goto skip_full_check;
 
+       if (bpf_prog_is_dev_bound(env->prog->aux)) {
+               ret = bpf_prog_offload_verifier_prep(env->prog);
+               if (ret)
+                       goto skip_full_check;
+       }
+
        ret = check_cfg(env);
        if (ret < 0)
                goto skip_full_check;
index 391aa570369bba0d4726d6822eab5da2c0b5dd11..8190b6bfc9784906b81392520679510bdadc8de5 100644 (file)
@@ -1001,7 +1001,7 @@ static int check_cgroupfs_options(struct fs_context *fc)
        ctx->subsys_mask &= enabled;
 
        /*
-        * In absense of 'none', 'name=' or subsystem name options,
+        * In absence of 'none', 'name=' and subsystem name options,
         * let's default to 'all'.
         */
        if (!ctx->subsys_mask && !ctx->none && !ctx->name)
index e049edd66776096a0654c71c7f3c74217a9b3508..21ecc6ee6a6d3d3d97d551c830cf771c92cd782e 100644 (file)
@@ -468,7 +468,7 @@ static struct cgroup_subsys_state *cgroup_css(struct cgroup *cgrp,
  * @cgrp: the cgroup of interest
  * @ss: the subsystem of interest
  *
- * Find and get @cgrp's css assocaited with @ss.  If the css doesn't exist
+ * Find and get @cgrp's css associated with @ss.  If the css doesn't exist
  * or is offline, %NULL is returned.
  */
 static struct cgroup_subsys_state *cgroup_tryget_css(struct cgroup *cgrp,
@@ -1633,7 +1633,7 @@ static void cgroup_rm_file(struct cgroup *cgrp, const struct cftype *cft)
 
 /**
  * css_clear_dir - remove subsys files in a cgroup directory
- * @css: taget css
+ * @css: target css
  */
 static void css_clear_dir(struct cgroup_subsys_state *css)
 {
@@ -5350,7 +5350,7 @@ out_unlock:
 /*
  * This is called when the refcnt of a css is confirmed to be killed.
  * css_tryget_online() is now guaranteed to fail.  Tell the subsystem to
- * initate destruction and put the css ref from kill_css().
+ * initiate destruction and put the css ref from kill_css().
  */
 static void css_killed_work_fn(struct work_struct *work)
 {
@@ -5634,8 +5634,6 @@ int __init cgroup_init_early(void)
        return 0;
 }
 
-static u16 cgroup_disable_mask __initdata;
-
 /**
  * cgroup_init - cgroup initialization
  *
@@ -5694,12 +5692,8 @@ int __init cgroup_init(void)
                 * disabled flag and cftype registration needs kmalloc,
                 * both of which aren't available during early_init.
                 */
-               if (cgroup_disable_mask & (1 << ssid)) {
-                       static_branch_disable(cgroup_subsys_enabled_key[ssid]);
-                       printk(KERN_INFO "Disabling %s control group subsystem\n",
-                              ss->name);
+               if (!cgroup_ssid_enabled(ssid))
                        continue;
-               }
 
                if (cgroup1_ssid_disabled(ssid))
                        printk(KERN_INFO "Disabling %s control group subsystem in v1 mounts\n",
@@ -6058,7 +6052,7 @@ out_revert:
  * @kargs: the arguments passed to create the child process
  *
  * This calls the cancel_fork() callbacks if a fork failed *after*
- * cgroup_can_fork() succeded and cleans up references we took to
+ * cgroup_can_fork() succeeded and cleans up references we took to
  * prepare a new css_set for the child process in cgroup_can_fork().
  */
 void cgroup_cancel_fork(struct task_struct *child,
@@ -6214,7 +6208,10 @@ static int __init cgroup_disable(char *str)
                        if (strcmp(token, ss->name) &&
                            strcmp(token, ss->legacy_name))
                                continue;
-                       cgroup_disable_mask |= 1 << i;
+
+                       static_branch_disable(cgroup_subsys_enabled_key[i]);
+                       pr_info("Disabling %s control group subsystem\n",
+                               ss->name);
                }
        }
        return 1;
index a945504c0ae7f038ec76ab34f87b5a6e6874191f..adb5190c44296b854e8bcb28d29da990031d32c5 100644 (file)
@@ -3376,7 +3376,7 @@ nodemask_t cpuset_mems_allowed(struct task_struct *tsk)
 }
 
 /**
- * cpuset_nodemask_valid_mems_allowed - check nodemask vs. curremt mems_allowed
+ * cpuset_nodemask_valid_mems_allowed - check nodemask vs. current mems_allowed
  * @nodemask: the nodemask to be checked
  *
  * Are any of the nodes in the nodemask allowed in current->mems_allowed?
index ae042c347c640adc09191dfd5db18ce329edce70..3135406608c75db085e7d7bfcfb2ea1109156f55 100644 (file)
@@ -244,7 +244,7 @@ EXPORT_SYMBOL(rdmacg_uncharge);
  * This function follows charging resource in hierarchical way.
  * It will fail if the charge would cause the new value to exceed the
  * hierarchical limit.
- * Returns 0 if the charge succeded, otherwise -EAGAIN, -ENOMEM or -EINVAL.
+ * Returns 0 if the charge succeeded, otherwise -EAGAIN, -ENOMEM or -EINVAL.
  * Returns pointer to rdmacg for this resource when charging is successful.
  *
  * Charger needs to account resources on two criteria.
index 3a3fd2993a6500d79b8c206656222b15296f9a28..cee265cb535cc8178149319a0339d11454c28614 100644 (file)
@@ -75,7 +75,7 @@ void cgroup_rstat_updated(struct cgroup *cgrp, int cpu)
  * @root: root of the tree to traversal
  * @cpu: target cpu
  *
- * Walks the udpated rstat_cpu tree on @cpu from @root.  %NULL @pos starts
+ * Walks the updated rstat_cpu tree on @cpu from @root.  %NULL @pos starts
  * the traversal and %NULL return indicates the end.  During traversal,
  * each returned cgroup is unlinked from the tree.  Must be called with the
  * matching cgroup_rstat_cpu_lock held.
index 2e947a485898344772980a740016dc071fbb030d..6fee4a7e88d7d1146fe75a564007868c3ffedacf 100644 (file)
@@ -6389,8 +6389,6 @@ void perf_event_wakeup(struct perf_event *event)
 
 static void perf_sigtrap(struct perf_event *event)
 {
-       struct kernel_siginfo info;
-
        /*
         * We'd expect this to only occur if the irq_work is delayed and either
         * ctx->task or current has changed in the meantime. This can be the
@@ -6405,13 +6403,8 @@ static void perf_sigtrap(struct perf_event *event)
        if (current->flags & PF_EXITING)
                return;
 
-       clear_siginfo(&info);
-       info.si_signo = SIGTRAP;
-       info.si_code = TRAP_PERF;
-       info.si_errno = event->attr.type;
-       info.si_perf = event->attr.sig_data;
-       info.si_addr = (void __user *)event->pending_addr;
-       force_sig_info(&info);
+       force_sig_perf((void __user *)event->pending_addr,
+                      event->attr.type, event->attr.sig_data);
 }
 
 static void perf_pending_event_disable(struct perf_event *event)
index c1dd02f3be8b8c5e22c7bb7de3588d9f32e6096a..e65de172ccf7cf81734db28d193e0ab4154bfb58 100644 (file)
@@ -266,9 +266,10 @@ static const struct file_operations debugfs_ops =
        .release = single_release
 };
 
-static void __init kcsan_debugfs_init(void)
+static int __init kcsan_debugfs_init(void)
 {
        debugfs_create_file("kcsan", 0644, NULL, NULL, &debugfs_ops);
+       return 0;
 }
 
 late_initcall(kcsan_debugfs_init);
index 48d736aa03b24bf377ece9fbe06199eb27adab44..7641bd4072390de193fdb28489a3dad76c132586 100644 (file)
@@ -5736,7 +5736,7 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip)
 {
        unsigned long flags;
 
-       trace_lock_acquired(lock, ip);
+       trace_lock_contended(lock, ip);
 
        if (unlikely(!lock_stat || !lockdep_enabled()))
                return;
@@ -5754,7 +5754,7 @@ void lock_acquired(struct lockdep_map *lock, unsigned long ip)
 {
        unsigned long flags;
 
-       trace_lock_contended(lock, ip);
+       trace_lock_acquired(lock, ip);
 
        if (unlikely(!lock_stat || !lockdep_enabled()))
                return;
index a7276aaf2abc0b75ee5cf15738b5a2d7e0e46f5c..db9301591e3fcca7bfba67c11942a07ae2cf3de6 100644 (file)
@@ -57,7 +57,7 @@ void debug_mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
        task->blocked_on = waiter;
 }
 
-void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
                         struct task_struct *task)
 {
        DEBUG_LOCKS_WARN_ON(list_empty(&waiter->list));
@@ -65,7 +65,7 @@ void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
        DEBUG_LOCKS_WARN_ON(task->blocked_on != waiter);
        task->blocked_on = NULL;
 
-       list_del_init(&waiter->list);
+       INIT_LIST_HEAD(&waiter->list);
        waiter->task = NULL;
 }
 
index 1edd3f45a4ecbad7979f26944a9173b3de028959..53e631e1d76da7858839a9aa92d47bff9603c9c2 100644 (file)
@@ -22,7 +22,7 @@ extern void debug_mutex_free_waiter(struct mutex_waiter *waiter);
 extern void debug_mutex_add_waiter(struct mutex *lock,
                                   struct mutex_waiter *waiter,
                                   struct task_struct *task);
-extern void mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
+extern void debug_mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter,
                                struct task_struct *task);
 extern void debug_mutex_unlock(struct mutex *lock);
 extern void debug_mutex_init(struct mutex *lock, const char *name,
index cb6b112ce1550d9bcf17b53eb770279f1c040a5d..013e1b08a1bfb3438ec7424f26321dfd007e8742 100644 (file)
@@ -194,7 +194,7 @@ static inline bool __mutex_waiter_is_first(struct mutex *lock, struct mutex_wait
  * Add @waiter to a given location in the lock wait_list and set the
  * FLAG_WAITERS flag if it's the first waiter.
  */
-static void __sched
+static void
 __mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
                   struct list_head *list)
 {
@@ -205,6 +205,16 @@ __mutex_add_waiter(struct mutex *lock, struct mutex_waiter *waiter,
                __mutex_set_flag(lock, MUTEX_FLAG_WAITERS);
 }
 
+static void
+__mutex_remove_waiter(struct mutex *lock, struct mutex_waiter *waiter)
+{
+       list_del(&waiter->list);
+       if (likely(list_empty(&lock->wait_list)))
+               __mutex_clear_flag(lock, MUTEX_FLAGS);
+
+       debug_mutex_remove_waiter(lock, waiter, current);
+}
+
 /*
  * Give up ownership to a specific task, when @task = NULL, this is equivalent
  * to a regular unlock. Sets PICKUP on a handoff, clears HANDOFF, preserves
@@ -1061,9 +1071,7 @@ acquired:
                        __ww_mutex_check_waiters(lock, ww_ctx);
        }
 
-       mutex_remove_waiter(lock, &waiter, current);
-       if (likely(list_empty(&lock->wait_list)))
-               __mutex_clear_flag(lock, MUTEX_FLAGS);
+       __mutex_remove_waiter(lock, &waiter);
 
        debug_mutex_free_waiter(&waiter);
 
@@ -1080,7 +1088,7 @@ skip_wait:
 
 err:
        __set_current_state(TASK_RUNNING);
-       mutex_remove_waiter(lock, &waiter, current);
+       __mutex_remove_waiter(lock, &waiter);
 err_early_kill:
        spin_unlock(&lock->wait_lock);
        debug_mutex_free_waiter(&waiter);
index 1c2287d3fa7191589c6d8f0d5f4e67c3282f8dfe..f0c710b1d1927131c2526dcfc7b96010ecaa45af 100644 (file)
  * !CONFIG_DEBUG_MUTEXES case. Most of them are NOPs:
  */
 
-#define mutex_remove_waiter(lock, waiter, task) \
-               __list_del((waiter)->list.prev, (waiter)->list.next)
-
 #define debug_mutex_wake_waiter(lock, waiter)          do { } while (0)
 #define debug_mutex_free_waiter(waiter)                        do { } while (0)
 #define debug_mutex_add_waiter(lock, waiter, ti)       do { } while (0)
+#define debug_mutex_remove_waiter(lock, waiter, ti)     do { } while (0)
 #define debug_mutex_unlock(lock)                       do { } while (0)
 #define debug_mutex_init(lock, name, key)              do { } while (0)
 
index b5dd92e35b02a78b44532cbdcf69292350dca456..7e78dfabca97fc652b1e2f7fd4d4e6168ae3a149 100644 (file)
@@ -2401,6 +2401,15 @@ static long get_offset(struct module *mod, unsigned int *size,
        return ret;
 }
 
+static bool module_init_layout_section(const char *sname)
+{
+#ifndef CONFIG_MODULE_UNLOAD
+       if (module_exit_section(sname))
+               return true;
+#endif
+       return module_init_section(sname);
+}
+
 /*
  * Lay out the SHF_ALLOC sections in a way not dissimilar to how ld
  * might -- code, read-only data, read-write data, small data.  Tally
@@ -2435,7 +2444,7 @@ static void layout_sections(struct module *mod, struct load_info *info)
                        if ((s->sh_flags & masks[m][0]) != masks[m][0]
                            || (s->sh_flags & masks[m][1])
                            || s->sh_entsize != ~0UL
-                           || module_init_section(sname))
+                           || module_init_layout_section(sname))
                                continue;
                        s->sh_entsize = get_offset(mod, &mod->core_layout.size, s, i);
                        pr_debug("\t%s\n", sname);
@@ -2468,7 +2477,7 @@ static void layout_sections(struct module *mod, struct load_info *info)
                        if ((s->sh_flags & masks[m][0]) != masks[m][0]
                            || (s->sh_flags & masks[m][1])
                            || s->sh_entsize != ~0UL
-                           || !module_init_section(sname))
+                           || !module_init_layout_section(sname))
                                continue;
                        s->sh_entsize = (get_offset(mod, &mod->init_layout.size, s, i)
                                         | INIT_OFFSET_MASK);
@@ -2807,11 +2816,7 @@ void * __weak module_alloc(unsigned long size)
 
 bool __weak module_init_section(const char *name)
 {
-#ifndef CONFIG_MODULE_UNLOAD
-       return strstarts(name, ".init") || module_exit_section(name);
-#else
        return strstarts(name, ".init");
-#endif
 }
 
 bool __weak module_exit_section(const char *name)
index 6ecd3f3a52b5b040f4c35aa918d8548b4817a295..9f58049ac16d906dac4af0e281a83133379b1eee 100644 (file)
@@ -1105,28 +1105,30 @@ static int seccomp_do_user_notification(int this_syscall,
 
        up(&match->notif->request);
        wake_up_poll(&match->wqh, EPOLLIN | EPOLLRDNORM);
-       mutex_unlock(&match->notify_lock);
 
        /*
         * This is where we wait for a reply from userspace.
         */
-wait:
-       err = wait_for_completion_interruptible(&n.ready);
-       mutex_lock(&match->notify_lock);
-       if (err == 0) {
-               /* Check if we were woken up by a addfd message */
+       do {
+               mutex_unlock(&match->notify_lock);
+               err = wait_for_completion_interruptible(&n.ready);
+               mutex_lock(&match->notify_lock);
+               if (err != 0)
+                       goto interrupted;
+
                addfd = list_first_entry_or_null(&n.addfd,
                                                 struct seccomp_kaddfd, list);
-               if (addfd && n.state != SECCOMP_NOTIFY_REPLIED) {
+               /* Check if we were woken up by a addfd message */
+               if (addfd)
                        seccomp_handle_addfd(addfd);
-                       mutex_unlock(&match->notify_lock);
-                       goto wait;
-               }
-               ret = n.val;
-               err = n.error;
-               flags = n.flags;
-       }
 
+       }  while (n.state != SECCOMP_NOTIFY_REPLIED);
+
+       ret = n.val;
+       err = n.error;
+       flags = n.flags;
+
+interrupted:
        /* If there were any pending addfd calls, clear them out */
        list_for_each_entry_safe(addfd, tmp, &n.addfd, list) {
                /* The process went away before we got a chance to handle it */
index 66e88649cf742043c4875ec2c8a81ef646f235a8..f7c6ffcbd04407adf91a0594a949a7bd4ca1463f 100644 (file)
@@ -1236,6 +1236,7 @@ static inline bool has_si_pid_and_uid(struct kernel_siginfo *info)
        case SIL_TIMER:
        case SIL_POLL:
        case SIL_FAULT:
+       case SIL_FAULT_TRAPNO:
        case SIL_FAULT_MCEERR:
        case SIL_FAULT_BNDERR:
        case SIL_FAULT_PKUERR:
@@ -1804,6 +1805,21 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
 }
 #endif
 
+int force_sig_perf(void __user *addr, u32 type, u64 sig_data)
+{
+       struct kernel_siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo     = SIGTRAP;
+       info.si_errno     = 0;
+       info.si_code      = TRAP_PERF;
+       info.si_addr      = addr;
+       info.si_perf_data = sig_data;
+       info.si_perf_type = type;
+
+       return force_sig_info(&info);
+}
+
 /* For the crazy architectures that include trap information in
  * the errno field, instead of an actual errno value.
  */
@@ -2564,6 +2580,7 @@ static void hide_si_addr_tag_bits(struct ksignal *ksig)
 {
        switch (siginfo_layout(ksig->sig, ksig->info.si_code)) {
        case SIL_FAULT:
+       case SIL_FAULT_TRAPNO:
        case SIL_FAULT_MCEERR:
        case SIL_FAULT_BNDERR:
        case SIL_FAULT_PKUERR:
@@ -3251,6 +3268,10 @@ enum siginfo_layout siginfo_layout(unsigned sig, int si_code)
 #endif
                        else if ((sig == SIGTRAP) && (si_code == TRAP_PERF))
                                layout = SIL_PERF_EVENT;
+#ifdef __ARCH_SI_TRAPNO
+                       else if (layout == SIL_FAULT)
+                               layout = SIL_FAULT_TRAPNO;
+#endif
                }
                else if (si_code <= NSIGPOLL)
                        layout = SIL_POLL;
@@ -3354,35 +3375,28 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
                break;
        case SIL_FAULT:
                to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
+               break;
+       case SIL_FAULT_TRAPNO:
+               to->si_addr = ptr_to_compat(from->si_addr);
                to->si_trapno = from->si_trapno;
-#endif
                break;
        case SIL_FAULT_MCEERR:
                to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from->si_trapno;
-#endif
                to->si_addr_lsb = from->si_addr_lsb;
                break;
        case SIL_FAULT_BNDERR:
                to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from->si_trapno;
-#endif
                to->si_lower = ptr_to_compat(from->si_lower);
                to->si_upper = ptr_to_compat(from->si_upper);
                break;
        case SIL_FAULT_PKUERR:
                to->si_addr = ptr_to_compat(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from->si_trapno;
-#endif
                to->si_pkey = from->si_pkey;
                break;
        case SIL_PERF_EVENT:
                to->si_addr = ptr_to_compat(from->si_addr);
-               to->si_perf = from->si_perf;
+               to->si_perf_data = from->si_perf_data;
+               to->si_perf_type = from->si_perf_type;
                break;
        case SIL_CHLD:
                to->si_pid = from->si_pid;
@@ -3438,35 +3452,28 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
                break;
        case SIL_FAULT:
                to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
+               break;
+       case SIL_FAULT_TRAPNO:
+               to->si_addr = compat_ptr(from->si_addr);
                to->si_trapno = from->si_trapno;
-#endif
                break;
        case SIL_FAULT_MCEERR:
                to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from->si_trapno;
-#endif
                to->si_addr_lsb = from->si_addr_lsb;
                break;
        case SIL_FAULT_BNDERR:
                to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from->si_trapno;
-#endif
                to->si_lower = compat_ptr(from->si_lower);
                to->si_upper = compat_ptr(from->si_upper);
                break;
        case SIL_FAULT_PKUERR:
                to->si_addr = compat_ptr(from->si_addr);
-#ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from->si_trapno;
-#endif
                to->si_pkey = from->si_pkey;
                break;
        case SIL_PERF_EVENT:
                to->si_addr = compat_ptr(from->si_addr);
-               to->si_perf = from->si_perf;
+               to->si_perf_data = from->si_perf_data;
+               to->si_perf_type = from->si_perf_type;
                break;
        case SIL_CHLD:
                to->si_pid    = from->si_pid;
@@ -4644,11 +4651,13 @@ static inline void siginfo_buildtime_checks(void)
 
        /* sigfault */
        CHECK_OFFSET(si_addr);
+       CHECK_OFFSET(si_trapno);
        CHECK_OFFSET(si_addr_lsb);
        CHECK_OFFSET(si_lower);
        CHECK_OFFSET(si_upper);
        CHECK_OFFSET(si_pkey);
-       CHECK_OFFSET(si_perf);
+       CHECK_OFFSET(si_perf_data);
+       CHECK_OFFSET(si_perf_type);
 
        /* sigpoll */
        CHECK_OFFSET(si_band);
index 14edf84cc571f5c19b8eec330719e3f36807f19a..d4a78e08f6d89c3d26207ae405f15018fdd442bf 100644 (file)
@@ -225,7 +225,27 @@ static int bpf_stats_handler(struct ctl_table *table, int write,
        mutex_unlock(&bpf_stats_enabled_mutex);
        return ret;
 }
-#endif
+
+static int bpf_unpriv_handler(struct ctl_table *table, int write,
+                             void *buffer, size_t *lenp, loff_t *ppos)
+{
+       int ret, unpriv_enable = *(int *)table->data;
+       bool locked_state = unpriv_enable == 1;
+       struct ctl_table tmp = *table;
+
+       if (write && !capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       tmp.data = &unpriv_enable;
+       ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
+       if (write && !ret) {
+               if (locked_state && unpriv_enable != 1)
+                       return -EPERM;
+               *(int *)table->data = unpriv_enable;
+       }
+       return ret;
+}
+#endif /* CONFIG_BPF_SYSCALL && CONFIG_SYSCTL */
 
 /*
  * /proc/sys support
@@ -2600,10 +2620,9 @@ static struct ctl_table kern_table[] = {
                .data           = &sysctl_unprivileged_bpf_disabled,
                .maxlen         = sizeof(sysctl_unprivileged_bpf_disabled),
                .mode           = 0644,
-               /* only handle a transition from default "0" to "1" */
-               .proc_handler   = proc_dointvec_minmax,
-               .extra1         = SYSCTL_ONE,
-               .extra2         = SYSCTL_ONE,
+               .proc_handler   = bpf_unpriv_handler,
+               .extra1         = SYSCTL_ZERO,
+               .extra2         = &two,
        },
        {
                .procname       = "bpf_stats_enabled",
index 7c397907d0e950dcb2f2c140621905bfbee32c87..92d3bcc5a5e0984cc3e09828d3cab049aa08f070 100644 (file)
@@ -302,10 +302,10 @@ void touch_softlockup_watchdog_sync(void)
        __this_cpu_write(watchdog_report_ts, SOFTLOCKUP_DELAY_REPORT);
 }
 
-static int is_softlockup(unsigned long touch_ts, unsigned long period_ts)
+static int is_softlockup(unsigned long touch_ts,
+                        unsigned long period_ts,
+                        unsigned long now)
 {
-       unsigned long now = get_timestamp();
-
        if ((watchdog_enabled & SOFT_WATCHDOG_ENABLED) && watchdog_thresh){
                /* Warn about unreasonable delays. */
                if (time_after(now, period_ts + get_softlockup_thresh()))
@@ -353,8 +353,7 @@ static int softlockup_fn(void *data)
 /* watchdog kicker functions */
 static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
 {
-       unsigned long touch_ts = __this_cpu_read(watchdog_touch_ts);
-       unsigned long period_ts = __this_cpu_read(watchdog_report_ts);
+       unsigned long touch_ts, period_ts, now;
        struct pt_regs *regs = get_irq_regs();
        int duration;
        int softlockup_all_cpu_backtrace = sysctl_softlockup_all_cpu_backtrace;
@@ -376,12 +375,23 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
        /* .. and repeat */
        hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period));
 
+       /*
+        * Read the current timestamp first. It might become invalid anytime
+        * when a virtual machine is stopped by the host or when the watchog
+        * is touched from NMI.
+        */
+       now = get_timestamp();
        /*
         * If a virtual machine is stopped by the host it can look to
-        * the watchdog like a soft lockup. Check to see if the host
-        * stopped the vm before we process the timestamps.
+        * the watchdog like a soft lockup. This function touches the watchdog.
         */
        kvm_check_and_clear_guest_paused();
+       /*
+        * The stored timestamp is comparable with @now only when not touched.
+        * It might get touched anytime from NMI. Make sure that is_softlockup()
+        * uses the same (valid) value.
+        */
+       period_ts = READ_ONCE(*this_cpu_ptr(&watchdog_report_ts));
 
        /* Reset the interval when touched by known problematic code. */
        if (period_ts == SOFTLOCKUP_DELAY_REPORT) {
@@ -398,13 +408,9 @@ static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
                return HRTIMER_RESTART;
        }
 
-       /* check for a softlockup
-        * This is done by making sure a high priority task is
-        * being scheduled.  The task touches the watchdog to
-        * indicate it is getting cpu time.  If it hasn't then
-        * this is a good indication some task is hogging the cpu
-        */
-       duration = is_softlockup(touch_ts, period_ts);
+       /* Check for a softlockup. */
+       touch_ts = __this_cpu_read(watchdog_touch_ts);
+       duration = is_softlockup(touch_ts, period_ts, now);
        if (unlikely(duration)) {
                /*
                 * Prevent multiple soft-lockup reports if one cpu is already
index b19d759e55a5d897e8d283f1b646c13d7e740466..50142fc08902d5a78cef0dca684e2b98b1bcd26f 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/uaccess.h>
 #include <linux/sched/isolation.h>
 #include <linux/nmi.h>
+#include <linux/kvm_para.h>
 
 #include "workqueue_internal.h"
 
@@ -5772,6 +5773,7 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
 {
        unsigned long thresh = READ_ONCE(wq_watchdog_thresh) * HZ;
        bool lockup_detected = false;
+       unsigned long now = jiffies;
        struct worker_pool *pool;
        int pi;
 
@@ -5786,6 +5788,12 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
                if (list_empty(&pool->worklist))
                        continue;
 
+               /*
+                * If a virtual machine is stopped by the host it can look to
+                * the watchdog like a stall.
+                */
+               kvm_check_and_clear_guest_paused();
+
                /* get the latest of pool and touched timestamps */
                if (pool->cpu >= 0)
                        touched = READ_ONCE(per_cpu(wq_watchdog_touched_cpu, pool->cpu));
@@ -5799,12 +5807,12 @@ static void wq_watchdog_timer_fn(struct timer_list *unused)
                        ts = touched;
 
                /* did we stall? */
-               if (time_after(jiffies, ts + thresh)) {
+               if (time_after(now, ts + thresh)) {
                        lockup_detected = true;
                        pr_emerg("BUG: workqueue lockup - pool");
                        pr_cont_pool_info(pool);
                        pr_cont(" stuck for %us!\n",
-                               jiffies_to_msecs(jiffies - pool_ts) / 1000);
+                               jiffies_to_msecs(now - pool_ts) / 1000);
                }
        }
 
index e11cfc18b6c0826ffc8bdcf1329dd1ec1aa2ef2e..2cc359ec1fdd3e1c7115bdc0dfbeaa0f59118bd9 100644 (file)
@@ -348,6 +348,7 @@ obj-$(CONFIG_OBJAGG) += objagg.o
 obj-$(CONFIG_PLDMFW) += pldmfw/
 
 # KUnit tests
+CFLAGS_bitfield_kunit.o := $(call cc-option,-Wframe-larger-than=10240)
 obj-$(CONFIG_BITFIELD_KUNIT) += bitfield_kunit.o
 obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
 obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
index 921d0a654243ce7c58d5288f25a78fd3ba781cf7..641767b0dce29be6d333b08b14031878e71436a7 100644 (file)
@@ -586,13 +586,11 @@ static int remaining(int wrote)
        return 0;
 }
 
-static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
+static char *__dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
 {
        int pos_after_tid;
        int pos = 0;
 
-       *buf = '\0';
-
        if (desc->flags & _DPRINTK_FLAGS_INCL_TID) {
                if (in_interrupt())
                        pos += snprintf(buf + pos, remaining(pos), "<intr> ");
@@ -618,11 +616,18 @@ static char *dynamic_emit_prefix(const struct _ddebug *desc, char *buf)
        return buf;
 }
 
+static inline char *dynamic_emit_prefix(struct _ddebug *desc, char *buf)
+{
+       if (unlikely(desc->flags & _DPRINTK_FLAGS_INCL_ANY))
+               return __dynamic_emit_prefix(desc, buf);
+       return buf;
+}
+
 void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
 {
        va_list args;
        struct va_format vaf;
-       char buf[PREFIX_SIZE];
+       char buf[PREFIX_SIZE] = "";
 
        BUG_ON(!descriptor);
        BUG_ON(!fmt);
@@ -655,7 +660,7 @@ void __dynamic_dev_dbg(struct _ddebug *descriptor,
        if (!dev) {
                printk(KERN_DEBUG "(NULL device *): %pV", &vaf);
        } else {
-               char buf[PREFIX_SIZE];
+               char buf[PREFIX_SIZE] = "";
 
                dev_printk_emit(LOGLEVEL_DEBUG, dev, "%s%s %s: %pV",
                                dynamic_emit_prefix(descriptor, buf),
@@ -684,7 +689,7 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
        vaf.va = &args;
 
        if (dev && dev->dev.parent) {
-               char buf[PREFIX_SIZE];
+               char buf[PREFIX_SIZE] = "";
 
                dev_printk_emit(LOGLEVEL_DEBUG, dev->dev.parent,
                                "%s%s %s %s%s: %pV",
@@ -720,7 +725,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
        vaf.va = &args;
 
        if (ibdev && ibdev->dev.parent) {
-               char buf[PREFIX_SIZE];
+               char buf[PREFIX_SIZE] = "";
 
                dev_printk_emit(LOGLEVEL_DEBUG, ibdev->dev.parent,
                                "%s%s %s %s: %pV",
@@ -915,7 +920,6 @@ static const struct seq_operations ddebug_proc_seqops = {
 
 static int ddebug_proc_open(struct inode *inode, struct file *file)
 {
-       vpr_info("called\n");
        return seq_open_private(file, &ddebug_proc_seqops,
                                sizeof(struct ddebug_iter));
 }
index a1071cdefb5aa4e629493ae1f32c7a15422a695b..af9302141bcf63983b8bac15468174f63ed0edc7 100644 (file)
@@ -275,7 +275,7 @@ static void __percpu_ref_switch_mode(struct percpu_ref *ref,
        wait_event_lock_irq(percpu_ref_switch_waitq, !data->confirm_switch,
                            percpu_ref_switch_lock);
 
-       if (data->force_atomic || (ref->percpu_count_ptr & __PERCPU_REF_DEAD))
+       if (data->force_atomic || percpu_ref_is_dying(ref))
                __percpu_ref_switch_to_atomic(ref, confirm_switch);
        else
                __percpu_ref_switch_to_percpu(ref);
@@ -385,7 +385,7 @@ void percpu_ref_kill_and_confirm(struct percpu_ref *ref,
 
        spin_lock_irqsave(&percpu_ref_switch_lock, flags);
 
-       WARN_ONCE(ref->percpu_count_ptr & __PERCPU_REF_DEAD,
+       WARN_ONCE(percpu_ref_is_dying(ref),
                  "%s called more than once on %ps!", __func__,
                  ref->data->release);
 
@@ -465,7 +465,7 @@ void percpu_ref_resurrect(struct percpu_ref *ref)
 
        spin_lock_irqsave(&percpu_ref_switch_lock, flags);
 
-       WARN_ON_ONCE(!(ref->percpu_count_ptr & __PERCPU_REF_DEAD));
+       WARN_ON_ONCE(!percpu_ref_is_dying(ref));
        WARN_ON_ONCE(__ref_is_percpu(ref, &percpu_count));
 
        ref->percpu_count_ptr &= ~__PERCPU_REF_DEAD;
index 0697134b6a12cb4d0aec4eda2facaa67213487c9..3ded6a5f26b259e859cba3a9f164cd1b6e8b235c 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1593,10 +1593,6 @@ struct page *get_dump_page(unsigned long addr)
                                      FOLL_FORCE | FOLL_DUMP | FOLL_GET);
        if (locked)
                mmap_read_unlock(mm);
-
-       if (ret == 1 && is_page_poisoned(page))
-               return NULL;
-
        return (ret == 1) ? page : NULL;
 }
 #endif /* CONFIG_ELF_CORE */
index 54bd0dc2c23c1b02858cadd73a5de94fe696e12c..2f1182948aa6e7a6603515c4dfe6e8eabfded734 100644 (file)
@@ -96,26 +96,6 @@ static inline void set_page_refcounted(struct page *page)
        set_page_count(page, 1);
 }
 
-/*
- * When kernel touch the user page, the user page may be have been marked
- * poison but still mapped in user space, if without this page, the kernel
- * can guarantee the data integrity and operation success, the kernel is
- * better to check the posion status and avoid touching it, be good not to
- * panic, coredump for process fatal signal is a sample case matching this
- * scenario. Or if kernel can't guarantee the data integrity, it's better
- * not to call this function, let kernel touch the poison page and get to
- * panic.
- */
-static inline bool is_page_poisoned(struct page *page)
-{
-       if (PageHWPoison(page))
-               return true;
-       else if (PageHuge(page) && PageHWPoison(compound_head(page)))
-               return true;
-
-       return false;
-}
-
 extern unsigned long highest_memmap_pfn;
 
 /*
index 71b784f0b7c3ed4fc94f237828294938da219742..cec62984f7d3b22b346cc0b72d4b9aeaf51c7595 100644 (file)
@@ -10,7 +10,7 @@
 DECLARE_STATIC_KEY_FALSE(page_alloc_shuffle_key);
 extern void __shuffle_free_memory(pg_data_t *pgdat);
 extern bool shuffle_pick_tail(void);
-static inline void shuffle_free_memory(pg_data_t *pgdat)
+static inline void __meminit shuffle_free_memory(pg_data_t *pgdat)
 {
        if (!static_branch_unlikely(&page_alloc_shuffle_key))
                return;
@@ -18,7 +18,7 @@ static inline void shuffle_free_memory(pg_data_t *pgdat)
 }
 
 extern void __shuffle_zone(struct zone *z);
-static inline void shuffle_zone(struct zone *z)
+static inline void __meminit shuffle_zone(struct zone *z)
 {
        if (!static_branch_unlikely(&page_alloc_shuffle_key))
                return;
index 438fa8d4c970d97932f1b14620d989e4e7032bcd..3f96e099817a17e9c09fc0263405026cf1c2ceb9 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -301,6 +301,7 @@ static inline void *get_freepointer_safe(struct kmem_cache *s, void *object)
        if (!debug_pagealloc_enabled_static())
                return get_freepointer(s, object);
 
+       object = kasan_reset_tag(object);
        freepointer_addr = (unsigned long)object + s->offset;
        copy_from_kernel_nofault(&p, (void **)freepointer_addr, sizeof(p));
        return freelist_ptr(s, p, freepointer_addr);
index e14b3820c6a814ec3962227cc7dbdc52ffc72a50..63a73e164d5510fba964eec777b7486b634a1343 100644 (file)
@@ -360,38 +360,38 @@ out:
                 * If a reservation for the page existed in the reservation
                 * map of a private mapping, the map was modified to indicate
                 * the reservation was consumed when the page was allocated.
-                * We clear the PagePrivate flag now so that the global
+                * We clear the HPageRestoreReserve flag now so that the global
                 * reserve count will not be incremented in free_huge_page.
                 * The reservation map will still indicate the reservation
                 * was consumed and possibly prevent later page allocation.
                 * This is better than leaking a global reservation.  If no
-                * reservation existed, it is still safe to clear PagePrivate
-                * as no adjustments to reservation counts were made during
-                * allocation.
+                * reservation existed, it is still safe to clear
+                * HPageRestoreReserve as no adjustments to reservation counts
+                * were made during allocation.
                 *
                 * The reservation map for shared mappings indicates which
                 * pages have reservations.  When a huge page is allocated
                 * for an address with a reservation, no change is made to
-                * the reserve map.  In this case PagePrivate will be set
-                * to indicate that the global reservation count should be
+                * the reserve map.  In this case HPageRestoreReserve will be
+                * set to indicate that the global reservation count should be
                 * incremented when the page is freed.  This is the desired
                 * behavior.  However, when a huge page is allocated for an
                 * address without a reservation a reservation entry is added
-                * to the reservation map, and PagePrivate will not be set.
-                * When the page is freed, the global reserve count will NOT
-                * be incremented and it will appear as though we have leaked
-                * reserved page.  In this case, set PagePrivate so that the
-                * global reserve count will be incremented to match the
-                * reservation map entry which was created.
+                * to the reservation map, and HPageRestoreReserve will not be
+                * set. When the page is freed, the global reserve count will
+                * NOT be incremented and it will appear as though we have
+                * leaked reserved page.  In this case, set HPageRestoreReserve
+                * so that the global reserve count will be incremented to
+                * match the reservation map entry which was created.
                 *
                 * Note that vm_alloc_shared is based on the flags of the vma
                 * for which the page was originally allocated.  dst_vma could
                 * be different or NULL on error.
                 */
                if (vm_alloc_shared)
-                       SetPagePrivate(page);
+                       SetHPageRestoreReserve(page);
                else
-                       ClearPagePrivate(page);
+                       ClearHPageRestoreReserve(page);
                put_page(page);
        }
        BUG_ON(copied < 0);
index f5ee7c65e6b4b905970ae91c7ab8e06eeb9878fc..c7392c449b254b8887866711f660efd001b8e10b 100644 (file)
@@ -302,21 +302,6 @@ config BQL
        select DQL
        default y
 
-config BPF_JIT
-       bool "enable BPF Just In Time compiler"
-       depends on HAVE_CBPF_JIT || HAVE_EBPF_JIT
-       depends on MODULES
-       help
-         Berkeley Packet Filter filtering capabilities are normally handled
-         by an interpreter. This option allows kernel to generate a native
-         code when filter is loaded in memory. This should speedup
-         packet sniffing (libpcap/tcpdump).
-
-         Note, admin should enable this feature changing:
-         /proc/sys/net/core/bpf_jit_enable
-         /proc/sys/net/core/bpf_jit_harden   (optional)
-         /proc/sys/net/core/bpf_jit_kallsyms (optional)
-
 config BPF_STREAM_PARSER
        bool "enable BPF STREAM_PARSER"
        depends on INET
@@ -470,15 +455,3 @@ config ETHTOOL_NETLINK
          e.g. notification messages.
 
 endif   # if NET
-
-# Used by archs to tell that they support BPF JIT compiler plus which flavour.
-# Only one of the two can be selected for a specific arch since eBPF JIT supersedes
-# the cBPF JIT.
-
-# Classic BPF JIT (cBPF)
-config HAVE_CBPF_JIT
-       bool
-
-# Extended BPF JIT (eBPF)
-config HAVE_EBPF_JIT
-       bool
index 9f94ad3caee92938a81e0fb22e850ec97d73b9c9..253b24417c8e5c05559c3e503aedfd6dcee7a13d 100644 (file)
@@ -1062,27 +1062,31 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len)
        if (len < ISOTP_MIN_NAMELEN)
                return -EINVAL;
 
+       if (addr->can_addr.tp.tx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG))
+               return -EADDRNOTAVAIL;
+
+       if (!addr->can_ifindex)
+               return -ENODEV;
+
+       lock_sock(sk);
+
        /* do not register frame reception for functional addressing */
        if (so->opt.flags & CAN_ISOTP_SF_BROADCAST)
                do_rx_reg = 0;
 
        /* do not validate rx address for functional addressing */
        if (do_rx_reg) {
-               if (addr->can_addr.tp.rx_id == addr->can_addr.tp.tx_id)
-                       return -EADDRNOTAVAIL;
+               if (addr->can_addr.tp.rx_id == addr->can_addr.tp.tx_id) {
+                       err = -EADDRNOTAVAIL;
+                       goto out;
+               }
 
-               if (addr->can_addr.tp.rx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG))
-                       return -EADDRNOTAVAIL;
+               if (addr->can_addr.tp.rx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG)) {
+                       err = -EADDRNOTAVAIL;
+                       goto out;
+               }
        }
 
-       if (addr->can_addr.tp.tx_id & (CAN_ERR_FLAG | CAN_RTR_FLAG))
-               return -EADDRNOTAVAIL;
-
-       if (!addr->can_ifindex)
-               return -ENODEV;
-
-       lock_sock(sk);
-
        if (so->bound && addr->can_ifindex == so->ifindex &&
            addr->can_addr.tp.rx_id == so->rxid &&
            addr->can_addr.tp.tx_id == so->txid)
@@ -1164,16 +1168,13 @@ static int isotp_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
        return ISOTP_MIN_NAMELEN;
 }
 
-static int isotp_setsockopt(struct socket *sock, int level, int optname,
+static int isotp_setsockopt_locked(struct socket *sock, int level, int optname,
                            sockptr_t optval, unsigned int optlen)
 {
        struct sock *sk = sock->sk;
        struct isotp_sock *so = isotp_sk(sk);
        int ret = 0;
 
-       if (level != SOL_CAN_ISOTP)
-               return -EINVAL;
-
        if (so->bound)
                return -EISCONN;
 
@@ -1248,6 +1249,22 @@ static int isotp_setsockopt(struct socket *sock, int level, int optname,
        return ret;
 }
 
+static int isotp_setsockopt(struct socket *sock, int level, int optname,
+                           sockptr_t optval, unsigned int optlen)
+
+{
+       struct sock *sk = sock->sk;
+       int ret;
+
+       if (level != SOL_CAN_ISOTP)
+               return -EINVAL;
+
+       lock_sock(sk);
+       ret = isotp_setsockopt_locked(sock, level, optname, optval, optlen);
+       release_sock(sk);
+       return ret;
+}
+
 static int isotp_getsockopt(struct socket *sock, int level, int optname,
                            char __user *optval, int __user *optlen)
 {
index 222b1d322c9693e351ebc0c2548e3e3a50860e46..ef8cf7619bafa3a229ad9b18cc003792df7b3fac 100644 (file)
@@ -3853,7 +3853,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,
 
        if (q->flags & TCQ_F_NOLOCK) {
                rc = q->enqueue(skb, q, &to_free) & NET_XMIT_MASK;
-               qdisc_run(q);
+               if (likely(!netif_xmit_frozen_or_stopped(txq)))
+                       qdisc_run(q);
 
                if (unlikely(to_free))
                        kfree_skb_list(to_free);
@@ -5025,25 +5026,43 @@ static __latent_entropy void net_tx_action(struct softirq_action *h)
                sd->output_queue_tailp = &sd->output_queue;
                local_irq_enable();
 
+               rcu_read_lock();
+
                while (head) {
                        struct Qdisc *q = head;
                        spinlock_t *root_lock = NULL;
 
                        head = head->next_sched;
 
-                       if (!(q->flags & TCQ_F_NOLOCK)) {
-                               root_lock = qdisc_lock(q);
-                               spin_lock(root_lock);
-                       }
                        /* We need to make sure head->next_sched is read
                         * before clearing __QDISC_STATE_SCHED
                         */
                        smp_mb__before_atomic();
+
+                       if (!(q->flags & TCQ_F_NOLOCK)) {
+                               root_lock = qdisc_lock(q);
+                               spin_lock(root_lock);
+                       } else if (unlikely(test_bit(__QDISC_STATE_DEACTIVATED,
+                                                    &q->state))) {
+                               /* There is a synchronize_net() between
+                                * STATE_DEACTIVATED flag being set and
+                                * qdisc_reset()/some_qdisc_is_busy() in
+                                * dev_deactivate(), so we can safely bail out
+                                * early here to avoid data race between
+                                * qdisc_deactivate() and some_qdisc_is_busy()
+                                * for lockless qdisc.
+                                */
+                               clear_bit(__QDISC_STATE_SCHED, &q->state);
+                               continue;
+                       }
+
                        clear_bit(__QDISC_STATE_SCHED, &q->state);
                        qdisc_run(q);
                        if (root_lock)
                                spin_unlock(root_lock);
                }
+
+               rcu_read_unlock();
        }
 
        xfrm_dev_backlog(sd);
index cae56d08a67079bb2fa0335eec6afbd4c91c6ced..65ab4e21c087f6854cd0af2f15571db6db47887f 100644 (file)
@@ -3784,6 +3784,7 @@ static inline int __bpf_skb_change_head(struct sk_buff *skb, u32 head_room,
                __skb_push(skb, head_room);
                memset(skb->data, 0, head_room);
                skb_reset_mac_header(skb);
+               skb_reset_mac_len(skb);
        }
 
        return ret;
index c761c4a0b66b1d34ed1671727daf86738bff6c92..958614ea16edb4ec0181a522c0703ffb3cef15ad 100644 (file)
@@ -2132,10 +2132,10 @@ void skb_orphan_partial(struct sk_buff *skb)
        if (skb_is_tcp_pure_ack(skb))
                return;
 
-       if (can_skb_orphan_partial(skb))
-               skb_set_owner_sk_safe(skb, skb->sk);
-       else
-               skb_orphan(skb);
+       if (can_skb_orphan_partial(skb) && skb_set_owner_sk_safe(skb, skb->sk))
+               return;
+
+       skb_orphan(skb);
 }
 EXPORT_SYMBOL(skb_orphan_partial);
 
index 052a977914a6ded18c2455631678392ea1c17c85..63adbc21a735a445ebf0408d188743b51821191d 100644 (file)
@@ -147,8 +147,7 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
        struct dsa_switch *ds = cpu_dp->ds;
        int port = cpu_dp->index;
        int len = ETH_GSTRING_LEN;
-       int mcount = 0, count;
-       unsigned int i;
+       int mcount = 0, count, i;
        uint8_t pfx[4];
        uint8_t *ndata;
 
@@ -178,6 +177,8 @@ static void dsa_master_get_strings(struct net_device *dev, uint32_t stringset,
                 */
                ds->ops->get_strings(ds, port, stringset, ndata);
                count = ds->ops->get_sset_count(ds, port, stringset);
+               if (count < 0)
+                       return;
                for (i = 0; i < count; i++) {
                        memmove(ndata + (i * len + sizeof(pfx)),
                                ndata + i * len, len - sizeof(pfx));
index 8c0f3c6ab3654dd10f3ed1953fe2215afc539ac6..d4756b9201089292acfb05a7a0cb9557b7da5ce9 100644 (file)
@@ -776,13 +776,15 @@ static int dsa_slave_get_sset_count(struct net_device *dev, int sset)
        struct dsa_switch *ds = dp->ds;
 
        if (sset == ETH_SS_STATS) {
-               int count;
+               int count = 0;
 
-               count = 4;
-               if (ds->ops->get_sset_count)
-                       count += ds->ops->get_sset_count(ds, dp->index, sset);
+               if (ds->ops->get_sset_count) {
+                       count = ds->ops->get_sset_count(ds, dp->index, sset);
+                       if (count < 0)
+                               return count;
+               }
 
-               return count;
+               return count + 4;
        } else if (sset ==  ETH_SS_TEST) {
                return net_selftest_get_count();
        }
index b7642dc96d5072d66efb43b63516f258551ac70b..ec07f5765e030d5f4784db178d60e0ceb12cdc63 100644 (file)
@@ -119,7 +119,7 @@ static int stats_prepare_data(const struct ethnl_req_info *req_base,
         */
        memset(&data->phy_stats, 0xff, sizeof(data->phy_stats));
        memset(&data->mac_stats, 0xff, sizeof(data->mac_stats));
-       memset(&data->ctrl_stats, 0xff, sizeof(data->mac_stats));
+       memset(&data->ctrl_stats, 0xff, sizeof(data->ctrl_stats));
        memset(&data->rmon_stats, 0xff, sizeof(data->rmon_stats));
 
        if (test_bit(ETHTOOL_STATS_ETH_PHY, req_info->stat_mask) &&
index bfcdc75fc01e65136a29370a79bac6ba181d5faa..26c32407f029096e9c3133e9da56c4f22e049e1f 100644 (file)
@@ -218,6 +218,7 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev)
        if (master) {
                skb->dev = master->dev;
                skb_reset_mac_header(skb);
+               skb_reset_mac_len(skb);
                hsr_forward_skb(skb, master);
        } else {
                atomic_long_inc(&dev->tx_dropped);
@@ -259,6 +260,7 @@ static struct sk_buff *hsr_init_skb(struct hsr_port *master)
                goto out;
 
        skb_reset_mac_header(skb);
+       skb_reset_mac_len(skb);
        skb_reset_network_header(skb);
        skb_reset_transport_header(skb);
 
index 6852e9bccf5b8c694004e6f94851bf528039ba6d..ceb8afb2a62f4bd34b6b081f682da3698285af07 100644 (file)
@@ -474,8 +474,8 @@ static void handle_std_frame(struct sk_buff *skb,
        }
 }
 
-void hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
-                        struct hsr_frame_info *frame)
+int hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
+                       struct hsr_frame_info *frame)
 {
        struct hsr_port *port = frame->port_rcv;
        struct hsr_priv *hsr = port->hsr;
@@ -483,20 +483,26 @@ void hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
        /* HSRv0 supervisory frames double as a tag so treat them as tagged. */
        if ((!hsr->prot_version && proto == htons(ETH_P_PRP)) ||
            proto == htons(ETH_P_HSR)) {
+               /* Check if skb contains hsr_ethhdr */
+               if (skb->mac_len < sizeof(struct hsr_ethhdr))
+                       return -EINVAL;
+
                /* HSR tagged frame :- Data or Supervision */
                frame->skb_std = NULL;
                frame->skb_prp = NULL;
                frame->skb_hsr = skb;
                frame->sequence_nr = hsr_get_skb_sequence_nr(skb);
-               return;
+               return 0;
        }
 
        /* Standard frame or PRP from master port */
        handle_std_frame(skb, frame);
+
+       return 0;
 }
 
-void prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
-                        struct hsr_frame_info *frame)
+int prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
+                       struct hsr_frame_info *frame)
 {
        /* Supervision frame */
        struct prp_rct *rct = skb_get_PRP_rct(skb);
@@ -507,9 +513,11 @@ void prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
                frame->skb_std = NULL;
                frame->skb_prp = skb;
                frame->sequence_nr = prp_get_skb_sequence_nr(rct);
-               return;
+               return 0;
        }
        handle_std_frame(skb, frame);
+
+       return 0;
 }
 
 static int fill_frame_info(struct hsr_frame_info *frame,
@@ -519,9 +527,10 @@ static int fill_frame_info(struct hsr_frame_info *frame,
        struct hsr_vlan_ethhdr *vlan_hdr;
        struct ethhdr *ethhdr;
        __be16 proto;
+       int ret;
 
-       /* Check if skb contains hsr_ethhdr */
-       if (skb->mac_len < sizeof(struct hsr_ethhdr))
+       /* Check if skb contains ethhdr */
+       if (skb->mac_len < sizeof(struct ethhdr))
                return -EINVAL;
 
        memset(frame, 0, sizeof(*frame));
@@ -548,7 +557,10 @@ static int fill_frame_info(struct hsr_frame_info *frame,
 
        frame->is_from_san = false;
        frame->port_rcv = port;
-       hsr->proto_ops->fill_frame_info(proto, skb, frame);
+       ret = hsr->proto_ops->fill_frame_info(proto, skb, frame);
+       if (ret)
+               return ret;
+
        check_local_dest(port->hsr, skb, frame);
 
        return 0;
index b6acaafa83fc218506aa31031dc51941aa052ff8..206636750b3001d218fb52aacd9b5d822e75bd1f 100644 (file)
@@ -24,8 +24,8 @@ struct sk_buff *prp_get_untagged_frame(struct hsr_frame_info *frame,
                                       struct hsr_port *port);
 bool prp_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port);
 bool hsr_drop_frame(struct hsr_frame_info *frame, struct hsr_port *port);
-void prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
-                        struct hsr_frame_info *frame);
-void hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
-                        struct hsr_frame_info *frame);
+int prp_fill_frame_info(__be16 proto, struct sk_buff *skb,
+                       struct hsr_frame_info *frame);
+int hsr_fill_frame_info(__be16 proto, struct sk_buff *skb,
+                       struct hsr_frame_info *frame);
 #endif /* __HSR_FORWARD_H */
index 8f264672b70bd6bd042232db415112fe4efa2c28..53d1f7a8246308e437b7b8a20a6f677e891b5e1c 100644 (file)
@@ -186,8 +186,8 @@ struct hsr_proto_ops {
                                               struct hsr_port *port);
        struct sk_buff * (*create_tagged_frame)(struct hsr_frame_info *frame,
                                                struct hsr_port *port);
-       void (*fill_frame_info)(__be16 proto, struct sk_buff *skb,
-                               struct hsr_frame_info *frame);
+       int (*fill_frame_info)(__be16 proto, struct sk_buff *skb,
+                              struct hsr_frame_info *frame);
        bool (*invalid_dan_ingress_frame)(__be16 protocol);
        void (*update_san_info)(struct hsr_node *node, bool is_sup);
 };
index c5227d42faf56243e89db4027bdd79718e45ff3b..b70e6bbf6021f5dcc50ced0d8811aa0280680376 100644 (file)
@@ -60,12 +60,11 @@ static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb)
                goto finish_pass;
 
        skb_push(skb, ETH_HLEN);
-
-       if (skb_mac_header(skb) != skb->data) {
-               WARN_ONCE(1, "%s:%d: Malformed frame at source port %s)\n",
-                         __func__, __LINE__, port->dev->name);
-               goto finish_consume;
-       }
+       skb_reset_mac_header(skb);
+       if ((!hsr->prot_version && protocol == htons(ETH_P_PRP)) ||
+           protocol == htons(ETH_P_HSR))
+               skb_set_network_header(skb, ETH_HLEN + HSR_HLEN);
+       skb_reset_mac_len(skb);
 
        hsr_forward_skb(skb, port);
 
index dff4f0eb96b0f22d076a1168c8225c3100b4cabd..9e41eff4a68588e0cf869415dccddf9c6fd48a0c 100644 (file)
@@ -185,6 +185,7 @@ BTF_ID(func, tcp_reno_cong_avoid)
 BTF_ID(func, tcp_reno_undo_cwnd)
 BTF_ID(func, tcp_slow_start)
 BTF_ID(func, tcp_cong_avoid_ai)
+#ifdef CONFIG_X86
 #ifdef CONFIG_DYNAMIC_FTRACE
 #if IS_BUILTIN(CONFIG_TCP_CONG_CUBIC)
 BTF_ID(func, cubictcp_init)
@@ -213,6 +214,7 @@ BTF_ID(func, bbr_min_tso_segs)
 BTF_ID(func, bbr_set_state)
 #endif
 #endif  /* CONFIG_DYNAMIC_FTRACE */
+#endif /* CONFIG_X86 */
 BTF_SET_END(bpf_tcp_ca_kfunc_ids)
 
 static bool bpf_tcp_ca_check_kfunc_call(u32 kfunc_btf_id)
index 0d59efb6b49ecfe3d45cd59949ce93a6ea207e32..d36ef9d25e73cb14eed45701acafcaf78e08451e 100644 (file)
@@ -1745,10 +1745,7 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu)
                     IPV6_TLV_PADN, 0 };
 
        /* we assume size > sizeof(ra) here */
-       /* limit our allocations to order-0 page */
-       size = min_t(int, size, SKB_MAX_ORDER(0, 0));
        skb = sock_alloc_send_skb(sk, size, 1, &err);
-
        if (!skb)
                return NULL;
 
index 47a0dc46cbdb0a16e6fb7cee505fcbe28d5d01fc..28e44782c94d1e0485c9d7c685179716ab252c22 100644 (file)
@@ -343,7 +343,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
        hdr = ipv6_hdr(skb);
        fhdr = (struct frag_hdr *)skb_transport_header(skb);
 
-       if (!(fhdr->frag_off & htons(0xFFF9))) {
+       if (!(fhdr->frag_off & htons(IP6_OFFSET | IP6_MF))) {
                /* It is not a fragmented frame */
                skb->transport_header += sizeof(struct frag_hdr);
                __IP6_INC_STATS(net,
@@ -351,6 +351,8 @@ static int ipv6_frag_rcv(struct sk_buff *skb)
 
                IP6CB(skb)->nhoff = (u8 *)fhdr - skb_network_header(skb);
                IP6CB(skb)->flags |= IP6SKB_FRAGMENTED;
+               IP6CB(skb)->frag_max_size = ntohs(hdr->payload_len) +
+                                           sizeof(struct ipv6hdr);
                return 1;
        }
 
index 8fcbaa1eedf3ed1809a46f99f8a5eaf39e8a07ae..214404a558fb6fea556c10cbb4886c175e34acf5 100644 (file)
@@ -50,12 +50,6 @@ struct ieee80211_local;
 #define IEEE80211_ENCRYPT_HEADROOM 8
 #define IEEE80211_ENCRYPT_TAILROOM 18
 
-/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent
- * reception of at least three fragmented frames. This limit can be increased
- * by changing this define, at the cost of slower frame reassembly and
- * increased memory use (about 2 kB of RAM per entry). */
-#define IEEE80211_FRAGMENT_MAX 4
-
 /* power level hasn't been configured (or set to automatic) */
 #define IEEE80211_UNSET_POWER_LEVEL    INT_MIN
 
@@ -88,18 +82,6 @@ extern const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS];
 
 #define IEEE80211_MAX_NAN_INSTANCE_ID 255
 
-struct ieee80211_fragment_entry {
-       struct sk_buff_head skb_list;
-       unsigned long first_frag_time;
-       u16 seq;
-       u16 extra_len;
-       u16 last_frag;
-       u8 rx_queue;
-       bool check_sequential_pn; /* needed for CCMP/GCMP */
-       u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
-};
-
-
 struct ieee80211_bss {
        u32 device_ts_beacon, device_ts_presp;
 
@@ -241,8 +223,15 @@ struct ieee80211_rx_data {
         */
        int security_idx;
 
-       u32 tkip_iv32;
-       u16 tkip_iv16;
+       union {
+               struct {
+                       u32 iv32;
+                       u16 iv16;
+               } tkip;
+               struct {
+                       u8 pn[IEEE80211_CCMP_PN_LEN];
+               } ccm_gcm;
+       };
 };
 
 struct ieee80211_csa_settings {
@@ -902,9 +891,7 @@ struct ieee80211_sub_if_data {
 
        char name[IFNAMSIZ];
 
-       /* Fragment table for host-based reassembly */
-       struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
-       unsigned int fragment_next;
+       struct ieee80211_fragment_cache frags;
 
        /* TID bitmap for NoAck policy */
        u16 noack_map;
@@ -2320,4 +2307,7 @@ u32 ieee80211_calc_expected_tx_airtime(struct ieee80211_hw *hw,
 #define debug_noinline
 #endif
 
+void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache);
+void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache);
+
 #endif /* IEEE80211_I_H */
index 7032a2b59249cb2d42c3c38aaeec0cc57a4741ba..2e2f73a4aa7340bf3aed51eb12d0313667f81807 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (c) 2016        Intel Deutschland GmbH
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2021 Intel Corporation
  */
 #include <linux/slab.h>
 #include <linux/kernel.h>
@@ -677,16 +677,12 @@ static void ieee80211_set_multicast_list(struct net_device *dev)
  */
 static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
 {
-       int i;
-
        /* free extra data */
        ieee80211_free_keys(sdata, false);
 
        ieee80211_debugfs_remove_netdev(sdata);
 
-       for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
-               __skb_queue_purge(&sdata->fragments[i].skb_list);
-       sdata->fragment_next = 0;
+       ieee80211_destroy_frag_cache(&sdata->frags);
 
        if (ieee80211_vif_is_mesh(&sdata->vif))
                ieee80211_mesh_teardown_sdata(sdata);
@@ -1930,8 +1926,7 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
        sdata->wdev.wiphy = local->hw.wiphy;
        sdata->local = local;
 
-       for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
-               skb_queue_head_init(&sdata->fragments[i].skb_list);
+       ieee80211_init_frag_cache(&sdata->frags);
 
        INIT_LIST_HEAD(&sdata->key_list);
 
index 56c068cb49c4ddaef3d4fb9355b4912f5f72fc58..f695fc80088bc98a8380785c8fbed89063ffcb47 100644 (file)
@@ -799,6 +799,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
                       struct ieee80211_sub_if_data *sdata,
                       struct sta_info *sta)
 {
+       static atomic_t key_color = ATOMIC_INIT(0);
        struct ieee80211_key *old_key;
        int idx = key->conf.keyidx;
        bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
@@ -850,6 +851,12 @@ int ieee80211_key_link(struct ieee80211_key *key,
        key->sdata = sdata;
        key->sta = sta;
 
+       /*
+        * Assign a unique ID to every key so we can easily prevent mixed
+        * key and fragment cache attacks.
+        */
+       key->color = atomic_inc_return(&key_color);
+
        increment_tailroom_need_count(sdata);
 
        ret = ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
index 7ad72e9b4991d2f4ca14df03a8ccc86fedf18b62..1e326c89d72173775dee1927b82e73b2ad8f817a 100644 (file)
@@ -128,6 +128,8 @@ struct ieee80211_key {
        } debugfs;
 #endif
 
+       unsigned int color;
+
        /*
         * key config, must be last because it contains key
         * material as variable length member
index 62047e93e217be086cada92237b978f614eaa29e..1bb43edd47b6cb7d5f62a22a8af6507bdb58d26a 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2021 Intel Corporation
  */
 
 #include <linux/jiffies.h>
@@ -2123,19 +2123,34 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
        return result;
 }
 
+void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(cache->entries); i++)
+               skb_queue_head_init(&cache->entries[i].skb_list);
+}
+
+void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(cache->entries); i++)
+               __skb_queue_purge(&cache->entries[i].skb_list);
+}
+
 static inline struct ieee80211_fragment_entry *
-ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
+ieee80211_reassemble_add(struct ieee80211_fragment_cache *cache,
                         unsigned int frag, unsigned int seq, int rx_queue,
                         struct sk_buff **skb)
 {
        struct ieee80211_fragment_entry *entry;
 
-       entry = &sdata->fragments[sdata->fragment_next++];
-       if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
-               sdata->fragment_next = 0;
+       entry = &cache->entries[cache->next++];
+       if (cache->next >= IEEE80211_FRAGMENT_MAX)
+               cache->next = 0;
 
-       if (!skb_queue_empty(&entry->skb_list))
-               __skb_queue_purge(&entry->skb_list);
+       __skb_queue_purge(&entry->skb_list);
 
        __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
        *skb = NULL;
@@ -2150,14 +2165,14 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
 }
 
 static inline struct ieee80211_fragment_entry *
-ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
+ieee80211_reassemble_find(struct ieee80211_fragment_cache *cache,
                          unsigned int frag, unsigned int seq,
                          int rx_queue, struct ieee80211_hdr *hdr)
 {
        struct ieee80211_fragment_entry *entry;
        int i, idx;
 
-       idx = sdata->fragment_next;
+       idx = cache->next;
        for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
                struct ieee80211_hdr *f_hdr;
                struct sk_buff *f_skb;
@@ -2166,7 +2181,7 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
                if (idx < 0)
                        idx = IEEE80211_FRAGMENT_MAX - 1;
 
-               entry = &sdata->fragments[idx];
+               entry = &cache->entries[idx];
                if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
                    entry->rx_queue != rx_queue ||
                    entry->last_frag + 1 != frag)
@@ -2194,15 +2209,27 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
        return NULL;
 }
 
+static bool requires_sequential_pn(struct ieee80211_rx_data *rx, __le16 fc)
+{
+       return rx->key &&
+               (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
+                rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
+                rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
+                rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
+               ieee80211_has_protected(fc);
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 {
+       struct ieee80211_fragment_cache *cache = &rx->sdata->frags;
        struct ieee80211_hdr *hdr;
        u16 sc;
        __le16 fc;
        unsigned int frag, seq;
        struct ieee80211_fragment_entry *entry;
        struct sk_buff *skb;
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
 
        hdr = (struct ieee80211_hdr *)rx->skb->data;
        fc = hdr->frame_control;
@@ -2218,6 +2245,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                goto out_no_led;
        }
 
+       if (rx->sta)
+               cache = &rx->sta->frags;
+
        if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
                goto out;
 
@@ -2236,20 +2266,17 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 
        if (frag == 0) {
                /* This is the first fragment of a new frame. */
-               entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
+               entry = ieee80211_reassemble_add(cache, frag, seq,
                                                 rx->seqno_idx, &(rx->skb));
-               if (rx->key &&
-                   (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
-                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
-                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
-                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
-                   ieee80211_has_protected(fc)) {
+               if (requires_sequential_pn(rx, fc)) {
                        int queue = rx->security_idx;
 
                        /* Store CCMP/GCMP PN so that we can verify that the
                         * next fragment has a sequential PN value.
                         */
                        entry->check_sequential_pn = true;
+                       entry->is_protected = true;
+                       entry->key_color = rx->key->color;
                        memcpy(entry->last_pn,
                               rx->key->u.ccmp.rx_pn[queue],
                               IEEE80211_CCMP_PN_LEN);
@@ -2261,6 +2288,11 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                                     sizeof(rx->key->u.gcmp.rx_pn[queue]));
                        BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
                                     IEEE80211_GCMP_PN_LEN);
+               } else if (rx->key &&
+                          (ieee80211_has_protected(fc) ||
+                           (status->flag & RX_FLAG_DECRYPTED))) {
+                       entry->is_protected = true;
+                       entry->key_color = rx->key->color;
                }
                return RX_QUEUED;
        }
@@ -2268,7 +2300,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
        /* This is a fragment for a frame that should already be pending in
         * fragment cache. Add this fragment to the end of the pending entry.
         */
-       entry = ieee80211_reassemble_find(rx->sdata, frag, seq,
+       entry = ieee80211_reassemble_find(cache, frag, seq,
                                          rx->seqno_idx, hdr);
        if (!entry) {
                I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
@@ -2283,25 +2315,39 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
        if (entry->check_sequential_pn) {
                int i;
                u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
-               int queue;
 
-               if (!rx->key ||
-                   (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
-                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
-                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
-                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
+               if (!requires_sequential_pn(rx, fc))
+                       return RX_DROP_UNUSABLE;
+
+               /* Prevent mixed key and fragment cache attacks */
+               if (entry->key_color != rx->key->color)
                        return RX_DROP_UNUSABLE;
+
                memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
                for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
                        pn[i]++;
                        if (pn[i])
                                break;
                }
-               queue = rx->security_idx;
-               rpn = rx->key->u.ccmp.rx_pn[queue];
+
+               rpn = rx->ccm_gcm.pn;
                if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
                        return RX_DROP_UNUSABLE;
                memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
+       } else if (entry->is_protected &&
+                  (!rx->key ||
+                   (!ieee80211_has_protected(fc) &&
+                    !(status->flag & RX_FLAG_DECRYPTED)) ||
+                   rx->key->color != entry->key_color)) {
+               /* Drop this as a mixed key or fragment cache attack, even
+                * if for TKIP Michael MIC should protect us, and WEP is a
+                * lost cause anyway.
+                */
+               return RX_DROP_UNUSABLE;
+       } else if (entry->is_protected && rx->key &&
+                  entry->key_color != rx->key->color &&
+                  (status->flag & RX_FLAG_DECRYPTED)) {
+               return RX_DROP_UNUSABLE;
        }
 
        skb_pull(rx->skb, ieee80211_hdrlen(fc));
@@ -2494,13 +2540,13 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
        struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
 
        /*
-        * Allow EAPOL frames to us/the PAE group address regardless
-        * of whether the frame was encrypted or not.
+        * Allow EAPOL frames to us/the PAE group address regardless of
+        * whether the frame was encrypted or not, and always disallow
+        * all other destination addresses for them.
         */
-       if (ehdr->h_proto == rx->sdata->control_port_protocol &&
-           (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
-            ether_addr_equal(ehdr->h_dest, pae_group_addr)))
-               return true;
+       if (unlikely(ehdr->h_proto == rx->sdata->control_port_protocol))
+               return ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
+                      ether_addr_equal(ehdr->h_dest, pae_group_addr);
 
        if (ieee80211_802_1x_port_control(rx) ||
            ieee80211_drop_unencrypted(rx, fc))
@@ -2525,8 +2571,28 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb,
                cfg80211_rx_control_port(dev, skb, noencrypt);
                dev_kfree_skb(skb);
        } else {
+               struct ethhdr *ehdr = (void *)skb_mac_header(skb);
+
                memset(skb->cb, 0, sizeof(skb->cb));
 
+               /*
+                * 802.1X over 802.11 requires that the authenticator address
+                * be used for EAPOL frames. However, 802.1X allows the use of
+                * the PAE group address instead. If the interface is part of
+                * a bridge and we pass the frame with the PAE group address,
+                * then the bridge will forward it to the network (even if the
+                * client was not associated yet), which isn't supposed to
+                * happen.
+                * To avoid that, rewrite the destination address to our own
+                * address, so that the authenticator (e.g. hostapd) will see
+                * the frame, but bridge won't forward it anywhere else. Note
+                * that due to earlier filtering, the only other address can
+                * be the PAE group address.
+                */
+               if (unlikely(skb->protocol == sdata->control_port_protocol &&
+                            !ether_addr_equal(ehdr->h_dest, sdata->vif.addr)))
+                       ether_addr_copy(ehdr->h_dest, sdata->vif.addr);
+
                /* deliver to local stack */
                if (rx->list)
                        list_add_tail(&skb->list, rx->list);
@@ -2566,6 +2632,7 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
        if ((sdata->vif.type == NL80211_IFTYPE_AP ||
             sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
            !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
+           ehdr->h_proto != rx->sdata->control_port_protocol &&
            (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
                if (is_multicast_ether_addr(ehdr->h_dest) &&
                    ieee80211_vif_get_num_mcast_if(sdata) != 0) {
@@ -2675,7 +2742,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)
        if (ieee80211_data_to_8023_exthdr(skb, &ethhdr,
                                          rx->sdata->vif.addr,
                                          rx->sdata->vif.type,
-                                         data_offset))
+                                         data_offset, true))
                return RX_DROP_UNUSABLE;
 
        ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
@@ -2732,6 +2799,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
        if (is_multicast_ether_addr(hdr->addr1))
                return RX_DROP_UNUSABLE;
 
+       if (rx->key) {
+               /*
+                * We should not receive A-MSDUs on pre-HT connections,
+                * and HT connections cannot use old ciphers. Thus drop
+                * them, as in those cases we couldn't even have SPP
+                * A-MSDUs or such.
+                */
+               switch (rx->key->conf.cipher) {
+               case WLAN_CIPHER_SUITE_WEP40:
+               case WLAN_CIPHER_SUITE_WEP104:
+               case WLAN_CIPHER_SUITE_TKIP:
+                       return RX_DROP_UNUSABLE;
+               default:
+                       break;
+               }
+       }
+
        return __ieee80211_rx_h_amsdu(rx, 0);
 }
 
index ec6973ee88ef49d9169ce9141642859166c6059f..f2fb69da9b6e1e945387253aa46154454c7d6ba1 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2021 Intel Corporation
  */
 
 #include <linux/module.h>
@@ -392,6 +392,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
 
        u64_stats_init(&sta->rx_stats.syncp);
 
+       ieee80211_init_frag_cache(&sta->frags);
+
        sta->sta_state = IEEE80211_STA_NONE;
 
        /* Mark TID as unreserved */
@@ -1102,6 +1104,8 @@ static void __sta_info_destroy_part2(struct sta_info *sta)
 
        ieee80211_sta_debugfs_remove(sta);
 
+       ieee80211_destroy_frag_cache(&sta->frags);
+
        cleanup_single_sta(sta);
 }
 
index 78b9d0c7cc583dc1d9455583ff93797bcfdfb54f..0333072ebd98223bd31d54187644a7b0f6c9c2f2 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright 2002-2005, Devicescape Software, Inc.
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright(c) 2020 Intel Corporation
+ * Copyright(c) 2020-2021 Intel Corporation
  */
 
 #ifndef STA_INFO_H
@@ -438,6 +438,34 @@ struct ieee80211_sta_rx_stats {
        u64 msdu[IEEE80211_NUM_TIDS + 1];
 };
 
+/*
+ * IEEE 802.11-2016 (10.6 "Defragmentation") recommends support for "concurrent
+ * reception of at least one MSDU per access category per associated STA"
+ * on APs, or "at least one MSDU per access category" on other interface types.
+ *
+ * This limit can be increased by changing this define, at the cost of slower
+ * frame reassembly and increased memory use while fragments are pending.
+ */
+#define IEEE80211_FRAGMENT_MAX 4
+
+struct ieee80211_fragment_entry {
+       struct sk_buff_head skb_list;
+       unsigned long first_frag_time;
+       u16 seq;
+       u16 extra_len;
+       u16 last_frag;
+       u8 rx_queue;
+       u8 check_sequential_pn:1, /* needed for CCMP/GCMP */
+          is_protected:1;
+       u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
+       unsigned int key_color;
+};
+
+struct ieee80211_fragment_cache {
+       struct ieee80211_fragment_entry entries[IEEE80211_FRAGMENT_MAX];
+       unsigned int next;
+};
+
 /*
  * The bandwidth threshold below which the per-station CoDel parameters will be
  * scaled to be more lenient (to prevent starvation of slow stations). This
@@ -531,6 +559,7 @@ struct ieee80211_sta_rx_stats {
  * @status_stats.last_ack_signal: last ACK signal
  * @status_stats.ack_signal_filled: last ACK signal validity
  * @status_stats.avg_ack_signal: average ACK signal
+ * @frags: fragment cache
  */
 struct sta_info {
        /* General information, mostly static */
@@ -639,6 +668,8 @@ struct sta_info {
 
        struct cfg80211_chan_def tdls_chandef;
 
+       struct ieee80211_fragment_cache frags;
+
        /* keep last! */
        struct ieee80211_sta sta;
 };
index 91bf32af55e9aab807ee350d4db06da2c9bdb161..bca47fad5a16280b808bef4c8832d6f0e0626b37 100644 (file)
@@ -3,6 +3,7 @@
  * Copyright 2002-2004, Instant802 Networks, Inc.
  * Copyright 2008, Jouni Malinen <j@w1.fi>
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
+ * Copyright (C) 2020-2021 Intel Corporation
  */
 
 #include <linux/netdevice.h>
@@ -167,8 +168,8 @@ ieee80211_rx_h_michael_mic_verify(struct ieee80211_rx_data *rx)
 
 update_iv:
        /* update IV in key information to be able to detect replays */
-       rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32;
-       rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16;
+       rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip.iv32;
+       rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip.iv16;
 
        return RX_CONTINUE;
 
@@ -294,8 +295,8 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx)
                                          key, skb->data + hdrlen,
                                          skb->len - hdrlen, rx->sta->sta.addr,
                                          hdr->addr1, hwaccel, rx->security_idx,
-                                         &rx->tkip_iv32,
-                                         &rx->tkip_iv16);
+                                         &rx->tkip.iv32,
+                                         &rx->tkip.iv16);
        if (res != TKIP_DECRYPT_OK)
                return RX_DROP_UNUSABLE;
 
@@ -553,6 +554,8 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx,
                }
 
                memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
+               if (unlikely(ieee80211_is_frag(hdr)))
+                       memcpy(rx->ccm_gcm.pn, pn, IEEE80211_CCMP_PN_LEN);
        }
 
        /* Remove CCMP header and MIC */
@@ -781,6 +784,8 @@ ieee80211_crypto_gcmp_decrypt(struct ieee80211_rx_data *rx)
                }
 
                memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN);
+               if (unlikely(ieee80211_is_frag(hdr)))
+                       memcpy(rx->ccm_gcm.pn, pn, IEEE80211_CCMP_PN_LEN);
        }
 
        /* Remove GCMP header and MIC */
index 99fc21406168bc94500aa3740bf49dd62e05c28b..6b825fb3fa8322ef4fd96a7a92d02c4ec2bb6628 100644 (file)
@@ -130,7 +130,6 @@ static void mptcp_parse_option(const struct sk_buff *skb,
                        memcpy(mp_opt->hmac, ptr, MPTCPOPT_HMAC_LEN);
                        pr_debug("MP_JOIN hmac");
                } else {
-                       pr_warn("MP_JOIN bad option size");
                        mp_opt->mp_join = 0;
                }
                break;
@@ -1024,7 +1023,7 @@ void mptcp_incoming_options(struct sock *sk, struct sk_buff *skb)
                        MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ADDADDR);
                } else {
                        mptcp_pm_add_addr_echoed(msk, &mp_opt.addr);
-                       mptcp_pm_del_add_timer(msk, &mp_opt.addr);
+                       mptcp_pm_del_add_timer(msk, &mp_opt.addr, true);
                        MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_ECHOADD);
                }
 
index 6ba040897738b8a9889406add01664c5093b7cf5..2469e06a3a9d6019973d5dd83c497f9e5ebf97c5 100644 (file)
@@ -346,18 +346,18 @@ out:
 
 struct mptcp_pm_add_entry *
 mptcp_pm_del_add_timer(struct mptcp_sock *msk,
-                      struct mptcp_addr_info *addr)
+                      struct mptcp_addr_info *addr, bool check_id)
 {
        struct mptcp_pm_add_entry *entry;
        struct sock *sk = (struct sock *)msk;
 
        spin_lock_bh(&msk->pm.lock);
        entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
-       if (entry)
+       if (entry && (!check_id || entry->addr.id == addr->id))
                entry->retrans_times = ADD_ADDR_RETRANS_MAX;
        spin_unlock_bh(&msk->pm.lock);
 
-       if (entry)
+       if (entry && (!check_id || entry->addr.id == addr->id))
                sk_stop_timer_sync(sk, &entry->add_timer);
 
        return entry;
@@ -1064,7 +1064,7 @@ static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
 {
        struct mptcp_pm_add_entry *entry;
 
-       entry = mptcp_pm_del_add_timer(msk, addr);
+       entry = mptcp_pm_del_add_timer(msk, addr, false);
        if (entry) {
                list_del(&entry->list);
                kfree(entry);
index 29a2d690d8d5950cf4ff35189ae1e0d31392a7b4..2bc199549a88712487ca6544cfa3b3958c2cbaf4 100644 (file)
@@ -879,12 +879,18 @@ static bool mptcp_skb_can_collapse_to(u64 write_seq,
               !mpext->frozen;
 }
 
+/* we can append data to the given data frag if:
+ * - there is space available in the backing page_frag
+ * - the data frag tail matches the current page_frag free offset
+ * - the data frag end sequence number matches the current write seq
+ */
 static bool mptcp_frag_can_collapse_to(const struct mptcp_sock *msk,
                                       const struct page_frag *pfrag,
                                       const struct mptcp_data_frag *df)
 {
        return df && pfrag->page == df->page &&
                pfrag->size - pfrag->offset > 0 &&
+               pfrag->offset == (df->offset + df->data_len) &&
                df->data_seq + df->data_len == msk->write_seq;
 }
 
@@ -2418,13 +2424,12 @@ static int __mptcp_init_sock(struct sock *sk)
        timer_setup(&msk->sk.icsk_retransmit_timer, mptcp_retransmit_timer, 0);
        timer_setup(&sk->sk_timer, mptcp_timeout_timer, 0);
 
-       tcp_assign_congestion_control(sk);
-
        return 0;
 }
 
 static int mptcp_init_sock(struct sock *sk)
 {
+       struct inet_connection_sock *icsk = inet_csk(sk);
        struct net *net = sock_net(sk);
        int ret;
 
@@ -2442,6 +2447,16 @@ static int mptcp_init_sock(struct sock *sk)
        if (ret)
                return ret;
 
+       /* fetch the ca name; do it outside __mptcp_init_sock(), so that clone will
+        * propagate the correct value
+        */
+       tcp_assign_congestion_control(sk);
+       strcpy(mptcp_sk(sk)->ca_name, icsk->icsk_ca_ops->name);
+
+       /* no need to keep a reference to the ops, the name will suffice */
+       tcp_cleanup_congestion_control(sk);
+       icsk->icsk_ca_ops = NULL;
+
        sk_sockets_allocated_inc(sk);
        sk->sk_rcvbuf = sock_net(sk)->ipv4.sysctl_tcp_rmem[1];
        sk->sk_sndbuf = sock_net(sk)->ipv4.sysctl_tcp_wmem[1];
@@ -2616,7 +2631,6 @@ static void __mptcp_destroy_sock(struct sock *sk)
        sk_stream_kill_queues(sk);
        xfrm_sk_free_policy(sk);
 
-       tcp_cleanup_congestion_control(sk);
        sk_refcnt_debug_release(sk);
        mptcp_dispose_initial_subflow(msk);
        sock_put(sk);
index edc0128730dfe0eb5d4be65c0e446530fa9cf8c9..0c6f99c6734575446d29ddbd839eebf9deefade2 100644 (file)
@@ -258,6 +258,7 @@ struct mptcp_sock {
        } rcvq_space;
 
        u32 setsockopt_seq;
+       char            ca_name[TCP_CA_NAME_MAX];
 };
 
 #define mptcp_lock_sock(___sk, cb) do {                                        \
@@ -671,7 +672,7 @@ void mptcp_pm_free_anno_list(struct mptcp_sock *msk);
 bool mptcp_pm_sport_in_anno_list(struct mptcp_sock *msk, const struct sock *sk);
 struct mptcp_pm_add_entry *
 mptcp_pm_del_add_timer(struct mptcp_sock *msk,
-                      struct mptcp_addr_info *addr);
+                      struct mptcp_addr_info *addr, bool check_id);
 struct mptcp_pm_add_entry *
 mptcp_lookup_anno_list_by_saddr(struct mptcp_sock *msk,
                                struct mptcp_addr_info *addr);
index 00d941b66c1e5907906eb1efc1e7aef909b6152d..a797981895995edae37ba612fdd120ac07d20e01 100644 (file)
@@ -547,7 +547,7 @@ static int mptcp_setsockopt_sol_tcp_congestion(struct mptcp_sock *msk, sockptr_t
        }
 
        if (ret == 0)
-               tcp_set_congestion_control(sk, name, false, cap_net_admin);
+               strcpy(msk->ca_name, name);
 
        release_sock(sk);
        return ret;
@@ -705,7 +705,7 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk)
        sock_valbool_flag(ssk, SOCK_DBG, sock_flag(sk, SOCK_DBG));
 
        if (inet_csk(sk)->icsk_ca_ops != inet_csk(ssk)->icsk_ca_ops)
-               tcp_set_congestion_control(ssk, inet_csk(sk)->icsk_ca_ops->name, false, true);
+               tcp_set_congestion_control(ssk, msk->ca_name, false, true);
 }
 
 static void __mptcp_sockopt_sync(struct mptcp_sock *msk, struct sock *ssk)
index a5ede357cfbc54ec1fc8fb43b0d6929f5942b425..bde6be77ea73bd5ded5041c10282753e345d349a 100644 (file)
@@ -867,7 +867,6 @@ static enum mapping_status get_mapping_status(struct sock *ssk,
 
        data_len = mpext->data_len;
        if (data_len == 0) {
-               pr_err("Infinite mapping not handled");
                MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX);
                return MAPPING_INVALID;
        }
index 39c02d1aeedfa11308e43fac67f28e890dcb36ad..1d02650dd715ab8b6e502f9d49f736ab73d9b1ba 100644 (file)
@@ -306,8 +306,7 @@ void flow_offload_refresh(struct nf_flowtable *flow_table,
 {
        flow->timeout = nf_flowtable_time_stamp + NF_FLOW_TIMEOUT;
 
-       if (likely(!nf_flowtable_hw_offload(flow_table) ||
-                  !test_and_clear_bit(NF_FLOW_HW_REFRESH, &flow->flags)))
+       if (likely(!nf_flowtable_hw_offload(flow_table)))
                return;
 
        nf_flow_offload_add(flow_table, flow);
index 2af7bdb384077a692fa6a743b0ffb25e1fb3c86c..528b2f1726844564fcce9054030fb4cd2a2f4419 100644 (file)
@@ -902,10 +902,11 @@ static void flow_offload_work_add(struct flow_offload_work *offload)
 
        err = flow_offload_rule_add(offload, flow_rule);
        if (err < 0)
-               set_bit(NF_FLOW_HW_REFRESH, &offload->flow->flags);
-       else
-               set_bit(IPS_HW_OFFLOAD_BIT, &offload->flow->ct->status);
+               goto out;
+
+       set_bit(IPS_HW_OFFLOAD_BIT, &offload->flow->ct->status);
 
+out:
        nf_flow_offload_destroy(flow_rule);
 }
 
index 528a2d7ca9918372b072b51962b0a4be97ca3db8..dce866d93feed1bf60493d7ff89a4892096f6e30 100644 (file)
@@ -408,8 +408,8 @@ int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
  *
  * Return: true on match, false otherwise.
  */
-static bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
-                             const u32 *key, const struct nft_set_ext **ext)
+bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
+                      const u32 *key, const struct nft_set_ext **ext)
 {
        struct nft_pipapo *priv = nft_set_priv(set);
        unsigned long *res_map, *fill_map;
index 25a75591583ebec982a53a67135721c7f4902047..d84afb8fa79a13b563ef175cddcf12ee4cb1ef24 100644 (file)
@@ -178,6 +178,8 @@ struct nft_pipapo_elem {
 
 int pipapo_refill(unsigned long *map, int len, int rules, unsigned long *dst,
                  union nft_pipapo_map_bucket *mt, bool match_only);
+bool nft_pipapo_lookup(const struct net *net, const struct nft_set *set,
+                      const u32 *key, const struct nft_set_ext **ext);
 
 /**
  * pipapo_and_field_buckets_4bit() - Intersect 4-bit buckets
index d65ae0e23028d10fbca9109cb378251f7b53edc2..eabdb8d552eef95329fbcc792d20f42ca01449ba 100644 (file)
@@ -1131,6 +1131,9 @@ bool nft_pipapo_avx2_lookup(const struct net *net, const struct nft_set *set,
        bool map_index;
        int i, ret = 0;
 
+       if (unlikely(!irq_fpu_usable()))
+               return nft_pipapo_lookup(net, set, key, ext);
+
        m = rcu_dereference(priv->match);
 
        /* This also protects access to all data related to scratch maps */
index 3a62f97acf39d11a18547308a2f375eb5f37abaa..6133e412b948c4cd3373d249bd5c29f917ba4322 100644 (file)
@@ -461,11 +461,13 @@ void netlink_table_ungrab(void)
 static inline void
 netlink_lock_table(void)
 {
+       unsigned long flags;
+
        /* read_lock() synchronizes us to netlink_table_grab */
 
-       read_lock(&nl_table_lock);
+       read_lock_irqsave(&nl_table_lock, flags);
        atomic_inc(&nl_table_users);
-       read_unlock(&nl_table_lock);
+       read_unlock_irqrestore(&nl_table_lock, flags);
 }
 
 static inline void
index 9a585332ea84a488f6186058900e2ada8a3864fe..da7fe9db1b00fdfed75f26d5181c2d80bfbd2e81 100644 (file)
@@ -1191,6 +1191,7 @@ EXPORT_SYMBOL(nci_allocate_device);
 void nci_free_device(struct nci_dev *ndev)
 {
        nfc_free_device(ndev->nfc_dev);
+       nci_hci_deallocate(ndev);
        kfree(ndev);
 }
 EXPORT_SYMBOL(nci_free_device);
index 6b275a387a92acf9f046c22b3136062239bb2586..96865142104f48f71e291f42cee8297bc1471e1c 100644 (file)
@@ -792,3 +792,8 @@ struct nci_hci_dev *nci_hci_allocate(struct nci_dev *ndev)
 
        return hdev;
 }
+
+void nci_hci_deallocate(struct nci_dev *ndev)
+{
+       kfree(ndev->hci_dev);
+}
index 9c7eb8455ba8eb275133f0d0bfc0b8d5a6fbdd70..5f1d438a0a23f15946a6055edad795e5000576b9 100644 (file)
@@ -329,7 +329,7 @@ static int rawsock_create(struct net *net, struct socket *sock,
                return -ESOCKTNOSUPPORT;
 
        if (sock->type == SOCK_RAW) {
-               if (!capable(CAP_NET_RAW))
+               if (!ns_capable(net->user_ns, CAP_NET_RAW))
                        return -EPERM;
                sock->ops = &rawsock_raw_ops;
        } else {
index 96b524ceabca4f53b07411ae4d5d5c49e7d24656..896b8f5bc885350980a9547fc921583515dff7ec 100644 (file)
@@ -611,6 +611,14 @@ bool ovs_meter_execute(struct datapath *dp, struct sk_buff *skb,
        spin_lock(&meter->lock);
 
        long_delta_ms = (now_ms - meter->used); /* ms */
+       if (long_delta_ms < 0) {
+               /* This condition means that we have several threads fighting
+                * for a meter lock, and the one who received the packets a
+                * bit later wins. Assuming that all racing threads received
+                * packets at the same time to avoid overflow.
+                */
+               long_delta_ms = 0;
+       }
 
        /* Make sure delta_ms will not be too large, so that bucket will not
         * wrap around below.
index ba96db1880eae89febf77ba6ff943b054cd268d7..ae906eb4b269e858434828a383491e8d4c33c422 100644 (file)
@@ -422,7 +422,8 @@ static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec64 *ts,
            ktime_to_timespec64_cond(shhwtstamps->hwtstamp, ts))
                return TP_STATUS_TS_RAW_HARDWARE;
 
-       if (ktime_to_timespec64_cond(skb->tstamp, ts))
+       if ((flags & SOF_TIMESTAMPING_SOFTWARE) &&
+           ktime_to_timespec64_cond(skb->tstamp, ts))
                return TP_STATUS_TS_SOFTWARE;
 
        return 0;
@@ -2340,7 +2341,12 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
 
        skb_copy_bits(skb, 0, h.raw + macoff, snaplen);
 
-       if (!(ts_status = tpacket_get_timestamp(skb, &ts, po->tp_tstamp)))
+       /* Always timestamp; prefer an existing software timestamp taken
+        * closer to the time of capture.
+        */
+       ts_status = tpacket_get_timestamp(skb, &ts,
+                                         po->tp_tstamp | SOF_TIMESTAMPING_SOFTWARE);
+       if (!ts_status)
                ktime_get_real_ts64(&ts);
 
        status |= ts_status;
index f2fcab182095cbc39f991a4d2886aa2237aec1c8..a3bc4b54d4910567c915f41cd6bc44f279eaadf3 100644 (file)
@@ -240,12 +240,23 @@ static struct rds_connection *__rds_conn_create(struct net *net,
        if (loop_trans) {
                rds_trans_put(loop_trans);
                conn->c_loopback = 1;
-               if (is_outgoing && trans->t_prefer_loopback) {
-                       /* "outgoing" connection - and the transport
-                        * says it wants the connection handled by the
-                        * loopback transport. This is what TCP does.
-                        */
-                       trans = &rds_loop_transport;
+               if (trans->t_prefer_loopback) {
+                       if (likely(is_outgoing)) {
+                               /* "outgoing" connection to local address.
+                                * Protocol says it wants the connection
+                                * handled by the loopback transport.
+                                * This is what TCP does.
+                                */
+                               trans = &rds_loop_transport;
+                       } else {
+                               /* No transport currently in use
+                                * should end up here, but if it
+                                * does, reset/destroy the connection.
+                                */
+                               kmem_cache_free(rds_conn_slab, conn);
+                               conn = ERR_PTR(-EOPNOTSUPP);
+                               goto out;
+                       }
                }
        }
 
index 43db0eca911fad13c21a4e4091580e0c9f3901cc..abf19c0e3ba0bfcf0396df2d78b937e288b84ab0 100644 (file)
@@ -313,8 +313,8 @@ out:
 }
 #endif
 
-static int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
-                              __u32 scope_id)
+int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
+                       __u32 scope_id)
 {
        struct net_device *dev = NULL;
 #if IS_ENABLED(CONFIG_IPV6)
index bad9cf49d56572cd163019c2beb6ea5e65b17d7f..dc8d745d68575f019ca96c706efc77125552a5d2 100644 (file)
@@ -59,7 +59,8 @@ u32 rds_tcp_snd_una(struct rds_tcp_connection *tc);
 u64 rds_tcp_map_seq(struct rds_tcp_connection *tc, u32 seq);
 extern struct rds_transport rds_tcp_transport;
 void rds_tcp_accept_work(struct sock *sk);
-
+int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,
+                       __u32 scope_id);
 /* tcp_connect.c */
 int rds_tcp_conn_path_connect(struct rds_conn_path *cp);
 void rds_tcp_conn_path_shutdown(struct rds_conn_path *conn);
index 101cf14215a0b30f5395fd3d4317655d3167f0f9..09cadd556d1e188fde086f356718ab149d567632 100644 (file)
@@ -167,6 +167,12 @@ int rds_tcp_accept_one(struct socket *sock)
        }
 #endif
 
+       if (!rds_tcp_laddr_check(sock_net(sock->sk), peer_addr, dev_if)) {
+               /* local address connection is only allowed via loopback */
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
        conn = rds_conn_create(sock_net(sock->sk),
                               my_addr, peer_addr,
                               &rds_tcp_transport, 0, GFP_KERNEL, dev_if);
index 40fbea626dfd2a4ea9f36abfe55210f99c04c2db..279f9e2a2319ad6f026b7cfa4c56be856b4b96a8 100644 (file)
@@ -1624,7 +1624,7 @@ int tcf_classify_ingress(struct sk_buff *skb,
 
        /* If we missed on some chain */
        if (ret == TC_ACT_UNSPEC && last_executed_chain) {
-               ext = skb_ext_add(skb, TC_SKB_EXT);
+               ext = tc_skb_ext_alloc(skb);
                if (WARN_ON_ONCE(!ext))
                        return TC_ACT_SHOT;
                ext->chain = last_executed_chain;
index cd2748e2d4a2057e327e61478618a1ca8b1bf5b7..d320bcfb2da2c9aac72c546750dac1586860df25 100644 (file)
@@ -407,7 +407,8 @@ static void dsmark_reset(struct Qdisc *sch)
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
 
        pr_debug("%s(sch %p,[qdisc %p])\n", __func__, sch, p);
-       qdisc_reset(p->q);
+       if (p->q)
+               qdisc_reset(p->q);
        sch->qstats.backlog = 0;
        sch->q.qlen = 0;
 }
index 949163fe68afdeb95638998b8b28499d930ae023..cac684952edc55712197b307536fdc9ad3c7e064 100644 (file)
@@ -138,8 +138,15 @@ static int fq_pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
 
        /* Classifies packet into corresponding flow */
        idx = fq_pie_classify(skb, sch, &ret);
-       sel_flow = &q->flows[idx];
+       if (idx == 0) {
+               if (ret & __NET_XMIT_BYPASS)
+                       qdisc_qstats_drop(sch);
+               __qdisc_drop(skb, to_free);
+               return ret;
+       }
+       idx--;
 
+       sel_flow = &q->flows[idx];
        /* Checks whether adding a new packet would exceed memory limit */
        get_pie_cb(skb)->mem_usage = skb->truesize;
        memory_limited = q->memory_usage > q->memory_limit + skb->truesize;
@@ -297,9 +304,9 @@ static int fq_pie_change(struct Qdisc *sch, struct nlattr *opt,
                        goto flow_error;
                }
                q->flows_cnt = nla_get_u32(tb[TCA_FQ_PIE_FLOWS]);
-               if (!q->flows_cnt || q->flows_cnt >= 65536) {
+               if (!q->flows_cnt || q->flows_cnt > 65536) {
                        NL_SET_ERR_MSG_MOD(extack,
-                                          "Number of flows must range in [1..65535]");
+                                          "Number of flows must range in [1..65536]");
                        goto flow_error;
                }
        }
@@ -367,7 +374,7 @@ static void fq_pie_timer(struct timer_list *t)
        struct fq_pie_sched_data *q = from_timer(q, t, adapt_timer);
        struct Qdisc *sch = q->sch;
        spinlock_t *root_lock; /* to lock qdisc for probability calculations */
-       u16 idx;
+       u32 idx;
 
        root_lock = qdisc_lock(qdisc_root_sleeping(sch));
        spin_lock(root_lock);
@@ -388,7 +395,7 @@ static int fq_pie_init(struct Qdisc *sch, struct nlattr *opt,
 {
        struct fq_pie_sched_data *q = qdisc_priv(sch);
        int err;
-       u16 idx;
+       u32 idx;
 
        pie_params_init(&q->p_params);
        sch->limit = 10 * 1024;
@@ -500,7 +507,7 @@ static int fq_pie_dump_stats(struct Qdisc *sch, struct gnet_dump *d)
 static void fq_pie_reset(struct Qdisc *sch)
 {
        struct fq_pie_sched_data *q = qdisc_priv(sch);
-       u16 idx;
+       u32 idx;
 
        INIT_LIST_HEAD(&q->new_flows);
        INIT_LIST_HEAD(&q->old_flows);
index 44991ea726fc730596ade2c8814961f016656938..fc8b56bcabf39f01053894781ddf040df42e0c1e 100644 (file)
 const struct Qdisc_ops *default_qdisc_ops = &pfifo_fast_ops;
 EXPORT_SYMBOL(default_qdisc_ops);
 
+static void qdisc_maybe_clear_missed(struct Qdisc *q,
+                                    const struct netdev_queue *txq)
+{
+       clear_bit(__QDISC_STATE_MISSED, &q->state);
+
+       /* Make sure the below netif_xmit_frozen_or_stopped()
+        * checking happens after clearing STATE_MISSED.
+        */
+       smp_mb__after_atomic();
+
+       /* Checking netif_xmit_frozen_or_stopped() again to
+        * make sure STATE_MISSED is set if the STATE_MISSED
+        * set by netif_tx_wake_queue()'s rescheduling of
+        * net_tx_action() is cleared by the above clear_bit().
+        */
+       if (!netif_xmit_frozen_or_stopped(txq))
+               set_bit(__QDISC_STATE_MISSED, &q->state);
+}
+
 /* Main transmission queue. */
 
 /* Modifications to data participating in scheduling must be protected with
@@ -74,6 +93,7 @@ static inline struct sk_buff *__skb_dequeue_bad_txq(struct Qdisc *q)
                        }
                } else {
                        skb = SKB_XOFF_MAGIC;
+                       qdisc_maybe_clear_missed(q, txq);
                }
        }
 
@@ -242,6 +262,7 @@ static struct sk_buff *dequeue_skb(struct Qdisc *q, bool *validate,
                        }
                } else {
                        skb = NULL;
+                       qdisc_maybe_clear_missed(q, txq);
                }
                if (lock)
                        spin_unlock(lock);
@@ -251,8 +272,10 @@ validate:
        *validate = true;
 
        if ((q->flags & TCQ_F_ONETXQUEUE) &&
-           netif_xmit_frozen_or_stopped(txq))
+           netif_xmit_frozen_or_stopped(txq)) {
+               qdisc_maybe_clear_missed(q, txq);
                return skb;
+       }
 
        skb = qdisc_dequeue_skb_bad_txq(q);
        if (unlikely(skb)) {
@@ -311,6 +334,8 @@ bool sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q,
                HARD_TX_LOCK(dev, txq, smp_processor_id());
                if (!netif_xmit_frozen_or_stopped(txq))
                        skb = dev_hard_start_xmit(skb, dev, txq, &ret);
+               else
+                       qdisc_maybe_clear_missed(q, txq);
 
                HARD_TX_UNLOCK(dev, txq);
        } else {
@@ -640,8 +665,10 @@ static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *qdisc)
 {
        struct pfifo_fast_priv *priv = qdisc_priv(qdisc);
        struct sk_buff *skb = NULL;
+       bool need_retry = true;
        int band;
 
+retry:
        for (band = 0; band < PFIFO_FAST_BANDS && !skb; band++) {
                struct skb_array *q = band2list(priv, band);
 
@@ -652,6 +679,23 @@ static struct sk_buff *pfifo_fast_dequeue(struct Qdisc *qdisc)
        }
        if (likely(skb)) {
                qdisc_update_stats_at_dequeue(qdisc, skb);
+       } else if (need_retry &&
+                  test_bit(__QDISC_STATE_MISSED, &qdisc->state)) {
+               /* Delay clearing the STATE_MISSED here to reduce
+                * the overhead of the second spin_trylock() in
+                * qdisc_run_begin() and __netif_schedule() calling
+                * in qdisc_run_end().
+                */
+               clear_bit(__QDISC_STATE_MISSED, &qdisc->state);
+
+               /* Make sure dequeuing happens after clearing
+                * STATE_MISSED.
+                */
+               smp_mb__after_atomic();
+
+               need_retry = false;
+
+               goto retry;
        } else {
                WRITE_ONCE(qdisc->empty, true);
        }
@@ -1158,8 +1202,10 @@ static void dev_reset_queue(struct net_device *dev,
        qdisc_reset(qdisc);
 
        spin_unlock_bh(qdisc_lock(qdisc));
-       if (nolock)
+       if (nolock) {
+               clear_bit(__QDISC_STATE_MISSED, &qdisc->state);
                spin_unlock_bh(&qdisc->seqlock);
+       }
 }
 
 static bool some_qdisc_is_busy(struct net_device *dev)
index 40f9f6c4a0a1d4592e5eb3e6b28911fde7131f59..a79d193ff872012a913bccad583a77a0d824d65a 100644 (file)
@@ -4473,6 +4473,7 @@ static int sctp_setsockopt_encap_port(struct sock *sk,
                                    transports)
                        t->encap_port = encap_port;
 
+               asoc->encap_port = encap_port;
                return 0;
        }
 
index e92df779af73381351b6521910bcd8e79e6df715..55871b277f475e8068692015f4a67ce1ce111c00 100644 (file)
@@ -307,7 +307,7 @@ static struct ctl_table sctp_net_table[] = {
                .data           = &init_net.sctp.encap_port,
                .maxlen         = sizeof(int),
                .mode           = 0644,
-               .proc_handler   = proc_dointvec,
+               .proc_handler   = proc_dointvec_minmax,
                .extra1         = SYSCTL_ZERO,
                .extra2         = &udp_port_max,
        },
index 9c6e95882553eb97374e3d080b581308bba91a89..967712ba52a0d36d525ce808ad1d0ffb62bf5837 100644 (file)
@@ -402,6 +402,14 @@ struct smcd_dev *smcd_alloc_dev(struct device *parent, const char *name,
                return NULL;
        }
 
+       smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)",
+                                                WQ_MEM_RECLAIM, name);
+       if (!smcd->event_wq) {
+               kfree(smcd->conn);
+               kfree(smcd);
+               return NULL;
+       }
+
        smcd->dev.parent = parent;
        smcd->dev.release = smcd_release;
        device_initialize(&smcd->dev);
@@ -415,19 +423,14 @@ struct smcd_dev *smcd_alloc_dev(struct device *parent, const char *name,
        INIT_LIST_HEAD(&smcd->vlan);
        INIT_LIST_HEAD(&smcd->lgr_list);
        init_waitqueue_head(&smcd->lgrs_deleted);
-       smcd->event_wq = alloc_ordered_workqueue("ism_evt_wq-%s)",
-                                                WQ_MEM_RECLAIM, name);
-       if (!smcd->event_wq) {
-               kfree(smcd->conn);
-               kfree(smcd);
-               return NULL;
-       }
        return smcd;
 }
 EXPORT_SYMBOL_GPL(smcd_alloc_dev);
 
 int smcd_register_dev(struct smcd_dev *smcd)
 {
+       int rc;
+
        mutex_lock(&smcd_dev_list.mutex);
        if (list_empty(&smcd_dev_list.list)) {
                u8 *system_eid = NULL;
@@ -447,7 +450,14 @@ int smcd_register_dev(struct smcd_dev *smcd)
                            dev_name(&smcd->dev), smcd->pnetid,
                            smcd->pnetid_by_user ? " (user defined)" : "");
 
-       return device_add(&smcd->dev);
+       rc = device_add(&smcd->dev);
+       if (rc) {
+               mutex_lock(&smcd_dev_list.mutex);
+               list_del(&smcd->list);
+               mutex_unlock(&smcd_dev_list.mutex);
+       }
+
+       return rc;
 }
 EXPORT_SYMBOL_GPL(smcd_register_dev);
 
index f555d335e910d878d85d956510f08e622e367a58..42623d6b8f0ecb9eb3f78c11eca0a7cf87ac2daa 100644 (file)
@@ -1677,13 +1677,6 @@ call_reserveresult(struct rpc_task *task)
                return;
        }
 
-       /*
-        * Even though there was an error, we may have acquired
-        * a request slot somehow.  Make sure not to leak it.
-        */
-       if (task->tk_rqstp)
-               xprt_release(task);
-
        switch (status) {
        case -ENOMEM:
                rpc_delay(task, HZ >> 2);
index e5b5a960a69b874a409e7fa7dae9cdc9dcfc1ddd..3509a7f139b98c6c11f91cdafd0d9d0c1c0a5dfe 100644 (file)
@@ -70,6 +70,7 @@
 static void     xprt_init(struct rpc_xprt *xprt, struct net *net);
 static __be32  xprt_alloc_xid(struct rpc_xprt *xprt);
 static void     xprt_destroy(struct rpc_xprt *xprt);
+static void     xprt_request_init(struct rpc_task *task);
 
 static DEFINE_SPINLOCK(xprt_list_lock);
 static LIST_HEAD(xprt_list);
@@ -1606,17 +1607,40 @@ xprt_transmit(struct rpc_task *task)
        spin_unlock(&xprt->queue_lock);
 }
 
-static void xprt_add_backlog(struct rpc_xprt *xprt, struct rpc_task *task)
+static void xprt_complete_request_init(struct rpc_task *task)
+{
+       if (task->tk_rqstp)
+               xprt_request_init(task);
+}
+
+void xprt_add_backlog(struct rpc_xprt *xprt, struct rpc_task *task)
 {
        set_bit(XPRT_CONGESTED, &xprt->state);
-       rpc_sleep_on(&xprt->backlog, task, NULL);
+       rpc_sleep_on(&xprt->backlog, task, xprt_complete_request_init);
+}
+EXPORT_SYMBOL_GPL(xprt_add_backlog);
+
+static bool __xprt_set_rq(struct rpc_task *task, void *data)
+{
+       struct rpc_rqst *req = data;
+
+       if (task->tk_rqstp == NULL) {
+               memset(req, 0, sizeof(*req));   /* mark unused */
+               task->tk_rqstp = req;
+               return true;
+       }
+       return false;
 }
 
-static void xprt_wake_up_backlog(struct rpc_xprt *xprt)
+bool xprt_wake_up_backlog(struct rpc_xprt *xprt, struct rpc_rqst *req)
 {
-       if (rpc_wake_up_next(&xprt->backlog) == NULL)
+       if (rpc_wake_up_first(&xprt->backlog, __xprt_set_rq, req) == NULL) {
                clear_bit(XPRT_CONGESTED, &xprt->state);
+               return false;
+       }
+       return true;
 }
+EXPORT_SYMBOL_GPL(xprt_wake_up_backlog);
 
 static bool xprt_throttle_congested(struct rpc_xprt *xprt, struct rpc_task *task)
 {
@@ -1626,7 +1650,7 @@ static bool xprt_throttle_congested(struct rpc_xprt *xprt, struct rpc_task *task
                goto out;
        spin_lock(&xprt->reserve_lock);
        if (test_bit(XPRT_CONGESTED, &xprt->state)) {
-               rpc_sleep_on(&xprt->backlog, task, NULL);
+               xprt_add_backlog(xprt, task);
                ret = true;
        }
        spin_unlock(&xprt->reserve_lock);
@@ -1703,11 +1727,11 @@ EXPORT_SYMBOL_GPL(xprt_alloc_slot);
 void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
 {
        spin_lock(&xprt->reserve_lock);
-       if (!xprt_dynamic_free_slot(xprt, req)) {
+       if (!xprt_wake_up_backlog(xprt, req) &&
+           !xprt_dynamic_free_slot(xprt, req)) {
                memset(req, 0, sizeof(*req));   /* mark unused */
                list_add(&req->rq_list, &xprt->free);
        }
-       xprt_wake_up_backlog(xprt);
        spin_unlock(&xprt->reserve_lock);
 }
 EXPORT_SYMBOL_GPL(xprt_free_slot);
@@ -1894,10 +1918,10 @@ void xprt_release(struct rpc_task *task)
        xdr_free_bvec(&req->rq_snd_buf);
        if (req->rq_cred != NULL)
                put_rpccred(req->rq_cred);
-       task->tk_rqstp = NULL;
        if (req->rq_release_snd_buf)
                req->rq_release_snd_buf(req);
 
+       task->tk_rqstp = NULL;
        if (likely(!bc_prealloc(req)))
                xprt->ops->free_slot(xprt, req);
        else
index 649f7d8b973313dbebc8434f32ea07d920d4e48c..c335c13615645cc73478f84b3ac72ec5d3b19893 100644 (file)
@@ -628,8 +628,9 @@ out_mapping_err:
        return false;
 }
 
-/* The tail iovec might not reside in the same page as the
- * head iovec.
+/* The tail iovec may include an XDR pad for the page list,
+ * as well as additional content, and may not reside in the
+ * same page as the head iovec.
  */
 static bool rpcrdma_prepare_tail_iov(struct rpcrdma_req *req,
                                     struct xdr_buf *xdr,
@@ -747,19 +748,27 @@ static bool rpcrdma_prepare_readch(struct rpcrdma_xprt *r_xprt,
                                   struct rpcrdma_req *req,
                                   struct xdr_buf *xdr)
 {
-       struct kvec *tail = &xdr->tail[0];
-
        if (!rpcrdma_prepare_head_iov(r_xprt, req, xdr->head[0].iov_len))
                return false;
 
-       /* If there is a Read chunk, the page list is handled
+       /* If there is a Read chunk, the page list is being handled
         * via explicit RDMA, and thus is skipped here.
         */
 
-       if (tail->iov_len) {
-               if (!rpcrdma_prepare_tail_iov(req, xdr,
-                                             offset_in_page(tail->iov_base),
-                                             tail->iov_len))
+       /* Do not include the tail if it is only an XDR pad */
+       if (xdr->tail[0].iov_len > 3) {
+               unsigned int page_base, len;
+
+               /* If the content in the page list is an odd length,
+                * xdr_write_pages() adds a pad at the beginning of
+                * the tail iovec. Force the tail's non-pad content to
+                * land at the next XDR position in the Send message.
+                */
+               page_base = offset_in_page(xdr->tail[0].iov_base);
+               len = xdr->tail[0].iov_len;
+               page_base += len & 3;
+               len -= len & 3;
+               if (!rpcrdma_prepare_tail_iov(req, xdr, page_base, len))
                        return false;
                kref_get(&req->rl_kref);
        }
index 09953597d055a01ae52f54eb04b17189733f1930..19a49d26b1e41063e85fde128f1c555325cb382b 100644 (file)
@@ -520,9 +520,8 @@ xprt_rdma_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
        return;
 
 out_sleep:
-       set_bit(XPRT_CONGESTED, &xprt->state);
-       rpc_sleep_on(&xprt->backlog, task, NULL);
        task->tk_status = -EAGAIN;
+       xprt_add_backlog(xprt, task);
 }
 
 /**
@@ -537,10 +536,11 @@ xprt_rdma_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *rqst)
        struct rpcrdma_xprt *r_xprt =
                container_of(xprt, struct rpcrdma_xprt, rx_xprt);
 
-       memset(rqst, 0, sizeof(*rqst));
-       rpcrdma_buffer_put(&r_xprt->rx_buf, rpcr_to_rdmar(rqst));
-       if (unlikely(!rpc_wake_up_next(&xprt->backlog)))
-               clear_bit(XPRT_CONGESTED, &xprt->state);
+       rpcrdma_reply_put(&r_xprt->rx_buf, rpcr_to_rdmar(rqst));
+       if (!xprt_wake_up_backlog(xprt, rqst)) {
+               memset(rqst, 0, sizeof(*rqst));
+               rpcrdma_buffer_put(&r_xprt->rx_buf, rpcr_to_rdmar(rqst));
+       }
 }
 
 static bool rpcrdma_check_regbuf(struct rpcrdma_xprt *r_xprt,
index 1e965a38089666a04485e50d2fefcd8f781d2d02..649c23518ec042285a12159b498c06359ffc49f2 100644 (file)
@@ -1200,6 +1200,20 @@ rpcrdma_mr_get(struct rpcrdma_xprt *r_xprt)
        return mr;
 }
 
+/**
+ * rpcrdma_reply_put - Put reply buffers back into pool
+ * @buffers: buffer pool
+ * @req: object to return
+ *
+ */
+void rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
+{
+       if (req->rl_reply) {
+               rpcrdma_rep_put(buffers, req->rl_reply);
+               req->rl_reply = NULL;
+       }
+}
+
 /**
  * rpcrdma_buffer_get - Get a request buffer
  * @buffers: Buffer pool from which to obtain a buffer
@@ -1228,9 +1242,7 @@ rpcrdma_buffer_get(struct rpcrdma_buffer *buffers)
  */
 void rpcrdma_buffer_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req)
 {
-       if (req->rl_reply)
-               rpcrdma_rep_put(buffers, req->rl_reply);
-       req->rl_reply = NULL;
+       rpcrdma_reply_put(buffers, req);
 
        spin_lock(&buffers->rb_lock);
        list_add(&req->rl_list, &buffers->rb_send_bufs);
index 436ad731261410b46180401cac45d4c71fe45746..5d231d94e94402bf6718701152719b4e994ab77d 100644 (file)
@@ -479,6 +479,7 @@ struct rpcrdma_req *rpcrdma_buffer_get(struct rpcrdma_buffer *);
 void rpcrdma_buffer_put(struct rpcrdma_buffer *buffers,
                        struct rpcrdma_req *req);
 void rpcrdma_rep_put(struct rpcrdma_buffer *buf, struct rpcrdma_rep *rep);
+void rpcrdma_reply_put(struct rpcrdma_buffer *buffers, struct rpcrdma_req *req);
 
 bool rpcrdma_regbuf_realloc(struct rpcrdma_regbuf *rb, size_t size,
                            gfp_t flags);
index 47aa47a2b07c50f93abcfb3661829c1e67f6f784..316d049455876a95b7281ac4fb69db825a0f2408 100644 (file)
@@ -1010,6 +1010,8 @@ static int xs_tcp_send_request(struct rpc_rqst *req)
                        kernel_sock_shutdown(transport->sock, SHUT_RDWR);
                return -ENOTCONN;
        }
+       if (!transport->inet)
+               return -ENOTCONN;
 
        xs_pktdump("packet data:",
                                req->rq_svec->iov_base,
index 5cc1f03072150f31b05b7f5117e11c9f85d75b63..3f4542e0f0650ba81935cb57d9d362738a55eb8f 100644 (file)
@@ -60,7 +60,7 @@ static int __net_init tipc_init_net(struct net *net)
        tn->trial_addr = 0;
        tn->addr_trial_end = 0;
        tn->capabilities = TIPC_NODE_CAPABILITIES;
-       INIT_WORK(&tn->final_work.work, tipc_net_finalize_work);
+       INIT_WORK(&tn->work, tipc_net_finalize_work);
        memset(tn->node_id, 0, sizeof(tn->node_id));
        memset(tn->node_id_string, 0, sizeof(tn->node_id_string));
        tn->mon_threshold = TIPC_DEF_MON_THRESHOLD;
@@ -110,7 +110,7 @@ static void __net_exit tipc_exit_net(struct net *net)
 
        tipc_detach_loopback(net);
        /* Make sure the tipc_net_finalize_work() finished */
-       cancel_work_sync(&tn->final_work.work);
+       cancel_work_sync(&tn->work);
        tipc_net_stop(net);
 
        tipc_bcast_stop(net);
@@ -119,6 +119,8 @@ static void __net_exit tipc_exit_net(struct net *net)
 #ifdef CONFIG_TIPC_CRYPTO
        tipc_crypto_stop(&tipc_net(net)->crypto_tx);
 #endif
+       while (atomic_read(&tn->wq_count))
+               cond_resched();
 }
 
 static void __net_exit tipc_pernet_pre_exit(struct net *net)
index 03de7b213f55346409f1f472713c80d8cec80d16..0a3f7a70a50a17b2785da8010e7a7d7814ac305b 100644 (file)
@@ -91,12 +91,6 @@ extern unsigned int tipc_net_id __read_mostly;
 extern int sysctl_tipc_rmem[3] __read_mostly;
 extern int sysctl_tipc_named_timeout __read_mostly;
 
-struct tipc_net_work {
-       struct work_struct work;
-       struct net *net;
-       u32 addr;
-};
-
 struct tipc_net {
        u8  node_id[NODE_ID_LEN];
        u32 node_addr;
@@ -148,7 +142,9 @@ struct tipc_net {
        struct tipc_crypto *crypto_tx;
 #endif
        /* Work item for net finalize */
-       struct tipc_net_work final_work;
+       struct work_struct work;
+       /* The numbers of work queues in schedule */
+       atomic_t wq_count;
 };
 
 static inline struct tipc_net *tipc_net(struct net *net)
index 5380f605b8514409befa7e88dc13fd97358b6a94..da69e1abf68ff7359c9b9918014eafd58ab73da1 100644 (file)
@@ -168,7 +168,7 @@ static bool tipc_disc_addr_trial_msg(struct tipc_discoverer *d,
 
        /* Apply trial address if we just left trial period */
        if (!trial && !self) {
-               tipc_sched_net_finalize(net, tn->trial_addr);
+               schedule_work(&tn->work);
                msg_set_prevnode(buf_msg(d->skb), tn->trial_addr);
                msg_set_type(buf_msg(d->skb), DSC_REQ_MSG);
        }
@@ -308,7 +308,7 @@ static void tipc_disc_timeout(struct timer_list *t)
        if (!time_before(jiffies, tn->addr_trial_end) && !tipc_own_addr(net)) {
                mod_timer(&d->timer, jiffies + TIPC_DISC_INIT);
                spin_unlock_bh(&d->lock);
-               tipc_sched_net_finalize(net, tn->trial_addr);
+               schedule_work(&tn->work);
                return;
        }
 
index 11510925943020b96436ab3a371f7e9e2a100dfe..c44b4bfaaee6a9e6534debab968bc611db9e6515 100644 (file)
@@ -372,6 +372,11 @@ char tipc_link_plane(struct tipc_link *l)
        return l->net_plane;
 }
 
+struct net *tipc_link_net(struct tipc_link *l)
+{
+       return l->net;
+}
+
 void tipc_link_update_caps(struct tipc_link *l, u16 capabilities)
 {
        l->peer_caps = capabilities;
index fc07232c9a12782ccbd628c87ac59a4abaa7ca1c..a16f401fdabda346e71ff4ef964c98287ba1d7b0 100644 (file)
@@ -156,4 +156,5 @@ int tipc_link_bc_sync_rcv(struct tipc_link *l,   struct tipc_msg *hdr,
 int tipc_link_bc_nack_rcv(struct tipc_link *l, struct sk_buff *skb,
                          struct sk_buff_head *xmitq);
 bool tipc_link_too_silent(struct tipc_link *l);
+struct net *tipc_link_net(struct tipc_link *l);
 #endif
index 3f0a25345a7c089ca4e328aa4a668148a2311767..ce6ab54822d8db184ac6b41dc380467668408547 100644 (file)
@@ -149,18 +149,13 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf)
                if (unlikely(head))
                        goto err;
                *buf = NULL;
+               if (skb_has_frag_list(frag) && __skb_linearize(frag))
+                       goto err;
                frag = skb_unshare(frag, GFP_ATOMIC);
                if (unlikely(!frag))
                        goto err;
                head = *headbuf = frag;
                TIPC_SKB_CB(head)->tail = NULL;
-               if (skb_is_nonlinear(head)) {
-                       skb_walk_frags(head, tail) {
-                               TIPC_SKB_CB(head)->tail = tail;
-                       }
-               } else {
-                       skb_frag_list_init(head);
-               }
                return 0;
        }
 
index a130195af188302b3aa306d1e6b94c3d643e0914..0e95572e56b41eb24ffd8e016cbf771fd174f725 100644 (file)
@@ -41,6 +41,7 @@
 #include "socket.h"
 #include "node.h"
 #include "bcast.h"
+#include "link.h"
 #include "netlink.h"
 #include "monitor.h"
 
@@ -142,19 +143,9 @@ static void tipc_net_finalize(struct net *net, u32 addr)
 
 void tipc_net_finalize_work(struct work_struct *work)
 {
-       struct tipc_net_work *fwork;
+       struct tipc_net *tn = container_of(work, struct tipc_net, work);
 
-       fwork = container_of(work, struct tipc_net_work, work);
-       tipc_net_finalize(fwork->net, fwork->addr);
-}
-
-void tipc_sched_net_finalize(struct net *net, u32 addr)
-{
-       struct tipc_net *tn = tipc_net(net);
-
-       tn->final_work.net = net;
-       tn->final_work.addr = addr;
-       schedule_work(&tn->final_work.work);
+       tipc_net_finalize(tipc_link_net(tn->bcl), tn->trial_addr);
 }
 
 void tipc_net_stop(struct net *net)
index 8217905348f48a454444eb943c0432135e991b30..81af92954c6c250045570641f14362a2ebd6a539 100644 (file)
@@ -423,18 +423,18 @@ static void tipc_node_write_unlock(struct tipc_node *n)
        write_unlock_bh(&n->lock);
 
        if (flags & TIPC_NOTIFY_NODE_DOWN)
-               tipc_publ_notify(net, publ_list, n->addr, n->capabilities);
+               tipc_publ_notify(net, publ_list, sk.node, n->capabilities);
 
        if (flags & TIPC_NOTIFY_NODE_UP)
-               tipc_named_node_up(net, n->addr, n->capabilities);
+               tipc_named_node_up(net, sk.node, n->capabilities);
 
        if (flags & TIPC_NOTIFY_LINK_UP) {
-               tipc_mon_peer_up(net, n->addr, bearer_id);
-               tipc_nametbl_publish(net, &ua, &sk, n->link_id);
+               tipc_mon_peer_up(net, sk.node, bearer_id);
+               tipc_nametbl_publish(net, &ua, &sk, sk.ref);
        }
        if (flags & TIPC_NOTIFY_LINK_DOWN) {
-               tipc_mon_peer_down(net, n->addr, bearer_id);
-               tipc_nametbl_withdraw(net, &ua, &sk, n->link_id);
+               tipc_mon_peer_down(net, sk.node, bearer_id);
+               tipc_nametbl_withdraw(net, &ua, &sk, sk.ref);
        }
 }
 
index 58935cd0d068a155fc11d0a59344b211ba33b761..53af72824c9cebc9aee0a392045e51fd8acaa010 100644 (file)
@@ -1262,7 +1262,10 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq,
                spin_lock_bh(&inputq->lock);
                if (skb_peek(arrvq) == skb) {
                        skb_queue_splice_tail_init(&tmpq, inputq);
-                       __skb_dequeue(arrvq);
+                       /* Decrease the skb's refcnt as increasing in the
+                        * function tipc_skb_peek
+                        */
+                       kfree_skb(__skb_dequeue(arrvq));
                }
                spin_unlock_bh(&inputq->lock);
                __skb_queue_purge(&tmpq);
index e556d2cdc06447eb6cbc5088b5317c1648a9f485..c2bb818704c8ff19c03030816857e4eb06a020bf 100644 (file)
@@ -814,6 +814,7 @@ static void cleanup_bearer(struct work_struct *work)
                kfree_rcu(rcast, rcu);
        }
 
+       atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
        dst_cache_destroy(&ub->rcast.dst_cache);
        udp_tunnel_sock_release(ub->ubsock);
        synchronize_net();
@@ -834,6 +835,7 @@ static void tipc_udp_disable(struct tipc_bearer *b)
        RCU_INIT_POINTER(ub->bearer, NULL);
 
        /* sock_release need to be done outside of rtnl lock */
+       atomic_inc(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
        INIT_WORK(&ub->work, cleanup_bearer);
        schedule_work(&ub->work);
 }
index 1dcb34dfd56b35a8cd4e29f5ab3dcbb8a91db42e..694de024d0ee6cc1722b4cd7420b5a191bbb4b63 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <linux/sched/signal.h>
 #include <linux/module.h>
+#include <linux/splice.h>
 #include <crypto/aead.h>
 
 #include <net/strparser.h>
@@ -1281,7 +1282,7 @@ int tls_sw_sendpage(struct sock *sk, struct page *page,
 }
 
 static struct sk_buff *tls_wait_data(struct sock *sk, struct sk_psock *psock,
-                                    int flags, long timeo, int *err)
+                                    bool nonblock, long timeo, int *err)
 {
        struct tls_context *tls_ctx = tls_get_ctx(sk);
        struct tls_sw_context_rx *ctx = tls_sw_ctx_rx(tls_ctx);
@@ -1306,7 +1307,7 @@ static struct sk_buff *tls_wait_data(struct sock *sk, struct sk_psock *psock,
                if (sock_flag(sk, SOCK_DONE))
                        return NULL;
 
-               if ((flags & MSG_DONTWAIT) || !timeo) {
+               if (nonblock || !timeo) {
                        *err = -EAGAIN;
                        return NULL;
                }
@@ -1786,7 +1787,7 @@ int tls_sw_recvmsg(struct sock *sk,
                bool async_capable;
                bool async = false;
 
-               skb = tls_wait_data(sk, psock, flags, timeo, &err);
+               skb = tls_wait_data(sk, psock, flags & MSG_DONTWAIT, timeo, &err);
                if (!skb) {
                        if (psock) {
                                int ret = sk_msg_recvmsg(sk, psock, msg, len,
@@ -1990,9 +1991,9 @@ ssize_t tls_sw_splice_read(struct socket *sock,  loff_t *ppos,
 
        lock_sock(sk);
 
-       timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+       timeo = sock_rcvtimeo(sk, flags & SPLICE_F_NONBLOCK);
 
-       skb = tls_wait_data(sk, NULL, flags, timeo, &err);
+       skb = tls_wait_data(sk, NULL, flags & SPLICE_F_NONBLOCK, timeo, &err);
        if (!skb)
                goto splice_read_end;
 
index 382c5262d997dd7c439b11382ab3846e941c9400..7ec021a610aebd69edda19f2ca25ff9ef681d5b0 100644 (file)
@@ -542,7 +542,7 @@ EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
 
 int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
                                  const u8 *addr, enum nl80211_iftype iftype,
-                                 u8 data_offset)
+                                 u8 data_offset, bool is_amsdu)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct {
@@ -629,7 +629,7 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
        skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
        tmp.h_proto = payload.proto;
 
-       if (likely((ether_addr_equal(payload.hdr, rfc1042_header) &&
+       if (likely((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
                    tmp.h_proto != htons(ETH_P_AARP) &&
                    tmp.h_proto != htons(ETH_P_IPX)) ||
                   ether_addr_equal(payload.hdr, bridge_tunnel_header)))
@@ -771,6 +771,9 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
                remaining = skb->len - offset;
                if (subframe_len > remaining)
                        goto purge;
+               /* mitigate A-MSDU aggregation injection attacks */
+               if (ether_addr_equal(eth.h_dest, rfc1042_header))
+                       goto purge;
 
                offset += sizeof(struct ethhdr);
                last = remaining <= subframe_len + padding;
index aa696854be787e117a878fd9b8f4ab38af99fa8e..53e300f860bb4f4290307e8443fbf68f4d8cf7e0 100644 (file)
@@ -1255,7 +1255,7 @@ static void tx_only(struct xsk_socket_info *xsk, u32 *frame_nb, int batch_size)
        for (i = 0; i < batch_size; i++) {
                struct xdp_desc *tx_desc = xsk_ring_prod__tx_desc(&xsk->tx,
                                                                  idx + i);
-               tx_desc->addr = (*frame_nb + i) << XSK_UMEM__DEFAULT_FRAME_SHIFT;
+               tx_desc->addr = (*frame_nb + i) * opt_xsk_frame_size;
                tx_desc->len = PKT_SIZE;
        }
 
index f6d543725f1ed685870ae14d3528522ac133f716..b2483149bbe55028527b8bbf439e663d6d032560 100755 (executable)
@@ -76,7 +76,11 @@ fi
 if arg_contain -S "$@"; then
        # For scripts/gcc-x86-*-has-stack-protector.sh
        if arg_contain -fstack-protector "$@"; then
-               echo "%gs"
+               if arg_contain -mstack-protector-guard-reg=fs "$@"; then
+                       echo "%fs"
+               else
+                       echo "%gs"
+               fi
                exit 0
        fi
 
index 48d141e3ec56f280045a996f926a8213ace36dac..8762887a970ce2479eb6a43ae654c36136369f6c 100755 (executable)
@@ -10,7 +10,7 @@ from __future__ import print_function
 import os, sys, errno
 import subprocess
 
-# Extract and prepare jobserver file descriptors from envirnoment.
+# Extract and prepare jobserver file descriptors from environment.
 claim = 0
 jobs = b""
 try:
index 25778765cbfe932f4b702737441a5141bd1cab62..9897bd26a438852603d28b6f96a6f4f801754451 100644 (file)
@@ -38,7 +38,7 @@ config SND_OXFW
           * Mackie(Loud) Onyx 1640i (former model)
           * Mackie(Loud) Onyx Satellite
           * Mackie(Loud) Tapco Link.Firewire
-          * Mackie(Loud) d.2 pro/d.4 pro
+          * Mackie(Loud) d.4 pro
           * Mackie(Loud) U.420/U.420d
           * TASCAM FireOne
           * Stanton Controllers & Systems 1 Deck/Mixer
@@ -84,7 +84,7 @@ config SND_BEBOB
          * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394
          * BridgeCo RDAudio1/Audio5
          * Mackie Onyx 1220/1620/1640 (FireWire I/O Card)
-         * Mackie d.2 (FireWire Option)
+         * Mackie d.2 (FireWire Option) and d.2 Pro
          * Stanton FinalScratch 2 (ScratchAmp)
          * Tascam IF-FW/DM
          * Behringer XENIX UFX 1204/1604
index 26e7cb555d3c593d81c2653267f95469190e6cbe..aa53c13b89d34ec0ba77338e839429106689095f 100644 (file)
@@ -14,8 +14,8 @@
 #include <linux/tracepoint.h>
 
 TRACE_EVENT(amdtp_packet,
-       TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int data_block_counter, unsigned int index),
-       TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, data_block_counter, index),
+       TP_PROTO(const struct amdtp_stream *s, u32 cycles, const __be32 *cip_header, unsigned int payload_length, unsigned int data_blocks, unsigned int data_block_counter, unsigned int packet_index, unsigned int index),
+       TP_ARGS(s, cycles, cip_header, payload_length, data_blocks, data_block_counter, packet_index, index),
        TP_STRUCT__entry(
                __field(unsigned int, second)
                __field(unsigned int, cycle)
@@ -48,7 +48,7 @@ TRACE_EVENT(amdtp_packet,
                __entry->payload_quadlets = payload_length / sizeof(__be32);
                __entry->data_blocks = data_blocks;
                __entry->data_block_counter = data_block_counter,
-               __entry->packet_index = s->packet_index;
+               __entry->packet_index = packet_index;
                __entry->irq = !!in_interrupt();
                __entry->index = index;
        ),
index 4e2f2bb7879fb2fcdbb1fcc5868542ea836a2a7b..e0faa6601966cae2a53e82e80b4a768d79997192 100644 (file)
@@ -526,7 +526,7 @@ static void build_it_pkt_header(struct amdtp_stream *s, unsigned int cycle,
        }
 
        trace_amdtp_packet(s, cycle, cip_header, payload_length, data_blocks,
-                          data_block_counter, index);
+                          data_block_counter, s->packet_index, index);
 }
 
 static int check_cip_header(struct amdtp_stream *s, const __be32 *buf,
@@ -630,21 +630,27 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle,
                               unsigned int *payload_length,
                               unsigned int *data_blocks,
                               unsigned int *data_block_counter,
-                              unsigned int *syt, unsigned int index)
+                              unsigned int *syt, unsigned int packet_index, unsigned int index)
 {
        const __be32 *cip_header;
+       unsigned int cip_header_size;
        int err;
 
        *payload_length = be32_to_cpu(ctx_header[0]) >> ISO_DATA_LENGTH_SHIFT;
-       if (*payload_length > s->ctx_data.tx.ctx_header_size +
-                                       s->ctx_data.tx.max_ctx_payload_length) {
+
+       if (!(s->flags & CIP_NO_HEADER))
+               cip_header_size = 8;
+       else
+               cip_header_size = 0;
+
+       if (*payload_length > cip_header_size + s->ctx_data.tx.max_ctx_payload_length) {
                dev_err(&s->unit->device,
                        "Detect jumbo payload: %04x %04x\n",
-                       *payload_length, s->ctx_data.tx.max_ctx_payload_length);
+                       *payload_length, cip_header_size + s->ctx_data.tx.max_ctx_payload_length);
                return -EIO;
        }
 
-       if (!(s->flags & CIP_NO_HEADER)) {
+       if (cip_header_size > 0) {
                cip_header = ctx_header + 2;
                err = check_cip_header(s, cip_header, *payload_length,
                                       data_blocks, data_block_counter, syt);
@@ -662,7 +668,7 @@ static int parse_ir_ctx_header(struct amdtp_stream *s, unsigned int cycle,
        }
 
        trace_amdtp_packet(s, cycle, cip_header, *payload_length, *data_blocks,
-                          *data_block_counter, index);
+                          *data_block_counter, packet_index, index);
 
        return err;
 }
@@ -701,12 +707,13 @@ static int generate_device_pkt_descs(struct amdtp_stream *s,
                                     unsigned int packets)
 {
        unsigned int dbc = s->data_block_counter;
+       unsigned int packet_index = s->packet_index;
+       unsigned int queue_size = s->queue_size;
        int i;
        int err;
 
        for (i = 0; i < packets; ++i) {
                struct pkt_desc *desc = descs + i;
-               unsigned int index = (s->packet_index + i) % s->queue_size;
                unsigned int cycle;
                unsigned int payload_length;
                unsigned int data_blocks;
@@ -715,7 +722,7 @@ static int generate_device_pkt_descs(struct amdtp_stream *s,
                cycle = compute_cycle_count(ctx_header[1]);
 
                err = parse_ir_ctx_header(s, cycle, ctx_header, &payload_length,
-                                         &data_blocks, &dbc, &syt, i);
+                                         &data_blocks, &dbc, &syt, packet_index, i);
                if (err < 0)
                        return err;
 
@@ -723,13 +730,15 @@ static int generate_device_pkt_descs(struct amdtp_stream *s,
                desc->syt = syt;
                desc->data_blocks = data_blocks;
                desc->data_block_counter = dbc;
-               desc->ctx_payload = s->buffer.packets[index].buffer;
+               desc->ctx_payload = s->buffer.packets[packet_index].buffer;
 
                if (!(s->flags & CIP_DBC_IS_END_EVENT))
                        dbc = (dbc + desc->data_blocks) & 0xff;
 
                ctx_header +=
                        s->ctx_data.tx.ctx_header_size / sizeof(*ctx_header);
+
+               packet_index = (packet_index + 1) % queue_size;
        }
 
        s->data_block_counter = dbc;
@@ -1065,23 +1074,22 @@ static int amdtp_stream_start(struct amdtp_stream *s, int channel, int speed,
                s->data_block_counter = 0;
        }
 
-       /* initialize packet buffer */
+       // initialize packet buffer.
+       max_ctx_payload_size = amdtp_stream_get_max_payload(s);
        if (s->direction == AMDTP_IN_STREAM) {
                dir = DMA_FROM_DEVICE;
                type = FW_ISO_CONTEXT_RECEIVE;
-               if (!(s->flags & CIP_NO_HEADER))
+               if (!(s->flags & CIP_NO_HEADER)) {
+                       max_ctx_payload_size -= 8;
                        ctx_header_size = IR_CTX_HEADER_SIZE_CIP;
-               else
+               } else {
                        ctx_header_size = IR_CTX_HEADER_SIZE_NO_CIP;
-
-               max_ctx_payload_size = amdtp_stream_get_max_payload(s) -
-                                      ctx_header_size;
+               }
        } else {
                dir = DMA_TO_DEVICE;
                type = FW_ISO_CONTEXT_TRANSMIT;
                ctx_header_size = 0;    // No effect for IT context.
 
-               max_ctx_payload_size = amdtp_stream_get_max_payload(s);
                if (!(s->flags & CIP_NO_HEADER))
                        max_ctx_payload_size -= IT_PKT_HEADER_SIZE_CIP;
        }
index 2c8e3392a4903a129acc28ecb9d21ffc698eae18..daeecfa8b9aac3e6666de77fcf4d31cb91264dbb 100644 (file)
@@ -387,7 +387,7 @@ static const struct ieee1394_device_id bebob_id_table[] = {
        SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal),
        /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */
        SND_BEBOB_DEV_ENTRY(VEN_MACKIE2, 0x00010065, &spec_normal),
-       /* Mackie, d.2 (Firewire Option) */
+       // Mackie, d.2 (Firewire option card) and d.2 Pro (the card is built-in).
        SND_BEBOB_DEV_ENTRY(VEN_MACKIE1, 0x00010067, &spec_normal),
        /* Stanton, ScratchAmp */
        SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal),
index 0916864511d50607e9326b498a77f2587778fef9..27c13b9cc9efda96346088cdc4dd0ab7ce6a5fdc 100644 (file)
@@ -16,7 +16,7 @@ alesis_io14_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {
 static const unsigned int
 alesis_io26_tx_pcm_chs[MAX_STREAMS][SND_DICE_RATE_MODE_COUNT] = {
        {10, 10, 4},    /* Tx0 = Analog + S/PDIF. */
-       {16, 8, 0},     /* Tx1 = ADAT1 + ADAT2. */
+       {16, 4, 0},     /* Tx1 = ADAT1 + ADAT2 (available at low rate). */
 };
 
 int snd_dice_detect_alesis_formats(struct snd_dice *dice)
index af8a90ee40f395adb5e7c2dbefae9684d2110e80..a69ca1111b0332f5386f154d6a2d4998d23c55b6 100644 (file)
@@ -218,7 +218,7 @@ static int pcm_open(struct snd_pcm_substream *substream)
 
                if (frames_per_period > 0) {
                        // For double_pcm_frame quirk.
-                       if (rate > 96000) {
+                       if (rate > 96000 && !dice->disable_double_pcm_frames) {
                                frames_per_period *= 2;
                                frames_per_buffer *= 2;
                        }
@@ -273,7 +273,7 @@ static int pcm_hw_params(struct snd_pcm_substream *substream,
 
                mutex_lock(&dice->mutex);
                // For double_pcm_frame quirk.
-               if (rate > 96000) {
+               if (rate > 96000 && !dice->disable_double_pcm_frames) {
                        events_per_period /= 2;
                        events_per_buffer /= 2;
                }
index 1a14c083e8ceaac63488d37f367878323d5a7459..c4dfe76500c29038a8cbcbddd12ae7694c4d23d7 100644 (file)
@@ -181,7 +181,7 @@ static int keep_resources(struct snd_dice *dice, struct amdtp_stream *stream,
        // as 'Dual Wire'.
        // For this quirk, blocking mode is required and PCM buffer size should
        // be aligned to SYT_INTERVAL.
-       double_pcm_frames = rate > 96000;
+       double_pcm_frames = (rate > 96000 && !dice->disable_double_pcm_frames);
        if (double_pcm_frames) {
                rate /= 2;
                pcm_chs *= 2;
index a8875d24ba2aa00aa1743dbde59c310af8ec310d..43a3bcb15b3d17e5ee4d18bbe0b4c9f70487ea82 100644 (file)
@@ -38,8 +38,8 @@ static const struct dice_tc_spec konnekt_24d = {
 };
 
 static const struct dice_tc_spec konnekt_live = {
-       .tx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
-       .rx_pcm_chs = {{16, 16, 16}, {0, 0, 0} },
+       .tx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
+       .rx_pcm_chs = {{16, 16, 6}, {0, 0, 0} },
        .has_midi = true,
 };
 
index 107a81691f0e819fad9bb79c858c844c58723cc9..239d164b0eea85e5d0667c3d8e45d60716a70e9b 100644 (file)
@@ -21,6 +21,7 @@ MODULE_LICENSE("GPL v2");
 #define OUI_SSL                        0x0050c2        // Actually ID reserved by IEEE.
 #define OUI_PRESONUS           0x000a92
 #define OUI_HARMAN             0x000fd7
+#define OUI_AVID               0x00a07e
 
 #define DICE_CATEGORY_ID       0x04
 #define WEISS_CATEGORY_ID      0x00
@@ -222,6 +223,14 @@ static int dice_probe(struct fw_unit *unit,
                                (snd_dice_detect_formats_t)entry->driver_data;
        }
 
+       // Below models are compliant to IEC 61883-1/6 and have no quirk at high sampling transfer
+       // frequency.
+       // * Avid M-Box 3 Pro
+       // * M-Audio Profire 610
+       // * M-Audio Profire 2626
+       if (entry->vendor_id == OUI_MAUDIO || entry->vendor_id == OUI_AVID)
+               dice->disable_double_pcm_frames = true;
+
        spin_lock_init(&dice->lock);
        mutex_init(&dice->mutex);
        init_completion(&dice->clock_accepted);
@@ -278,7 +287,22 @@ static void dice_bus_reset(struct fw_unit *unit)
 
 #define DICE_INTERFACE 0x000001
 
+#define DICE_DEV_ENTRY_TYPICAL(vendor, model, data) \
+       { \
+               .match_flags    = IEEE1394_MATCH_VENDOR_ID | \
+                                 IEEE1394_MATCH_MODEL_ID | \
+                                 IEEE1394_MATCH_SPECIFIER_ID | \
+                                 IEEE1394_MATCH_VERSION, \
+               .vendor_id      = (vendor), \
+               .model_id       = (model), \
+               .specifier_id   = (vendor), \
+               .version        = DICE_INTERFACE, \
+               .driver_data = (kernel_ulong_t)(data), \
+       }
+
 static const struct ieee1394_device_id dice_id_table[] = {
+       // Avid M-Box 3 Pro. To match in probe function.
+       DICE_DEV_ENTRY_TYPICAL(OUI_AVID, 0x000004, snd_dice_detect_extension_formats),
        /* M-Audio Profire 2626 has a different value in version field. */
        {
                .match_flags    = IEEE1394_MATCH_VENDOR_ID |
index adc6f7c8446091f0b2ef5370ff0765dee879ae68..3c967d1b3605d83f763ae8e163ffdd5f411c79bc 100644 (file)
@@ -109,7 +109,8 @@ struct snd_dice {
        struct fw_iso_resources rx_resources[MAX_STREAMS];
        struct amdtp_stream tx_stream[MAX_STREAMS];
        struct amdtp_stream rx_stream[MAX_STREAMS];
-       bool global_enabled;
+       bool global_enabled:1;
+       bool disable_double_pcm_frames:1;
        struct completion clock_accepted;
        unsigned int substreams_counter;
 
index 1f1e3236efb8e045300d4cc074f95bda46fd6a8c..9eea25c46dc7e8b43305fb22effa0482a7910707 100644 (file)
@@ -355,7 +355,6 @@ static const struct ieee1394_device_id oxfw_id_table[] = {
         *  Onyx-i series (former models):      0x081216
         *  Mackie Onyx Satellite:              0x00200f
         *  Tapco LINK.firewire 4x6:            0x000460
-        *  d.2 pro:                            Unknown
         *  d.4 pro:                            Unknown
         *  U.420:                              Unknown
         *  U.420d:                             Unknown
index afc088f0377ce4f36136a8fbcda49b34ee45eeaf..b7518122a10d6ff3bdf17d1dcfd6090896c5869c 100644 (file)
@@ -77,17 +77,8 @@ static const struct snd_kcontrol_new snd_gus_joystick_control = {
 
 static void snd_gus_init_control(struct snd_gus_card *gus)
 {
-       int ret;
-
-       if (!gus->ace_flag) {
-               ret =
-                       snd_ctl_add(gus->card,
-                                       snd_ctl_new1(&snd_gus_joystick_control,
-                                               gus));
-               if (ret)
-                       snd_printk(KERN_ERR "gus: snd_ctl_add failed: %d\n",
-                                       ret);
-       }
+       if (!gus->ace_flag)
+               snd_ctl_add(gus->card, snd_ctl_new1(&snd_gus_joystick_control, gus));
 }
 
 /*
index 38dc1fde25f3cbbe53c754ad87d51cebbe3223cf..aa48705310231c274ce5d8c8d332a1aca25723d2 100644 (file)
@@ -846,14 +846,10 @@ int snd_sb16dsp_pcm(struct snd_sb *chip, int device)
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_sb16_playback_ops);
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_sb16_capture_ops);
 
-       if (chip->dma16 >= 0 && chip->dma8 != chip->dma16) {
-               err = snd_ctl_add(card, snd_ctl_new1(
-                                       &snd_sb16_dma_control, chip));
-               if (err)
-                       return err;
-       } else {
+       if (chip->dma16 >= 0 && chip->dma8 != chip->dma16)
+               snd_ctl_add(card, snd_ctl_new1(&snd_sb16_dma_control, chip));
+       else
                pcm->info_flags = SNDRV_PCM_INFO_HALF_DUPLEX;
-       }
 
        snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
                                       card->dev, 64*1024, 128*1024);
index 6c9d534ce8b6133f57cd0f47dfd61b7a2945e83e..ed3a87ebe3f4119cc0698dc3852471891826c03a 100644 (file)
@@ -93,12 +93,12 @@ static int snd_sb8_probe(struct device *pdev, unsigned int dev)
        acard = card->private_data;
        card->private_free = snd_sb8_free;
 
-       /* block the 0x388 port to avoid PnP conflicts */
+       /*
+        * Block the 0x388 port to avoid PnP conflicts.
+        * No need to check this value after request_region,
+        * as we never do anything with it.
+        */
        acard->fm_res = request_region(0x388, 4, "SoundBlaster FM");
-       if (!acard->fm_res) {
-               err = -EBUSY;
-               goto _err;
-       }
 
        if (port[dev] != SNDRV_AUTO_PORT) {
                if ((err = snd_sbdsp_create(card, port[dev], irq[dev],
index 6d58f24c9702f963ad60b5d9c4af4de9a970ece0..61a60c420f6fda2dd926add9d40101825fd78066 100644 (file)
@@ -395,7 +395,6 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0282:
        case 0x10ec0283:
        case 0x10ec0286:
-       case 0x10ec0287:
        case 0x10ec0288:
        case 0x10ec0285:
        case 0x10ec0298:
@@ -406,6 +405,10 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0275:
                alc_update_coef_idx(codec, 0xe, 0, 1<<0);
                break;
+       case 0x10ec0287:
+               alc_update_coef_idx(codec, 0x10, 1<<9, 0);
+               alc_write_coef_idx(codec, 0x8, 0x4ab7);
+               break;
        case 0x10ec0293:
                alc_update_coef_idx(codec, 0xa, 1<<13, 0);
                break;
@@ -2600,6 +2603,28 @@ static const struct hda_model_fixup alc882_fixup_models[] = {
        {}
 };
 
+static const struct snd_hda_pin_quirk alc882_pin_fixup_tbl[] = {
+       SND_HDA_PIN_QUIRK(0x10ec1220, 0x1043, "ASUS", ALC1220_FIXUP_CLEVO_P950,
+               {0x14, 0x01014010},
+               {0x15, 0x01011012},
+               {0x16, 0x01016011},
+               {0x18, 0x01a19040},
+               {0x19, 0x02a19050},
+               {0x1a, 0x0181304f},
+               {0x1b, 0x0221401f},
+               {0x1e, 0x01456130}),
+       SND_HDA_PIN_QUIRK(0x10ec1220, 0x1462, "MS-7C35", ALC1220_FIXUP_CLEVO_P950,
+               {0x14, 0x01015010},
+               {0x15, 0x01011012},
+               {0x16, 0x01011011},
+               {0x18, 0x01a11040},
+               {0x19, 0x02a19050},
+               {0x1a, 0x0181104f},
+               {0x1b, 0x0221401f},
+               {0x1e, 0x01451130}),
+       {}
+};
+
 /*
  * BIOS auto configuration
  */
@@ -2641,6 +2666,7 @@ static int patch_alc882(struct hda_codec *codec)
 
        snd_hda_pick_fixup(codec, alc882_fixup_models, alc882_fixup_tbl,
                       alc882_fixups);
+       snd_hda_pick_pin_fixup(codec, alc882_pin_fixup_tbl, alc882_fixups, true);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
        alc_auto_parse_customize_define(codec);
@@ -6251,6 +6277,35 @@ static void alc294_fixup_gx502_hp(struct hda_codec *codec,
        }
 }
 
+static void alc294_gu502_toggle_output(struct hda_codec *codec,
+                                      struct hda_jack_callback *cb)
+{
+       /* Windows sets 0x10 to 0x8420 for Node 0x20 which is
+        * responsible from changes between speakers and headphones
+        */
+       if (snd_hda_jack_detect_state(codec, 0x21) == HDA_JACK_PRESENT)
+               alc_write_coef_idx(codec, 0x10, 0x8420);
+       else
+               alc_write_coef_idx(codec, 0x10, 0x0a20);
+}
+
+static void alc294_fixup_gu502_hp(struct hda_codec *codec,
+                                 const struct hda_fixup *fix, int action)
+{
+       if (!is_jack_detectable(codec, 0x21))
+               return;
+
+       switch (action) {
+       case HDA_FIXUP_ACT_PRE_PROBE:
+               snd_hda_jack_detect_enable_callback(codec, 0x21,
+                               alc294_gu502_toggle_output);
+               break;
+       case HDA_FIXUP_ACT_INIT:
+               alc294_gu502_toggle_output(codec, NULL);
+               break;
+       }
+}
+
 static void  alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
                              const struct hda_fixup *fix, int action)
 {
@@ -6468,6 +6523,9 @@ enum {
        ALC294_FIXUP_ASUS_GX502_HP,
        ALC294_FIXUP_ASUS_GX502_PINS,
        ALC294_FIXUP_ASUS_GX502_VERBS,
+       ALC294_FIXUP_ASUS_GU502_HP,
+       ALC294_FIXUP_ASUS_GU502_PINS,
+       ALC294_FIXUP_ASUS_GU502_VERBS,
        ALC285_FIXUP_HP_GPIO_LED,
        ALC285_FIXUP_HP_MUTE_LED,
        ALC236_FIXUP_HP_GPIO_LED,
@@ -6507,6 +6565,9 @@ enum {
        ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST,
        ALC295_FIXUP_ASUS_DACS,
        ALC295_FIXUP_HP_OMEN,
+       ALC285_FIXUP_HP_SPECTRE_X360,
+       ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP,
+       ALC623_FIXUP_LENOVO_THINKSTATION_P340,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -7709,6 +7770,35 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc294_fixup_gx502_hp,
        },
+       [ALC294_FIXUP_ASUS_GU502_PINS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x01a11050 }, /* rear HP mic */
+                       { 0x1a, 0x01a11830 }, /* rear external mic */
+                       { 0x21, 0x012110f0 }, /* rear HP out */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_GU502_VERBS
+       },
+       [ALC294_FIXUP_ASUS_GU502_VERBS] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* set 0x15 to HP-OUT ctrl */
+                       { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+                       /* unmute the 0x15 amp */
+                       { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+                       /* set 0x1b to HP-OUT */
+                       { 0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC294_FIXUP_ASUS_GU502_HP
+       },
+       [ALC294_FIXUP_ASUS_GU502_HP] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc294_fixup_gu502_hp,
+       },
        [ALC294_FIXUP_ASUS_COEF_1B] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -8035,6 +8125,27 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC269_FIXUP_HP_LINE1_MIC1_LED,
        },
+       [ALC285_FIXUP_HP_SPECTRE_X360] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x14, 0x90170110 }, /* enable top speaker */
+                       {}
+               },
+               .chained = true,
+               .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1,
+       },
+       [ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc285_fixup_ideapad_s740_coef,
+               .chained = true,
+               .chain_id = ALC285_FIXUP_THINKPAD_HEADSET_JACK,
+       },
+       [ALC623_FIXUP_LENOVO_THINKSTATION_P340] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_no_shutup,
+               .chained = true,
+               .chain_id = ALC283_FIXUP_HEADSET_MIC,
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -8195,6 +8306,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x8497, "HP Envy x360", ALC269_FIXUP_HP_MUTE_LED_MIC3),
        SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
        SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
+       SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
        SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO),
        SND_PCI_QUIRK(0x103c, 0x8724, "HP EliteBook 850 G7", ALC285_FIXUP_HP_GPIO_LED),
@@ -8216,6 +8328,10 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP),
        SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
        SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED),
+       SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+       SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+       SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT),
+       SND_PCI_QUIRK(0x103c, 0x8896, "HP EliteBook 855 G8 Notebook PC", ALC285_FIXUP_HP_MUTE_LED),
        SND_PCI_QUIRK(0x103c, 0x8898, "HP EliteBook 845 G8 Notebook PC", ALC285_FIXUP_HP_LIMIT_INT_MIC_BOOST),
        SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
@@ -8253,6 +8369,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1043, 0x1ccd, "ASUS X555UB", ALC256_FIXUP_ASUS_MIC),
        SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
        SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
+       SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
        SND_PCI_QUIRK(0x1043, 0x1e8e, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x1f11, "ASUS Zephyrus G14", ALC289_FIXUP_ASUS_GA401),
        SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
@@ -8309,12 +8426,19 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x50b8, "Clevo NK50SZ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x50d5, "Clevo NP50D5", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x50f0, "Clevo NH50A[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50f2, "Clevo NH50E[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x50f3, "Clevo NH58DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50f5, "Clevo NH55EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x50f6, "Clevo NH55DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x5101, "Clevo S510WU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x5157, "Clevo W517GU1", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x51a1, "Clevo NS50MU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70f2, "Clevo NH79EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70f3, "Clevo NH77DPQ", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70f4, "Clevo NH77EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x70f6, "Clevo NH77DPQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8228, "Clevo NR40BU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8520, "Clevo NH50D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8521, "Clevo NH77D[CD]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -8332,11 +8456,19 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x8a51, "Clevo NH70RCQ-Y", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x8d50, "Clevo NH55RCQ-M", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x951d, "Clevo N950T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0x9600, "Clevo N960K[PR]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x961d, "Clevo N960S[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0x971d, "Clevo N970T[CDF]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1558, 0xa500, "Clevo NL53RU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xa600, "Clevo NL5XNU", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xb018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xb019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xb022, "Clevo NH77D[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xc018, "Clevo NP50D[BE]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xc019, "Clevo NH77D[BE]Q", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+       SND_PCI_QUIRK(0x1558, 0xc022, "Clevo NH77[DC][QW]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
-       SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x17aa, 0x1048, "ThinkCentre Station", ALC623_FIXUP_LENOVO_THINKSTATION_P340),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
@@ -8386,6 +8518,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x17aa, 0x3178, "ThinkCentre Station", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940", ALC298_FIXUP_LENOVO_SPK_VOLUME),
        SND_PCI_QUIRK(0x17aa, 0x3827, "Ideapad S740", ALC285_FIXUP_IDEAPAD_S740_COEF),
+       SND_PCI_QUIRK(0x17aa, 0x3843, "Yoga 9i", ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP),
        SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
        SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
        SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
@@ -8600,6 +8733,9 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC274_FIXUP_HP_MIC, .name = "alc274-hp-mic-detect"},
        {.id = ALC245_FIXUP_HP_X360_AMP, .name = "alc245-hp-x360-amp"},
        {.id = ALC295_FIXUP_HP_OMEN, .name = "alc295-hp-omen"},
+       {.id = ALC285_FIXUP_HP_SPECTRE_X360, .name = "alc285-hp-spectre-x360"},
+       {.id = ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP, .name = "alc287-ideapad-bass-spk-amp"},
+       {.id = ALC623_FIXUP_LENOVO_THINKSTATION_P340, .name = "alc623-lenovo-thinkstation-p340"},
        {}
 };
 #define ALC225_STANDARD_PINS \
index 35903d1a1cbd27696e28cac536d5cfc03ea629cf..5b124c4ad5725b108a8aec464cbe5581419bef20 100644 (file)
@@ -331,6 +331,7 @@ struct ichdev {
        unsigned int ali_slot;                  /* ALI DMA slot */
        struct ac97_pcm *pcm;
        int pcm_open_flag;
+       unsigned int prepared:1;
        unsigned int suspended: 1;
 };
 
@@ -691,6 +692,9 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich
        int status, civ, i, step;
        int ack = 0;
 
+       if (!ichdev->prepared || ichdev->suspended)
+               return;
+
        spin_lock_irqsave(&chip->reg_lock, flags);
        status = igetbyte(chip, port + ichdev->roff_sr);
        civ = igetbyte(chip, port + ICH_REG_OFF_CIV);
@@ -881,6 +885,7 @@ static int snd_intel8x0_hw_params(struct snd_pcm_substream *substream,
        if (ichdev->pcm_open_flag) {
                snd_ac97_pcm_close(ichdev->pcm);
                ichdev->pcm_open_flag = 0;
+               ichdev->prepared = 0;
        }
        err = snd_ac97_pcm_open(ichdev->pcm, params_rate(hw_params),
                                params_channels(hw_params),
@@ -902,6 +907,7 @@ static int snd_intel8x0_hw_free(struct snd_pcm_substream *substream)
        if (ichdev->pcm_open_flag) {
                snd_ac97_pcm_close(ichdev->pcm);
                ichdev->pcm_open_flag = 0;
+               ichdev->prepared = 0;
        }
        return 0;
 }
@@ -976,6 +982,7 @@ static int snd_intel8x0_pcm_prepare(struct snd_pcm_substream *substream)
                        ichdev->pos_shift = (runtime->sample_bits > 16) ? 2 : 1;
        }
        snd_intel8x0_setup_periods(chip, ichdev);
+       ichdev->prepared = 1;
        return 0;
 }
 
index f22bb2bdf527a94364e78a2892fbf0722abdb94d..8148b0d22e880398fbaed3f9e0fbd5a1bffbb661 100644 (file)
@@ -235,10 +235,6 @@ static int acp3x_dma_open(struct snd_soc_component *component,
                return ret;
        }
 
-       if (!adata->play_stream && !adata->capture_stream &&
-           !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
-               rv_writel(1, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
-
        i2s_data->acp3x_base = adata->acp3x_base;
        runtime->private_data = i2s_data;
        return ret;
@@ -365,12 +361,6 @@ static int acp3x_dma_close(struct snd_soc_component *component,
                }
        }
 
-       /* Disable ACP irq, when the current stream is being closed and
-        * another stream is also not active.
-        */
-       if (!adata->play_stream && !adata->capture_stream &&
-               !adata->i2ssp_play_stream && !adata->i2ssp_capture_stream)
-               rv_writel(0, adata->acp3x_base + mmACP_EXTERNAL_INTR_ENB);
        return 0;
 }
 
index 03fe93913e12e39ce506d5218e2ec06c4f481734..c3f0c8b7545db11760e1c20167cc7c9270e9fb9e 100644 (file)
@@ -77,6 +77,7 @@
 #define ACP_POWER_OFF_IN_PROGRESS      0x03
 
 #define ACP3x_ITER_IRER_SAMP_LEN_MASK  0x38
+#define ACP_EXT_INTR_STAT_CLEAR_MASK 0xFFFFFFFF
 
 struct acp3x_platform_info {
        u16 play_i2s_instance;
index d3536fd6a12400644a4cfa5b26795956fd2cedb3..a013a607b3d4705c1b9ea6e44dfcf5900849dc5d 100644 (file)
@@ -76,6 +76,19 @@ static int acp3x_reset(void __iomem *acp3x_base)
        return -ETIMEDOUT;
 }
 
+static void acp3x_enable_interrupts(void __iomem *acp_base)
+{
+       rv_writel(0x01, acp_base + mmACP_EXTERNAL_INTR_ENB);
+}
+
+static void acp3x_disable_interrupts(void __iomem *acp_base)
+{
+       rv_writel(ACP_EXT_INTR_STAT_CLEAR_MASK, acp_base +
+                 mmACP_EXTERNAL_INTR_STAT);
+       rv_writel(0x00, acp_base + mmACP_EXTERNAL_INTR_CNTL);
+       rv_writel(0x00, acp_base + mmACP_EXTERNAL_INTR_ENB);
+}
+
 static int acp3x_init(struct acp3x_dev_data *adata)
 {
        void __iomem *acp3x_base = adata->acp3x_base;
@@ -93,6 +106,7 @@ static int acp3x_init(struct acp3x_dev_data *adata)
                pr_err("ACP3x reset failed\n");
                return ret;
        }
+       acp3x_enable_interrupts(acp3x_base);
        return 0;
 }
 
@@ -100,6 +114,7 @@ static int acp3x_deinit(void __iomem *acp3x_base)
 {
        int ret;
 
+       acp3x_disable_interrupts(acp3x_base);
        /* Reset */
        ret = acp3x_reset(acp3x_base);
        if (ret) {
index 34aed80db0eb046b26a70f2110b31cedc5fd419d..37d4600b6f2c27c737830f1cfaeda1386497ba7a 100644 (file)
@@ -307,7 +307,7 @@ static struct snd_soc_dai_driver ak5558_dai = {
 };
 
 static struct snd_soc_dai_driver ak5552_dai = {
-       .name = "ak5558-aif",
+       .name = "ak5552-aif",
        .capture = {
                .stream_name = "Capture",
                .channels_min = 1,
index f4067230ac425a5388771343bb50cc527759436a..88e79b9f52edca0893eb98e8375f87f47fd90d43 100644 (file)
@@ -261,6 +261,9 @@ static const struct regmap_config cs35l32_regmap = {
        .readable_reg = cs35l32_readable_register,
        .precious_reg = cs35l32_precious_register,
        .cache_type = REGCACHE_RBTREE,
+
+       .use_single_read = true,
+       .use_single_write = true,
 };
 
 static int cs35l32_handle_of_data(struct i2c_client *i2c_client,
index 7ad7b733af9b6731c4778660b27af8278302af5a..e8f3dcfd144dadb61b3ebcdbc69adc677ce7f47e 100644 (file)
@@ -1201,6 +1201,7 @@ static int cs35l33_i2c_probe(struct i2c_client *i2c_client,
                dev_err(&i2c_client->dev,
                        "CS35L33 Device ID (%X). Expected ID %X\n",
                        devid, CS35L33_CHIP_ID);
+               ret = -EINVAL;
                goto err_enable;
        }
 
index 110ee2d063581c0879c9792565bf3d1c974c6ad7..3d3c3c34dfe273ee3cc79c89996a2a469fe8bdbb 100644 (file)
@@ -800,6 +800,9 @@ static struct regmap_config cs35l34_regmap = {
        .readable_reg = cs35l34_readable_register,
        .precious_reg = cs35l34_precious_register,
        .cache_type = REGCACHE_RBTREE,
+
+       .use_single_read = true,
+       .use_single_write = true,
 };
 
 static int cs35l34_handle_of_data(struct i2c_client *i2c_client,
index bf982e145e945f4774d5c306522426f381433c14..77473c226f9ec022e8b73b1edeb7ece1fb1ef8e2 100644 (file)
@@ -399,6 +399,9 @@ static const struct regmap_config cs42l42_regmap = {
        .reg_defaults = cs42l42_reg_defaults,
        .num_reg_defaults = ARRAY_SIZE(cs42l42_reg_defaults),
        .cache_type = REGCACHE_RBTREE,
+
+       .use_single_read = true,
+       .use_single_write = true,
 };
 
 static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, false);
index c44a5cdb796ecf8e0350ff5f488af0028408440b..7cdffdf6b8cf05381a2a74bbdaffc1470f94a4cd 100644 (file)
@@ -1175,7 +1175,7 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
        struct cs42l56_platform_data *pdata =
                dev_get_platdata(&i2c_client->dev);
        int ret, i;
-       unsigned int devid = 0;
+       unsigned int devid;
        unsigned int alpha_rev, metal_rev;
        unsigned int reg;
 
@@ -1245,6 +1245,11 @@ static int cs42l56_i2c_probe(struct i2c_client *i2c_client,
        }
 
        ret = regmap_read(cs42l56->regmap, CS42L56_CHIP_ID_1, &reg);
+       if (ret) {
+               dev_err(&i2c_client->dev, "Failed to read chip ID: %d\n", ret);
+               return ret;
+       }
+
        devid = reg & CS42L56_CHIP_ID_MASK;
        if (devid != CS42L56_DEVID) {
                dev_err(&i2c_client->dev,
index c3f974ec78e58b31d9c88f9c394ccc5c02027ef0..e92bacaab53fccdc81e6e332852f9658236d6691 100644 (file)
@@ -1268,6 +1268,9 @@ static const struct regmap_config cs42l73_regmap = {
        .volatile_reg = cs42l73_volatile_register,
        .readable_reg = cs42l73_readable_register,
        .cache_type = REGCACHE_RBTREE,
+
+       .use_single_read = true,
+       .use_single_write = true,
 };
 
 static int cs42l73_i2c_probe(struct i2c_client *i2c_client,
index 80bc7c10ed757fc693c4a9f57d64bbaf8ae3e495..80cd3ea0c1577261b8df0ecee488ad8b198dc025 100644 (file)
@@ -1735,6 +1735,14 @@ static DEVICE_ATTR(hpload_dc_r, 0444, cs43130_show_dc_r, NULL);
 static DEVICE_ATTR(hpload_ac_l, 0444, cs43130_show_ac_l, NULL);
 static DEVICE_ATTR(hpload_ac_r, 0444, cs43130_show_ac_r, NULL);
 
+static struct attribute *hpload_attrs[] = {
+       &dev_attr_hpload_dc_l.attr,
+       &dev_attr_hpload_dc_r.attr,
+       &dev_attr_hpload_ac_l.attr,
+       &dev_attr_hpload_ac_r.attr,
+};
+ATTRIBUTE_GROUPS(hpload);
+
 static struct reg_sequence hp_en_cal_seq[] = {
        {CS43130_INT_MASK_4, CS43130_INT_MASK_ALL},
        {CS43130_HP_MEAS_LOAD_1, 0},
@@ -2302,25 +2310,15 @@ static int cs43130_probe(struct snd_soc_component *component)
 
        cs43130->hpload_done = false;
        if (cs43130->dc_meas) {
-               ret = device_create_file(component->dev, &dev_attr_hpload_dc_l);
-               if (ret < 0)
-                       return ret;
-
-               ret = device_create_file(component->dev, &dev_attr_hpload_dc_r);
-               if (ret < 0)
-                       return ret;
-
-               ret = device_create_file(component->dev, &dev_attr_hpload_ac_l);
-               if (ret < 0)
-                       return ret;
-
-               ret = device_create_file(component->dev, &dev_attr_hpload_ac_r);
-               if (ret < 0)
+               ret = sysfs_create_groups(&component->dev->kobj, hpload_groups);
+               if (ret)
                        return ret;
 
                cs43130->wq = create_singlethread_workqueue("cs43130_hp");
-               if (!cs43130->wq)
+               if (!cs43130->wq) {
+                       sysfs_remove_groups(&component->dev->kobj, hpload_groups);
                        return -ENOMEM;
+               }
                INIT_WORK(&cs43130->work, cs43130_imp_meas);
        }
 
index 3d67cbf9eaaa2b58e78860cfbbec37020900089d..abe0cc0bc03a94bf6d4838eb56e6d0235a55e7e0 100644 (file)
@@ -912,6 +912,9 @@ static struct regmap_config cs53l30_regmap = {
        .writeable_reg = cs53l30_writeable_register,
        .readable_reg = cs53l30_readable_register,
        .cache_type = REGCACHE_RBTREE,
+
+       .use_single_read = true,
+       .use_single_write = true,
 };
 
 static int cs53l30_i2c_probe(struct i2c_client *client,
index bd3c523a86171e31ddf9e887c796f0d8abc53f27..13009d08b09ac5ed3271ffdc66b60d7d57cd1b41 100644 (file)
@@ -2181,10 +2181,7 @@ static int da7219_register_dai_clks(struct snd_soc_component *component)
                                 ret);
                        goto err;
                }
-
-               da7219->dai_clks[i] = devm_clk_hw_get_clk(dev, dai_clk_hw, NULL);
-               if (IS_ERR(da7219->dai_clks[i]))
-                       return PTR_ERR(da7219->dai_clks[i]);
+               da7219->dai_clks[i] = dai_clk_hw->clk;
 
                /* For DT setup onecell data, otherwise create lookup */
                if (np) {
index b0ebfc8d180ca231d0d65bee41f9fc348de6266e..171ab7f519c0461ce61a1431ca745fee4ffa60b7 100644 (file)
@@ -3579,6 +3579,7 @@ static const struct of_device_id rx_macro_dt_match[] = {
        { .compatible = "qcom,sm8250-lpass-rx-macro" },
        { }
 };
+MODULE_DEVICE_TABLE(of, rx_macro_dt_match);
 
 static struct platform_driver rx_macro_driver = {
        .driver = {
index acd2fbc0ca7c69b9d19cf69c59e21045a2da4a26..27a0d5defd273da7dd4f5e8316ab2617b118d1e7 100644 (file)
@@ -1846,6 +1846,7 @@ static const struct of_device_id tx_macro_dt_match[] = {
        { .compatible = "qcom,sm8250-lpass-tx-macro" },
        { }
 };
+MODULE_DEVICE_TABLE(of, tx_macro_dt_match);
 static struct platform_driver tx_macro_driver = {
        .driver = {
                .name = "tx_macro",
index 4be24e7f51c89e41a979a9ee14c4f23fc1ba1ab3..f8e49e45ce33f112a707a80ed520ff9327c0e261 100644 (file)
@@ -41,6 +41,7 @@ struct max98088_priv {
        enum max98088_type devtype;
        struct max98088_pdata *pdata;
        struct clk *mclk;
+       unsigned char mclk_prescaler;
        unsigned int sysclk;
        struct max98088_cdata dai[2];
        int eq_textcnt;
@@ -998,13 +999,16 @@ static int max98088_dai1_hw_params(struct snd_pcm_substream *substream,
        /* Configure NI when operating as master */
        if (snd_soc_component_read(component, M98088_REG_14_DAI1_FORMAT)
                & M98088_DAI_MAS) {
+               unsigned long pclk;
+
                if (max98088->sysclk == 0) {
                        dev_err(component->dev, "Invalid system clock frequency\n");
                        return -EINVAL;
                }
                ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
                                * (unsigned long long int)rate;
-               do_div(ni, (unsigned long long int)max98088->sysclk);
+               pclk = DIV_ROUND_CLOSEST(max98088->sysclk, max98088->mclk_prescaler);
+               ni = DIV_ROUND_CLOSEST_ULL(ni, pclk);
                snd_soc_component_write(component, M98088_REG_12_DAI1_CLKCFG_HI,
                        (ni >> 8) & 0x7F);
                snd_soc_component_write(component, M98088_REG_13_DAI1_CLKCFG_LO,
@@ -1065,13 +1069,16 @@ static int max98088_dai2_hw_params(struct snd_pcm_substream *substream,
        /* Configure NI when operating as master */
        if (snd_soc_component_read(component, M98088_REG_1C_DAI2_FORMAT)
                & M98088_DAI_MAS) {
+               unsigned long pclk;
+
                if (max98088->sysclk == 0) {
                        dev_err(component->dev, "Invalid system clock frequency\n");
                        return -EINVAL;
                }
                ni = 65536ULL * (rate < 50000 ? 96ULL : 48ULL)
                                * (unsigned long long int)rate;
-               do_div(ni, (unsigned long long int)max98088->sysclk);
+               pclk = DIV_ROUND_CLOSEST(max98088->sysclk, max98088->mclk_prescaler);
+               ni = DIV_ROUND_CLOSEST_ULL(ni, pclk);
                snd_soc_component_write(component, M98088_REG_1A_DAI2_CLKCFG_HI,
                        (ni >> 8) & 0x7F);
                snd_soc_component_write(component, M98088_REG_1B_DAI2_CLKCFG_LO,
@@ -1113,8 +1120,10 @@ static int max98088_dai_set_sysclk(struct snd_soc_dai *dai,
         */
        if ((freq >= 10000000) && (freq < 20000000)) {
                snd_soc_component_write(component, M98088_REG_10_SYS_CLK, 0x10);
+               max98088->mclk_prescaler = 1;
        } else if ((freq >= 20000000) && (freq < 30000000)) {
                snd_soc_component_write(component, M98088_REG_10_SYS_CLK, 0x20);
+               max98088->mclk_prescaler = 2;
        } else {
                dev_err(component->dev, "Invalid master clock frequency\n");
                return -EINVAL;
index 9408ee63cb2688127d150acc99480cab60ac49d9..438fa18bcb55d6a67a18dbd86265d63aaf1f18ea 100644 (file)
@@ -3388,30 +3388,44 @@ static int rt5645_probe(struct snd_soc_component *component)
 {
        struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component);
        struct rt5645_priv *rt5645 = snd_soc_component_get_drvdata(component);
+       int ret = 0;
 
        rt5645->component = component;
 
        switch (rt5645->codec_type) {
        case CODEC_TYPE_RT5645:
-               snd_soc_dapm_new_controls(dapm,
+               ret = snd_soc_dapm_new_controls(dapm,
                        rt5645_specific_dapm_widgets,
                        ARRAY_SIZE(rt5645_specific_dapm_widgets));
-               snd_soc_dapm_add_routes(dapm,
+               if (ret < 0)
+                       goto exit;
+
+               ret = snd_soc_dapm_add_routes(dapm,
                        rt5645_specific_dapm_routes,
                        ARRAY_SIZE(rt5645_specific_dapm_routes));
+               if (ret < 0)
+                       goto exit;
+
                if (rt5645->v_id < 3) {
-                       snd_soc_dapm_add_routes(dapm,
+                       ret = snd_soc_dapm_add_routes(dapm,
                                rt5645_old_dapm_routes,
                                ARRAY_SIZE(rt5645_old_dapm_routes));
+                       if (ret < 0)
+                               goto exit;
                }
                break;
        case CODEC_TYPE_RT5650:
-               snd_soc_dapm_new_controls(dapm,
+               ret = snd_soc_dapm_new_controls(dapm,
                        rt5650_specific_dapm_widgets,
                        ARRAY_SIZE(rt5650_specific_dapm_widgets));
-               snd_soc_dapm_add_routes(dapm,
+               if (ret < 0)
+                       goto exit;
+
+               ret = snd_soc_dapm_add_routes(dapm,
                        rt5650_specific_dapm_routes,
                        ARRAY_SIZE(rt5650_specific_dapm_routes));
+               if (ret < 0)
+                       goto exit;
                break;
        }
 
@@ -3419,9 +3433,17 @@ static int rt5645_probe(struct snd_soc_component *component)
 
        /* for JD function */
        if (rt5645->pdata.jd_mode) {
-               snd_soc_dapm_force_enable_pin(dapm, "JD Power");
-               snd_soc_dapm_force_enable_pin(dapm, "LDO2");
-               snd_soc_dapm_sync(dapm);
+               ret = snd_soc_dapm_force_enable_pin(dapm, "JD Power");
+               if (ret < 0)
+                       goto exit;
+
+               ret = snd_soc_dapm_force_enable_pin(dapm, "LDO2");
+               if (ret < 0)
+                       goto exit;
+
+               ret = snd_soc_dapm_sync(dapm);
+               if (ret < 0)
+                       goto exit;
        }
 
        if (rt5645->pdata.long_name)
@@ -3432,9 +3454,14 @@ static int rt5645_probe(struct snd_soc_component *component)
                GFP_KERNEL);
 
        if (!rt5645->eq_param)
-               return -ENOMEM;
-
-       return 0;
+               ret = -ENOMEM;
+exit:
+       /*
+        * If there was an error above, everything will be cleaned up by the
+        * caller if we return an error here.  This will be done with a later
+        * call to rt5645_remove().
+        */
+       return ret;
 }
 
 static void rt5645_remove(struct snd_soc_component *component)
index cc36739f7fcfb8223ca532b67b596fe1f604229f..24a084e0b48a1b71e5044dc4f36d78baa417c31f 100644 (file)
@@ -683,13 +683,13 @@ static int rt711_sdca_set_fu1e_capture_ctl(struct rt711_sdca_priv *rt711)
        ch_r = (rt711->fu1e_dapm_mute || rt711->fu1e_mixer_r_mute) ? 0x01 : 0x00;
 
        err = regmap_write(rt711->regmap,
-                       SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU1E,
+                       SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E,
                        RT711_SDCA_CTL_FU_MUTE, CH_L), ch_l);
        if (err < 0)
                return err;
 
        err = regmap_write(rt711->regmap,
-                       SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU1E,
+                       SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E,
                        RT711_SDCA_CTL_FU_MUTE, CH_R), ch_r);
        if (err < 0)
                return err;
index ffdf7e55951537609c21fdd9c714f6716568ee76..82a24e330065f882d1243d3cb2126a991fe2241f 100644 (file)
@@ -408,6 +408,7 @@ static const struct of_device_id sti_sas_dev_match[] = {
        },
        {},
 };
+MODULE_DEVICE_TABLE(of, sti_sas_dev_match);
 
 static int sti_sas_driver_probe(struct platform_device *pdev)
 {
index 0917d65d69213f57f380e523fda6e509ee74901e..556c284f49dd3531789b3eb109189b54f2574dc2 100644 (file)
@@ -119,6 +119,7 @@ config SND_SOC_FSL_RPMSG
        tristate "NXP Audio Base On RPMSG support"
        depends on COMMON_CLK
        depends on RPMSG
+       depends on SND_IMX_SOC || SND_IMX_SOC = n
        select SND_SOC_IMX_RPMSG if SND_IMX_SOC != n
        help
          Say Y if you want to add rpmsg audio support for the Freescale CPUs.
index 2c8a2fcb7922a24841507136e7aec24587a4581f..5e71382467e88614200853e069ae757e85196a9f 100644 (file)
@@ -209,7 +209,7 @@ static void graph_parse_mclk_fs(struct device_node *top,
 static int graph_parse_node(struct asoc_simple_priv *priv,
                            struct device_node *ep,
                            struct link_info *li,
-                           int is_cpu)
+                           int *cpu)
 {
        struct device *dev = simple_priv_to_dev(priv);
        struct device_node *top = dev->of_node;
@@ -217,9 +217,9 @@ static int graph_parse_node(struct asoc_simple_priv *priv,
        struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
        struct snd_soc_dai_link_component *dlc;
        struct asoc_simple_dai *dai;
-       int ret, single = 0;
+       int ret;
 
-       if (is_cpu) {
+       if (cpu) {
                dlc = asoc_link_to_cpu(dai_link, 0);
                dai = simple_props_to_dai_cpu(dai_props, 0);
        } else {
@@ -229,7 +229,7 @@ static int graph_parse_node(struct asoc_simple_priv *priv,
 
        graph_parse_mclk_fs(top, ep, dai_props);
 
-       ret = asoc_simple_parse_dai(ep, dlc, &single);
+       ret = asoc_simple_parse_dai(ep, dlc, cpu);
        if (ret < 0)
                return ret;
 
@@ -241,9 +241,6 @@ static int graph_parse_node(struct asoc_simple_priv *priv,
        if (ret < 0)
                return ret;
 
-       if (is_cpu)
-               asoc_simple_canonicalize_cpu(dlc, single);
-
        return 0;
 }
 
@@ -276,33 +273,29 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
                                  struct link_info *li)
 {
        struct device *dev = simple_priv_to_dev(priv);
-       struct snd_soc_card *card = simple_priv_to_card(priv);
        struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
        struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
        struct device_node *top = dev->of_node;
        struct device_node *ep = li->cpu ? cpu_ep : codec_ep;
-       struct device_node *port;
-       struct device_node *ports;
-       struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
-       struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
        char dai_name[64];
        int ret;
 
-       port    = of_get_parent(ep);
-       ports   = of_get_parent(port);
-
        dev_dbg(dev, "link_of DPCM (%pOF)\n", ep);
 
        if (li->cpu) {
+               struct snd_soc_card *card = simple_priv_to_card(priv);
+               struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
+               int is_single_links = 0;
+
                /* Codec is dummy */
 
                /* FE settings */
                dai_link->dynamic               = 1;
                dai_link->dpcm_merged_format    = 1;
 
-               ret = graph_parse_node(priv, cpu_ep, li, 1);
+               ret = graph_parse_node(priv, cpu_ep, li, &is_single_links);
                if (ret)
-                       goto out_put_node;
+                       return ret;
 
                snprintf(dai_name, sizeof(dai_name),
                         "fe.%pOFP.%s", cpus->of_node, cpus->dai_name);
@@ -318,8 +311,13 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
                 */
                if (card->component_chaining && !soc_component_is_pcm(cpus))
                        dai_link->no_pcm = 1;
+
+               asoc_simple_canonicalize_cpu(cpus, is_single_links);
        } else {
-               struct snd_soc_codec_conf *cconf;
+               struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, 0);
+               struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
+               struct device_node *port;
+               struct device_node *ports;
 
                /* CPU is dummy */
 
@@ -327,22 +325,25 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
                dai_link->no_pcm                = 1;
                dai_link->be_hw_params_fixup    = asoc_simple_be_hw_params_fixup;
 
-               cconf   = simple_props_to_codec_conf(dai_props, 0);
-
-               ret = graph_parse_node(priv, codec_ep, li, 0);
+               ret = graph_parse_node(priv, codec_ep, li, NULL);
                if (ret < 0)
-                       goto out_put_node;
+                       return ret;
 
                snprintf(dai_name, sizeof(dai_name),
                         "be.%pOFP.%s", codecs->of_node, codecs->dai_name);
 
                /* check "prefix" from top node */
+               port = of_get_parent(ep);
+               ports = of_get_parent(port);
                snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
                                              "prefix");
                if (of_node_name_eq(ports, "ports"))
                        snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix");
                snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node,
                                             "prefix");
+
+               of_node_put(ports);
+               of_node_put(port);
        }
 
        graph_parse_convert(dev, ep, &dai_props->adata);
@@ -351,11 +352,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv,
 
        ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name);
 
-out_put_node:
        li->link++;
 
-       of_node_put(ports);
-       of_node_put(port);
        return ret;
 }
 
@@ -369,20 +367,23 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv,
        struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
        struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
        char dai_name[64];
-       int ret;
+       int ret, is_single_links = 0;
 
        dev_dbg(dev, "link_of (%pOF)\n", cpu_ep);
 
-       ret = graph_parse_node(priv, cpu_ep, li, 1);
+       ret = graph_parse_node(priv, cpu_ep, li, &is_single_links);
        if (ret < 0)
                return ret;
 
-       ret = graph_parse_node(priv, codec_ep, li, 0);
+       ret = graph_parse_node(priv, codec_ep, li, NULL);
        if (ret < 0)
                return ret;
 
        snprintf(dai_name, sizeof(dai_name),
                 "%s-%s", cpus->dai_name, codecs->dai_name);
+
+       asoc_simple_canonicalize_cpu(cpus, is_single_links);
+
        ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name);
        if (ret < 0)
                return ret;
index a1373be4558f3f40faf84a37b4b69d6249737453..0015f534d42d9fe511cef9fce1150b7c0b9ac1eb 100644 (file)
@@ -93,12 +93,11 @@ static void simple_parse_convert(struct device *dev,
 }
 
 static void simple_parse_mclk_fs(struct device_node *top,
-                                struct device_node *cpu,
-                                struct device_node *codec,
+                                struct device_node *np,
                                 struct simple_dai_props *props,
                                 char *prefix)
 {
-       struct device_node *node = of_get_parent(cpu);
+       struct device_node *node = of_get_parent(np);
        char prop[128];
 
        snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX);
@@ -106,12 +105,71 @@ static void simple_parse_mclk_fs(struct device_node *top,
 
        snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
        of_property_read_u32(node,      prop, &props->mclk_fs);
-       of_property_read_u32(cpu,       prop, &props->mclk_fs);
-       of_property_read_u32(codec,     prop, &props->mclk_fs);
+       of_property_read_u32(np,        prop, &props->mclk_fs);
 
        of_node_put(node);
 }
 
+static int simple_parse_node(struct asoc_simple_priv *priv,
+                            struct device_node *np,
+                            struct link_info *li,
+                            char *prefix,
+                            int *cpu)
+{
+       struct device *dev = simple_priv_to_dev(priv);
+       struct device_node *top = dev->of_node;
+       struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
+       struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
+       struct snd_soc_dai_link_component *dlc;
+       struct asoc_simple_dai *dai;
+       int ret;
+
+       if (cpu) {
+               dlc = asoc_link_to_cpu(dai_link, 0);
+               dai = simple_props_to_dai_cpu(dai_props, 0);
+       } else {
+               dlc = asoc_link_to_codec(dai_link, 0);
+               dai = simple_props_to_dai_codec(dai_props, 0);
+       }
+
+       simple_parse_mclk_fs(top, np, dai_props, prefix);
+
+       ret = asoc_simple_parse_dai(np, dlc, cpu);
+       if (ret)
+               return ret;
+
+       ret = asoc_simple_parse_clk(dev, np, dai, dlc);
+       if (ret)
+               return ret;
+
+       ret = asoc_simple_parse_tdm(np, dai);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int simple_link_init(struct asoc_simple_priv *priv,
+                           struct device_node *node,
+                           struct device_node *codec,
+                           struct link_info *li,
+                           char *prefix, char *name)
+{
+       struct device *dev = simple_priv_to_dev(priv);
+       struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
+       int ret;
+
+       ret = asoc_simple_parse_daifmt(dev, node, codec,
+                                      prefix, &dai_link->dai_fmt);
+       if (ret < 0)
+               return 0;
+
+       dai_link->init                  = asoc_simple_dai_init;
+       dai_link->ops                   = &simple_ops;
+
+       return asoc_simple_set_dailink_name(dev, dai_link, name);
+}
+
 static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
                                   struct device_node *np,
                                   struct device_node *codec,
@@ -121,24 +179,21 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
        struct device *dev = simple_priv_to_dev(priv);
        struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
        struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
-       struct asoc_simple_dai *dai;
-       struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
-       struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
-       struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0);
        struct device_node *top = dev->of_node;
        struct device_node *node = of_get_parent(np);
        char *prefix = "";
+       char dai_name[64];
        int ret;
 
        dev_dbg(dev, "link_of DPCM (%pOF)\n", np);
 
-       li->link++;
-
        /* For single DAI link & old style of DT node */
        if (is_top)
                prefix = PREFIX;
 
        if (li->cpu) {
+               struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
+               struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0);
                int is_single_links = 0;
 
                /* Codec is dummy */
@@ -147,25 +202,16 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
                dai_link->dynamic               = 1;
                dai_link->dpcm_merged_format    = 1;
 
-               dai = simple_props_to_dai_cpu(dai_props, 0);
-
-               ret = asoc_simple_parse_dai(np, cpus, &is_single_links);
-               if (ret)
-                       goto out_put_node;
-
-               ret = asoc_simple_parse_clk(dev, np, dai, cpus);
+               ret = simple_parse_node(priv, np, li, prefix, &is_single_links);
                if (ret < 0)
                        goto out_put_node;
 
-               ret = asoc_simple_set_dailink_name(dev, dai_link,
-                                                  "fe.%s",
-                                                  cpus->dai_name);
-               if (ret < 0)
-                       goto out_put_node;
+               snprintf(dai_name, sizeof(dai_name), "fe.%s", cpus->dai_name);
 
                asoc_simple_canonicalize_cpu(cpus, is_single_links);
                asoc_simple_canonicalize_platform(platforms, cpus);
        } else {
+               struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
                struct snd_soc_codec_conf *cconf;
 
                /* CPU is dummy */
@@ -174,22 +220,13 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
                dai_link->no_pcm                = 1;
                dai_link->be_hw_params_fixup    = asoc_simple_be_hw_params_fixup;
 
-               dai     = simple_props_to_dai_codec(dai_props, 0);
                cconf   = simple_props_to_codec_conf(dai_props, 0);
 
-               ret = asoc_simple_parse_dai(np, codecs, NULL);
+               ret = simple_parse_node(priv, np, li, prefix, NULL);
                if (ret < 0)
                        goto out_put_node;
 
-               ret = asoc_simple_parse_clk(dev, np, dai, codecs);
-               if (ret < 0)
-                       goto out_put_node;
-
-               ret = asoc_simple_set_dailink_name(dev, dai_link,
-                                                  "be.%s",
-                                                  codecs->dai_name);
-               if (ret < 0)
-                       goto out_put_node;
+               snprintf(dai_name, sizeof(dai_name), "be.%s", codecs->dai_name);
 
                /* check "prefix" from top node */
                snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
@@ -201,23 +238,14 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
        }
 
        simple_parse_convert(dev, np, &dai_props->adata);
-       simple_parse_mclk_fs(top, np, codec, dai_props, prefix);
-
-       ret = asoc_simple_parse_tdm(np, dai);
-       if (ret)
-               goto out_put_node;
-
-       ret = asoc_simple_parse_daifmt(dev, node, codec,
-                                      prefix, &dai_link->dai_fmt);
-       if (ret < 0)
-               goto out_put_node;
 
        snd_soc_dai_link_set_capabilities(dai_link);
 
-       dai_link->ops                   = &simple_ops;
-       dai_link->init                  = asoc_simple_dai_init;
+       ret = simple_link_init(priv, node, codec, li, prefix, dai_name);
 
 out_put_node:
+       li->link++;
+
        of_node_put(node);
        return ret;
 }
@@ -230,23 +258,19 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv,
 {
        struct device *dev = simple_priv_to_dev(priv);
        struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
-       struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
-       struct asoc_simple_dai *cpu_dai = simple_props_to_dai_cpu(dai_props, 0);
-       struct asoc_simple_dai *codec_dai = simple_props_to_dai_codec(dai_props, 0);
        struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0);
        struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0);
        struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0);
-       struct device_node *top = dev->of_node;
        struct device_node *cpu = NULL;
        struct device_node *node = NULL;
        struct device_node *plat = NULL;
+       char dai_name[64];
        char prop[128];
        char *prefix = "";
        int ret, single_cpu = 0;
 
        cpu  = np;
        node = of_get_parent(np);
-       li->link++;
 
        dev_dbg(dev, "link_of (%pOF)\n", node);
 
@@ -257,18 +281,11 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv,
        snprintf(prop, sizeof(prop), "%splat", prefix);
        plat = of_get_child_by_name(node, prop);
 
-       ret = asoc_simple_parse_daifmt(dev, node, codec,
-                                      prefix, &dai_link->dai_fmt);
-       if (ret < 0)
-               goto dai_link_of_err;
-
-       simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix);
-
-       ret = asoc_simple_parse_dai(cpu, cpus, &single_cpu);
+       ret = simple_parse_node(priv, cpu, li, prefix, &single_cpu);
        if (ret < 0)
                goto dai_link_of_err;
 
-       ret = asoc_simple_parse_dai(codec, codecs, NULL);
+       ret = simple_parse_node(priv, codec, li, prefix, NULL);
        if (ret < 0)
                goto dai_link_of_err;
 
@@ -276,39 +293,20 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv,
        if (ret < 0)
                goto dai_link_of_err;
 
-       ret = asoc_simple_parse_tdm(cpu, cpu_dai);
-       if (ret < 0)
-               goto dai_link_of_err;
-
-       ret = asoc_simple_parse_tdm(codec, codec_dai);
-       if (ret < 0)
-               goto dai_link_of_err;
-
-       ret = asoc_simple_parse_clk(dev, cpu, cpu_dai, cpus);
-       if (ret < 0)
-               goto dai_link_of_err;
-
-       ret = asoc_simple_parse_clk(dev, codec, codec_dai, codecs);
-       if (ret < 0)
-               goto dai_link_of_err;
-
-       ret = asoc_simple_set_dailink_name(dev, dai_link,
-                                          "%s-%s",
-                                          cpus->dai_name,
-                                          codecs->dai_name);
-       if (ret < 0)
-               goto dai_link_of_err;
-
-       dai_link->ops = &simple_ops;
-       dai_link->init = asoc_simple_dai_init;
+       snprintf(dai_name, sizeof(dai_name),
+                "%s-%s", cpus->dai_name, codecs->dai_name);
 
        asoc_simple_canonicalize_cpu(cpus, single_cpu);
        asoc_simple_canonicalize_platform(platforms, cpus);
 
+       ret = simple_link_init(priv, node, codec, li, prefix, dai_name);
+
 dai_link_of_err:
        of_node_put(plat);
        of_node_put(node);
 
+       li->link++;
+
        return ret;
 }
 
index df2f5d55e8ffec9d1501bdb4ff8ea97bcadd115e..22dbd9d93c1ef5bece4b63fffeb57e1851e5bf39 100644 (file)
@@ -574,6 +574,17 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                                        BYT_RT5640_SSP0_AIF1 |
                                        BYT_RT5640_MCLK_EN),
        },
+       {       /* Glavey TM800A550L */
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+                       DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+                       /* Above strings are too generic, also match on BIOS version */
+                       DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"),
+               },
+               .driver_data = (void *)(BYTCR_INPUT_DEFAULTS |
+                                       BYT_RT5640_SSP0_AIF1 |
+                                       BYT_RT5640_MCLK_EN),
+       },
        {
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -652,6 +663,20 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = {
                                        BYT_RT5640_MONO_SPEAKER |
                                        BYT_RT5640_MCLK_EN),
        },
+       {       /* Lenovo Miix 3-830 */
+               .matches = {
+                       DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+                       DMI_EXACT_MATCH(DMI_PRODUCT_VERSION, "Lenovo MIIX 3-830"),
+               },
+               .driver_data = (void *)(BYT_RT5640_IN1_MAP |
+                                       BYT_RT5640_JD_SRC_JD2_IN4N |
+                                       BYT_RT5640_OVCD_TH_2000UA |
+                                       BYT_RT5640_OVCD_SF_0P75 |
+                                       BYT_RT5640_MONO_SPEAKER |
+                                       BYT_RT5640_DIFF_MIC |
+                                       BYT_RT5640_SSP0_AIF1 |
+                                       BYT_RT5640_MCLK_EN),
+       },
        {       /* Linx Linx7 tablet */
                .matches = {
                        DMI_EXACT_MATCH(DMI_SYS_VENDOR, "LINX"),
index c62d2612e8f5e281cc8482250a78d130bad1fe9e..28c7497344e336c9e32a5869b4f1c5b4c76bfa4c 100644 (file)
@@ -835,18 +835,8 @@ int asoc_qcom_lpass_cpu_platform_probe(struct platform_device *pdev)
                if (dai_id == LPASS_DP_RX)
                        continue;
 
-               drvdata->mi2s_osr_clk[dai_id] = devm_clk_get(dev,
+               drvdata->mi2s_osr_clk[dai_id] = devm_clk_get_optional(dev,
                                             variant->dai_osr_clk_names[i]);
-               if (IS_ERR(drvdata->mi2s_osr_clk[dai_id])) {
-                       dev_warn(dev,
-                               "%s() error getting optional %s: %ld\n",
-                               __func__,
-                               variant->dai_osr_clk_names[i],
-                               PTR_ERR(drvdata->mi2s_osr_clk[dai_id]));
-
-                       drvdata->mi2s_osr_clk[dai_id] = NULL;
-               }
-
                drvdata->mi2s_bit_clk[dai_id] = devm_clk_get(dev,
                                                variant->dai_bit_clk_names[i]);
                if (IS_ERR(drvdata->mi2s_bit_clk[dai_id])) {
index 8d7bab433fb33b4ee63f084cb406e07d0723574c..c1f9f0f5846476a3641f849d10006390dda7796d 100644 (file)
@@ -421,11 +421,16 @@ static int ssp_dai_hw_params(struct snd_pcm_substream *substream,
        struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
        struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
        struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
+       struct sof_ipc_fw_version *v = &sdev->fw_ready.version;
        struct sof_ipc_dai_config *config;
        struct snd_sof_dai *sof_dai;
        struct sof_ipc_reply reply;
        int ret;
 
+       /* DAI_CONFIG IPC during hw_params is not supported in older firmware */
+       if (v->abi_version < SOF_ABI_VER(3, 18, 0))
+               return 0;
+
        list_for_each_entry(sof_dai, &sdev->dai_list, list) {
                if (!sof_dai->cpu_dai_name || !sof_dai->dai_config)
                        continue;
index c1561237ee24b292a80d872115c7bd65701a7d47..3aa1cf262402034f0706ec8bb923e19fe4b52d1f 100644 (file)
@@ -484,10 +484,7 @@ static int stm32_sai_add_mclk_provider(struct stm32_sai_sub_data *sai)
                dev_err(dev, "mclk register returned %d\n", ret);
                return ret;
        }
-
-       sai->sai_mclk = devm_clk_hw_get_clk(dev, hw, NULL);
-       if (IS_ERR(sai->sai_mclk))
-               return PTR_ERR(sai->sai_mclk);
+       sai->sai_mclk = hw->clk;
 
        /* register mclk provider */
        return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw);
index e6ff317a678520a20ff5f6109886d5018fab9043..2287f8c653150a4aa6ed555287b6a80e2b8c32e2 100644 (file)
@@ -436,7 +436,7 @@ static bool check_valid_altsetting_v2v3(struct snd_usb_audio *chip, int iface,
        if (snd_BUG_ON(altsetting >= 64 - 8))
                return false;
 
-       err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
                              USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
                              UAC2_AS_VAL_ALT_SETTINGS << 8,
                              iface, &raw_data, sizeof(raw_data));
index a030dd65eb2805993a03ef49cd78b4b438bc9fec..9602929b7de9001df963e137c7f4c77a50b05ed8 100644 (file)
@@ -699,6 +699,10 @@ static int line6_init_cap_control(struct usb_line6 *line6)
                line6->buffer_message = kmalloc(LINE6_MIDI_MESSAGE_MAXLEN, GFP_KERNEL);
                if (!line6->buffer_message)
                        return -ENOMEM;
+
+               ret = line6_init_midi(line6);
+               if (ret < 0)
+                       return ret;
        } else {
                ret = line6_hwdep_init(line6);
                if (ret < 0)
index cd44cb5f1310c639f5772705d4660a0ec52425bc..16e644330c4d63c9a0ff40548bac7e975b82a59f 100644 (file)
@@ -376,11 +376,6 @@ static int pod_init(struct usb_line6 *line6,
        if (err < 0)
                return err;
 
-       /* initialize MIDI subsystem: */
-       err = line6_init_midi(line6);
-       if (err < 0)
-               return err;
-
        /* initialize PCM subsystem: */
        err = line6_init_pcm(line6, &pod_pcm_properties);
        if (err < 0)
index ed158f04de80f9c0a0b4c1bfbde24b1895bce543..c2245aa93b08ff3a50cfe23691c88ce2fe40f83b 100644 (file)
@@ -159,7 +159,6 @@ static int variax_init(struct usb_line6 *line6,
                       const struct usb_device_id *id)
 {
        struct usb_line6_variax *variax = line6_to_variax(line6);
-       int err;
 
        line6->process_message = line6_variax_process_message;
        line6->disconnect = line6_variax_disconnect;
@@ -172,11 +171,6 @@ static int variax_init(struct usb_line6 *line6,
        if (variax->buffer_activate == NULL)
                return -ENOMEM;
 
-       /* initialize MIDI subsystem: */
-       err = line6_init_midi(&variax->line6);
-       if (err < 0)
-               return err;
-
        /* initiate startup procedure: */
        schedule_delayed_work(&line6->startup_work,
                              msecs_to_jiffies(VARIAX_STARTUP_DELAY1));
index a10ac75969a8f05486b491ffe11569e3e9f60864..2c01649c70f619d6e9994e81bdc16c171bb6e471 100644 (file)
@@ -1750,7 +1750,7 @@ static struct usb_midi_in_jack_descriptor *find_usb_in_jack_descriptor(
                struct usb_midi_in_jack_descriptor *injd =
                                (struct usb_midi_in_jack_descriptor *)extra;
 
-               if (injd->bLength > 4 &&
+               if (injd->bLength >= sizeof(*injd) &&
                    injd->bDescriptorType == USB_DT_CS_INTERFACE &&
                    injd->bDescriptorSubtype == UAC_MIDI_IN_JACK &&
                                injd->bJackID == jack_id)
@@ -1773,7 +1773,7 @@ static struct usb_midi_out_jack_descriptor *find_usb_out_jack_descriptor(
                struct usb_midi_out_jack_descriptor *outjd =
                                (struct usb_midi_out_jack_descriptor *)extra;
 
-               if (outjd->bLength > 4 &&
+               if (outjd->bLength >= sizeof(*outjd) &&
                    outjd->bDescriptorType == USB_DT_CS_INTERFACE &&
                    outjd->bDescriptorSubtype == UAC_MIDI_OUT_JACK &&
                                outjd->bJackID == jack_id)
@@ -1820,7 +1820,8 @@ static void snd_usbmidi_init_substream(struct snd_usb_midi *umidi,
                        outjd = find_usb_out_jack_descriptor(hostif, jack_id);
                        if (outjd) {
                                sz = USB_DT_MIDI_OUT_SIZE(outjd->bNrInputPins);
-                               iJack = *(((uint8_t *) outjd) + sz - sizeof(uint8_t));
+                               if (outjd->bLength >= sz)
+                                       iJack = *(((uint8_t *) outjd) + sz - sizeof(uint8_t));
                        }
                } else {
                        /* and out jacks connect to ins */
@@ -1956,8 +1957,12 @@ static int snd_usbmidi_get_ms_info(struct snd_usb_midi *umidi,
                ms_ep = find_usb_ms_endpoint_descriptor(hostep);
                if (!ms_ep)
                        continue;
+               if (ms_ep->bLength <= sizeof(*ms_ep))
+                       continue;
                if (ms_ep->bNumEmbMIDIJack > 0x10)
                        continue;
+               if (ms_ep->bLength < sizeof(*ms_ep) + ms_ep->bNumEmbMIDIJack)
+                       continue;
                if (usb_endpoint_dir_out(ep)) {
                        if (endpoints[epidx].out_ep) {
                                if (++epidx >= MIDI_MAX_ENDPOINTS) {
index fda66b2dbb017b80bee78a793f0150dda7724534..37ad77524c0b3c40fee5d8114463b1d24d26bb84 100644 (file)
@@ -3060,7 +3060,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
        case USB_ID(0x1235, 0x8203): /* Focusrite Scarlett 6i6 2nd Gen */
        case USB_ID(0x1235, 0x8204): /* Focusrite Scarlett 18i8 2nd Gen */
        case USB_ID(0x1235, 0x8201): /* Focusrite Scarlett 18i20 2nd Gen */
-               err = snd_scarlett_gen2_controls_create(mixer);
+               err = snd_scarlett_gen2_init(mixer);
                break;
 
        case USB_ID(0x041e, 0x323b): /* Creative Sound Blaster E1 */
index 560c2ade829d08b0c501a963e35a1b4e47692fb0..4caf379d5b9912a71ae23296505cbd1b6297fc5a 100644 (file)
@@ -635,7 +635,7 @@ static int scarlett2_usb(
        /* send a second message to get the response */
 
        err = snd_usb_ctl_msg(mixer->chip->dev,
-                       usb_sndctrlpipe(mixer->chip->dev, 0),
+                       usb_rcvctrlpipe(mixer->chip->dev, 0),
                        SCARLETT2_USB_VENDOR_SPECIFIC_CMD_RESP,
                        USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
                        0,
@@ -1997,38 +1997,11 @@ static int scarlett2_mixer_status_create(struct usb_mixer_interface *mixer)
        return usb_submit_urb(mixer->urb, GFP_KERNEL);
 }
 
-/* Entry point */
-int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
+static int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer,
+                                            const struct scarlett2_device_info *info)
 {
-       const struct scarlett2_device_info *info;
        int err;
 
-       /* only use UAC_VERSION_2 */
-       if (!mixer->protocol)
-               return 0;
-
-       switch (mixer->chip->usb_id) {
-       case USB_ID(0x1235, 0x8203):
-               info = &s6i6_gen2_info;
-               break;
-       case USB_ID(0x1235, 0x8204):
-               info = &s18i8_gen2_info;
-               break;
-       case USB_ID(0x1235, 0x8201):
-               info = &s18i20_gen2_info;
-               break;
-       default: /* device not (yet) supported */
-               return -EINVAL;
-       }
-
-       if (!(mixer->chip->setup & SCARLETT2_ENABLE)) {
-               usb_audio_err(mixer->chip,
-                       "Focusrite Scarlett Gen 2 Mixer Driver disabled; "
-                       "use options snd_usb_audio device_setup=1 "
-                       "to enable and report any issues to g@b4.vu");
-               return 0;
-       }
-
        /* Initialise private data, routing, sequence number */
        err = scarlett2_init_private(mixer, info);
        if (err < 0)
@@ -2073,3 +2046,51 @@ int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer)
 
        return 0;
 }
+
+int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer)
+{
+       struct snd_usb_audio *chip = mixer->chip;
+       const struct scarlett2_device_info *info;
+       int err;
+
+       /* only use UAC_VERSION_2 */
+       if (!mixer->protocol)
+               return 0;
+
+       switch (chip->usb_id) {
+       case USB_ID(0x1235, 0x8203):
+               info = &s6i6_gen2_info;
+               break;
+       case USB_ID(0x1235, 0x8204):
+               info = &s18i8_gen2_info;
+               break;
+       case USB_ID(0x1235, 0x8201):
+               info = &s18i20_gen2_info;
+               break;
+       default: /* device not (yet) supported */
+               return -EINVAL;
+       }
+
+       if (!(chip->setup & SCARLETT2_ENABLE)) {
+               usb_audio_info(chip,
+                       "Focusrite Scarlett Gen 2 Mixer Driver disabled; "
+                       "use options snd_usb_audio vid=0x%04x pid=0x%04x "
+                       "device_setup=1 to enable and report any issues "
+                       "to g@b4.vu",
+                       USB_ID_VENDOR(chip->usb_id),
+                       USB_ID_PRODUCT(chip->usb_id));
+               return 0;
+       }
+
+       usb_audio_info(chip,
+               "Focusrite Scarlett Gen 2 Mixer Driver enabled pid=0x%04x",
+               USB_ID_PRODUCT(chip->usb_id));
+
+       err = snd_scarlett_gen2_controls_create(mixer, info);
+       if (err < 0)
+               usb_audio_err(mixer->chip,
+                             "Error initialising Scarlett Mixer Driver: %d",
+                             err);
+
+       return err;
+}
index 52e1dad77afd44bb1c0f084b0de61588cf0d7362..668c6b0cb50a63bf10c6ca99ab49f74f5b3d5872 100644 (file)
@@ -2,6 +2,6 @@
 #ifndef __USB_MIXER_SCARLETT_GEN2_H
 #define __USB_MIXER_SCARLETT_GEN2_H
 
-int snd_scarlett_gen2_controls_create(struct usb_mixer_interface *mixer);
+int snd_scarlett_gen2_init(struct usb_mixer_interface *mixer);
 
 #endif /* __USB_MIXER_SCARLETT_GEN2_H */
index 5a3022c8af82b8af1b88e5ed9d8b9af8afc5c9dd..0662f644aad9da71e25b9f7554d20d6981a5e7c7 100644 (file)
@@ -437,6 +437,8 @@ struct kvm_vmx_nested_state_hdr {
                __u16 flags;
        } smm;
 
+       __u16 pad;
+
        __u32 flags;
        __u64 preemption_timer_deadline;
 };
index 790944c356025f31df49787f3e60407a025cabda..baee8591ac76a4f9a869a558aac52fab37733e55 100644 (file)
@@ -30,7 +30,8 @@ CGROUP COMMANDS
 |      *ATTACH_TYPE* := { **ingress** | **egress** | **sock_create** | **sock_ops** | **device** |
 |              **bind4** | **bind6** | **post_bind4** | **post_bind6** | **connect4** | **connect6** |
 |               **getpeername4** | **getpeername6** | **getsockname4** | **getsockname6** | **sendmsg4** |
-|               **sendmsg6** | **recvmsg4** | **recvmsg6** | **sysctl** | **getsockopt** | **setsockopt** }
+|               **sendmsg6** | **recvmsg4** | **recvmsg6** | **sysctl** | **getsockopt** | **setsockopt** |
+|               **sock_release** }
 |      *ATTACH_FLAGS* := { **multi** | **override** }
 
 DESCRIPTION
@@ -106,6 +107,7 @@ DESCRIPTION
                  **getpeername6** call to getpeername(2) for an inet6 socket (since 5.8);
                  **getsockname4** call to getsockname(2) for an inet4 socket (since 5.8);
                  **getsockname6** call to getsockname(2) for an inet6 socket (since 5.8).
+                 **sock_release** closing an userspace inet socket (since 5.9).
 
        **bpftool cgroup detach** *CGROUP* *ATTACH_TYPE* *PROG*
                  Detach *PROG* from the cgroup *CGROUP* and attach type
index 358c7309d4191e01deb727f5e5df36da5a3703c0..fe1b38e7e887d3013b4ed940dd493375029255b9 100644 (file)
@@ -44,7 +44,7 @@ PROG COMMANDS
 |              **cgroup/connect4** | **cgroup/connect6** | **cgroup/getpeername4** | **cgroup/getpeername6** |
 |               **cgroup/getsockname4** | **cgroup/getsockname6** | **cgroup/sendmsg4** | **cgroup/sendmsg6** |
 |              **cgroup/recvmsg4** | **cgroup/recvmsg6** | **cgroup/sysctl** |
-|              **cgroup/getsockopt** | **cgroup/setsockopt** |
+|              **cgroup/getsockopt** | **cgroup/setsockopt** | **cgroup/sock_release** |
 |              **struct_ops** | **fentry** | **fexit** | **freplace** | **sk_lookup**
 |      }
 |       *ATTACH_TYPE* := {
index d67518bcbd4484e165fc4317036180832ee22eaf..cc33c5824a2f277444b7987e0bda90d900074574 100644 (file)
@@ -478,7 +478,7 @@ _bpftool()
                                 cgroup/recvmsg4 cgroup/recvmsg6 \
                                 cgroup/post_bind4 cgroup/post_bind6 \
                                 cgroup/sysctl cgroup/getsockopt \
-                                cgroup/setsockopt struct_ops \
+                                cgroup/setsockopt cgroup/sock_release struct_ops \
                                 fentry fexit freplace sk_lookup" -- \
                                                    "$cur" ) )
                             return 0
@@ -1021,7 +1021,7 @@ _bpftool()
                         device bind4 bind6 post_bind4 post_bind6 connect4 connect6 \
                         getpeername4 getpeername6 getsockname4 getsockname6 \
                         sendmsg4 sendmsg6 recvmsg4 recvmsg6 sysctl getsockopt \
-                        setsockopt'
+                        setsockopt sock_release'
                     local ATTACH_FLAGS='multi override'
                     local PROG_TYPE='id pinned tag name'
                     case $prev in
@@ -1032,7 +1032,7 @@ _bpftool()
                         ingress|egress|sock_create|sock_ops|device|bind4|bind6|\
                         post_bind4|post_bind6|connect4|connect6|getpeername4|\
                         getpeername6|getsockname4|getsockname6|sendmsg4|sendmsg6|\
-                        recvmsg4|recvmsg6|sysctl|getsockopt|setsockopt)
+                        recvmsg4|recvmsg6|sysctl|getsockopt|setsockopt|sock_release)
                             COMPREPLY=( $( compgen -W "$PROG_TYPE" -- \
                                 "$cur" ) )
                             return 0
index d901cc1b904afebbab9cf5e1b638597ef9f1bf25..6e53b1d393f4a497a700ee9d4da97361b109a3dd 100644 (file)
@@ -28,7 +28,8 @@
        "                        connect6 | getpeername4 | getpeername6 |\n"   \
        "                        getsockname4 | getsockname6 | sendmsg4 |\n"   \
        "                        sendmsg6 | recvmsg4 | recvmsg6 |\n"           \
-       "                        sysctl | getsockopt | setsockopt }"
+       "                        sysctl | getsockopt | setsockopt |\n"         \
+       "                        sock_release }"
 
 static unsigned int query_flags;
 
index 3f067d2d7584508821eb068ea553e7afd561f6cd..da4846c9856af9e1f314bc8f300863ebb7469b50 100644 (file)
@@ -2138,7 +2138,7 @@ static int do_help(int argc, char **argv)
                "                 cgroup/getpeername4 | cgroup/getpeername6 |\n"
                "                 cgroup/getsockname4 | cgroup/getsockname6 | cgroup/sendmsg4 |\n"
                "                 cgroup/sendmsg6 | cgroup/recvmsg4 | cgroup/recvmsg6 |\n"
-               "                 cgroup/getsockopt | cgroup/setsockopt |\n"
+               "                 cgroup/getsockopt | cgroup/setsockopt | cgroup/sock_release |\n"
                "                 struct_ops | fentry | fexit | freplace | sk_lookup }\n"
                "       ATTACH_TYPE := { msg_verdict | stream_verdict | stream_parser |\n"
                "                        flow_dissector }\n"
index cd72016c3cfa71159511549a5dc74e7cc36e82b0..715092fc6a239e3f848198ca7bf6047e2363fb37 100644 (file)
@@ -51,39 +51,39 @@ subdir-obj-y :=
 build-file := $(dir)/Build
 -include $(build-file)
 
-quiet_cmd_flex  = FLEX     $@
-quiet_cmd_bison = BISON    $@
+quiet_cmd_flex  = FLEX    $@
+quiet_cmd_bison = BISON   $@
 
 # Create directory unless it exists
-quiet_cmd_mkdir = MKDIR    $(dir $@)
+quiet_cmd_mkdir = MKDIR   $(dir $@)
       cmd_mkdir = mkdir -p $(dir $@)
      rule_mkdir = $(if $(wildcard $(dir $@)),,@$(call echo-cmd,mkdir) $(cmd_mkdir))
 
 # Compile command
-quiet_cmd_cc_o_c = CC       $@
+quiet_cmd_cc_o_c = CC      $@
       cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
 
-quiet_cmd_host_cc_o_c = HOSTCC   $@
+quiet_cmd_host_cc_o_c = HOSTCC  $@
       cmd_host_cc_o_c = $(HOSTCC) $(host_c_flags) -c -o $@ $<
 
-quiet_cmd_cxx_o_c = CXX      $@
+quiet_cmd_cxx_o_c = CXX     $@
       cmd_cxx_o_c = $(CXX) $(cxx_flags) -c -o $@ $<
 
-quiet_cmd_cpp_i_c = CPP      $@
+quiet_cmd_cpp_i_c = CPP     $@
       cmd_cpp_i_c = $(CC) $(c_flags) -E -o $@ $<
 
-quiet_cmd_cc_s_c = AS       $@
+quiet_cmd_cc_s_c = AS      $@
       cmd_cc_s_c = $(CC) $(c_flags) -S -o $@ $<
 
-quiet_cmd_gen = GEN      $@
+quiet_cmd_gen = GEN     $@
 
 # Link agregate command
 # If there's nothing to link, create empty $@ object.
-quiet_cmd_ld_multi = LD       $@
+quiet_cmd_ld_multi = LD      $@
       cmd_ld_multi = $(if $(strip $(obj-y)),\
                      $(LD) -r -o $@  $(filter $(obj-y),$^),rm -f $@; $(AR) rcs $@)
 
-quiet_cmd_host_ld_multi = HOSTLD   $@
+quiet_cmd_host_ld_multi = HOSTLD  $@
       cmd_host_ld_multi = $(if $(strip $(obj-y)),\
                           $(HOSTLD) -r -o $@  $(filter $(obj-y),$^),rm -f $@; $(HOSTAR) rcs $@)
 
index 7f475d59a0974f17d7a9765c643b798a1dc6ee83..87d112650dfbb0ec9ac6825ae2746c61b2659960 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/build_bug.h>
 #define GENMASK_INPUT_CHECK(h, l) \
        (BUILD_BUG_ON_ZERO(__builtin_choose_expr( \
-               __builtin_constant_p((l) > (h)), (l) > (h), 0)))
+               __is_constexpr((l) > (h)), (l) > (h), 0)))
 #else
 /*
  * BUILD_BUG_ON_ZERO is not available in h files included from asm files,
index 81b8aae5a8559c9fabf0665c48d8e8659db4f239..435ddd72d2c464fdedd33889190009dde0a3bda9 100644 (file)
@@ -3,4 +3,12 @@
 
 #include <vdso/const.h>
 
+/*
+ * This returns a constant expression while determining if an argument is
+ * a constant expression, most importantly without evaluating the argument.
+ * Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
+ */
+#define __is_constexpr(x) \
+       (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
+
 #endif /* _LINUX_CONST_H */
index f44eb0a04afdd8cea369af1395c3637a5f69122d..4c32e97dcdf00a22ebbcfc3c03f849ea90b2d9f5 100644 (file)
@@ -185,7 +185,7 @@ struct fsxattr {
 #define BLKROTATIONAL _IO(0x12,126)
 #define BLKZEROOUT _IO(0x12,127)
 /*
- * A jump here: 130-131 are reserved for zoned block devices
+ * A jump here: 130-136 are reserved for zoned block devices
  * (see uapi/linux/blkzoned.h)
  */
 
index bf8143505c49d033c697653121ec0a2054810e89..f92880a15645a4177406eca6e153665ea1ce0ea0 100644 (file)
@@ -464,7 +464,7 @@ struct perf_event_attr {
 
        /*
         * User provided data if sigtrap=1, passed back to user via
-        * siginfo_t::si_perf, e.g. to permit user to identify the event.
+        * siginfo_t::si_perf_data, e.g. to permit user to identify the event.
         */
        __u64   sig_data;
 };
index e2a3cf4378140f2ccabe45df70d40accc63d7bb3..c41d9b2b59aceff4ca23767527d187eafbc3ce92 100644 (file)
@@ -3216,6 +3216,9 @@ static int add_dummy_ksym_var(struct btf *btf)
        const struct btf_var_secinfo *vs;
        const struct btf_type *sec;
 
+       if (!btf)
+               return 0;
+
        sec_btf_id = btf__find_by_name_kind(btf, KSYMS_SEC,
                                            BTF_KIND_DATASEC);
        if (sec_btf_id < 0)
index ee426226928f1283ddb94ce867f7922bc1e71593..acbcf6c7bdf82cf219d8e985d8f9a6e5b69e5489 100644 (file)
 #define ELF_C_READ_MMAP ELF_C_READ
 #endif
 
+/* Older libelf all end up in this expression, for both 32 and 64 bit */
+#ifndef GELF_ST_VISIBILITY
+#define GELF_ST_VISIBILITY(o) ((o) & 0x03)
+#endif
+
 #define BTF_INFO_ENC(kind, kind_flag, vlen) \
        ((!!(kind_flag) << 31) | ((kind) << 24) | ((vlen) & BTF_MAX_VLEN))
 #define BTF_TYPE_ENC(name, info, size_or_type) (name), (info), (size_or_type)
index 1dcec73c910c192434b2a48ce519a3e9abcbff34..bcf3eca5afbe989b7df7fc75040df967162a06f7 100644 (file)
@@ -108,9 +108,9 @@ displayed as follows:
 
        perf script --itrace=ibxwpe -F+flags
 
-The flags are "bcrosyiABEx" which stand for branch, call, return, conditional,
-system, asynchronous, interrupt, transaction abort, trace begin, trace end, and
-in transaction, respectively.
+The flags are "bcrosyiABExgh" which stand for branch, call, return, conditional,
+system, asynchronous, interrupt, transaction abort, trace begin, trace end,
+in transaction, VM-entry, and VM-exit respectively.
 
 perf script also supports higher level ways to dump instruction traces:
 
index 5b8b610750393be05868e580f281f6a88b7bb9b1..48a5f5b26dd4450a1140336059c0b5d05f3afc3f 100644 (file)
@@ -183,14 +183,15 @@ OPTIONS
        At this point usage is displayed, and perf-script exits.
 
        The flags field is synthesized and may have a value when Instruction
-       Trace decoding. The flags are "bcrosyiABEx" which stand for branch,
+       Trace decoding. The flags are "bcrosyiABExgh" which stand for branch,
        call, return, conditional, system, asynchronous, interrupt,
-       transaction abort, trace begin, trace end, and in transaction,
+       transaction abort, trace begin, trace end, in transaction, VM-Entry, and VM-Exit
        respectively. Known combinations of flags are printed more nicely e.g.
        "call" for "bc", "return" for "br", "jcc" for "bo", "jmp" for "b",
        "int" for "bci", "iret" for "bri", "syscall" for "bcs", "sysret" for "brs",
        "async" for "by", "hw int" for "bcyi", "tx abrt" for "bA", "tr strt" for "bB",
-       "tr end" for "bE". However the "x" flag will be display separately in those
+       "tr end" for "bE", "vmentry" for "bcg", "vmexit" for "bch".
+       However the "x" flag will be displayed separately in those
        cases e.g. "jcc     (x)" for a condition branch within a transaction.
 
        The callindent field is synthesized and may have a value when
index 9974f5f8e49bce05819434ff65479b98caf85b91..9cd1c34f31b5040434060a7b242be5946bd5c988 100644 (file)
 440    n64     process_madvise                 sys_process_madvise
 441    n64     epoll_pwait2                    sys_epoll_pwait2
 442    n64     mount_setattr                   sys_mount_setattr
-443    n64     quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    n64     landlock_create_ruleset         sys_landlock_create_ruleset
 445    n64     landlock_add_rule               sys_landlock_add_rule
 446    n64     landlock_restrict_self          sys_landlock_restrict_self
index 2e68fbb57cc66de2e451c9e9721d425d9d76d9c1..8f052ff4058ce5534327ea64550af52bff5f5de2 100644 (file)
 440    common  process_madvise                 sys_process_madvise
 441    common  epoll_pwait2                    sys_epoll_pwait2                compat_sys_epoll_pwait2
 442    common  mount_setattr                   sys_mount_setattr
-443    common  quotactl_path                   sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset         sys_landlock_create_ruleset
 445    common  landlock_add_rule               sys_landlock_add_rule
 446    common  landlock_restrict_self          sys_landlock_restrict_self
index 7e4a2aba366df088e153856f93f94cb0be0a2b4e..0690263df1dd0b58268941074441cb4e820744bc 100644 (file)
 440  common    process_madvise         sys_process_madvise             sys_process_madvise
 441  common    epoll_pwait2            sys_epoll_pwait2                compat_sys_epoll_pwait2
 442  common    mount_setattr           sys_mount_setattr               sys_mount_setattr
-443  common    quotactl_path           sys_quotactl_path               sys_quotactl_path
+# 443 reserved for quotactl_path
 444  common    landlock_create_ruleset sys_landlock_create_ruleset     sys_landlock_create_ruleset
 445  common    landlock_add_rule       sys_landlock_add_rule           sys_landlock_add_rule
 446  common    landlock_restrict_self  sys_landlock_restrict_self      sys_landlock_restrict_self
index ecd551b08d05256af7235764c72d711460b2d58a..ce18119ea0d0f0c6deaf54959a9a7de1ed2e89ef 100644 (file)
 440    common  process_madvise         sys_process_madvise
 441    common  epoll_pwait2            sys_epoll_pwait2
 442    common  mount_setattr           sys_mount_setattr
-443    common  quotactl_path           sys_quotactl_path
+# 443 reserved for quotactl_path
 444    common  landlock_create_ruleset sys_landlock_create_ruleset
 445    common  landlock_add_rule       sys_landlock_add_rule
 446    common  landlock_restrict_self  sys_landlock_restrict_self
index 87f5b1a4a7fa84d4704da213aed22ddd3824434e..833405c27dae2abd66324422a54cb8f6fa0a88f3 100644 (file)
@@ -80,6 +80,9 @@ static int perf_session__list_build_ids(bool force, bool with_hits)
        if (!perf_header__has_feat(&session->header, HEADER_BUILD_ID))
                with_hits = true;
 
+       if (zstd_init(&(session->zstd_data), 0) < 0)
+               pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
+
        /*
         * in pipe-mode, the only way to get the buildids is to parse
         * the record stream. Buildids are stored as RECORD_HEADER_BUILD_ID
index 5a830ae09418edb76e56d206127a3171b38e25b9..f9f74a5143159ffbcc0d322604fc8ccfb35a1b97 100644 (file)
@@ -572,7 +572,8 @@ static int enable_counters(void)
         * - we have initial delay configured
         */
        if (!target__none(&target) || stat_config.initial_delay) {
-               evlist__enable(evsel_list);
+               if (!all_counters_use_bpf)
+                       evlist__enable(evsel_list);
                if (stat_config.initial_delay > 0)
                        pr_info(EVLIST_ENABLED_MSG);
        }
@@ -581,13 +582,19 @@ static int enable_counters(void)
 
 static void disable_counters(void)
 {
+       struct evsel *counter;
+
        /*
         * If we don't have tracee (attaching to task or cpu), counters may
         * still be running. To get accurate group ratios, we must stop groups
         * from counting before reading their constituent counters.
         */
-       if (!target__none(&target))
-               evlist__disable(evsel_list);
+       if (!target__none(&target)) {
+               evlist__for_each_entry(evsel_list, counter)
+                       bpf_counter__disable(counter);
+               if (!all_counters_use_bpf)
+                       evlist__disable(evsel_list);
+       }
 }
 
 static volatile int workload_exec_errno;
index 20cb91ef06ffc9ef97c3aff3b191098ea08bb83d..2f6b67189b426c33b07f66f6cd6209743afc297b 100644 (file)
@@ -443,6 +443,8 @@ int main(int argc, const char **argv)
        const char *cmd;
        char sbuf[STRERR_BUFSIZE];
 
+       perf_debug_setup();
+
        /* libsubcmd init */
        exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
        pager_init(PERF_PAGER_ENVIRONMENT);
@@ -531,8 +533,6 @@ int main(int argc, const char **argv)
         */
        pthread__block_sigwinch();
 
-       perf_debug_setup();
-
        while (1) {
                static int done_help;
 
index 616f29098c710cb84150f512f8f4d912649cedac..605be14f441c8153ad308b0ab2b3e95dbdd69076 100644 (file)
@@ -1,46 +1,56 @@
 [
   {
-    "EventCode": "1003C",
+    "EventCode": "0x1003C",
     "EventName": "PM_EXEC_STALL_DMISS_L2L3",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from either the local L2 or local L3."
   },
   {
-    "EventCode": "34056",
+    "EventCode": "0x1E054",
+    "EventName": "PM_EXEC_STALL_DMISS_L21_L31",
+    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from another core's L2 or L3 on the same chip."
+  },
+  {
+    "EventCode": "0x34054",
+    "EventName": "PM_EXEC_STALL_DMISS_L2L3_NOCONFLICT",
+    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from the local L2 or local L3, without a dispatch conflict."
+  },
+  {
+    "EventCode": "0x34056",
     "EventName": "PM_EXEC_STALL_LOAD_FINISH",
-    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was finishing a load after its data was reloaded from a data source beyond the local L1; cycles in which the LSU was processing an L1-hit; cycles in which the NTF instruction merged with another load in the LMQ."
+    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was finishing a load after its data was reloaded from a data source beyond the local L1; cycles in which the LSU was processing an L1-hit; cycles in which the NTF instruction merged with another load in the LMQ; cycles in which the NTF instruction is waiting for a data reload for a load miss, but the data comes back with a non-NTF instruction."
   },
   {
-    "EventCode": "3006C",
+    "EventCode": "0x3006C",
     "EventName": "PM_RUN_CYC_SMT2_MODE",
     "BriefDescription": "Cycles when this thread's run latch is set and the core is in SMT2 mode."
   },
   {
-    "EventCode": "300F4",
+    "EventCode": "0x300F4",
     "EventName": "PM_RUN_INST_CMPL_CONC",
     "BriefDescription": "PowerPC instructions completed by this thread when all threads in the core had the run-latch set."
   },
   {
-    "EventCode": "4C016",
+    "EventCode": "0x4C016",
     "EventName": "PM_EXEC_STALL_DMISS_L2L3_CONFLICT",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from the local L2 or local L3, with a dispatch conflict."
   },
   {
-    "EventCode": "4D014",
+    "EventCode": "0x4D014",
     "EventName": "PM_EXEC_STALL_LOAD",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a load instruction executing in the Load Store Unit."
   },
   {
-    "EventCode": "4D016",
+    "EventCode": "0x4D016",
     "EventName": "PM_EXEC_STALL_PTESYNC",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a PTESYNC instruction executing in the Load Store Unit."
   },
   {
-    "EventCode": "401EA",
+    "EventCode": "0x401EA",
     "EventName": "PM_THRESH_EXC_128",
     "BriefDescription": "Threshold counter exceeded a value of 128."
   },
   {
-    "EventCode": "400F6",
+    "EventCode": "0x400F6",
     "EventName": "PM_BR_MPRED_CMPL",
     "BriefDescription": "A mispredicted branch completed. Includes direction and target."
   }
index 703cd431ae5b0e0c0c6a08d67bc1da85b1a09731..54acb55e2c8c683bde7021c3631d06c136661284 100644 (file)
@@ -1,6 +1,6 @@
 [
   {
-    "EventCode": "4016E",
+    "EventCode": "0x4016E",
     "EventName": "PM_THRESH_NOT_MET",
     "BriefDescription": "Threshold counter did not meet threshold."
   }
index eac8609dcc90d61ae052fbe5482b3660970a2a1a..558f9530f54ecb9d5fb48d0b54e4c343b4e46d2f 100644 (file)
 [
   {
-    "EventCode": "10004",
+    "EventCode": "0x10004",
     "EventName": "PM_EXEC_STALL_TRANSLATION",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline suffered a TLB miss or ERAT miss and waited for it to resolve."
   },
   {
-    "EventCode": "10010",
+    "EventCode": "0x10006",
+    "EventName": "PM_DISP_STALL_HELD_OTHER_CYC",
+    "BriefDescription": "Cycles in which the NTC instruction is held at dispatch for any other reason."
+  },
+  {
+    "EventCode": "0x10010",
     "EventName": "PM_PMC4_OVERFLOW",
     "BriefDescription": "The event selected for PMC4 caused the event counter to overflow."
   },
   {
-    "EventCode": "10020",
+    "EventCode": "0x10020",
     "EventName": "PM_PMC4_REWIND",
     "BriefDescription": "The speculative event selected for PMC4 rewinds and the counter for PMC4 is not charged."
   },
   {
-    "EventCode": "10038",
+    "EventCode": "0x10038",
     "EventName": "PM_DISP_STALL_TRANSLATION",
     "BriefDescription": "Cycles when dispatch was stalled for this thread because the MMU was handling a translation miss."
   },
   {
-    "EventCode": "1003A",
+    "EventCode": "0x1003A",
     "EventName": "PM_DISP_STALL_BR_MPRED_IC_L2",
     "BriefDescription": "Cycles when dispatch was stalled while the instruction was fetched from the local L2 after suffering a branch mispredict."
   },
   {
-    "EventCode": "1E050",
+    "EventCode": "0x1D05E",
+    "EventName": "PM_DISP_STALL_HELD_HALT_CYC",
+    "BriefDescription": "Cycles in which the NTC instruction is held at dispatch because of power management."
+  },
+  {
+    "EventCode": "0x1E050",
     "EventName": "PM_DISP_STALL_HELD_STF_MAPPER_CYC",
     "BriefDescription": "Cycles in which the NTC instruction is held at dispatch because the STF mapper/SRB was full. Includes GPR (count, link, tar), VSR, VMR, FPR."
   },
   {
-    "EventCode": "1F054",
+    "EventCode": "0x1F054",
     "EventName": "PM_DTLB_HIT",
     "BriefDescription": "The PTE required by the instruction was resident in the TLB (data TLB access). When MMCR1[16]=0 this event counts only demand hits. When MMCR1[16]=1 this event includes demand and prefetch. Applies to both HPT and RPT."
   },
   {
-    "EventCode": "101E8",
+    "EventCode": "0x10064",
+    "EventName": "PM_DISP_STALL_IC_L2",
+    "BriefDescription": "Cycles when dispatch was stalled while the instruction was fetched from the local L2."
+  },
+  {
+    "EventCode": "0x101E8",
     "EventName": "PM_THRESH_EXC_256",
     "BriefDescription": "Threshold counter exceeded a count of 256."
   },
   {
-    "EventCode": "101EC",
+    "EventCode": "0x101EC",
     "EventName": "PM_THRESH_MET",
     "BriefDescription": "Threshold exceeded."
   },
   {
-    "EventCode": "100F2",
+    "EventCode": "0x100F2",
     "EventName": "PM_1PLUS_PPC_CMPL",
     "BriefDescription": "Cycles in which at least one instruction is completed by this thread."
   },
   {
-    "EventCode": "100F6",
+    "EventCode": "0x100F6",
     "EventName": "PM_IERAT_MISS",
     "BriefDescription": "IERAT Reloaded to satisfy an IERAT miss. All page sizes are counted by this event."
   },
   {
-    "EventCode": "100F8",
+    "EventCode": "0x100F8",
     "EventName": "PM_DISP_STALL_CYC",
     "BriefDescription": "Cycles the ICT has no itags assigned to this thread (no instructions were dispatched during these cycles)."
   },
   {
-    "EventCode": "20114",
+    "EventCode": "0x20006",
+    "EventName": "PM_DISP_STALL_HELD_ISSQ_FULL_CYC",
+    "BriefDescription": "Cycles in which the NTC instruction is held at dispatch due to Issue queue full. Includes issue queue and branch queue."
+  },
+  {
+    "EventCode": "0x20114",
     "EventName": "PM_MRK_L2_RC_DISP",
     "BriefDescription": "Marked instruction RC dispatched in L2."
   },
   {
-    "EventCode": "2C010",
+    "EventCode": "0x2C010",
     "EventName": "PM_EXEC_STALL_LSU",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was executing in the Load Store Unit. This does not include simple fixed point instructions."
   },
   {
-    "EventCode": "2C016",
+    "EventCode": "0x2C016",
     "EventName": "PM_DISP_STALL_IERAT_ONLY_MISS",
     "BriefDescription": "Cycles when dispatch was stalled while waiting to resolve an instruction ERAT miss."
   },
   {
-    "EventCode": "2C01E",
+    "EventCode": "0x2C01E",
     "EventName": "PM_DISP_STALL_BR_MPRED_IC_L3",
     "BriefDescription": "Cycles when dispatch was stalled while the instruction was fetched from the local L3 after suffering a branch mispredict."
   },
   {
-    "EventCode": "2D01A",
+    "EventCode": "0x2D01A",
     "EventName": "PM_DISP_STALL_IC_MISS",
     "BriefDescription": "Cycles when dispatch was stalled for this thread due to an Icache Miss."
   },
   {
-    "EventCode": "2D01C",
-    "EventName": "PM_CMPL_STALL_STCX",
-    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a stcx waiting for resolution from the nest before completing."
-  },
-  {
-    "EventCode": "2E018",
+    "EventCode": "0x2E018",
     "EventName": "PM_DISP_STALL_FETCH",
     "BriefDescription": "Cycles when dispatch was stalled for this thread because Fetch was being held."
   },
   {
-    "EventCode": "2E01A",
+    "EventCode": "0x2E01A",
     "EventName": "PM_DISP_STALL_HELD_XVFC_MAPPER_CYC",
     "BriefDescription": "Cycles in which the NTC instruction is held at dispatch because the XVFC mapper/SRB was full."
   },
   {
-    "EventCode": "2C142",
+    "EventCode": "0x2C142",
     "EventName": "PM_MRK_XFER_FROM_SRC_PMC2",
     "BriefDescription": "For a marked data transfer instruction, the processor's L1 data cache was reloaded from the source specified in MMCR3[15:27]. If MMCR1[16|17] is 0 (default), this count includes only lines that were reloaded to satisfy a demand miss. If MMCR1[16|17] is 1, this count includes both demand misses and prefetch reloads."
   },
   {
-    "EventCode": "24050",
+    "EventCode": "0x24050",
     "EventName": "PM_IOPS_DISP",
     "BriefDescription": "Internal Operations dispatched. PM_IOPS_DISP / PM_INST_DISP will show the average number of internal operations per PowerPC instruction."
   },
   {
-    "EventCode": "2405E",
+    "EventCode": "0x2405E",
     "EventName": "PM_ISSUE_CANCEL",
     "BriefDescription": "An instruction issued and the issue was later cancelled. Only one cancel per PowerPC instruction."
   },
   {
-    "EventCode": "200FA",
+    "EventCode": "0x200FA",
     "EventName": "PM_BR_TAKEN_CMPL",
     "BriefDescription": "Branch Taken instruction completed."
   },
   {
-    "EventCode": "30012",
+    "EventCode": "0x30004",
+    "EventName": "PM_DISP_STALL_FLUSH",
+    "BriefDescription": "Cycles when dispatch was stalled because of a flush that happened to an instruction(s) that was not yet NTC. PM_EXEC_STALL_NTC_FLUSH only includes instructions that were flushed after becoming NTC."
+  },
+  {
+    "EventCode": "0x3000A",
+    "EventName": "PM_DISP_STALL_ITLB_MISS",
+    "BriefDescription": "Cycles when dispatch was stalled while waiting to resolve an instruction TLB miss."
+  },
+  {
+    "EventCode": "0x30012",
     "EventName": "PM_FLUSH_COMPLETION",
     "BriefDescription": "The instruction that was next to complete (oldest in the pipeline) did not complete because it suffered a flush."
   },
   {
-    "EventCode": "30014",
+    "EventCode": "0x30014",
     "EventName": "PM_EXEC_STALL_STORE",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a store instruction executing in the Load Store Unit."
   },
   {
-    "EventCode": "30018",
+    "EventCode": "0x30018",
     "EventName": "PM_DISP_STALL_HELD_SCOREBOARD_CYC",
     "BriefDescription": "Cycles in which the NTC instruction is held at dispatch while waiting on the Scoreboard. This event combines VSCR and FPSCR together."
   },
   {
-    "EventCode": "30026",
+    "EventCode": "0x30026",
     "EventName": "PM_EXEC_STALL_STORE_MISS",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a store whose cache line was not resident in the L1 and was waiting for allocation of the missing line into the L1."
   },
   {
-    "EventCode": "3012A",
+    "EventCode": "0x3012A",
     "EventName": "PM_MRK_L2_RC_DONE",
     "BriefDescription": "L2 RC machine completed the transaction for the marked instruction."
   },
   {
-    "EventCode": "3F046",
+    "EventCode": "0x3F046",
     "EventName": "PM_ITLB_HIT_1G",
     "BriefDescription": "Instruction TLB hit (IERAT reload) page size 1G, which implies Radix Page Table translation is in use. When MMCR1[17]=0 this event counts only for demand misses. When MMCR1[17]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "34058",
+    "EventCode": "0x34058",
     "EventName": "PM_DISP_STALL_BR_MPRED_ICMISS",
     "BriefDescription": "Cycles when dispatch was stalled after a mispredicted branch resulted in an instruction cache miss."
   },
   {
-    "EventCode": "3D05C",
+    "EventCode": "0x3D05C",
     "EventName": "PM_DISP_STALL_HELD_RENAME_CYC",
     "BriefDescription": "Cycles in which the NTC instruction is held at dispatch because the mapper/SRB was full. Includes GPR (count, link, tar), VSR, VMR, FPR and XVFC."
   },
   {
-    "EventCode": "3E052",
+    "EventCode": "0x3E052",
     "EventName": "PM_DISP_STALL_IC_L3",
     "BriefDescription": "Cycles when dispatch was stalled while the instruction was fetched from the local L3."
   },
   {
-    "EventCode": "3E054",
+    "EventCode": "0x3E054",
     "EventName": "PM_LD_MISS_L1",
     "BriefDescription": "Load Missed L1, counted at execution time (can be greater than loads finished). LMQ merges are not included in this count. i.e. if a load instruction misses on an address that is already allocated on the LMQ, this event will not increment for that load). Note that this count is per slice, so if a load spans multiple slices this event will increment multiple times for a single load."
   },
   {
-    "EventCode": "301EA",
+    "EventCode": "0x301EA",
     "EventName": "PM_THRESH_EXC_1024",
     "BriefDescription": "Threshold counter exceeded a value of 1024."
   },
   {
-    "EventCode": "300FA",
+    "EventCode": "0x300FA",
     "EventName": "PM_INST_FROM_L3MISS",
     "BriefDescription": "The processor's instruction cache was reloaded from a source other than the local core's L1, L2, or L3 due to a demand miss."
   },
   {
-    "EventCode": "40006",
+    "EventCode": "0x40006",
     "EventName": "PM_ISSUE_KILL",
     "BriefDescription": "Cycles in which an instruction or group of instructions were cancelled after being issued. This event increments once per occurrence, regardless of how many instructions are included in the issue group."
   },
   {
-    "EventCode": "40116",
+    "EventCode": "0x40116",
     "EventName": "PM_MRK_LARX_FIN",
     "BriefDescription": "Marked load and reserve instruction (LARX) finished. LARX and STCX are instructions used to acquire a lock."
   },
   {
-    "EventCode": "4C010",
+    "EventCode": "0x4C010",
     "EventName": "PM_DISP_STALL_BR_MPRED_IC_L3MISS",
     "BriefDescription": "Cycles when dispatch was stalled while the instruction was fetched from sources beyond the local L3 after suffering a mispredicted branch."
   },
   {
-    "EventCode": "4D01E",
+    "EventCode": "0x4D01E",
     "EventName": "PM_DISP_STALL_BR_MPRED",
     "BriefDescription": "Cycles when dispatch was stalled for this thread due to a mispredicted branch."
   },
   {
-    "EventCode": "4E010",
+    "EventCode": "0x4E010",
     "EventName": "PM_DISP_STALL_IC_L3MISS",
     "BriefDescription": "Cycles when dispatch was stalled while the instruction was fetched from any source beyond the local L3."
   },
   {
-    "EventCode": "4E01A",
+    "EventCode": "0x4E01A",
     "EventName": "PM_DISP_STALL_HELD_CYC",
     "BriefDescription": "Cycles in which the NTC instruction is held at dispatch for any reason."
   },
   {
-    "EventCode": "44056",
+    "EventCode": "0x4003C",
+    "EventName": "PM_DISP_STALL_HELD_SYNC_CYC",
+    "BriefDescription": "Cycles in which the NTC instruction is held at dispatch because of a synchronizing instruction that requires the ICT to be empty before dispatch."
+  },
+  {
+    "EventCode": "0x44056",
     "EventName": "PM_VECTOR_ST_CMPL",
     "BriefDescription": "Vector store instructions completed."
   }
index 016d8de0e14ac281717db3d3d8f3897657908893..b5a0d65219631fb170debedeb49bef93114394a5 100644 (file)
@@ -1,11 +1,11 @@
 [
   {
-    "EventCode": "1E058",
+    "EventCode": "0x1E058",
     "EventName": "PM_STCX_FAIL_FIN",
     "BriefDescription": "Conditional store instruction (STCX) failed. LARX and STCX are instructions used to acquire a lock."
   },
   {
-    "EventCode": "4E050",
+    "EventCode": "0x4E050",
     "EventName": "PM_STCX_PASS_FIN",
     "BriefDescription": "Conditional store instruction (STCX) passed. LARX and STCX are instructions used to acquire a lock."
   }
index 93a5a59106480ab55fa93957105a3b67315b7568..58b5dfe3a273150ce9c7fd7ab38852c275bfef24 100644 (file)
 [
   {
-    "EventCode": "1002C",
+    "EventCode": "0x1002C",
     "EventName": "PM_LD_PREFETCH_CACHE_LINE_MISS",
     "BriefDescription": "The L1 cache was reloaded with a line that fulfills a prefetch request."
   },
   {
-    "EventCode": "10132",
+    "EventCode": "0x10132",
     "EventName": "PM_MRK_INST_ISSUED",
     "BriefDescription": "Marked instruction issued. Note that stores always get issued twice, the address gets issued to the LSU and the data gets issued to the VSU. Also, issues can sometimes get killed/cancelled and cause multiple sequential issues for the same instruction."
   },
   {
-    "EventCode": "101E0",
+    "EventCode": "0x101E0",
     "EventName": "PM_MRK_INST_DISP",
     "BriefDescription": "The thread has dispatched a randomly sampled marked instruction."
   },
   {
-    "EventCode": "101E2",
+    "EventCode": "0x101E2",
     "EventName": "PM_MRK_BR_TAKEN_CMPL",
     "BriefDescription": "Marked Branch Taken instruction completed."
   },
   {
-    "EventCode": "20112",
+    "EventCode": "0x20112",
     "EventName": "PM_MRK_NTF_FIN",
     "BriefDescription": "The marked instruction became the oldest in the pipeline before it finished. It excludes instructions that finish at dispatch."
   },
   {
-    "EventCode": "2C01C",
+    "EventCode": "0x2C01C",
     "EventName": "PM_EXEC_STALL_DMISS_OFF_CHIP",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from a remote chip."
   },
   {
-    "EventCode": "20138",
+    "EventCode": "0x20138",
     "EventName": "PM_MRK_ST_NEST",
     "BriefDescription": "A store has been sampled/marked and is at the point of execution where it has completed in the core and can no longer be flushed. At this point the store is sent to the L2."
   },
   {
-    "EventCode": "2013A",
+    "EventCode": "0x2013A",
     "EventName": "PM_MRK_BRU_FIN",
     "BriefDescription": "Marked Branch instruction finished."
   },
   {
-    "EventCode": "2C144",
+    "EventCode": "0x2C144",
     "EventName": "PM_MRK_XFER_FROM_SRC_CYC_PMC2",
     "BriefDescription": "Cycles taken for a marked demand miss to reload a line from the source specified in MMCR3[15:27]."
   },
   {
-    "EventCode": "24156",
+    "EventCode": "0x24156",
     "EventName": "PM_MRK_STCX_FIN",
     "BriefDescription": "Marked conditional store instruction (STCX) finished. LARX and STCX are instructions used to acquire a lock."
   },
   {
-    "EventCode": "24158",
+    "EventCode": "0x24158",
     "EventName": "PM_MRK_INST",
     "BriefDescription": "An instruction was marked. Includes both Random Instruction Sampling (RIS) at decode time and Random Event Sampling (RES) at the time the configured event happens."
   },
   {
-    "EventCode": "2415C",
+    "EventCode": "0x2415C",
     "EventName": "PM_MRK_BR_CMPL",
     "BriefDescription": "A marked branch completed. All branches are included."
   },
   {
-    "EventCode": "200FD",
+    "EventCode": "0x200FD",
     "EventName": "PM_L1_ICACHE_MISS",
     "BriefDescription": "Demand iCache Miss."
   },
   {
-    "EventCode": "30130",
+    "EventCode": "0x30130",
     "EventName": "PM_MRK_INST_FIN",
     "BriefDescription": "marked instruction finished. Excludes instructions that finish at dispatch. Note that stores always finish twice since the address gets issued to the LSU and the data gets issued to the VSU."
   },
   {
-    "EventCode": "34146",
+    "EventCode": "0x34146",
     "EventName": "PM_MRK_LD_CMPL",
     "BriefDescription": "Marked loads completed."
   },
   {
-    "EventCode": "3E158",
+    "EventCode": "0x3E158",
     "EventName": "PM_MRK_STCX_FAIL",
     "BriefDescription": "Marked conditional store instruction (STCX) failed. LARX and STCX are instructions used to acquire a lock."
   },
   {
-    "EventCode": "3E15A",
+    "EventCode": "0x3E15A",
     "EventName": "PM_MRK_ST_FIN",
     "BriefDescription": "The marked instruction was a store of any kind."
   },
   {
-    "EventCode": "30068",
+    "EventCode": "0x30068",
     "EventName": "PM_L1_ICACHE_RELOADED_PREF",
     "BriefDescription": "Counts all Icache prefetch reloads ( includes demand turned into prefetch)."
   },
   {
-    "EventCode": "301E4",
+    "EventCode": "0x301E4",
     "EventName": "PM_MRK_BR_MPRED_CMPL",
     "BriefDescription": "Marked Branch Mispredicted. Includes direction and target."
   },
   {
-    "EventCode": "300F6",
+    "EventCode": "0x300F6",
     "EventName": "PM_LD_DEMAND_MISS_L1",
     "BriefDescription": "The L1 cache was reloaded with a line that fulfills a demand miss request. Counted at reload time, before finish."
   },
   {
-    "EventCode": "300FE",
+    "EventCode": "0x300FE",
     "EventName": "PM_DATA_FROM_L3MISS",
     "BriefDescription": "The processor's data cache was reloaded from a source other than the local core's L1, L2, or L3 due to a demand miss."
   },
   {
-    "EventCode": "40012",
+    "EventCode": "0x40012",
     "EventName": "PM_L1_ICACHE_RELOADED_ALL",
     "BriefDescription": "Counts all Icache reloads includes demand, prefetch, prefetch turned into demand and demand turned into prefetch."
   },
   {
-    "EventCode": "40134",
+    "EventCode": "0x40134",
     "EventName": "PM_MRK_INST_TIMEO",
     "BriefDescription": "Marked instruction finish timeout (instruction was lost)."
   },
   {
-    "EventCode": "4003C",
-    "EventName": "PM_DISP_STALL_HELD_SYNC_CYC",
-    "BriefDescription": "Cycles in which the NTC instruction is held at dispatch because of a synchronizing instruction that requires the ICT to be empty before dispatch."
-  },
-  {
-    "EventCode": "4505A",
+    "EventCode": "0x4505A",
     "EventName": "PM_SP_FLOP_CMPL",
     "BriefDescription": "Single Precision floating point instructions completed."
   },
   {
-    "EventCode": "4D058",
+    "EventCode": "0x4D058",
     "EventName": "PM_VECTOR_FLOP_CMPL",
     "BriefDescription": "Vector floating point instructions completed."
   },
   {
-    "EventCode": "4D05A",
+    "EventCode": "0x4D05A",
     "EventName": "PM_NON_MATH_FLOP_CMPL",
     "BriefDescription": "Non Math instructions completed."
   },
   {
-    "EventCode": "401E0",
+    "EventCode": "0x401E0",
     "EventName": "PM_MRK_INST_CMPL",
     "BriefDescription": "marked instruction completed."
   },
   {
-    "EventCode": "400FE",
+    "EventCode": "0x400FE",
     "EventName": "PM_DATA_FROM_MEMORY",
     "BriefDescription": "The processor's data cache was reloaded from local, remote, or distant memory due to a demand miss."
   }
index b01141eeebee1b45de89e08023940bb3f9cb5f6f..843b51f531e9533bbc2374316e9c550af2831340 100644 (file)
 [
   {
-    "EventCode": "1000A",
+    "EventCode": "0x1000A",
     "EventName": "PM_PMC3_REWIND",
     "BriefDescription": "The speculative event selected for PMC3 rewinds and the counter for PMC3 is not charged."
   },
   {
-    "EventCode": "1C040",
+    "EventCode": "0x1C040",
     "EventName": "PM_XFER_FROM_SRC_PMC1",
     "BriefDescription": "The processor's L1 data cache was reloaded from the source specified in MMCR3[0:12]. If MMCR1[16|17] is 0 (default), this count includes only lines that were reloaded to satisfy a demand miss. If MMCR1[16|17] is 1, this count includes both demand misses and prefetch reloads."
   },
   {
-    "EventCode": "1C142",
+    "EventCode": "0x1C142",
     "EventName": "PM_MRK_XFER_FROM_SRC_PMC1",
     "BriefDescription": "For a marked data transfer instruction, the processor's L1 data cache was reloaded from the source specified in MMCR3[0:12]. If MMCR1[16|17] is 0 (default), this count includes only lines that were reloaded to satisfy a demand miss. If MMCR1[16|17] is 1, this count includes both demand misses and prefetch reloads."
   },
   {
-    "EventCode": "1C144",
+    "EventCode": "0x1C144",
     "EventName": "PM_MRK_XFER_FROM_SRC_CYC_PMC1",
     "BriefDescription": "Cycles taken for a marked demand miss to reload a line from the source specified in MMCR3[0:12]."
   },
   {
-    "EventCode": "1C056",
+    "EventCode": "0x1C056",
     "EventName": "PM_DERAT_MISS_4K",
     "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 4K. When MMCR1[16]=0 this event counts only DERAT reloads for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "1C058",
+    "EventCode": "0x1C058",
     "EventName": "PM_DTLB_MISS_16G",
     "BriefDescription": "Data TLB reload (after a miss) page size 16G. When MMCR1[16]=0 this event counts only for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "1C05C",
+    "EventCode": "0x1C05C",
     "EventName": "PM_DTLB_MISS_2M",
     "BriefDescription": "Data TLB reload (after a miss) page size 2M. Implies radix translation was used. When MMCR1[16]=0 this event counts only for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "1E056",
+    "EventCode": "0x1E056",
     "EventName": "PM_EXEC_STALL_STORE_PIPE",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was executing in the store unit. This does not include cycles spent handling store misses, PTESYNC instructions or TLBIE instructions."
   },
   {
-    "EventCode": "1F150",
+    "EventCode": "0x1F150",
     "EventName": "PM_MRK_ST_L2_CYC",
     "BriefDescription": "Cycles from L2 RC dispatch to L2 RC completion."
   },
   {
-    "EventCode": "10062",
+    "EventCode": "0x10062",
     "EventName": "PM_LD_L3MISS_PEND_CYC",
     "BriefDescription": "Cycles L3 miss was pending for this thread."
   },
   {
-    "EventCode": "20010",
+    "EventCode": "0x20010",
     "EventName": "PM_PMC1_OVERFLOW",
     "BriefDescription": "The event selected for PMC1 caused the event counter to overflow."
   },
   {
-    "EventCode": "2001A",
+    "EventCode": "0x2001A",
     "EventName": "PM_ITLB_HIT",
     "BriefDescription": "The PTE required to translate the instruction address was resident in the TLB (instruction TLB access/IERAT reload). Applies to both HPT and RPT. When MMCR1[17]=0 this event counts only for demand misses. When MMCR1[17]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "2003E",
+    "EventCode": "0x2003E",
     "EventName": "PM_PTESYNC_FIN",
     "BriefDescription": "Ptesync instruction finished in the store unit. Only one ptesync can finish at a time."
   },
   {
-    "EventCode": "2C040",
+    "EventCode": "0x2C040",
     "EventName": "PM_XFER_FROM_SRC_PMC2",
     "BriefDescription": "The processor's L1 data cache was reloaded from the source specified in MMCR3[15:27]. If MMCR1[16|17] is 0 (default), this count includes only lines that were reloaded to satisfy a demand miss. If MMCR1[16|17] is 1, this count includes both demand misses and prefetch reloads."
   },
   {
-    "EventCode": "2C054",
+    "EventCode": "0x2C054",
     "EventName": "PM_DERAT_MISS_64K",
     "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 64K. When MMCR1[16]=0 this event counts only DERAT reloads for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "2C056",
+    "EventCode": "0x2C056",
     "EventName": "PM_DTLB_MISS_4K",
     "BriefDescription": "Data TLB reload (after a miss) page size 4K. When MMCR1[16]=0 this event counts only for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "2D154",
+    "EventCode": "0x2D154",
     "EventName": "PM_MRK_DERAT_MISS_64K",
     "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 64K for a marked instruction. When MMCR1[16]=0 this event counts only DERAT reloads for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "200F6",
+    "EventCode": "0x200F6",
     "EventName": "PM_DERAT_MISS",
     "BriefDescription": "DERAT Reloaded to satisfy a DERAT miss. All page sizes are counted by this event. When MMCR1[16]=0 this event counts only DERAT reloads for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "3000A",
-    "EventName": "PM_DISP_STALL_ITLB_MISS",
-    "BriefDescription": "Cycles when dispatch was stalled while waiting to resolve an instruction TLB miss."
-  },
-  {
-    "EventCode": "30016",
+    "EventCode": "0x30016",
     "EventName": "PM_EXEC_STALL_DERAT_DTLB_MISS",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline suffered a TLB miss and waited for it resolve."
   },
   {
-    "EventCode": "3C040",
+    "EventCode": "0x3C040",
     "EventName": "PM_XFER_FROM_SRC_PMC3",
     "BriefDescription": "The processor's L1 data cache was reloaded from the source specified in MMCR3[30:42]. If MMCR1[16|17] is 0 (default), this count includes only lines that were reloaded to satisfy a demand miss. If MMCR1[16|17] is 1, this count includes both demand misses and prefetch reloads."
   },
   {
-    "EventCode": "3C142",
+    "EventCode": "0x3C142",
     "EventName": "PM_MRK_XFER_FROM_SRC_PMC3",
     "BriefDescription": "For a marked data transfer instruction, the processor's L1 data cache was reloaded from the source specified in MMCR3[30:42]. If MMCR1[16|17] is 0 (default), this count includes only lines that were reloaded to satisfy a demand miss. If MMCR1[16|17] is 1, this count includes both demand misses and prefetch reloads."
   },
   {
-    "EventCode": "3C144",
+    "EventCode": "0x3C144",
     "EventName": "PM_MRK_XFER_FROM_SRC_CYC_PMC3",
     "BriefDescription": "Cycles taken for a marked demand miss to reload a line from the source specified in MMCR3[30:42]."
   },
   {
-    "EventCode": "3C054",
+    "EventCode": "0x3C054",
     "EventName": "PM_DERAT_MISS_16M",
     "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 16M. When MMCR1[16]=0 this event counts only DERAT reloads for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "3C056",
+    "EventCode": "0x3C056",
     "EventName": "PM_DTLB_MISS_64K",
     "BriefDescription": "Data TLB reload (after a miss) page size 64K. When MMCR1[16]=0 this event counts only for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "3C058",
+    "EventCode": "0x3C058",
     "EventName": "PM_LARX_FIN",
     "BriefDescription": "Load and reserve instruction (LARX) finished. LARX and STCX are instructions used to acquire a lock."
   },
   {
-    "EventCode": "301E2",
+    "EventCode": "0x301E2",
     "EventName": "PM_MRK_ST_CMPL",
     "BriefDescription": "Marked store completed and sent to nest. Note that this count excludes cache-inhibited stores."
   },
   {
-    "EventCode": "300FC",
+    "EventCode": "0x300FC",
     "EventName": "PM_DTLB_MISS",
     "BriefDescription": "The DPTEG required for the load/store instruction in execution was missing from the TLB. It includes pages of all sizes for demand and prefetch activity."
   },
   {
-    "EventCode": "4D02C",
+    "EventCode": "0x4D02C",
     "EventName": "PM_PMC1_REWIND",
     "BriefDescription": "The speculative event selected for PMC1 rewinds and the counter for PMC1 is not charged."
   },
   {
-    "EventCode": "4003E",
+    "EventCode": "0x4003E",
     "EventName": "PM_LD_CMPL",
     "BriefDescription": "Loads completed."
   },
   {
-    "EventCode": "4C040",
+    "EventCode": "0x4C040",
     "EventName": "PM_XFER_FROM_SRC_PMC4",
     "BriefDescription": "The processor's L1 data cache was reloaded from the source specified in MMCR3[45:57]. If MMCR1[16|17] is 0 (default), this count includes only lines that were reloaded to satisfy a demand miss. If MMCR1[16|17] is 1, this count includes both demand misses and prefetch reloads."
   },
   {
-    "EventCode": "4C142",
+    "EventCode": "0x4C142",
     "EventName": "PM_MRK_XFER_FROM_SRC_PMC4",
     "BriefDescription": "For a marked data transfer instruction, the processor's L1 data cache was reloaded from the source specified in MMCR3[45:57]. If MMCR1[16|17] is 0 (default), this count includes only lines that were reloaded to satisfy a demand miss. If MMCR1[16|17] is 1, this count includes both demand misses and prefetch reloads."
   },
   {
-    "EventCode": "4C144",
+    "EventCode": "0x4C144",
     "EventName": "PM_MRK_XFER_FROM_SRC_CYC_PMC4",
     "BriefDescription": "Cycles taken for a marked demand miss to reload a line from the source specified in MMCR3[45:57]."
   },
   {
-    "EventCode": "4C056",
+    "EventCode": "0x4C056",
     "EventName": "PM_DTLB_MISS_16M",
     "BriefDescription": "Data TLB reload (after a miss) page size 16M. When MMCR1[16]=0 this event counts only for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "4C05A",
+    "EventCode": "0x4C05A",
     "EventName": "PM_DTLB_MISS_1G",
     "BriefDescription": "Data TLB reload (after a miss) page size 1G. Implies radix translation was used. When MMCR1[16]=0 this event counts only for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "4C15E",
+    "EventCode": "0x4C15E",
     "EventName": "PM_MRK_DTLB_MISS_64K",
     "BriefDescription": "Marked Data TLB reload (after a miss) page size 64K. When MMCR1[16]=0 this event counts only for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "4D056",
+    "EventCode": "0x4D056",
     "EventName": "PM_NON_FMA_FLOP_CMPL",
     "BriefDescription": "Non FMA instruction completed."
   },
   {
-    "EventCode": "40164",
+    "EventCode": "0x40164",
     "EventName": "PM_MRK_DERAT_MISS_2M",
     "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 2M for a marked instruction. When MMCR1[16]=0 this event counts only DERAT reloads for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   }
index a119e56cbf1c383adb051eeb47b8c5dcb8f7caad..7d0de1a2860b49cf4c58b37c901210076fd47c9a 100644 (file)
 [
   {
-    "EventCode": "10016",
+    "EventCode": "0x10016",
     "EventName": "PM_VSU0_ISSUE",
     "BriefDescription": "VSU instructions issued to VSU pipe 0."
   },
   {
-    "EventCode": "1001C",
+    "EventCode": "0x1001C",
     "EventName": "PM_ULTRAVISOR_INST_CMPL",
     "BriefDescription": "PowerPC instructions that completed while the thread was in ultravisor state."
   },
   {
-    "EventCode": "100F0",
+    "EventCode": "0x100F0",
     "EventName": "PM_CYC",
     "BriefDescription": "Processor cycles."
   },
   {
-    "EventCode": "10134",
+    "EventCode": "0x10134",
     "EventName": "PM_MRK_ST_DONE_L2",
     "BriefDescription": "Marked stores completed in L2 (RC machine done)."
   },
   {
-    "EventCode": "1505E",
+    "EventCode": "0x1505E",
     "EventName": "PM_LD_HIT_L1",
     "BriefDescription": "Loads that finished without experiencing an L1 miss."
   },
   {
-    "EventCode": "1D05E",
-    "EventName": "PM_DISP_STALL_HELD_HALT_CYC",
-    "BriefDescription": "Cycles in which the NTC instruction is held at dispatch because of power management."
-  },
-  {
-    "EventCode": "1E054",
-    "EventName": "PM_EXEC_STALL_DMISS_L21_L31",
-    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from another core's L2 or L3 on the same chip."
-  },
-  {
-    "EventCode": "1E05A",
-    "EventName": "PM_CMPL_STALL_LWSYNC",
-    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a lwsync waiting to complete."
-  },
-  {
-    "EventCode": "1F056",
+    "EventCode": "0x1F056",
     "EventName": "PM_DISP_SS0_2_INSTR_CYC",
     "BriefDescription": "Cycles in which Superslice 0 dispatches either 1 or 2 instructions."
   },
   {
-    "EventCode": "1F15C",
+    "EventCode": "0x1F15C",
     "EventName": "PM_MRK_STCX_L2_CYC",
     "BriefDescription": "Cycles spent in the nest portion of a marked Stcx instruction. It starts counting when the operation starts to drain to the L2 and it stops counting when the instruction retires from the Instruction Completion Table (ICT) in the Instruction Sequencing Unit (ISU)."
   },
   {
-    "EventCode": "10066",
+    "EventCode": "0x10066",
     "EventName": "PM_ADJUNCT_CYC",
     "BriefDescription": "Cycles in which the thread is in Adjunct state. MSR[S HV PR] bits = 011."
   },
   {
-    "EventCode": "101E4",
+    "EventCode": "0x101E4",
     "EventName": "PM_MRK_L1_ICACHE_MISS",
     "BriefDescription": "Marked Instruction suffered an icache Miss."
   },
   {
-    "EventCode": "101EA",
+    "EventCode": "0x101EA",
     "EventName": "PM_MRK_L1_RELOAD_VALID",
     "BriefDescription": "Marked demand reload."
   },
   {
-    "EventCode": "100F4",
+    "EventCode": "0x100F4",
     "EventName": "PM_FLOP_CMPL",
     "BriefDescription": "Floating Point Operations Completed. Includes any type. It counts once for each 1, 2, 4 or 8 flop instruction. Use PM_1|2|4|8_FLOP_CMPL events to count flops."
   },
   {
-    "EventCode": "100FA",
+    "EventCode": "0x100FA",
     "EventName": "PM_RUN_LATCH_ANY_THREAD_CYC",
     "BriefDescription": "Cycles when at least one thread has the run latch set."
   },
   {
-    "EventCode": "100FC",
+    "EventCode": "0x100FC",
     "EventName": "PM_LD_REF_L1",
     "BriefDescription": "All L1 D cache load references counted at finish, gated by reject. In P9 and earlier this event counted only cacheable loads but in P10 both cacheable and non-cacheable loads are included."
   },
   {
-    "EventCode": "20006",
-    "EventName": "PM_DISP_STALL_HELD_ISSQ_FULL_CYC",
-    "BriefDescription": "Cycles in which the NTC instruction is held at dispatch due to Issue queue full. Includes issue queue and branch queue."
-  },
-  {
-    "EventCode": "2000C",
+    "EventCode": "0x2000C",
     "EventName": "PM_RUN_LATCH_ALL_THREADS_CYC",
     "BriefDescription": "Cycles when the run latch is set for all threads."
   },
   {
-    "EventCode": "2E010",
+    "EventCode": "0x2E010",
     "EventName": "PM_ADJUNCT_INST_CMPL",
     "BriefDescription": "PowerPC instructions that completed while the thread is in Adjunct state."
   },
   {
-    "EventCode": "2E014",
+    "EventCode": "0x2E014",
     "EventName": "PM_STCX_FIN",
     "BriefDescription": "Conditional store instruction (STCX) finished. LARX and STCX are instructions used to acquire a lock."
   },
   {
-    "EventCode": "20130",
+    "EventCode": "0x20130",
     "EventName": "PM_MRK_INST_DECODED",
     "BriefDescription": "An instruction was marked at decode time. Random Instruction Sampling (RIS) only."
   },
   {
-    "EventCode": "20132",
+    "EventCode": "0x20132",
     "EventName": "PM_MRK_DFU_ISSUE",
     "BriefDescription": "The marked instruction was a decimal floating point operation issued to the VSU. Measured at issue time."
   },
   {
-    "EventCode": "20134",
+    "EventCode": "0x20134",
     "EventName": "PM_MRK_FXU_ISSUE",
     "BriefDescription": "The marked instruction was a fixed point operation issued to the VSU. Measured at issue time."
   },
   {
-    "EventCode": "2505C",
+    "EventCode": "0x2505C",
     "EventName": "PM_VSU_ISSUE",
     "BriefDescription": "At least one VSU instruction was issued to one of the VSU pipes. Up to 4 per cycle. Includes fixed point operations."
   },
   {
-    "EventCode": "2F054",
+    "EventCode": "0x2F054",
     "EventName": "PM_DISP_SS1_2_INSTR_CYC",
     "BriefDescription": "Cycles in which Superslice 1 dispatches either 1 or 2 instructions."
   },
   {
-    "EventCode": "2F056",
+    "EventCode": "0x2F056",
     "EventName": "PM_DISP_SS1_4_INSTR_CYC",
     "BriefDescription": "Cycles in which Superslice 1 dispatches either 3 or 4 instructions."
   },
   {
-    "EventCode": "2006C",
+    "EventCode": "0x2006C",
     "EventName": "PM_RUN_CYC_SMT4_MODE",
     "BriefDescription": "Cycles when this thread's run latch is set and the core is in SMT4 mode."
   },
   {
-    "EventCode": "201E0",
+    "EventCode": "0x201E0",
     "EventName": "PM_MRK_DATA_FROM_MEMORY",
     "BriefDescription": "The processor's data cache was reloaded from local, remote, or distant memory due to a demand miss for a marked load."
   },
   {
-    "EventCode": "201E4",
+    "EventCode": "0x201E4",
     "EventName": "PM_MRK_DATA_FROM_L3MISS",
     "BriefDescription": "The processor's data cache was reloaded from a source other than the local core's L1, L2, or L3 due to a demand miss for a marked load."
   },
   {
-    "EventCode": "201E8",
+    "EventCode": "0x201E8",
     "EventName": "PM_THRESH_EXC_512",
     "BriefDescription": "Threshold counter exceeded a value of 512."
   },
   {
-    "EventCode": "200F2",
+    "EventCode": "0x200F2",
     "EventName": "PM_INST_DISP",
     "BriefDescription": "PowerPC instructions dispatched."
   },
   {
-    "EventCode": "30132",
+    "EventCode": "0x30132",
     "EventName": "PM_MRK_VSU_FIN",
     "BriefDescription": "VSU marked instructions finished. Excludes simple FX instructions issued to the Store Unit."
   },
   {
-    "EventCode": "30038",
+    "EventCode": "0x30038",
     "EventName": "PM_EXEC_STALL_DMISS_LMEM",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from the local memory, local OpenCapp cache, or local OpenCapp memory."
   },
   {
-    "EventCode": "3F04A",
+    "EventCode": "0x3F04A",
     "EventName": "PM_LSU_ST5_FIN",
     "BriefDescription": "LSU Finished an internal operation in ST2 port."
   },
   {
-    "EventCode": "34054",
-    "EventName": "PM_EXEC_STALL_DMISS_L2L3_NOCONFLICT",
-    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from the local L2 or local L3, without a dispatch conflict."
-  },
-  {
-    "EventCode": "3405A",
+    "EventCode": "0x3405A",
     "EventName": "PM_PRIVILEGED_INST_CMPL",
     "BriefDescription": "PowerPC Instructions that completed while the thread is in Privileged state."
   },
   {
-    "EventCode": "3F150",
+    "EventCode": "0x3F150",
     "EventName": "PM_MRK_ST_DRAIN_CYC",
     "BriefDescription": "cycles to drain st from core to L2."
   },
   {
-    "EventCode": "3F054",
+    "EventCode": "0x3F054",
     "EventName": "PM_DISP_SS0_4_INSTR_CYC",
     "BriefDescription": "Cycles in which Superslice 0 dispatches either 3 or 4 instructions."
   },
   {
-    "EventCode": "3F056",
+    "EventCode": "0x3F056",
     "EventName": "PM_DISP_SS0_8_INSTR_CYC",
     "BriefDescription": "Cycles in which Superslice 0 dispatches either 5, 6, 7 or 8 instructions."
   },
   {
-    "EventCode": "30162",
+    "EventCode": "0x30162",
     "EventName": "PM_MRK_ISSUE_DEPENDENT_LOAD",
     "BriefDescription": "The marked instruction was dependent on a load. It is eligible for issue kill."
   },
   {
-    "EventCode": "40114",
+    "EventCode": "0x40114",
     "EventName": "PM_MRK_START_PROBE_NOP_DISP",
     "BriefDescription": "Marked Start probe nop dispatched. Instruction AND R0,R0,R0."
   },
   {
-    "EventCode": "4001C",
+    "EventCode": "0x4001C",
     "EventName": "PM_VSU_FIN",
     "BriefDescription": "VSU instructions finished."
   },
   {
-    "EventCode": "4C01A",
+    "EventCode": "0x4C01A",
     "EventName": "PM_EXEC_STALL_DMISS_OFF_NODE",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from a distant chip."
   },
   {
-    "EventCode": "4D012",
+    "EventCode": "0x4D012",
     "EventName": "PM_PMC3_SAVED",
     "BriefDescription": "The conditions for the speculative event selected for PMC3 are met and PMC3 is charged."
   },
   {
-    "EventCode": "4D022",
+    "EventCode": "0x4D022",
     "EventName": "PM_HYPERVISOR_INST_CMPL",
     "BriefDescription": "PowerPC instructions that completed while the thread is in hypervisor state."
   },
   {
-    "EventCode": "4D026",
+    "EventCode": "0x4D026",
     "EventName": "PM_ULTRAVISOR_CYC",
     "BriefDescription": "Cycles when the thread is in Ultravisor state. MSR[S HV PR]=110."
   },
   {
-    "EventCode": "4D028",
+    "EventCode": "0x4D028",
     "EventName": "PM_PRIVILEGED_CYC",
     "BriefDescription": "Cycles when the thread is in Privileged state. MSR[S HV PR]=x00."
   },
   {
-    "EventCode": "40030",
+    "EventCode": "0x40030",
     "EventName": "PM_INST_FIN",
     "BriefDescription": "Instructions finished."
   },
   {
-    "EventCode": "44146",
+    "EventCode": "0x44146",
     "EventName": "PM_MRK_STCX_CORE_CYC",
     "BriefDescription": "Cycles spent in the core portion of a marked Stcx instruction. It starts counting when the instruction is decoded and stops counting when it drains into the L2."
   },
   {
-    "EventCode": "44054",
+    "EventCode": "0x44054",
     "EventName": "PM_VECTOR_LD_CMPL",
     "BriefDescription": "Vector load instructions completed."
   },
   {
-    "EventCode": "45054",
+    "EventCode": "0x45054",
     "EventName": "PM_FMA_CMPL",
     "BriefDescription": "Two floating point instructions completed (FMA class of instructions: fmadd, fnmadd, fmsub, fnmsub). Scalar instructions only."
   },
   {
-    "EventCode": "45056",
+    "EventCode": "0x45056",
     "EventName": "PM_SCALAR_FLOP_CMPL",
     "BriefDescription": "Scalar floating point instructions completed."
   },
   {
-    "EventCode": "4505C",
+    "EventCode": "0x4505C",
     "EventName": "PM_MATH_FLOP_CMPL",
     "BriefDescription": "Math floating point instructions completed."
   },
   {
-    "EventCode": "4D05E",
+    "EventCode": "0x4D05E",
     "EventName": "PM_BR_CMPL",
     "BriefDescription": "A branch completed. All branches are included."
   },
   {
-    "EventCode": "4E15E",
+    "EventCode": "0x4E15E",
     "EventName": "PM_MRK_INST_FLUSHED",
     "BriefDescription": "The marked instruction was flushed."
   },
   {
-    "EventCode": "401E6",
+    "EventCode": "0x401E6",
     "EventName": "PM_MRK_INST_FROM_L3MISS",
     "BriefDescription": "The processor's instruction cache was reloaded from a source other than the local core's L1, L2, or L3 due to a demand miss for a marked instruction."
   },
   {
-    "EventCode": "401E8",
+    "EventCode": "0x401E8",
     "EventName": "PM_MRK_DATA_FROM_L2MISS",
     "BriefDescription": "The processor's data cache was reloaded from a source other than the local core's L1 or L2 due to a demand miss for a marked load."
   },
   {
-    "EventCode": "400F0",
+    "EventCode": "0x400F0",
     "EventName": "PM_LD_DEMAND_MISS_L1_FIN",
     "BriefDescription": "Load Missed L1, counted at finish time."
   },
   {
-    "EventCode": "400FA",
+    "EventCode": "0x400FA",
     "EventName": "PM_RUN_INST_CMPL",
     "BriefDescription": "Completed PowerPC instructions gated by the run latch."
   }
index b61b5cc157ee32dd89addd0529f54d8e48504f7d..b8aded6045faaf9c9697c192e63bfa7bd7833f99 100644 (file)
 [
   {
-    "EventCode": "100FE",
+    "EventCode": "0x100FE",
     "EventName": "PM_INST_CMPL",
     "BriefDescription": "PowerPC instructions completed."
   },
   {
-    "EventCode": "10006",
-    "EventName": "PM_DISP_STALL_HELD_OTHER_CYC",
-    "BriefDescription": "Cycles in which the NTC instruction is held at dispatch for any other reason."
-  },
-  {
-    "EventCode": "1000C",
+    "EventCode": "0x1000C",
     "EventName": "PM_LSU_LD0_FIN",
     "BriefDescription": "LSU Finished an internal operation in LD0 port."
   },
   {
-    "EventCode": "1000E",
+    "EventCode": "0x1000E",
     "EventName": "PM_MMA_ISSUED",
     "BriefDescription": "MMA instructions issued."
   },
   {
-    "EventCode": "10012",
+    "EventCode": "0x10012",
     "EventName": "PM_LSU_ST0_FIN",
     "BriefDescription": "LSU Finished an internal operation in ST0 port."
   },
   {
-    "EventCode": "10014",
+    "EventCode": "0x10014",
     "EventName": "PM_LSU_ST4_FIN",
     "BriefDescription": "LSU Finished an internal operation in ST4 port."
   },
   {
-    "EventCode": "10018",
+    "EventCode": "0x10018",
     "EventName": "PM_IC_DEMAND_CYC",
     "BriefDescription": "Cycles in which an instruction reload is pending to satisfy a demand miss."
   },
   {
-    "EventCode": "10022",
+    "EventCode": "0x10022",
     "EventName": "PM_PMC2_SAVED",
     "BriefDescription": "The conditions for the speculative event selected for PMC2 are met and PMC2 is charged."
   },
   {
-    "EventCode": "10024",
+    "EventCode": "0x10024",
     "EventName": "PM_PMC5_OVERFLOW",
     "BriefDescription": "The event selected for PMC5 caused the event counter to overflow."
   },
   {
-    "EventCode": "10058",
+    "EventCode": "0x10058",
     "EventName": "PM_EXEC_STALL_FIN_AT_DISP",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline finished at dispatch and did not require execution in the LSU, BRU or VSU."
   },
   {
-    "EventCode": "1005A",
+    "EventCode": "0x1005A",
     "EventName": "PM_FLUSH_MPRED",
     "BriefDescription": "A flush occurred due to a mispredicted branch. Includes target and direction."
   },
   {
-    "EventCode": "1C05A",
+    "EventCode": "0x1C05A",
     "EventName": "PM_DERAT_MISS_2M",
     "BriefDescription": "Data ERAT Miss (Data TLB Access) page size 2M. Implies radix translation. When MMCR1[16]=0 this event counts only DERAT reloads for demand misses. When MMCR1[16]=1 this event includes demand misses and prefetches."
   },
   {
-    "EventCode": "10064",
-    "EventName": "PM_DISP_STALL_IC_L2",
-    "BriefDescription": "Cycles when dispatch was stalled while the instruction was fetched from the local L2."
+    "EventCode": "0x1E05A",
+    "EventName": "PM_CMPL_STALL_LWSYNC",
+    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a lwsync waiting to complete."
   },
   {
-    "EventCode": "10068",
+    "EventCode": "0x10068",
     "EventName": "PM_BR_FIN",
     "BriefDescription": "A branch instruction finished. Includes predicted/mispredicted/unconditional."
   },
   {
-    "EventCode": "1006A",
+    "EventCode": "0x1006A",
     "EventName": "PM_FX_LSU_FIN",
     "BriefDescription": "Simple fixed point instruction issued to the store unit. Measured at finish time."
   },
   {
-    "EventCode": "1006C",
+    "EventCode": "0x1006C",
     "EventName": "PM_RUN_CYC_ST_MODE",
     "BriefDescription": "Cycles when the run latch is set and the core is in ST mode."
   },
   {
-    "EventCode": "20004",
+    "EventCode": "0x20004",
     "EventName": "PM_ISSUE_STALL",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was dispatched but not issued yet."
   },
   {
-    "EventCode": "2000A",
+    "EventCode": "0x2000A",
     "EventName": "PM_HYPERVISOR_CYC",
     "BriefDescription": "Cycles when the thread is in Hypervisor state. MSR[S HV PR]=010."
   },
   {
-    "EventCode": "2000E",
+    "EventCode": "0x2000E",
     "EventName": "PM_LSU_LD1_FIN",
     "BriefDescription": "LSU Finished an internal operation in LD1 port."
   },
   {
-    "EventCode": "2C014",
+    "EventCode": "0x2C014",
     "EventName": "PM_CMPL_STALL_SPECIAL",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline required special handling before completing."
   },
   {
-    "EventCode": "2C018",
+    "EventCode": "0x2C018",
     "EventName": "PM_EXEC_STALL_DMISS_L3MISS",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for a load miss to resolve from a source beyond the local L2 or local L3."
   },
   {
-    "EventCode": "2D010",
+    "EventCode": "0x2D010",
     "EventName": "PM_LSU_ST1_FIN",
     "BriefDescription": "LSU Finished an internal operation in ST1 port."
   },
   {
-    "EventCode": "2D012",
+    "EventCode": "0x2D012",
     "EventName": "PM_VSU1_ISSUE",
     "BriefDescription": "VSU instructions issued to VSU pipe 1."
   },
   {
-    "EventCode": "2D018",
+    "EventCode": "0x2D018",
     "EventName": "PM_EXEC_STALL_VSU",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was executing in the VSU (includes FXU, VSU, CRU)."
   },
   {
-    "EventCode": "2E01E",
+    "EventCode": "0x2D01C",
+    "EventName": "PM_CMPL_STALL_STCX",
+    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a stcx waiting for resolution from the nest before completing."
+  },
+  {
+    "EventCode": "0x2E01E",
     "EventName": "PM_EXEC_STALL_NTC_FLUSH",
-    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was executing in any unit before it was flushed. Note that if the flush of the oldest instruction happens after finish, the cycles from dispatch to issue will be included in PM_DISP_STALL and the cycles from issue to finish will be included in PM_EXEC_STALL and its corresponding children."
+    "BriefDescription": "Cycles in which the oldest instruction in the pipeline was executing in any unit before it was flushed. Note that if the flush of the oldest instruction happens after finish, the cycles from dispatch to issue will be included in PM_DISP_STALL and the cycles from issue to finish will be included in PM_EXEC_STALL and its corresponding children. This event will also count cycles when the previous NTF instruction is still completing and the new NTF instruction is stalled at dispatch."
   },
   {
-    "EventCode": "2013C",
+    "EventCode": "0x2013C",
     "EventName": "PM_MRK_FX_LSU_FIN",
     "BriefDescription": "The marked instruction was simple fixed point that was issued to the store unit. Measured at finish time."
   },
   {
-    "EventCode": "2405A",
+    "EventCode": "0x2405A",
     "EventName": "PM_NTC_FIN",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline (NTC) finishes. Note that instructions can finish out of order, therefore not all the instructions that finish have a Next-to-complete status."
   },
   {
-    "EventCode": "201E2",
+    "EventCode": "0x201E2",
     "EventName": "PM_MRK_LD_MISS_L1",
     "BriefDescription": "Marked DL1 Demand Miss counted at finish time."
   },
   {
-    "EventCode": "200F4",
+    "EventCode": "0x200F4",
     "EventName": "PM_RUN_CYC",
     "BriefDescription": "Processor cycles gated by the run latch."
   },
   {
-    "EventCode": "30004",
-    "EventName": "PM_DISP_STALL_FLUSH",
-    "BriefDescription": "Cycles when dispatch was stalled because of a flush that happened to an instruction(s) that was not yet NTC. PM_EXEC_STALL_NTC_FLUSH only includes instructions that were flushed after becoming NTC."
-  },
-  {
-    "EventCode": "30008",
+    "EventCode": "0x30008",
     "EventName": "PM_EXEC_STALL",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting to finish in one of the execution units (BRU, LSU, VSU). Only cycles between issue and finish are counted in this category."
   },
   {
-    "EventCode": "3001A",
+    "EventCode": "0x3001A",
     "EventName": "PM_LSU_ST2_FIN",
     "BriefDescription": "LSU Finished an internal operation in ST2 port."
   },
   {
-    "EventCode": "30020",
+    "EventCode": "0x30020",
     "EventName": "PM_PMC2_REWIND",
     "BriefDescription": "The speculative event selected for PMC2 rewinds and the counter for PMC2 is not charged."
   },
   {
-    "EventCode": "30022",
+    "EventCode": "0x30022",
     "EventName": "PM_PMC4_SAVED",
     "BriefDescription": "The conditions for the speculative event selected for PMC4 are met and PMC4 is charged."
   },
   {
-    "EventCode": "30024",
+    "EventCode": "0x30024",
     "EventName": "PM_PMC6_OVERFLOW",
     "BriefDescription": "The event selected for PMC6 caused the event counter to overflow."
   },
   {
-    "EventCode": "30028",
+    "EventCode": "0x30028",
     "EventName": "PM_CMPL_STALL_MEM_ECC",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was waiting for the non-speculative finish of either a stcx waiting for its result or a load waiting for non-critical sectors of data and ECC."
   },
   {
-    "EventCode": "30036",
+    "EventCode": "0x30036",
     "EventName": "PM_EXEC_STALL_SIMPLE_FX",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a simple fixed point instruction executing in the Load Store Unit."
   },
   {
-    "EventCode": "3003A",
+    "EventCode": "0x3003A",
     "EventName": "PM_CMPL_STALL_EXCEPTION",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was not allowed to complete because it was interrupted by ANY exception, which has to be serviced before the instruction can complete."
   },
   {
-    "EventCode": "3F044",
+    "EventCode": "0x3F044",
     "EventName": "PM_VSU2_ISSUE",
     "BriefDescription": "VSU instructions issued to VSU pipe 2."
   },
   {
-    "EventCode": "30058",
+    "EventCode": "0x30058",
     "EventName": "PM_TLBIE_FIN",
     "BriefDescription": "TLBIE instructions finished in the LSU. Two TLBIEs can finish each cycle. All will be counted."
   },
   {
-    "EventCode": "3D058",
+    "EventCode": "0x3D058",
     "EventName": "PM_SCALAR_FSQRT_FDIV_ISSUE",
     "BriefDescription": "Scalar versions of four floating point operations: fdiv,fsqrt (xvdivdp, xvdivsp, xvsqrtdp, xvsqrtsp)."
   },
   {
-    "EventCode": "30066",
+    "EventCode": "0x30066",
     "EventName": "PM_LSU_FIN",
     "BriefDescription": "LSU Finished an internal operation (up to 4 per cycle)."
   },
   {
-    "EventCode": "40004",
+    "EventCode": "0x40004",
     "EventName": "PM_FXU_ISSUE",
     "BriefDescription": "A fixed point instruction was issued to the VSU."
   },
   {
-    "EventCode": "40008",
+    "EventCode": "0x40008",
     "EventName": "PM_NTC_ALL_FIN",
     "BriefDescription": "Cycles in which both instructions in the ICT entry pair show as finished. These are the cycles between finish and completion for the oldest pair of instructions in the pipeline."
   },
   {
-    "EventCode": "40010",
+    "EventCode": "0x40010",
     "EventName": "PM_PMC3_OVERFLOW",
     "BriefDescription": "The event selected for PMC3 caused the event counter to overflow."
   },
   {
-    "EventCode": "4C012",
+    "EventCode": "0x4C012",
     "EventName": "PM_EXEC_STALL_DERAT_ONLY_MISS",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline suffered an ERAT miss and waited for it resolve."
   },
   {
-    "EventCode": "4C018",
+    "EventCode": "0x4C018",
     "EventName": "PM_CMPL_STALL",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline cannot complete because the thread was blocked for any reason."
   },
   {
-    "EventCode": "4C01E",
+    "EventCode": "0x4C01E",
     "EventName": "PM_LSU_ST3_FIN",
     "BriefDescription": "LSU Finished an internal operation in ST3 port."
   },
   {
-    "EventCode": "4D018",
+    "EventCode": "0x4D018",
     "EventName": "PM_EXEC_STALL_BRU",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was executing in the Branch unit."
   },
   {
-    "EventCode": "4D01A",
+    "EventCode": "0x4D01A",
     "EventName": "PM_CMPL_STALL_HWSYNC",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a hwsync waiting for response from L2 before completing."
   },
   {
-    "EventCode": "4D01C",
+    "EventCode": "0x4D01C",
     "EventName": "PM_EXEC_STALL_TLBIEL",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a TLBIEL instruction executing in the Load Store Unit. TLBIEL instructions have lower overhead than TLBIE instructions because they don't get set to the nest."
   },
   {
-    "EventCode": "4E012",
+    "EventCode": "0x4E012",
     "EventName": "PM_EXEC_STALL_UNKNOWN",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline completed without an ntf_type pulse. The ntf_pulse was missed by the ISU because the NTF finishes and completions came too close together."
   },
   {
-    "EventCode": "4D020",
+    "EventCode": "0x4D020",
     "EventName": "PM_VSU3_ISSUE",
     "BriefDescription": "VSU instruction was issued to VSU pipe 3."
   },
   {
-    "EventCode": "40132",
+    "EventCode": "0x40132",
     "EventName": "PM_MRK_LSU_FIN",
     "BriefDescription": "LSU marked instruction finish."
   },
   {
-    "EventCode": "45058",
+    "EventCode": "0x45058",
     "EventName": "PM_IC_MISS_CMPL",
     "BriefDescription": "Non-speculative icache miss, counted at completion."
   },
   {
-    "EventCode": "4D050",
+    "EventCode": "0x4D050",
     "EventName": "PM_VSU_NON_FLOP_CMPL",
     "BriefDescription": "Non-floating point VSU instructions completed."
   },
   {
-    "EventCode": "4D052",
+    "EventCode": "0x4D052",
     "EventName": "PM_2FLOP_CMPL",
     "BriefDescription": "Double Precision vector version of fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg completed."
   },
   {
-    "EventCode": "400F2",
+    "EventCode": "0x400F2",
     "EventName": "PM_1PLUS_PPC_DISP",
     "BriefDescription": "Cycles at least one Instr Dispatched."
   },
   {
-    "EventCode": "400F8",
+    "EventCode": "0x400F8",
     "EventName": "PM_FLUSH",
     "BriefDescription": "Flush (any type)."
   }
index ea122a91ceb0ffe2d3658351c442d9aee66dfcb1..b5d1bd39cfb2243c7f145676f65e30562f7c3486 100644 (file)
@@ -1,21 +1,21 @@
 [
   {
-    "EventCode": "301E8",
+    "EventCode": "0x301E8",
     "EventName": "PM_THRESH_EXC_64",
     "BriefDescription": "Threshold counter exceeded a value of 64."
   },
   {
-    "EventCode": "45050",
+    "EventCode": "0x45050",
     "EventName": "PM_1FLOP_CMPL",
     "BriefDescription": "One floating point instruction completed (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg)."
   },
   {
-    "EventCode": "45052",
+    "EventCode": "0x45052",
     "EventName": "PM_4FLOP_CMPL",
     "BriefDescription": "Four floating point instructions completed (fadd, fmul, fsub, fcmp, fsel, fabs, fnabs, fres, fsqrte, fneg)."
   },
   {
-    "EventCode": "4D054",
+    "EventCode": "0x4D054",
     "EventName": "PM_8FLOP_CMPL",
     "BriefDescription": "Four Double Precision vector instructions completed."
   }
index 5a714e3dd71acc9256396655424765020411de9f..db3766dca07c5955b4aa9510532d1d1b3699ad9c 100644 (file)
@@ -1,56 +1,56 @@
 [
   {
-    "EventCode": "1F15E",
+    "EventCode": "0x1F15E",
     "EventName": "PM_MRK_START_PROBE_NOP_CMPL",
     "BriefDescription": "Marked Start probe nop (AND R0,R0,R0) completed."
   },
   {
-    "EventCode": "20016",
+    "EventCode": "0x20016",
     "EventName": "PM_ST_FIN",
     "BriefDescription": "Store finish count. Includes speculative activity."
   },
   {
-    "EventCode": "20018",
+    "EventCode": "0x20018",
     "EventName": "PM_ST_FWD",
     "BriefDescription": "Store forwards that finished."
   },
   {
-    "EventCode": "2011C",
+    "EventCode": "0x2011C",
     "EventName": "PM_MRK_NTF_CYC",
     "BriefDescription": "Cycles during which the marked instruction is the oldest in the pipeline (NTF or NTC)."
   },
   {
-    "EventCode": "2E01C",
+    "EventCode": "0x2E01C",
     "EventName": "PM_EXEC_STALL_TLBIE",
     "BriefDescription": "Cycles in which the oldest instruction in the pipeline was a TLBIE instruction executing in the Load Store Unit."
   },
   {
-    "EventCode": "201E6",
+    "EventCode": "0x201E6",
     "EventName": "PM_THRESH_EXC_32",
     "BriefDescription": "Threshold counter exceeded a value of 32."
   },
   {
-    "EventCode": "200F0",
+    "EventCode": "0x200F0",
     "EventName": "PM_ST_CMPL",
     "BriefDescription": "Stores completed from S2Q (2nd-level store queue). This event includes regular stores, stcx and cache inhibited stores. The following operations are excluded (pteupdate, snoop tlbie complete, store atomics, miso, load atomic payloads, tlbie, tlbsync, slbieg, isync, msgsnd, slbiag, cpabort, copy, tcheck, tend, stsync, dcbst, icbi, dcbf, hwsync, lwsync, ptesync, eieio, msgsync)."
   },
   {
-    "EventCode": "200FE",
+    "EventCode": "0x200FE",
     "EventName": "PM_DATA_FROM_L2MISS",
     "BriefDescription": "The processor's data cache was reloaded from a source other than the local core's L1 or L2 due to a demand miss."
   },
   {
-    "EventCode": "30010",
+    "EventCode": "0x30010",
     "EventName": "PM_PMC2_OVERFLOW",
     "BriefDescription": "The event selected for PMC2 caused the event counter to overflow."
   },
   {
-    "EventCode": "4D010",
+    "EventCode": "0x4D010",
     "EventName": "PM_PMC1_SAVED",
     "BriefDescription": "The conditions for the speculative event selected for PMC1 are met and PMC1 is charged."
   },
   {
-    "EventCode": "4D05C",
+    "EventCode": "0x4D05C",
     "EventName": "PM_DPP_FLOP_CMPL",
     "BriefDescription": "Double-Precision or Quad-Precision instructions completed."
   }
index 7422b0ea879017f0543515657e2b4b1902ae35b1..9604446f8360be061a5e5c911c9c29fad6e224c6 100644 (file)
@@ -960,7 +960,7 @@ static int get_maxfds(void)
        struct rlimit rlim;
 
        if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
-               return min((int)rlim.rlim_max / 2, 512);
+               return min(rlim.rlim_max / 2, (rlim_t)512);
 
        return 512;
 }
index 7daa8bb70a5a09e85189bfd15da7f59b263f2fda..711d4f9f5645cf33aa721f7c8a263a6b2d691305 100755 (executable)
 from __future__ import print_function
 
 import sys
+# Only change warnings if the python -W option was not used
+if not sys.warnoptions:
+       import warnings
+       # PySide2 causes deprecation warnings, ignore them.
+       warnings.filterwarnings("ignore", category=DeprecationWarning)
 import argparse
 import weakref
 import threading
@@ -125,8 +130,9 @@ if pyside_version_1:
        from PySide.QtGui import *
        from PySide.QtSql import *
 
-from decimal import *
-from ctypes import *
+from decimal import Decimal, ROUND_HALF_UP
+from ctypes import CDLL, Structure, create_string_buffer, addressof, sizeof, \
+                  c_void_p, c_bool, c_byte, c_char, c_int, c_uint, c_longlong, c_ulonglong
 from multiprocessing import Process, Array, Value, Event
 
 # xrange is range in Python3
@@ -3868,7 +3874,7 @@ def CopyTableCellsToClipboard(view, as_csv=False, with_hdr=False):
        if with_hdr:
                model = indexes[0].model()
                for col in range(min_col, max_col + 1):
-                       val = model.headerData(col, Qt.Horizontal)
+                       val = model.headerData(col, Qt.Horizontal, Qt.DisplayRole)
                        if as_csv:
                                text += sep + ToCSValue(val)
                                sep = ","
index 76a53126efdf173bdd035017a547a56b0739c081..d4b0ef74defccfea45805a75c293eefec30e18e8 100644 (file)
@@ -131,8 +131,8 @@ static int test__pfm_group(void)
                },
                {
                        .events = "{},{instructions}",
-                       .nr_events = 0,
-                       .nr_groups = 0,
+                       .nr_events = 1,
+                       .nr_groups = 1,
                },
                {
                        .events = "{instructions},{instructions}",
index ddb52f748c8e8613cc293a366d4475d3b2f73bd1..974f10e356f063340e28f02c6895d1e02b78a0ab 100644 (file)
@@ -451,10 +451,10 @@ static int bperf_reload_leader_program(struct evsel *evsel, int attr_map_fd,
                goto out;
        }
 
-       err = -1;
        link = bpf_program__attach(skel->progs.on_switch);
-       if (!link) {
+       if (IS_ERR(link)) {
                pr_err("Failed to attach leader program\n");
+               err = PTR_ERR(link);
                goto out;
        }
 
index 8a62fb39e365cac4a6c5dafb6fb152d8b71668e1..19ad64f2bd8302a9e33a2554703a3853ffae78d5 100644 (file)
@@ -100,7 +100,7 @@ enum {
        PERF_IP_FLAG_VMEXIT             = 1ULL << 12,
 };
 
-#define PERF_IP_FLAG_CHARS "bcrosyiABEx"
+#define PERF_IP_FLAG_CHARS "bcrosyiABExgh"
 
 #define PERF_BRANCH_MASK               (\
        PERF_IP_FLAG_BRANCH             |\
index 6e5c41528c7d0c7f91c4f9196485737c6b104f0d..6ea3e677dc1e7328dbda9d653c909241ae9baeb2 100644 (file)
@@ -425,9 +425,6 @@ static void __evlist__disable(struct evlist *evlist, char *evsel_name)
        if (affinity__setup(&affinity) < 0)
                return;
 
-       evlist__for_each_entry(evlist, pos)
-               bpf_counter__disable(pos);
-
        /* Disable 'immediate' events last */
        for (imm = 0; imm <= 1; imm++) {
                evlist__for_each_cpu(evlist, i, cpu) {
index 8c59677bee130f5643f61382ebadb33a9421e7fc..20ad663978cc463074e56c1afcdce6c16c52de01 100644 (file)
@@ -1146,6 +1146,8 @@ static bool intel_pt_fup_event(struct intel_pt_decoder *decoder)
                decoder->set_fup_tx_flags = false;
                decoder->tx_flags = decoder->fup_tx_flags;
                decoder->state.type = INTEL_PT_TRANSACTION;
+               if (decoder->fup_tx_flags & INTEL_PT_ABORT_TX)
+                       decoder->state.type |= INTEL_PT_BRANCH;
                decoder->state.from_ip = decoder->ip;
                decoder->state.to_ip = 0;
                decoder->state.flags = decoder->fup_tx_flags;
@@ -1220,8 +1222,10 @@ static int intel_pt_walk_fup(struct intel_pt_decoder *decoder)
                        return 0;
                if (err == -EAGAIN ||
                    intel_pt_fup_with_nlip(decoder, &intel_pt_insn, ip, err)) {
+                       bool no_tip = decoder->pkt_state != INTEL_PT_STATE_FUP;
+
                        decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
-                       if (intel_pt_fup_event(decoder))
+                       if (intel_pt_fup_event(decoder) && no_tip)
                                return 0;
                        return -EAGAIN;
                }
index 8658d42ce57a09d97c42a348b2d94bb229524120..0dfec8761b9ac5b83d460ad888226ee8087660bb 100644 (file)
@@ -707,8 +707,10 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
 
                        *ip += intel_pt_insn->length;
 
-                       if (to_ip && *ip == to_ip)
+                       if (to_ip && *ip == to_ip) {
+                               intel_pt_insn->length = 0;
                                goto out_no_cache;
+                       }
 
                        if (*ip >= al.map->end)
                                break;
@@ -1198,6 +1200,7 @@ static void intel_pt_set_pid_tid_cpu(struct intel_pt *pt,
 
 static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
 {
+       ptq->insn_len = 0;
        if (ptq->state->flags & INTEL_PT_ABORT_TX) {
                ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT;
        } else if (ptq->state->flags & INTEL_PT_ASYNC) {
@@ -1211,7 +1214,6 @@ static void intel_pt_sample_flags(struct intel_pt_queue *ptq)
                        ptq->flags = PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL |
                                     PERF_IP_FLAG_ASYNC |
                                     PERF_IP_FLAG_INTERRUPT;
-               ptq->insn_len = 0;
        } else {
                if (ptq->state->from_ip)
                        ptq->flags = intel_pt_insn_type(ptq->state->insn_op);
index 4dad14265b81dfb85f48122a924bbeb74ee2c77f..84108c17f48d4a81f14d53b7c2df9f0aa75f563a 100644 (file)
@@ -150,6 +150,10 @@ struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
                .symbol = "bpf-output",
                .alias  = "",
        },
+       [PERF_COUNT_SW_CGROUP_SWITCHES] = {
+               .symbol = "cgroup-switches",
+               .alias  = "",
+       },
 };
 
 #define __PERF_EVENT_FIELD(config, name) \
@@ -2928,9 +2932,14 @@ restart:
        }
 
        for (i = 0; i < max; i++, syms++) {
+               /*
+                * New attr.config still not supported here, the latest
+                * example was PERF_COUNT_SW_CGROUP_SWITCHES
+                */
+               if (syms->symbol == NULL)
+                       continue;
 
-               if (event_glob != NULL && syms->symbol != NULL &&
-                   !(strglobmatch(syms->symbol, event_glob) ||
+               if (event_glob != NULL && !(strglobmatch(syms->symbol, event_glob) ||
                      (syms->alias && strglobmatch(syms->alias, event_glob))))
                        continue;
 
index fb8646cc3e834e288fd4a0ca163b69f8244f85ba..923849024b15fad18181de0526203a2fa46e5437 100644 (file)
@@ -347,6 +347,7 @@ emulation-faults                            { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EM
 dummy                                          { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_DUMMY); }
 duration_time                                  { return tool(yyscanner, PERF_TOOL_DURATION_TIME); }
 bpf-output                                     { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_BPF_OUTPUT); }
+cgroup-switches                                        { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CGROUP_SWITCHES); }
 
        /*
         * We have to handle the kernel PMU event cycles-ct/cycles-t/mem-loads/mem-stores separately.
index d735acb6c29cb0baa4ae08ffb73454254e6dc603..6eef6dfeaa574a74b76617e6df29153fbe7cdadb 100644 (file)
@@ -62,8 +62,16 @@ int parse_libpfm_events_option(const struct option *opt, const char *str,
                }
 
                /* no event */
-               if (*q == '\0')
+               if (*q == '\0') {
+                       if (*sep == '}') {
+                               if (grp_evt < 0) {
+                                       ui__error("cannot close a non-existing event group\n");
+                                       goto error;
+                               }
+                               grp_evt--;
+                       }
                        continue;
+               }
 
                memset(&attr, 0, sizeof(attr));
                event_attr_init(&attr);
@@ -107,6 +115,7 @@ int parse_libpfm_events_option(const struct option *opt, const char *str,
                        grp_evt = -1;
                }
        }
+       free(p_orig);
        return 0;
 error:
        free(p_orig);
index f9271f3ea91299d32fdf7a516093b99e695743cd..071312f5eb9280e8a7d37d6e4931a2aaac123e1a 100644 (file)
@@ -131,29 +131,29 @@ QUIET_SUBDIR1  =
 
 ifneq ($(silent),1)
   ifneq ($(V),1)
-       QUIET_CC       = @echo '  CC       '$@;
-       QUIET_CC_FPIC  = @echo '  CC FPIC  '$@;
-       QUIET_CLANG    = @echo '  CLANG    '$@;
-       QUIET_AR       = @echo '  AR       '$@;
-       QUIET_LINK     = @echo '  LINK     '$@;
-       QUIET_MKDIR    = @echo '  MKDIR    '$@;
-       QUIET_GEN      = @echo '  GEN      '$@;
+       QUIET_CC       = @echo '  CC      '$@;
+       QUIET_CC_FPIC  = @echo '  CC FPIC '$@;
+       QUIET_CLANG    = @echo '  CLANG   '$@;
+       QUIET_AR       = @echo '  AR      '$@;
+       QUIET_LINK     = @echo '  LINK    '$@;
+       QUIET_MKDIR    = @echo '  MKDIR   '$@;
+       QUIET_GEN      = @echo '  GEN     '$@;
        QUIET_SUBDIR0  = +@subdir=
        QUIET_SUBDIR1  = ;$(NO_SUBDIR) \
-                         echo '  SUBDIR   '$$subdir; \
+                         echo '  SUBDIR  '$$subdir; \
                         $(MAKE) $(PRINT_DIR) -C $$subdir
-       QUIET_FLEX     = @echo '  FLEX     '$@;
-       QUIET_BISON    = @echo '  BISON    '$@;
-       QUIET_GENSKEL  = @echo '  GEN-SKEL '$@;
+       QUIET_FLEX     = @echo '  FLEX    '$@;
+       QUIET_BISON    = @echo '  BISON   '$@;
+       QUIET_GENSKEL  = @echo '  GENSKEL '$@;
 
        descend = \
-               +@echo         '  DESCEND  '$(1); \
+               +@echo         '  DESCEND '$(1); \
                mkdir -p $(OUTPUT)$(1) && \
                $(MAKE) $(COMMAND_O) subdir=$(if $(subdir),$(subdir)/$(1),$(1)) $(PRINT_DIR) -C $(1) $(2)
 
-       QUIET_CLEAN    = @printf '  CLEAN    %s\n' $1;
-       QUIET_INSTALL  = @printf '  INSTALL  %s\n' $1;
-       QUIET_UNINST   = @printf '  UNINST   %s\n' $1;
+       QUIET_CLEAN    = @printf '  CLEAN   %s\n' $1;
+       QUIET_INSTALL  = @printf '  INSTALL %s\n' $1;
+       QUIET_UNINST   = @printf '  UNINST  %s\n' $1;
   endif
 endif
 
index 12ee40284da021686fc6501019d73cf649dfad87..2060bc122c53095b2fad4dd89f9ece2255f5c37f 100644 (file)
@@ -40,7 +40,7 @@ struct ipv6_packet pkt_v6 = {
        .tcp.doff = 5,
 };
 
-static int settimeo(int fd, int timeout_ms)
+int settimeo(int fd, int timeout_ms)
 {
        struct timeval timeout = { .tv_sec = 3 };
 
index 7205f8afdba1187fb1a2de3f0f767e1d5df7ce16..5e0d51c07b632ebf3cbf20c7d29bd576a63b2dbb 100644 (file)
@@ -33,6 +33,7 @@ struct ipv6_packet {
 } __packed;
 extern struct ipv6_packet pkt_v6;
 
+int settimeo(int fd, int timeout_ms);
 int start_server(int family, int type, const char *addr, __u16 port,
                 int timeout_ms);
 int connect_to_fd(int server_fd, int timeout_ms);
index de78617f65501f8b4cf7c9ca6c613dfb1f1cdd36..f9a8ae331963d6db8d5bc1e9afc391fe9f8e31fc 100644 (file)
@@ -86,8 +86,9 @@ void test_ringbuf(void)
        const size_t rec_sz = BPF_RINGBUF_HDR_SZ + sizeof(struct sample);
        pthread_t thread;
        long bg_ret = -1;
-       int err, cnt;
+       int err, cnt, rb_fd;
        int page_size = getpagesize();
+       void *mmap_ptr, *tmp_ptr;
 
        skel = test_ringbuf__open();
        if (CHECK(!skel, "skel_open", "skeleton open failed\n"))
@@ -101,6 +102,52 @@ void test_ringbuf(void)
        if (CHECK(err != 0, "skel_load", "skeleton load failed\n"))
                goto cleanup;
 
+       rb_fd = bpf_map__fd(skel->maps.ringbuf);
+       /* good read/write cons_pos */
+       mmap_ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, rb_fd, 0);
+       ASSERT_OK_PTR(mmap_ptr, "rw_cons_pos");
+       tmp_ptr = mremap(mmap_ptr, page_size, 2 * page_size, MREMAP_MAYMOVE);
+       if (!ASSERT_ERR_PTR(tmp_ptr, "rw_extend"))
+               goto cleanup;
+       ASSERT_ERR(mprotect(mmap_ptr, page_size, PROT_EXEC), "exec_cons_pos_protect");
+       ASSERT_OK(munmap(mmap_ptr, page_size), "unmap_rw");
+
+       /* bad writeable prod_pos */
+       mmap_ptr = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, rb_fd, page_size);
+       err = -errno;
+       ASSERT_ERR_PTR(mmap_ptr, "wr_prod_pos");
+       ASSERT_EQ(err, -EPERM, "wr_prod_pos_err");
+
+       /* bad writeable data pages */
+       mmap_ptr = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, rb_fd, 2 * page_size);
+       err = -errno;
+       ASSERT_ERR_PTR(mmap_ptr, "wr_data_page_one");
+       ASSERT_EQ(err, -EPERM, "wr_data_page_one_err");
+       mmap_ptr = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, rb_fd, 3 * page_size);
+       ASSERT_ERR_PTR(mmap_ptr, "wr_data_page_two");
+       mmap_ptr = mmap(NULL, 2 * page_size, PROT_WRITE, MAP_SHARED, rb_fd, 2 * page_size);
+       ASSERT_ERR_PTR(mmap_ptr, "wr_data_page_all");
+
+       /* good read-only pages */
+       mmap_ptr = mmap(NULL, 4 * page_size, PROT_READ, MAP_SHARED, rb_fd, 0);
+       if (!ASSERT_OK_PTR(mmap_ptr, "ro_prod_pos"))
+               goto cleanup;
+
+       ASSERT_ERR(mprotect(mmap_ptr, 4 * page_size, PROT_WRITE), "write_protect");
+       ASSERT_ERR(mprotect(mmap_ptr, 4 * page_size, PROT_EXEC), "exec_protect");
+       ASSERT_ERR_PTR(mremap(mmap_ptr, 0, 4 * page_size, MREMAP_MAYMOVE), "ro_remap");
+       ASSERT_OK(munmap(mmap_ptr, 4 * page_size), "unmap_ro");
+
+       /* good read-only pages with initial offset */
+       mmap_ptr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, rb_fd, page_size);
+       if (!ASSERT_OK_PTR(mmap_ptr, "ro_prod_pos"))
+               goto cleanup;
+
+       ASSERT_ERR(mprotect(mmap_ptr, page_size, PROT_WRITE), "write_protect");
+       ASSERT_ERR(mprotect(mmap_ptr, page_size, PROT_EXEC), "exec_protect");
+       ASSERT_ERR_PTR(mremap(mmap_ptr, 0, 3 * page_size, MREMAP_MAYMOVE), "ro_remap");
+       ASSERT_OK(munmap(mmap_ptr, page_size), "unmap_ro");
+
        /* only trigger BPF program for current process */
        skel->bss->pid = getpid();
 
diff --git a/tools/testing/selftests/bpf/prog_tests/tc_redirect.c b/tools/testing/selftests/bpf/prog_tests/tc_redirect.c
new file mode 100644 (file)
index 0000000..5703c91
--- /dev/null
@@ -0,0 +1,785 @@
+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
+
+/*
+ * This test sets up 3 netns (src <-> fwd <-> dst). There is no direct veth link
+ * between src and dst. The netns fwd has veth links to each src and dst. The
+ * client is in src and server in dst. The test installs a TC BPF program to each
+ * host facing veth in fwd which calls into i) bpf_redirect_neigh() to perform the
+ * neigh addr population and redirect or ii) bpf_redirect_peer() for namespace
+ * switch from ingress side; it also installs a checker prog on the egress side
+ * to drop unexpected traffic.
+ */
+
+#define _GNU_SOURCE
+
+#include <arpa/inet.h>
+#include <linux/limits.h>
+#include <linux/sysctl.h>
+#include <linux/if_tun.h>
+#include <linux/if.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+
+#include "test_progs.h"
+#include "network_helpers.h"
+#include "test_tc_neigh_fib.skel.h"
+#include "test_tc_neigh.skel.h"
+#include "test_tc_peer.skel.h"
+
+#define NS_SRC "ns_src"
+#define NS_FWD "ns_fwd"
+#define NS_DST "ns_dst"
+
+#define IP4_SRC "172.16.1.100"
+#define IP4_DST "172.16.2.100"
+#define IP4_TUN_SRC "172.17.1.100"
+#define IP4_TUN_FWD "172.17.1.200"
+#define IP4_PORT 9004
+
+#define IP6_SRC "0::1:dead:beef:cafe"
+#define IP6_DST "0::2:dead:beef:cafe"
+#define IP6_TUN_SRC "1::1:dead:beef:cafe"
+#define IP6_TUN_FWD "1::2:dead:beef:cafe"
+#define IP6_PORT 9006
+
+#define IP4_SLL "169.254.0.1"
+#define IP4_DLL "169.254.0.2"
+#define IP4_NET "169.254.0.0"
+
+#define MAC_DST_FWD "00:11:22:33:44:55"
+#define MAC_DST "00:22:33:44:55:66"
+
+#define IFADDR_STR_LEN 18
+#define PING_ARGS "-i 0.2 -c 3 -w 10 -q"
+
+#define SRC_PROG_PIN_FILE "/sys/fs/bpf/test_tc_src"
+#define DST_PROG_PIN_FILE "/sys/fs/bpf/test_tc_dst"
+#define CHK_PROG_PIN_FILE "/sys/fs/bpf/test_tc_chk"
+
+#define TIMEOUT_MILLIS 10000
+
+#define log_err(MSG, ...) \
+       fprintf(stderr, "(%s:%d: errno: %s) " MSG "\n", \
+               __FILE__, __LINE__, strerror(errno), ##__VA_ARGS__)
+
+static const char * const namespaces[] = {NS_SRC, NS_FWD, NS_DST, NULL};
+
+static int write_file(const char *path, const char *newval)
+{
+       FILE *f;
+
+       f = fopen(path, "r+");
+       if (!f)
+               return -1;
+       if (fwrite(newval, strlen(newval), 1, f) != 1) {
+               log_err("writing to %s failed", path);
+               fclose(f);
+               return -1;
+       }
+       fclose(f);
+       return 0;
+}
+
+struct nstoken {
+       int orig_netns_fd;
+};
+
+static int setns_by_fd(int nsfd)
+{
+       int err;
+
+       err = setns(nsfd, CLONE_NEWNET);
+       close(nsfd);
+
+       if (!ASSERT_OK(err, "setns"))
+               return err;
+
+       /* Switch /sys to the new namespace so that e.g. /sys/class/net
+        * reflects the devices in the new namespace.
+        */
+       err = unshare(CLONE_NEWNS);
+       if (!ASSERT_OK(err, "unshare"))
+               return err;
+
+       err = umount2("/sys", MNT_DETACH);
+       if (!ASSERT_OK(err, "umount2 /sys"))
+               return err;
+
+       err = mount("sysfs", "/sys", "sysfs", 0, NULL);
+       if (!ASSERT_OK(err, "mount /sys"))
+               return err;
+
+       err = mount("bpffs", "/sys/fs/bpf", "bpf", 0, NULL);
+       if (!ASSERT_OK(err, "mount /sys/fs/bpf"))
+               return err;
+
+       return 0;
+}
+
+/**
+ * open_netns() - Switch to specified network namespace by name.
+ *
+ * Returns token with which to restore the original namespace
+ * using close_netns().
+ */
+static struct nstoken *open_netns(const char *name)
+{
+       int nsfd;
+       char nspath[PATH_MAX];
+       int err;
+       struct nstoken *token;
+
+       token = malloc(sizeof(struct nstoken));
+       if (!ASSERT_OK_PTR(token, "malloc token"))
+               return NULL;
+
+       token->orig_netns_fd = open("/proc/self/ns/net", O_RDONLY);
+       if (!ASSERT_GE(token->orig_netns_fd, 0, "open /proc/self/ns/net"))
+               goto fail;
+
+       snprintf(nspath, sizeof(nspath), "%s/%s", "/var/run/netns", name);
+       nsfd = open(nspath, O_RDONLY | O_CLOEXEC);
+       if (!ASSERT_GE(nsfd, 0, "open netns fd"))
+               goto fail;
+
+       err = setns_by_fd(nsfd);
+       if (!ASSERT_OK(err, "setns_by_fd"))
+               goto fail;
+
+       return token;
+fail:
+       free(token);
+       return NULL;
+}
+
+static void close_netns(struct nstoken *token)
+{
+       ASSERT_OK(setns_by_fd(token->orig_netns_fd), "setns_by_fd");
+       free(token);
+}
+
+static int netns_setup_namespaces(const char *verb)
+{
+       const char * const *ns = namespaces;
+       char cmd[128];
+
+       while (*ns) {
+               snprintf(cmd, sizeof(cmd), "ip netns %s %s", verb, *ns);
+               if (!ASSERT_OK(system(cmd), cmd))
+                       return -1;
+               ns++;
+       }
+       return 0;
+}
+
+struct netns_setup_result {
+       int ifindex_veth_src_fwd;
+       int ifindex_veth_dst_fwd;
+};
+
+static int get_ifaddr(const char *name, char *ifaddr)
+{
+       char path[PATH_MAX];
+       FILE *f;
+       int ret;
+
+       snprintf(path, PATH_MAX, "/sys/class/net/%s/address", name);
+       f = fopen(path, "r");
+       if (!ASSERT_OK_PTR(f, path))
+               return -1;
+
+       ret = fread(ifaddr, 1, IFADDR_STR_LEN, f);
+       if (!ASSERT_EQ(ret, IFADDR_STR_LEN, "fread ifaddr")) {
+               fclose(f);
+               return -1;
+       }
+       fclose(f);
+       return 0;
+}
+
+static int get_ifindex(const char *name)
+{
+       char path[PATH_MAX];
+       char buf[32];
+       FILE *f;
+       int ret;
+
+       snprintf(path, PATH_MAX, "/sys/class/net/%s/ifindex", name);
+       f = fopen(path, "r");
+       if (!ASSERT_OK_PTR(f, path))
+               return -1;
+
+       ret = fread(buf, 1, sizeof(buf), f);
+       if (!ASSERT_GT(ret, 0, "fread ifindex")) {
+               fclose(f);
+               return -1;
+       }
+       fclose(f);
+       return atoi(buf);
+}
+
+#define SYS(fmt, ...)                                          \
+       ({                                                      \
+               char cmd[1024];                                 \
+               snprintf(cmd, sizeof(cmd), fmt, ##__VA_ARGS__); \
+               if (!ASSERT_OK(system(cmd), cmd))               \
+                       goto fail;                              \
+       })
+
+static int netns_setup_links_and_routes(struct netns_setup_result *result)
+{
+       struct nstoken *nstoken = NULL;
+       char veth_src_fwd_addr[IFADDR_STR_LEN+1] = {};
+
+       SYS("ip link add veth_src type veth peer name veth_src_fwd");
+       SYS("ip link add veth_dst type veth peer name veth_dst_fwd");
+
+       SYS("ip link set veth_dst_fwd address " MAC_DST_FWD);
+       SYS("ip link set veth_dst address " MAC_DST);
+
+       if (get_ifaddr("veth_src_fwd", veth_src_fwd_addr))
+               goto fail;
+
+       result->ifindex_veth_src_fwd = get_ifindex("veth_src_fwd");
+       if (result->ifindex_veth_src_fwd < 0)
+               goto fail;
+       result->ifindex_veth_dst_fwd = get_ifindex("veth_dst_fwd");
+       if (result->ifindex_veth_dst_fwd < 0)
+               goto fail;
+
+       SYS("ip link set veth_src netns " NS_SRC);
+       SYS("ip link set veth_src_fwd netns " NS_FWD);
+       SYS("ip link set veth_dst_fwd netns " NS_FWD);
+       SYS("ip link set veth_dst netns " NS_DST);
+
+       /** setup in 'src' namespace */
+       nstoken = open_netns(NS_SRC);
+       if (!ASSERT_OK_PTR(nstoken, "setns src"))
+               goto fail;
+
+       SYS("ip addr add " IP4_SRC "/32 dev veth_src");
+       SYS("ip addr add " IP6_SRC "/128 dev veth_src nodad");
+       SYS("ip link set dev veth_src up");
+
+       SYS("ip route add " IP4_DST "/32 dev veth_src scope global");
+       SYS("ip route add " IP4_NET "/16 dev veth_src scope global");
+       SYS("ip route add " IP6_DST "/128 dev veth_src scope global");
+
+       SYS("ip neigh add " IP4_DST " dev veth_src lladdr %s",
+           veth_src_fwd_addr);
+       SYS("ip neigh add " IP6_DST " dev veth_src lladdr %s",
+           veth_src_fwd_addr);
+
+       close_netns(nstoken);
+
+       /** setup in 'fwd' namespace */
+       nstoken = open_netns(NS_FWD);
+       if (!ASSERT_OK_PTR(nstoken, "setns fwd"))
+               goto fail;
+
+       /* The fwd netns automatically gets a v6 LL address / routes, but also
+        * needs v4 one in order to start ARP probing. IP4_NET route is added
+        * to the endpoints so that the ARP processing will reply.
+        */
+       SYS("ip addr add " IP4_SLL "/32 dev veth_src_fwd");
+       SYS("ip addr add " IP4_DLL "/32 dev veth_dst_fwd");
+       SYS("ip link set dev veth_src_fwd up");
+       SYS("ip link set dev veth_dst_fwd up");
+
+       SYS("ip route add " IP4_SRC "/32 dev veth_src_fwd scope global");
+       SYS("ip route add " IP6_SRC "/128 dev veth_src_fwd scope global");
+       SYS("ip route add " IP4_DST "/32 dev veth_dst_fwd scope global");
+       SYS("ip route add " IP6_DST "/128 dev veth_dst_fwd scope global");
+
+       close_netns(nstoken);
+
+       /** setup in 'dst' namespace */
+       nstoken = open_netns(NS_DST);
+       if (!ASSERT_OK_PTR(nstoken, "setns dst"))
+               goto fail;
+
+       SYS("ip addr add " IP4_DST "/32 dev veth_dst");
+       SYS("ip addr add " IP6_DST "/128 dev veth_dst nodad");
+       SYS("ip link set dev veth_dst up");
+
+       SYS("ip route add " IP4_SRC "/32 dev veth_dst scope global");
+       SYS("ip route add " IP4_NET "/16 dev veth_dst scope global");
+       SYS("ip route add " IP6_SRC "/128 dev veth_dst scope global");
+
+       SYS("ip neigh add " IP4_SRC " dev veth_dst lladdr " MAC_DST_FWD);
+       SYS("ip neigh add " IP6_SRC " dev veth_dst lladdr " MAC_DST_FWD);
+
+       close_netns(nstoken);
+
+       return 0;
+fail:
+       if (nstoken)
+               close_netns(nstoken);
+       return -1;
+}
+
+static int netns_load_bpf(void)
+{
+       SYS("tc qdisc add dev veth_src_fwd clsact");
+       SYS("tc filter add dev veth_src_fwd ingress bpf da object-pinned "
+           SRC_PROG_PIN_FILE);
+       SYS("tc filter add dev veth_src_fwd egress bpf da object-pinned "
+           CHK_PROG_PIN_FILE);
+
+       SYS("tc qdisc add dev veth_dst_fwd clsact");
+       SYS("tc filter add dev veth_dst_fwd ingress bpf da object-pinned "
+           DST_PROG_PIN_FILE);
+       SYS("tc filter add dev veth_dst_fwd egress bpf da object-pinned "
+           CHK_PROG_PIN_FILE);
+
+       return 0;
+fail:
+       return -1;
+}
+
+static void test_tcp(int family, const char *addr, __u16 port)
+{
+       int listen_fd = -1, accept_fd = -1, client_fd = -1;
+       char buf[] = "testing testing";
+       int n;
+       struct nstoken *nstoken;
+
+       nstoken = open_netns(NS_DST);
+       if (!ASSERT_OK_PTR(nstoken, "setns dst"))
+               return;
+
+       listen_fd = start_server(family, SOCK_STREAM, addr, port, 0);
+       if (!ASSERT_GE(listen_fd, 0, "listen"))
+               goto done;
+
+       close_netns(nstoken);
+       nstoken = open_netns(NS_SRC);
+       if (!ASSERT_OK_PTR(nstoken, "setns src"))
+               goto done;
+
+       client_fd = connect_to_fd(listen_fd, TIMEOUT_MILLIS);
+       if (!ASSERT_GE(client_fd, 0, "connect_to_fd"))
+               goto done;
+
+       accept_fd = accept(listen_fd, NULL, NULL);
+       if (!ASSERT_GE(accept_fd, 0, "accept"))
+               goto done;
+
+       if (!ASSERT_OK(settimeo(accept_fd, TIMEOUT_MILLIS), "settimeo"))
+               goto done;
+
+       n = write(client_fd, buf, sizeof(buf));
+       if (!ASSERT_EQ(n, sizeof(buf), "send to server"))
+               goto done;
+
+       n = read(accept_fd, buf, sizeof(buf));
+       ASSERT_EQ(n, sizeof(buf), "recv from server");
+
+done:
+       if (nstoken)
+               close_netns(nstoken);
+       if (listen_fd >= 0)
+               close(listen_fd);
+       if (accept_fd >= 0)
+               close(accept_fd);
+       if (client_fd >= 0)
+               close(client_fd);
+}
+
+static int test_ping(int family, const char *addr)
+{
+       const char *ping = family == AF_INET6 ? "ping6" : "ping";
+
+       SYS("ip netns exec " NS_SRC " %s " PING_ARGS " %s > /dev/null", ping, addr);
+       return 0;
+fail:
+       return -1;
+}
+
+static void test_connectivity(void)
+{
+       test_tcp(AF_INET, IP4_DST, IP4_PORT);
+       test_ping(AF_INET, IP4_DST);
+       test_tcp(AF_INET6, IP6_DST, IP6_PORT);
+       test_ping(AF_INET6, IP6_DST);
+}
+
+static int set_forwarding(bool enable)
+{
+       int err;
+
+       err = write_file("/proc/sys/net/ipv4/ip_forward", enable ? "1" : "0");
+       if (!ASSERT_OK(err, "set ipv4.ip_forward=0"))
+               return err;
+
+       err = write_file("/proc/sys/net/ipv6/conf/all/forwarding", enable ? "1" : "0");
+       if (!ASSERT_OK(err, "set ipv6.forwarding=0"))
+               return err;
+
+       return 0;
+}
+
+static void test_tc_redirect_neigh_fib(struct netns_setup_result *setup_result)
+{
+       struct nstoken *nstoken = NULL;
+       struct test_tc_neigh_fib *skel = NULL;
+       int err;
+
+       nstoken = open_netns(NS_FWD);
+       if (!ASSERT_OK_PTR(nstoken, "setns fwd"))
+               return;
+
+       skel = test_tc_neigh_fib__open();
+       if (!ASSERT_OK_PTR(skel, "test_tc_neigh_fib__open"))
+               goto done;
+
+       if (!ASSERT_OK(test_tc_neigh_fib__load(skel), "test_tc_neigh_fib__load"))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_src, SRC_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " SRC_PROG_PIN_FILE))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_chk, CHK_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " CHK_PROG_PIN_FILE))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_dst, DST_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " DST_PROG_PIN_FILE))
+               goto done;
+
+       if (netns_load_bpf())
+               goto done;
+
+       /* bpf_fib_lookup() checks if forwarding is enabled */
+       if (!ASSERT_OK(set_forwarding(true), "enable forwarding"))
+               goto done;
+
+       test_connectivity();
+
+done:
+       if (skel)
+               test_tc_neigh_fib__destroy(skel);
+       close_netns(nstoken);
+}
+
+static void test_tc_redirect_neigh(struct netns_setup_result *setup_result)
+{
+       struct nstoken *nstoken = NULL;
+       struct test_tc_neigh *skel = NULL;
+       int err;
+
+       nstoken = open_netns(NS_FWD);
+       if (!ASSERT_OK_PTR(nstoken, "setns fwd"))
+               return;
+
+       skel = test_tc_neigh__open();
+       if (!ASSERT_OK_PTR(skel, "test_tc_neigh__open"))
+               goto done;
+
+       skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd;
+       skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+
+       err = test_tc_neigh__load(skel);
+       if (!ASSERT_OK(err, "test_tc_neigh__load"))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_src, SRC_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " SRC_PROG_PIN_FILE))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_chk, CHK_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " CHK_PROG_PIN_FILE))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_dst, DST_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " DST_PROG_PIN_FILE))
+               goto done;
+
+       if (netns_load_bpf())
+               goto done;
+
+       if (!ASSERT_OK(set_forwarding(false), "disable forwarding"))
+               goto done;
+
+       test_connectivity();
+
+done:
+       if (skel)
+               test_tc_neigh__destroy(skel);
+       close_netns(nstoken);
+}
+
+static void test_tc_redirect_peer(struct netns_setup_result *setup_result)
+{
+       struct nstoken *nstoken;
+       struct test_tc_peer *skel;
+       int err;
+
+       nstoken = open_netns(NS_FWD);
+       if (!ASSERT_OK_PTR(nstoken, "setns fwd"))
+               return;
+
+       skel = test_tc_peer__open();
+       if (!ASSERT_OK_PTR(skel, "test_tc_peer__open"))
+               goto done;
+
+       skel->rodata->IFINDEX_SRC = setup_result->ifindex_veth_src_fwd;
+       skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+
+       err = test_tc_peer__load(skel);
+       if (!ASSERT_OK(err, "test_tc_peer__load"))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_src, SRC_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " SRC_PROG_PIN_FILE))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_chk, CHK_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " CHK_PROG_PIN_FILE))
+               goto done;
+
+       err = bpf_program__pin(skel->progs.tc_dst, DST_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " DST_PROG_PIN_FILE))
+               goto done;
+
+       if (netns_load_bpf())
+               goto done;
+
+       if (!ASSERT_OK(set_forwarding(false), "disable forwarding"))
+               goto done;
+
+       test_connectivity();
+
+done:
+       if (skel)
+               test_tc_peer__destroy(skel);
+       close_netns(nstoken);
+}
+
+static int tun_open(char *name)
+{
+       struct ifreq ifr;
+       int fd, err;
+
+       fd = open("/dev/net/tun", O_RDWR);
+       if (!ASSERT_GE(fd, 0, "open /dev/net/tun"))
+               return -1;
+
+       memset(&ifr, 0, sizeof(ifr));
+
+       ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
+       if (*name)
+               strncpy(ifr.ifr_name, name, IFNAMSIZ);
+
+       err = ioctl(fd, TUNSETIFF, &ifr);
+       if (!ASSERT_OK(err, "ioctl TUNSETIFF"))
+               goto fail;
+
+       SYS("ip link set dev %s up", name);
+
+       return fd;
+fail:
+       close(fd);
+       return -1;
+}
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+enum {
+       SRC_TO_TARGET = 0,
+       TARGET_TO_SRC = 1,
+};
+
+static int tun_relay_loop(int src_fd, int target_fd)
+{
+       fd_set rfds, wfds;
+
+       FD_ZERO(&rfds);
+       FD_ZERO(&wfds);
+
+       for (;;) {
+               char buf[1500];
+               int direction, nread, nwrite;
+
+               FD_SET(src_fd, &rfds);
+               FD_SET(target_fd, &rfds);
+
+               if (select(1 + MAX(src_fd, target_fd), &rfds, NULL, NULL, NULL) < 0) {
+                       log_err("select failed");
+                       return 1;
+               }
+
+               direction = FD_ISSET(src_fd, &rfds) ? SRC_TO_TARGET : TARGET_TO_SRC;
+
+               nread = read(direction == SRC_TO_TARGET ? src_fd : target_fd, buf, sizeof(buf));
+               if (nread < 0) {
+                       log_err("read failed");
+                       return 1;
+               }
+
+               nwrite = write(direction == SRC_TO_TARGET ? target_fd : src_fd, buf, nread);
+               if (nwrite != nread) {
+                       log_err("write failed");
+                       return 1;
+               }
+       }
+}
+
+static void test_tc_redirect_peer_l3(struct netns_setup_result *setup_result)
+{
+       struct test_tc_peer *skel = NULL;
+       struct nstoken *nstoken = NULL;
+       int err;
+       int tunnel_pid = -1;
+       int src_fd, target_fd;
+       int ifindex;
+
+       /* Start a L3 TUN/TAP tunnel between the src and dst namespaces.
+        * This test is using TUN/TAP instead of e.g. IPIP or GRE tunnel as those
+        * expose the L2 headers encapsulating the IP packet to BPF and hence
+        * don't have skb in suitable state for this test. Alternative to TUN/TAP
+        * would be e.g. Wireguard which would appear as a pure L3 device to BPF,
+        * but that requires much more complicated setup.
+        */
+       nstoken = open_netns(NS_SRC);
+       if (!ASSERT_OK_PTR(nstoken, "setns " NS_SRC))
+               return;
+
+       src_fd = tun_open("tun_src");
+       if (!ASSERT_GE(src_fd, 0, "tun_open tun_src"))
+               goto fail;
+
+       close_netns(nstoken);
+
+       nstoken = open_netns(NS_FWD);
+       if (!ASSERT_OK_PTR(nstoken, "setns " NS_FWD))
+               goto fail;
+
+       target_fd = tun_open("tun_fwd");
+       if (!ASSERT_GE(target_fd, 0, "tun_open tun_fwd"))
+               goto fail;
+
+       tunnel_pid = fork();
+       if (!ASSERT_GE(tunnel_pid, 0, "fork tun_relay_loop"))
+               goto fail;
+
+       if (tunnel_pid == 0)
+               exit(tun_relay_loop(src_fd, target_fd));
+
+       skel = test_tc_peer__open();
+       if (!ASSERT_OK_PTR(skel, "test_tc_peer__open"))
+               goto fail;
+
+       ifindex = get_ifindex("tun_fwd");
+       if (!ASSERT_GE(ifindex, 0, "get_ifindex tun_fwd"))
+               goto fail;
+
+       skel->rodata->IFINDEX_SRC = ifindex;
+       skel->rodata->IFINDEX_DST = setup_result->ifindex_veth_dst_fwd;
+
+       err = test_tc_peer__load(skel);
+       if (!ASSERT_OK(err, "test_tc_peer__load"))
+               goto fail;
+
+       err = bpf_program__pin(skel->progs.tc_src_l3, SRC_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " SRC_PROG_PIN_FILE))
+               goto fail;
+
+       err = bpf_program__pin(skel->progs.tc_dst_l3, DST_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " DST_PROG_PIN_FILE))
+               goto fail;
+
+       err = bpf_program__pin(skel->progs.tc_chk, CHK_PROG_PIN_FILE);
+       if (!ASSERT_OK(err, "pin " CHK_PROG_PIN_FILE))
+               goto fail;
+
+       /* Load "tc_src_l3" to the tun_fwd interface to redirect packets
+        * towards dst, and "tc_dst" to redirect packets
+        * and "tc_chk" on veth_dst_fwd to drop non-redirected packets.
+        */
+       SYS("tc qdisc add dev tun_fwd clsact");
+       SYS("tc filter add dev tun_fwd ingress bpf da object-pinned "
+           SRC_PROG_PIN_FILE);
+
+       SYS("tc qdisc add dev veth_dst_fwd clsact");
+       SYS("tc filter add dev veth_dst_fwd ingress bpf da object-pinned "
+           DST_PROG_PIN_FILE);
+       SYS("tc filter add dev veth_dst_fwd egress bpf da object-pinned "
+           CHK_PROG_PIN_FILE);
+
+       /* Setup route and neigh tables */
+       SYS("ip -netns " NS_SRC " addr add dev tun_src " IP4_TUN_SRC "/24");
+       SYS("ip -netns " NS_FWD " addr add dev tun_fwd " IP4_TUN_FWD "/24");
+
+       SYS("ip -netns " NS_SRC " addr add dev tun_src " IP6_TUN_SRC "/64 nodad");
+       SYS("ip -netns " NS_FWD " addr add dev tun_fwd " IP6_TUN_FWD "/64 nodad");
+
+       SYS("ip -netns " NS_SRC " route del " IP4_DST "/32 dev veth_src scope global");
+       SYS("ip -netns " NS_SRC " route add " IP4_DST "/32 via " IP4_TUN_FWD
+           " dev tun_src scope global");
+       SYS("ip -netns " NS_DST " route add " IP4_TUN_SRC "/32 dev veth_dst scope global");
+       SYS("ip -netns " NS_SRC " route del " IP6_DST "/128 dev veth_src scope global");
+       SYS("ip -netns " NS_SRC " route add " IP6_DST "/128 via " IP6_TUN_FWD
+           " dev tun_src scope global");
+       SYS("ip -netns " NS_DST " route add " IP6_TUN_SRC "/128 dev veth_dst scope global");
+
+       SYS("ip -netns " NS_DST " neigh add " IP4_TUN_SRC " dev veth_dst lladdr " MAC_DST_FWD);
+       SYS("ip -netns " NS_DST " neigh add " IP6_TUN_SRC " dev veth_dst lladdr " MAC_DST_FWD);
+
+       if (!ASSERT_OK(set_forwarding(false), "disable forwarding"))
+               goto fail;
+
+       test_connectivity();
+
+fail:
+       if (tunnel_pid > 0) {
+               kill(tunnel_pid, SIGTERM);
+               waitpid(tunnel_pid, NULL, 0);
+       }
+       if (src_fd >= 0)
+               close(src_fd);
+       if (target_fd >= 0)
+               close(target_fd);
+       if (skel)
+               test_tc_peer__destroy(skel);
+       if (nstoken)
+               close_netns(nstoken);
+}
+
+#define RUN_TEST(name)                                                                      \
+       ({                                                                                  \
+               struct netns_setup_result setup_result;                                     \
+               if (test__start_subtest(#name))                                             \
+                       if (ASSERT_OK(netns_setup_namespaces("add"), "setup namespaces")) { \
+                               if (ASSERT_OK(netns_setup_links_and_routes(&setup_result),  \
+                                             "setup links and routes"))                    \
+                                       test_ ## name(&setup_result);                       \
+                               netns_setup_namespaces("delete");                           \
+                       }                                                                   \
+       })
+
+static void *test_tc_redirect_run_tests(void *arg)
+{
+       RUN_TEST(tc_redirect_peer);
+       RUN_TEST(tc_redirect_peer_l3);
+       RUN_TEST(tc_redirect_neigh);
+       RUN_TEST(tc_redirect_neigh_fib);
+       return NULL;
+}
+
+void test_tc_redirect(void)
+{
+       pthread_t test_thread;
+       int err;
+
+       /* Run the tests in their own thread to isolate the namespace changes
+        * so they do not affect the environment of other tests.
+        * (specifically needed because of unshare(CLONE_NEWNS) in open_netns())
+        */
+       err = pthread_create(&test_thread, NULL, &test_tc_redirect_run_tests, NULL);
+       if (ASSERT_OK(err, "pthread_create"))
+               ASSERT_OK(pthread_join(test_thread, NULL), "pthread_join");
+}
index b985ac4e7a814a94a9a5e54f851152bfe6eacf80..0c93d326a663f90a1f95432ec89f71b115e0213d 100644 (file)
                                 a.s6_addr32[3] == b.s6_addr32[3])
 #endif
 
-enum {
-       dev_src,
-       dev_dst,
-};
-
-struct bpf_map_def SEC("maps") ifindex_map = {
-       .type           = BPF_MAP_TYPE_ARRAY,
-       .key_size       = sizeof(int),
-       .value_size     = sizeof(int),
-       .max_entries    = 2,
-};
+volatile const __u32 IFINDEX_SRC;
+volatile const __u32 IFINDEX_DST;
 
 static __always_inline bool is_remote_ep_v4(struct __sk_buff *skb,
                                            __be32 addr)
@@ -79,14 +70,8 @@ static __always_inline bool is_remote_ep_v6(struct __sk_buff *skb,
        return v6_equal(ip6h->daddr, addr);
 }
 
-static __always_inline int get_dev_ifindex(int which)
-{
-       int *ifindex = bpf_map_lookup_elem(&ifindex_map, &which);
-
-       return ifindex ? *ifindex : 0;
-}
-
-SEC("chk_egress") int tc_chk(struct __sk_buff *skb)
+SEC("classifier/chk_egress")
+int tc_chk(struct __sk_buff *skb)
 {
        void *data_end = ctx_ptr(skb->data_end);
        void *data = ctx_ptr(skb->data);
@@ -98,7 +83,8 @@ SEC("chk_egress") int tc_chk(struct __sk_buff *skb)
        return !raw[0] && !raw[1] && !raw[2] ? TC_ACT_SHOT : TC_ACT_OK;
 }
 
-SEC("dst_ingress") int tc_dst(struct __sk_buff *skb)
+SEC("classifier/dst_ingress")
+int tc_dst(struct __sk_buff *skb)
 {
        __u8 zero[ETH_ALEN * 2];
        bool redirect = false;
@@ -119,10 +105,11 @@ SEC("dst_ingress") int tc_dst(struct __sk_buff *skb)
        if (bpf_skb_store_bytes(skb, 0, &zero, sizeof(zero), 0) < 0)
                return TC_ACT_SHOT;
 
-       return bpf_redirect_neigh(get_dev_ifindex(dev_src), NULL, 0, 0);
+       return bpf_redirect_neigh(IFINDEX_SRC, NULL, 0, 0);
 }
 
-SEC("src_ingress") int tc_src(struct __sk_buff *skb)
+SEC("classifier/src_ingress")
+int tc_src(struct __sk_buff *skb)
 {
        __u8 zero[ETH_ALEN * 2];
        bool redirect = false;
@@ -143,7 +130,7 @@ SEC("src_ingress") int tc_src(struct __sk_buff *skb)
        if (bpf_skb_store_bytes(skb, 0, &zero, sizeof(zero), 0) < 0)
                return TC_ACT_SHOT;
 
-       return bpf_redirect_neigh(get_dev_ifindex(dev_dst), NULL, 0, 0);
+       return bpf_redirect_neigh(IFINDEX_DST, NULL, 0, 0);
 }
 
 char __license[] SEC("license") = "GPL";
index d82ed3457030f32584b0c23733ced91cfad77187..f7ab69cf018e5a81705a1219b87ab903774bd3a5 100644 (file)
@@ -75,7 +75,8 @@ static __always_inline int fill_fib_params_v6(struct __sk_buff *skb,
        return 0;
 }
 
-SEC("chk_egress") int tc_chk(struct __sk_buff *skb)
+SEC("classifier/chk_egress")
+int tc_chk(struct __sk_buff *skb)
 {
        void *data_end = ctx_ptr(skb->data_end);
        void *data = ctx_ptr(skb->data);
@@ -142,12 +143,14 @@ static __always_inline int tc_redir(struct __sk_buff *skb)
 /* these are identical, but keep them separate for compatibility with the
  * section names expected by test_tc_redirect.sh
  */
-SEC("dst_ingress") int tc_dst(struct __sk_buff *skb)
+SEC("classifier/dst_ingress")
+int tc_dst(struct __sk_buff *skb)
 {
        return tc_redir(skb);
 }
 
-SEC("src_ingress") int tc_src(struct __sk_buff *skb)
+SEC("classifier/src_ingress")
+int tc_src(struct __sk_buff *skb)
 {
        return tc_redir(skb);
 }
index fc84a7685aa2cc3b35a5a7e5a94896e3913d0117..fe818cd5f0109f440d702922e2055a6c875cbe34 100644 (file)
@@ -5,41 +5,59 @@
 #include <linux/bpf.h>
 #include <linux/stddef.h>
 #include <linux/pkt_cls.h>
+#include <linux/if_ether.h>
+#include <linux/ip.h>
 
 #include <bpf/bpf_helpers.h>
 
-enum {
-       dev_src,
-       dev_dst,
-};
+volatile const __u32 IFINDEX_SRC;
+volatile const __u32 IFINDEX_DST;
 
-struct bpf_map_def SEC("maps") ifindex_map = {
-       .type           = BPF_MAP_TYPE_ARRAY,
-       .key_size       = sizeof(int),
-       .value_size     = sizeof(int),
-       .max_entries    = 2,
-};
+static const __u8 src_mac[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55};
+static const __u8 dst_mac[] = {0x00, 0x22, 0x33, 0x44, 0x55, 0x66};
 
-static __always_inline int get_dev_ifindex(int which)
+SEC("classifier/chk_egress")
+int tc_chk(struct __sk_buff *skb)
 {
-       int *ifindex = bpf_map_lookup_elem(&ifindex_map, &which);
+       return TC_ACT_SHOT;
+}
 
-       return ifindex ? *ifindex : 0;
+SEC("classifier/dst_ingress")
+int tc_dst(struct __sk_buff *skb)
+{
+       return bpf_redirect_peer(IFINDEX_SRC, 0);
 }
 
-SEC("chk_egress") int tc_chk(struct __sk_buff *skb)
+SEC("classifier/src_ingress")
+int tc_src(struct __sk_buff *skb)
 {
-       return TC_ACT_SHOT;
+       return bpf_redirect_peer(IFINDEX_DST, 0);
 }
 
-SEC("dst_ingress") int tc_dst(struct __sk_buff *skb)
+SEC("classifier/dst_ingress_l3")
+int tc_dst_l3(struct __sk_buff *skb)
 {
-       return bpf_redirect_peer(get_dev_ifindex(dev_src), 0);
+       return bpf_redirect(IFINDEX_SRC, 0);
 }
 
-SEC("src_ingress") int tc_src(struct __sk_buff *skb)
+SEC("classifier/src_ingress_l3")
+int tc_src_l3(struct __sk_buff *skb)
 {
-       return bpf_redirect_peer(get_dev_ifindex(dev_dst), 0);
+       __u16 proto = skb->protocol;
+
+       if (bpf_skb_change_head(skb, ETH_HLEN, 0) != 0)
+               return TC_ACT_SHOT;
+
+       if (bpf_skb_store_bytes(skb, 0, &src_mac, ETH_ALEN, 0) != 0)
+               return TC_ACT_SHOT;
+
+       if (bpf_skb_store_bytes(skb, ETH_ALEN, &dst_mac, ETH_ALEN, 0) != 0)
+               return TC_ACT_SHOT;
+
+       if (bpf_skb_store_bytes(skb, ETH_ALEN + ETH_ALEN, &proto, sizeof(__u16), 0) != 0)
+               return TC_ACT_SHOT;
+
+       return bpf_redirect_peer(IFINDEX_DST, 0);
 }
 
 char __license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/test_tc_redirect.sh b/tools/testing/selftests/bpf/test_tc_redirect.sh
deleted file mode 100755 (executable)
index 8868aa1..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-#!/bin/bash
-# SPDX-License-Identifier: GPL-2.0
-#
-# This test sets up 3 netns (src <-> fwd <-> dst). There is no direct veth link
-# between src and dst. The netns fwd has veth links to each src and dst. The
-# client is in src and server in dst. The test installs a TC BPF program to each
-# host facing veth in fwd which calls into i) bpf_redirect_neigh() to perform the
-# neigh addr population and redirect or ii) bpf_redirect_peer() for namespace
-# switch from ingress side; it also installs a checker prog on the egress side
-# to drop unexpected traffic.
-
-if [[ $EUID -ne 0 ]]; then
-       echo "This script must be run as root"
-       echo "FAIL"
-       exit 1
-fi
-
-# check that needed tools are present
-command -v nc >/dev/null 2>&1 || \
-       { echo >&2 "nc is not available"; exit 1; }
-command -v dd >/dev/null 2>&1 || \
-       { echo >&2 "dd is not available"; exit 1; }
-command -v timeout >/dev/null 2>&1 || \
-       { echo >&2 "timeout is not available"; exit 1; }
-command -v ping >/dev/null 2>&1 || \
-       { echo >&2 "ping is not available"; exit 1; }
-if command -v ping6 >/dev/null 2>&1; then PING6=ping6; else PING6=ping; fi
-command -v perl >/dev/null 2>&1 || \
-       { echo >&2 "perl is not available"; exit 1; }
-command -v jq >/dev/null 2>&1 || \
-       { echo >&2 "jq is not available"; exit 1; }
-command -v bpftool >/dev/null 2>&1 || \
-       { echo >&2 "bpftool is not available"; exit 1; }
-
-readonly GREEN='\033[0;92m'
-readonly RED='\033[0;31m'
-readonly NC='\033[0m' # No Color
-
-readonly PING_ARG="-c 3 -w 10 -q"
-
-readonly TIMEOUT=10
-
-readonly NS_SRC="ns-src-$(mktemp -u XXXXXX)"
-readonly NS_FWD="ns-fwd-$(mktemp -u XXXXXX)"
-readonly NS_DST="ns-dst-$(mktemp -u XXXXXX)"
-
-readonly IP4_SRC="172.16.1.100"
-readonly IP4_DST="172.16.2.100"
-
-readonly IP6_SRC="::1:dead:beef:cafe"
-readonly IP6_DST="::2:dead:beef:cafe"
-
-readonly IP4_SLL="169.254.0.1"
-readonly IP4_DLL="169.254.0.2"
-readonly IP4_NET="169.254.0.0"
-
-netns_cleanup()
-{
-       ip netns del ${NS_SRC}
-       ip netns del ${NS_FWD}
-       ip netns del ${NS_DST}
-}
-
-netns_setup()
-{
-       ip netns add "${NS_SRC}"
-       ip netns add "${NS_FWD}"
-       ip netns add "${NS_DST}"
-
-       ip link add veth_src type veth peer name veth_src_fwd
-       ip link add veth_dst type veth peer name veth_dst_fwd
-
-       ip link set veth_src netns ${NS_SRC}
-       ip link set veth_src_fwd netns ${NS_FWD}
-
-       ip link set veth_dst netns ${NS_DST}
-       ip link set veth_dst_fwd netns ${NS_FWD}
-
-       ip -netns ${NS_SRC} addr add ${IP4_SRC}/32 dev veth_src
-       ip -netns ${NS_DST} addr add ${IP4_DST}/32 dev veth_dst
-
-       # The fwd netns automatically get a v6 LL address / routes, but also
-       # needs v4 one in order to start ARP probing. IP4_NET route is added
-       # to the endpoints so that the ARP processing will reply.
-
-       ip -netns ${NS_FWD} addr add ${IP4_SLL}/32 dev veth_src_fwd
-       ip -netns ${NS_FWD} addr add ${IP4_DLL}/32 dev veth_dst_fwd
-
-       ip -netns ${NS_SRC} addr add ${IP6_SRC}/128 dev veth_src nodad
-       ip -netns ${NS_DST} addr add ${IP6_DST}/128 dev veth_dst nodad
-
-       ip -netns ${NS_SRC} link set dev veth_src up
-       ip -netns ${NS_FWD} link set dev veth_src_fwd up
-
-       ip -netns ${NS_DST} link set dev veth_dst up
-       ip -netns ${NS_FWD} link set dev veth_dst_fwd up
-
-       ip -netns ${NS_SRC} route add ${IP4_DST}/32 dev veth_src scope global
-       ip -netns ${NS_SRC} route add ${IP4_NET}/16 dev veth_src scope global
-       ip -netns ${NS_FWD} route add ${IP4_SRC}/32 dev veth_src_fwd scope global
-
-       ip -netns ${NS_SRC} route add ${IP6_DST}/128 dev veth_src scope global
-       ip -netns ${NS_FWD} route add ${IP6_SRC}/128 dev veth_src_fwd scope global
-
-       ip -netns ${NS_DST} route add ${IP4_SRC}/32 dev veth_dst scope global
-       ip -netns ${NS_DST} route add ${IP4_NET}/16 dev veth_dst scope global
-       ip -netns ${NS_FWD} route add ${IP4_DST}/32 dev veth_dst_fwd scope global
-
-       ip -netns ${NS_DST} route add ${IP6_SRC}/128 dev veth_dst scope global
-       ip -netns ${NS_FWD} route add ${IP6_DST}/128 dev veth_dst_fwd scope global
-
-       fmac_src=$(ip netns exec ${NS_FWD} cat /sys/class/net/veth_src_fwd/address)
-       fmac_dst=$(ip netns exec ${NS_FWD} cat /sys/class/net/veth_dst_fwd/address)
-
-       ip -netns ${NS_SRC} neigh add ${IP4_DST} dev veth_src lladdr $fmac_src
-       ip -netns ${NS_DST} neigh add ${IP4_SRC} dev veth_dst lladdr $fmac_dst
-
-       ip -netns ${NS_SRC} neigh add ${IP6_DST} dev veth_src lladdr $fmac_src
-       ip -netns ${NS_DST} neigh add ${IP6_SRC} dev veth_dst lladdr $fmac_dst
-}
-
-netns_test_connectivity()
-{
-       set +e
-
-       ip netns exec ${NS_DST} bash -c "nc -4 -l -p 9004 &"
-       ip netns exec ${NS_DST} bash -c "nc -6 -l -p 9006 &"
-
-       TEST="TCPv4 connectivity test"
-       ip netns exec ${NS_SRC} bash -c "timeout ${TIMEOUT} dd if=/dev/zero bs=1000 count=100 > /dev/tcp/${IP4_DST}/9004"
-       if [ $? -ne 0 ]; then
-               echo -e "${TEST}: ${RED}FAIL${NC}"
-               exit 1
-       fi
-       echo -e "${TEST}: ${GREEN}PASS${NC}"
-
-       TEST="TCPv6 connectivity test"
-       ip netns exec ${NS_SRC} bash -c "timeout ${TIMEOUT} dd if=/dev/zero bs=1000 count=100 > /dev/tcp/${IP6_DST}/9006"
-       if [ $? -ne 0 ]; then
-               echo -e "${TEST}: ${RED}FAIL${NC}"
-               exit 1
-       fi
-       echo -e "${TEST}: ${GREEN}PASS${NC}"
-
-       TEST="ICMPv4 connectivity test"
-       ip netns exec ${NS_SRC} ping  $PING_ARG ${IP4_DST}
-       if [ $? -ne 0 ]; then
-               echo -e "${TEST}: ${RED}FAIL${NC}"
-               exit 1
-       fi
-       echo -e "${TEST}: ${GREEN}PASS${NC}"
-
-       TEST="ICMPv6 connectivity test"
-       ip netns exec ${NS_SRC} $PING6 $PING_ARG ${IP6_DST}
-       if [ $? -ne 0 ]; then
-               echo -e "${TEST}: ${RED}FAIL${NC}"
-               exit 1
-       fi
-       echo -e "${TEST}: ${GREEN}PASS${NC}"
-
-       set -e
-}
-
-hex_mem_str()
-{
-       perl -e 'print join(" ", unpack("(H2)8", pack("L", @ARGV)))' $1
-}
-
-netns_setup_bpf()
-{
-       local obj=$1
-       local use_forwarding=${2:-0}
-
-       ip netns exec ${NS_FWD} tc qdisc add dev veth_src_fwd clsact
-       ip netns exec ${NS_FWD} tc filter add dev veth_src_fwd ingress bpf da obj $obj sec src_ingress
-       ip netns exec ${NS_FWD} tc filter add dev veth_src_fwd egress  bpf da obj $obj sec chk_egress
-
-       ip netns exec ${NS_FWD} tc qdisc add dev veth_dst_fwd clsact
-       ip netns exec ${NS_FWD} tc filter add dev veth_dst_fwd ingress bpf da obj $obj sec dst_ingress
-       ip netns exec ${NS_FWD} tc filter add dev veth_dst_fwd egress  bpf da obj $obj sec chk_egress
-
-       if [ "$use_forwarding" -eq "1" ]; then
-               # bpf_fib_lookup() checks if forwarding is enabled
-               ip netns exec ${NS_FWD} sysctl -w net.ipv4.ip_forward=1
-               ip netns exec ${NS_FWD} sysctl -w net.ipv6.conf.veth_dst_fwd.forwarding=1
-               ip netns exec ${NS_FWD} sysctl -w net.ipv6.conf.veth_src_fwd.forwarding=1
-               return 0
-       fi
-
-       veth_src=$(ip netns exec ${NS_FWD} cat /sys/class/net/veth_src_fwd/ifindex)
-       veth_dst=$(ip netns exec ${NS_FWD} cat /sys/class/net/veth_dst_fwd/ifindex)
-
-       progs=$(ip netns exec ${NS_FWD} bpftool net --json | jq -r '.[] | .tc | map(.id) | .[]')
-       for prog in $progs; do
-               map=$(bpftool prog show id $prog --json | jq -r '.map_ids | .? | .[]')
-               if [ ! -z "$map" ]; then
-                       bpftool map update id $map key hex $(hex_mem_str 0) value hex $(hex_mem_str $veth_src)
-                       bpftool map update id $map key hex $(hex_mem_str 1) value hex $(hex_mem_str $veth_dst)
-               fi
-       done
-}
-
-trap netns_cleanup EXIT
-set -e
-
-netns_setup
-netns_setup_bpf test_tc_neigh.o
-netns_test_connectivity
-netns_cleanup
-netns_setup
-netns_setup_bpf test_tc_neigh_fib.o 1
-netns_test_connectivity
-netns_cleanup
-netns_setup
-netns_setup_bpf test_tc_peer.o
-netns_test_connectivity
index 07eaa04412ae40dfbdc034e9e28076fc63d3035e..8ab94d65f3d5439c1f57807cfb8c798ef3de6cf3 100644 (file)
        BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_1, 0),
        BPF_EXIT_INSN(),
        },
-       .result_unpriv = REJECT,
-       .errstr_unpriv = "invalid write to stack R1 off=0 size=1",
        .result = ACCEPT,
        .retval = 42,
 },
index e5913fd3b9030d41f944a1fd0babdd629d31293e..7ae2859d495c58a3fdea4c07956f656c75927208 100644 (file)
        },
        .fixup_map_array_48b = { 3 },
        .result = ACCEPT,
-       .result_unpriv = REJECT,
-       .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
        .retval = 1,
 },
 {
        },
        .fixup_map_array_48b = { 3 },
        .result = ACCEPT,
-       .result_unpriv = REJECT,
-       .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
        .retval = 1,
 },
 {
        },
        .fixup_map_array_48b = { 3 },
        .result = ACCEPT,
-       .result_unpriv = REJECT,
-       .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
        .retval = 1,
 },
 {
        },
        .fixup_map_array_48b = { 3 },
        .result = ACCEPT,
-       .result_unpriv = REJECT,
-       .errstr_unpriv = "R0 pointer arithmetic of map value goes out of range",
        .retval = 1,
 },
 {
index cf69b2fcce59ede2d862ea6a69fd41757ec3b07d..dd61118df66edbcde89f92a2626d2e9186122fda 100644 (file)
@@ -28,8 +28,8 @@ $(OUTPUT)/execveat.denatured: $(OUTPUT)/execveat
        cp $< $@
        chmod -x $@
 $(OUTPUT)/load_address_4096: load_address.c
-       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000 -pie $< -o $@
+       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000 -pie -static $< -o $@
 $(OUTPUT)/load_address_2097152: load_address.c
-       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x200000 -pie $< -o $@
+       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x200000 -pie -static $< -o $@
 $(OUTPUT)/load_address_16777216: load_address.c
-       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie $< -o $@
+       $(CC) $(CFLAGS) $(LDFLAGS) -Wl,-z,max-page-size=0x1000000 -pie -static $< -o $@
index d5bc9bf3b528e467e778d7e962e3dd1fdb1c6f25..06a351b4f93b6b4242d9857cd454119dbd52551a 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0-only
+/aarch64/debug-exceptions
 /aarch64/get-reg-list
-/aarch64/get-reg-list-sve
 /aarch64/vgic_init
 /s390x/memop
 /s390x/resets
index bc65c57ae40dab7604964b9f9d4a5250959efdad..b853be2ae3c6a8b46b7e4cd79323411d0101e31d 100644 (file)
@@ -35,7 +35,7 @@ endif
 
 LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/rbtree.c lib/sparsebit.c lib/test_util.c lib/guest_modes.c lib/perf_test_util.c
 LIBKVM_x86_64 = lib/x86_64/apic.c lib/x86_64/processor.c lib/x86_64/vmx.c lib/x86_64/svm.c lib/x86_64/ucall.c lib/x86_64/handlers.S
-LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c
+LIBKVM_aarch64 = lib/aarch64/processor.c lib/aarch64/ucall.c lib/aarch64/handlers.S
 LIBKVM_s390x = lib/s390x/processor.c lib/s390x/ucall.c lib/s390x/diag318_test_handler.c
 
 TEST_GEN_PROGS_x86_64 = x86_64/cr4_cpuid_sync_test
@@ -83,8 +83,8 @@ TEST_GEN_PROGS_x86_64 += set_memory_region_test
 TEST_GEN_PROGS_x86_64 += steal_time
 TEST_GEN_PROGS_x86_64 += kvm_binary_stats_test
 
+TEST_GEN_PROGS_aarch64 += aarch64/debug-exceptions
 TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list
-TEST_GEN_PROGS_aarch64 += aarch64/get-reg-list-sve
 TEST_GEN_PROGS_aarch64 += aarch64/vgic_init
 TEST_GEN_PROGS_aarch64 += demand_paging_test
 TEST_GEN_PROGS_aarch64 += dirty_log_test
diff --git a/tools/testing/selftests/kvm/aarch64/debug-exceptions.c b/tools/testing/selftests/kvm/aarch64/debug-exceptions.c
new file mode 100644 (file)
index 0000000..e5e6c92
--- /dev/null
@@ -0,0 +1,250 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <test_util.h>
+#include <kvm_util.h>
+#include <processor.h>
+
+#define VCPU_ID 0
+
+#define MDSCR_KDE      (1 << 13)
+#define MDSCR_MDE      (1 << 15)
+#define MDSCR_SS       (1 << 0)
+
+#define DBGBCR_LEN8    (0xff << 5)
+#define DBGBCR_EXEC    (0x0 << 3)
+#define DBGBCR_EL1     (0x1 << 1)
+#define DBGBCR_E       (0x1 << 0)
+
+#define DBGWCR_LEN8    (0xff << 5)
+#define DBGWCR_RD      (0x1 << 3)
+#define DBGWCR_WR      (0x2 << 3)
+#define DBGWCR_EL1     (0x1 << 1)
+#define DBGWCR_E       (0x1 << 0)
+
+#define SPSR_D         (1 << 9)
+#define SPSR_SS                (1 << 21)
+
+extern unsigned char sw_bp, hw_bp, bp_svc, bp_brk, hw_wp, ss_start;
+static volatile uint64_t sw_bp_addr, hw_bp_addr;
+static volatile uint64_t wp_addr, wp_data_addr;
+static volatile uint64_t svc_addr;
+static volatile uint64_t ss_addr[4], ss_idx;
+#define  PC(v)  ((uint64_t)&(v))
+
+static void reset_debug_state(void)
+{
+       asm volatile("msr daifset, #8");
+
+       write_sysreg(osdlr_el1, 0);
+       write_sysreg(oslar_el1, 0);
+       isb();
+
+       write_sysreg(mdscr_el1, 0);
+       /* This test only uses the first bp and wp slot. */
+       write_sysreg(dbgbvr0_el1, 0);
+       write_sysreg(dbgbcr0_el1, 0);
+       write_sysreg(dbgwcr0_el1, 0);
+       write_sysreg(dbgwvr0_el1, 0);
+       isb();
+}
+
+static void install_wp(uint64_t addr)
+{
+       uint32_t wcr;
+       uint32_t mdscr;
+
+       wcr = DBGWCR_LEN8 | DBGWCR_RD | DBGWCR_WR | DBGWCR_EL1 | DBGWCR_E;
+       write_sysreg(dbgwcr0_el1, wcr);
+       write_sysreg(dbgwvr0_el1, addr);
+       isb();
+
+       asm volatile("msr daifclr, #8");
+
+       mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
+       write_sysreg(mdscr_el1, mdscr);
+       isb();
+}
+
+static void install_hw_bp(uint64_t addr)
+{
+       uint32_t bcr;
+       uint32_t mdscr;
+
+       bcr = DBGBCR_LEN8 | DBGBCR_EXEC | DBGBCR_EL1 | DBGBCR_E;
+       write_sysreg(dbgbcr0_el1, bcr);
+       write_sysreg(dbgbvr0_el1, addr);
+       isb();
+
+       asm volatile("msr daifclr, #8");
+
+       mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_MDE;
+       write_sysreg(mdscr_el1, mdscr);
+       isb();
+}
+
+static void install_ss(void)
+{
+       uint32_t mdscr;
+
+       asm volatile("msr daifclr, #8");
+
+       mdscr = read_sysreg(mdscr_el1) | MDSCR_KDE | MDSCR_SS;
+       write_sysreg(mdscr_el1, mdscr);
+       isb();
+}
+
+static volatile char write_data;
+
+static void guest_code(void)
+{
+       GUEST_SYNC(0);
+
+       /* Software-breakpoint */
+       asm volatile("sw_bp: brk #0");
+       GUEST_ASSERT_EQ(sw_bp_addr, PC(sw_bp));
+
+       GUEST_SYNC(1);
+
+       /* Hardware-breakpoint */
+       reset_debug_state();
+       install_hw_bp(PC(hw_bp));
+       asm volatile("hw_bp: nop");
+       GUEST_ASSERT_EQ(hw_bp_addr, PC(hw_bp));
+
+       GUEST_SYNC(2);
+
+       /* Hardware-breakpoint + svc */
+       reset_debug_state();
+       install_hw_bp(PC(bp_svc));
+       asm volatile("bp_svc: svc #0");
+       GUEST_ASSERT_EQ(hw_bp_addr, PC(bp_svc));
+       GUEST_ASSERT_EQ(svc_addr, PC(bp_svc) + 4);
+
+       GUEST_SYNC(3);
+
+       /* Hardware-breakpoint + software-breakpoint */
+       reset_debug_state();
+       install_hw_bp(PC(bp_brk));
+       asm volatile("bp_brk: brk #0");
+       GUEST_ASSERT_EQ(sw_bp_addr, PC(bp_brk));
+       GUEST_ASSERT_EQ(hw_bp_addr, PC(bp_brk));
+
+       GUEST_SYNC(4);
+
+       /* Watchpoint */
+       reset_debug_state();
+       install_wp(PC(write_data));
+       write_data = 'x';
+       GUEST_ASSERT_EQ(write_data, 'x');
+       GUEST_ASSERT_EQ(wp_data_addr, PC(write_data));
+
+       GUEST_SYNC(5);
+
+       /* Single-step */
+       reset_debug_state();
+       install_ss();
+       ss_idx = 0;
+       asm volatile("ss_start:\n"
+                    "mrs x0, esr_el1\n"
+                    "add x0, x0, #1\n"
+                    "msr daifset, #8\n"
+                    : : : "x0");
+       GUEST_ASSERT_EQ(ss_addr[0], PC(ss_start));
+       GUEST_ASSERT_EQ(ss_addr[1], PC(ss_start) + 4);
+       GUEST_ASSERT_EQ(ss_addr[2], PC(ss_start) + 8);
+
+       GUEST_DONE();
+}
+
+static void guest_sw_bp_handler(struct ex_regs *regs)
+{
+       sw_bp_addr = regs->pc;
+       regs->pc += 4;
+}
+
+static void guest_hw_bp_handler(struct ex_regs *regs)
+{
+       hw_bp_addr = regs->pc;
+       regs->pstate |= SPSR_D;
+}
+
+static void guest_wp_handler(struct ex_regs *regs)
+{
+       wp_data_addr = read_sysreg(far_el1);
+       wp_addr = regs->pc;
+       regs->pstate |= SPSR_D;
+}
+
+static void guest_ss_handler(struct ex_regs *regs)
+{
+       GUEST_ASSERT_1(ss_idx < 4, ss_idx);
+       ss_addr[ss_idx++] = regs->pc;
+       regs->pstate |= SPSR_SS;
+}
+
+static void guest_svc_handler(struct ex_regs *regs)
+{
+       svc_addr = regs->pc;
+}
+
+static int debug_version(struct kvm_vm *vm)
+{
+       uint64_t id_aa64dfr0;
+
+       get_reg(vm, VCPU_ID, ARM64_SYS_REG(ID_AA64DFR0_EL1), &id_aa64dfr0);
+       return id_aa64dfr0 & 0xf;
+}
+
+int main(int argc, char *argv[])
+{
+       struct kvm_vm *vm;
+       struct ucall uc;
+       int stage;
+
+       vm = vm_create_default(VCPU_ID, 0, guest_code);
+       ucall_init(vm, NULL);
+
+       vm_init_descriptor_tables(vm);
+       vcpu_init_descriptor_tables(vm, VCPU_ID);
+
+       if (debug_version(vm) < 6) {
+               print_skip("Armv8 debug architecture not supported.");
+               kvm_vm_free(vm);
+               exit(KSFT_SKIP);
+       }
+
+       vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
+                               ESR_EC_BRK_INS, guest_sw_bp_handler);
+       vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
+                               ESR_EC_HW_BP_CURRENT, guest_hw_bp_handler);
+       vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
+                               ESR_EC_WP_CURRENT, guest_wp_handler);
+       vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
+                               ESR_EC_SSTEP_CURRENT, guest_ss_handler);
+       vm_install_sync_handler(vm, VECTOR_SYNC_CURRENT,
+                               ESR_EC_SVC64, guest_svc_handler);
+
+       for (stage = 0; stage < 7; stage++) {
+               vcpu_run(vm, VCPU_ID);
+
+               switch (get_ucall(vm, VCPU_ID, &uc)) {
+               case UCALL_SYNC:
+                       TEST_ASSERT(uc.args[1] == stage,
+                               "Stage %d: Unexpected sync ucall, got %lx",
+                               stage, (ulong)uc.args[1]);
+                       break;
+               case UCALL_ABORT:
+                       TEST_FAIL("%s at %s:%ld\n\tvalues: %#lx, %#lx",
+                               (const char *)uc.args[0],
+                               __FILE__, uc.args[1], uc.args[2], uc.args[3]);
+                       break;
+               case UCALL_DONE:
+                       goto done;
+               default:
+                       TEST_FAIL("Unknown ucall %lu", uc.cmd);
+               }
+       }
+
+done:
+       kvm_vm_free(vm);
+       return 0;
+}
diff --git a/tools/testing/selftests/kvm/aarch64/get-reg-list-sve.c b/tools/testing/selftests/kvm/aarch64/get-reg-list-sve.c
deleted file mode 100644 (file)
index efba766..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#define REG_LIST_SVE
-#include "get-reg-list.c"
index 486932164cf2152f0f346e0ba5f20c9c3a418355..a16c8f05366c624b706e7fb9ddfe16fd2515f572 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include "kvm_util.h"
 #include "test_util.h"
 #include "processor.h"
 
-#ifdef REG_LIST_SVE
-#define reg_list_sve() (true)
-#else
-#define reg_list_sve() (false)
-#endif
+static struct kvm_reg_list *reg_list;
+static __u64 *blessed_reg, blessed_n;
 
-#define REG_MASK (KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_COPROC_MASK)
+struct reg_sublist {
+       const char *name;
+       long capability;
+       int feature;
+       bool finalize;
+       __u64 *regs;
+       __u64 regs_n;
+       __u64 *rejects_set;
+       __u64 rejects_set_n;
+};
+
+struct vcpu_config {
+       char *name;
+       struct reg_sublist sublists[];
+};
+
+static struct vcpu_config *vcpu_configs[];
+static int vcpu_configs_n;
+
+#define for_each_sublist(c, s)                                                 \
+       for ((s) = &(c)->sublists[0]; (s)->regs; ++(s))
 
 #define for_each_reg(i)                                                                \
        for ((i) = 0; (i) < reg_list->n; ++(i))
        for_each_reg_filtered(i)                                                \
                if (!find_reg(blessed_reg, blessed_n, reg_list->reg[i]))
 
+static const char *config_name(struct vcpu_config *c)
+{
+       struct reg_sublist *s;
+       int len = 0;
 
-static struct kvm_reg_list *reg_list;
+       if (c->name)
+               return c->name;
 
-static __u64 base_regs[], vregs[], sve_regs[], rejects_set[];
-static __u64 base_regs_n, vregs_n, sve_regs_n, rejects_set_n;
-static __u64 *blessed_reg, blessed_n;
+       for_each_sublist(c, s)
+               len += strlen(s->name) + 1;
+
+       c->name = malloc(len);
+
+       len = 0;
+       for_each_sublist(c, s) {
+               if (!strcmp(s->name, "base"))
+                       continue;
+               strcat(c->name + len, s->name);
+               len += strlen(s->name) + 1;
+               c->name[len - 1] = '+';
+       }
+       c->name[len - 1] = '\0';
+
+       return c->name;
+}
+
+static bool has_cap(struct vcpu_config *c, long capability)
+{
+       struct reg_sublist *s;
+
+       for_each_sublist(c, s)
+               if (s->capability == capability)
+                       return true;
+       return false;
+}
 
 static bool filter_reg(__u64 reg)
 {
@@ -96,11 +145,13 @@ static const char *str_with_index(const char *template, __u64 index)
        return (const char *)str;
 }
 
+#define REG_MASK (KVM_REG_ARCH_MASK | KVM_REG_SIZE_MASK | KVM_REG_ARM_COPROC_MASK)
+
 #define CORE_REGS_XX_NR_WORDS  2
 #define CORE_SPSR_XX_NR_WORDS  2
 #define CORE_FPREGS_XX_NR_WORDS        4
 
-static const char *core_id_to_str(__u64 id)
+static const char *core_id_to_str(struct vcpu_config *c, __u64 id)
 {
        __u64 core_off = id & ~REG_MASK, idx;
 
@@ -111,7 +162,7 @@ static const char *core_id_to_str(__u64 id)
        case KVM_REG_ARM_CORE_REG(regs.regs[0]) ...
             KVM_REG_ARM_CORE_REG(regs.regs[30]):
                idx = (core_off - KVM_REG_ARM_CORE_REG(regs.regs[0])) / CORE_REGS_XX_NR_WORDS;
-               TEST_ASSERT(idx < 31, "Unexpected regs.regs index: %lld", idx);
+               TEST_ASSERT(idx < 31, "%s: Unexpected regs.regs index: %lld", config_name(c), idx);
                return str_with_index("KVM_REG_ARM_CORE_REG(regs.regs[##])", idx);
        case KVM_REG_ARM_CORE_REG(regs.sp):
                return "KVM_REG_ARM_CORE_REG(regs.sp)";
@@ -126,12 +177,12 @@ static const char *core_id_to_str(__u64 id)
        case KVM_REG_ARM_CORE_REG(spsr[0]) ...
             KVM_REG_ARM_CORE_REG(spsr[KVM_NR_SPSR - 1]):
                idx = (core_off - KVM_REG_ARM_CORE_REG(spsr[0])) / CORE_SPSR_XX_NR_WORDS;
-               TEST_ASSERT(idx < KVM_NR_SPSR, "Unexpected spsr index: %lld", idx);
+               TEST_ASSERT(idx < KVM_NR_SPSR, "%s: Unexpected spsr index: %lld", config_name(c), idx);
                return str_with_index("KVM_REG_ARM_CORE_REG(spsr[##])", idx);
        case KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]) ...
             KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]):
                idx = (core_off - KVM_REG_ARM_CORE_REG(fp_regs.vregs[0])) / CORE_FPREGS_XX_NR_WORDS;
-               TEST_ASSERT(idx < 32, "Unexpected fp_regs.vregs index: %lld", idx);
+               TEST_ASSERT(idx < 32, "%s: Unexpected fp_regs.vregs index: %lld", config_name(c), idx);
                return str_with_index("KVM_REG_ARM_CORE_REG(fp_regs.vregs[##])", idx);
        case KVM_REG_ARM_CORE_REG(fp_regs.fpsr):
                return "KVM_REG_ARM_CORE_REG(fp_regs.fpsr)";
@@ -139,11 +190,11 @@ static const char *core_id_to_str(__u64 id)
                return "KVM_REG_ARM_CORE_REG(fp_regs.fpcr)";
        }
 
-       TEST_FAIL("Unknown core reg id: 0x%llx", id);
+       TEST_FAIL("%s: Unknown core reg id: 0x%llx", config_name(c), id);
        return NULL;
 }
 
-static const char *sve_id_to_str(__u64 id)
+static const char *sve_id_to_str(struct vcpu_config *c, __u64 id)
 {
        __u64 sve_off, n, i;
 
@@ -153,37 +204,37 @@ static const char *sve_id_to_str(__u64 id)
        sve_off = id & ~(REG_MASK | ((1ULL << 5) - 1));
        i = id & (KVM_ARM64_SVE_MAX_SLICES - 1);
 
-       TEST_ASSERT(i == 0, "Currently we don't expect slice > 0, reg id 0x%llx", id);
+       TEST_ASSERT(i == 0, "%s: Currently we don't expect slice > 0, reg id 0x%llx", config_name(c), id);
 
        switch (sve_off) {
        case KVM_REG_ARM64_SVE_ZREG_BASE ...
             KVM_REG_ARM64_SVE_ZREG_BASE + (1ULL << 5) * KVM_ARM64_SVE_NUM_ZREGS - 1:
                n = (id >> 5) & (KVM_ARM64_SVE_NUM_ZREGS - 1);
                TEST_ASSERT(id == KVM_REG_ARM64_SVE_ZREG(n, 0),
-                           "Unexpected bits set in SVE ZREG id: 0x%llx", id);
+                           "%s: Unexpected bits set in SVE ZREG id: 0x%llx", config_name(c), id);
                return str_with_index("KVM_REG_ARM64_SVE_ZREG(##, 0)", n);
        case KVM_REG_ARM64_SVE_PREG_BASE ...
             KVM_REG_ARM64_SVE_PREG_BASE + (1ULL << 5) * KVM_ARM64_SVE_NUM_PREGS - 1:
                n = (id >> 5) & (KVM_ARM64_SVE_NUM_PREGS - 1);
                TEST_ASSERT(id == KVM_REG_ARM64_SVE_PREG(n, 0),
-                           "Unexpected bits set in SVE PREG id: 0x%llx", id);
+                           "%s: Unexpected bits set in SVE PREG id: 0x%llx", config_name(c), id);
                return str_with_index("KVM_REG_ARM64_SVE_PREG(##, 0)", n);
        case KVM_REG_ARM64_SVE_FFR_BASE:
                TEST_ASSERT(id == KVM_REG_ARM64_SVE_FFR(0),
-                           "Unexpected bits set in SVE FFR id: 0x%llx", id);
+                           "%s: Unexpected bits set in SVE FFR id: 0x%llx", config_name(c), id);
                return "KVM_REG_ARM64_SVE_FFR(0)";
        }
 
        return NULL;
 }
 
-static void print_reg(__u64 id)
+static void print_reg(struct vcpu_config *c, __u64 id)
 {
        unsigned op0, op1, crn, crm, op2;
        const char *reg_size = NULL;
 
        TEST_ASSERT((id & KVM_REG_ARCH_MASK) == KVM_REG_ARM64,
-                   "KVM_REG_ARM64 missing in reg id: 0x%llx", id);
+                   "%s: KVM_REG_ARM64 missing in reg id: 0x%llx", config_name(c), id);
 
        switch (id & KVM_REG_SIZE_MASK) {
        case KVM_REG_SIZE_U8:
@@ -214,17 +265,17 @@ static void print_reg(__u64 id)
                reg_size = "KVM_REG_SIZE_U2048";
                break;
        default:
-               TEST_FAIL("Unexpected reg size: 0x%llx in reg id: 0x%llx",
-                         (id & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT, id);
+               TEST_FAIL("%s: Unexpected reg size: 0x%llx in reg id: 0x%llx",
+                         config_name(c), (id & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT, id);
        }
 
        switch (id & KVM_REG_ARM_COPROC_MASK) {
        case KVM_REG_ARM_CORE:
-               printf("\tKVM_REG_ARM64 | %s | KVM_REG_ARM_CORE | %s,\n", reg_size, core_id_to_str(id));
+               printf("\tKVM_REG_ARM64 | %s | KVM_REG_ARM_CORE | %s,\n", reg_size, core_id_to_str(c, id));
                break;
        case KVM_REG_ARM_DEMUX:
                TEST_ASSERT(!(id & ~(REG_MASK | KVM_REG_ARM_DEMUX_ID_MASK | KVM_REG_ARM_DEMUX_VAL_MASK)),
-                           "Unexpected bits set in DEMUX reg id: 0x%llx", id);
+                           "%s: Unexpected bits set in DEMUX reg id: 0x%llx", config_name(c), id);
                printf("\tKVM_REG_ARM64 | %s | KVM_REG_ARM_DEMUX | KVM_REG_ARM_DEMUX_ID_CCSIDR | %lld,\n",
                       reg_size, id & KVM_REG_ARM_DEMUX_VAL_MASK);
                break;
@@ -235,23 +286,23 @@ static void print_reg(__u64 id)
                crm = (id & KVM_REG_ARM64_SYSREG_CRM_MASK) >> KVM_REG_ARM64_SYSREG_CRM_SHIFT;
                op2 = (id & KVM_REG_ARM64_SYSREG_OP2_MASK) >> KVM_REG_ARM64_SYSREG_OP2_SHIFT;
                TEST_ASSERT(id == ARM64_SYS_REG(op0, op1, crn, crm, op2),
-                           "Unexpected bits set in SYSREG reg id: 0x%llx", id);
+                           "%s: Unexpected bits set in SYSREG reg id: 0x%llx", config_name(c), id);
                printf("\tARM64_SYS_REG(%d, %d, %d, %d, %d),\n", op0, op1, crn, crm, op2);
                break;
        case KVM_REG_ARM_FW:
                TEST_ASSERT(id == KVM_REG_ARM_FW_REG(id & 0xffff),
-                           "Unexpected bits set in FW reg id: 0x%llx", id);
+                           "%s: Unexpected bits set in FW reg id: 0x%llx", config_name(c), id);
                printf("\tKVM_REG_ARM_FW_REG(%lld),\n", id & 0xffff);
                break;
        case KVM_REG_ARM64_SVE:
-               if (reg_list_sve())
-                       printf("\t%s,\n", sve_id_to_str(id));
+               if (has_cap(c, KVM_CAP_ARM_SVE))
+                       printf("\t%s,\n", sve_id_to_str(c, id));
                else
-                       TEST_FAIL("KVM_REG_ARM64_SVE is an unexpected coproc type in reg id: 0x%llx", id);
+                       TEST_FAIL("%s: KVM_REG_ARM64_SVE is an unexpected coproc type in reg id: 0x%llx", config_name(c), id);
                break;
        default:
-               TEST_FAIL("Unexpected coproc type: 0x%llx in reg id: 0x%llx",
-                         (id & KVM_REG_ARM_COPROC_MASK) >> KVM_REG_ARM_COPROC_SHIFT, id);
+               TEST_FAIL("%s: Unexpected coproc type: 0x%llx in reg id: 0x%llx",
+                         config_name(c), (id & KVM_REG_ARM_COPROC_MASK) >> KVM_REG_ARM_COPROC_SHIFT, id);
        }
 }
 
@@ -312,56 +363,58 @@ static void core_reg_fixup(void)
        reg_list = tmp;
 }
 
-static void prepare_vcpu_init(struct kvm_vcpu_init *init)
+static void prepare_vcpu_init(struct vcpu_config *c, struct kvm_vcpu_init *init)
 {
-       if (reg_list_sve())
-               init->features[0] |= 1 << KVM_ARM_VCPU_SVE;
+       struct reg_sublist *s;
+
+       for_each_sublist(c, s)
+               if (s->capability)
+                       init->features[s->feature / 32] |= 1 << (s->feature % 32);
 }
 
-static void finalize_vcpu(struct kvm_vm *vm, uint32_t vcpuid)
+static void finalize_vcpu(struct kvm_vm *vm, uint32_t vcpuid, struct vcpu_config *c)
 {
+       struct reg_sublist *s;
        int feature;
 
-       if (reg_list_sve()) {
-               feature = KVM_ARM_VCPU_SVE;
-               vcpu_ioctl(vm, vcpuid, KVM_ARM_VCPU_FINALIZE, &feature);
+       for_each_sublist(c, s) {
+               if (s->finalize) {
+                       feature = s->feature;
+                       vcpu_ioctl(vm, vcpuid, KVM_ARM_VCPU_FINALIZE, &feature);
+               }
        }
 }
 
-static void check_supported(void)
+static void check_supported(struct vcpu_config *c)
 {
-       if (reg_list_sve() && !kvm_check_cap(KVM_CAP_ARM_SVE)) {
-               fprintf(stderr, "SVE not available, skipping tests\n");
-               exit(KSFT_SKIP);
+       struct reg_sublist *s;
+
+       for_each_sublist(c, s) {
+               if (s->capability && !kvm_check_cap(s->capability)) {
+                       fprintf(stderr, "%s: %s not available, skipping tests\n", config_name(c), s->name);
+                       exit(KSFT_SKIP);
+               }
        }
 }
 
-int main(int ac, char **av)
+static bool print_list;
+static bool print_filtered;
+static bool fixup_core_regs;
+
+static void run_test(struct vcpu_config *c)
 {
        struct kvm_vcpu_init init = { .target = -1, };
-       int new_regs = 0, missing_regs = 0, i;
+       int new_regs = 0, missing_regs = 0, i, n;
        int failed_get = 0, failed_set = 0, failed_reject = 0;
-       bool print_list = false, print_filtered = false, fixup_core_regs = false;
        struct kvm_vm *vm;
-       __u64 *vec_regs;
+       struct reg_sublist *s;
 
-       check_supported();
-
-       for (i = 1; i < ac; ++i) {
-               if (strcmp(av[i], "--core-reg-fixup") == 0)
-                       fixup_core_regs = true;
-               else if (strcmp(av[i], "--list") == 0)
-                       print_list = true;
-               else if (strcmp(av[i], "--list-filtered") == 0)
-                       print_filtered = true;
-               else
-                       TEST_FAIL("Unknown option: %s\n", av[i]);
-       }
+       check_supported(c);
 
        vm = vm_create(VM_MODE_DEFAULT, DEFAULT_GUEST_PHY_PAGES, O_RDWR);
-       prepare_vcpu_init(&init);
+       prepare_vcpu_init(c, &init);
        aarch64_vcpu_add_default(vm, 0, &init, NULL);
-       finalize_vcpu(vm, 0);
+       finalize_vcpu(vm, 0, c);
 
        reg_list = vcpu_get_reg_list(vm, 0);
 
@@ -374,10 +427,10 @@ int main(int ac, char **av)
                        __u64 id = reg_list->reg[i];
                        if ((print_list && !filter_reg(id)) ||
                            (print_filtered && filter_reg(id)))
-                               print_reg(id);
+                               print_reg(c, id);
                }
                putchar('\n');
-               return 0;
+               return;
        }
 
        /*
@@ -396,50 +449,52 @@ int main(int ac, char **av)
                        .id = reg_list->reg[i],
                        .addr = (__u64)&addr,
                };
+               bool reject_reg = false;
                int ret;
 
                ret = _vcpu_ioctl(vm, 0, KVM_GET_ONE_REG, &reg);
                if (ret) {
-                       puts("Failed to get ");
-                       print_reg(reg.id);
+                       printf("%s: Failed to get ", config_name(c));
+                       print_reg(c, reg.id);
                        putchar('\n');
                        ++failed_get;
                }
 
                /* rejects_set registers are rejected after KVM_ARM_VCPU_FINALIZE */
-               if (find_reg(rejects_set, rejects_set_n, reg.id)) {
-                       ret = _vcpu_ioctl(vm, 0, KVM_SET_ONE_REG, &reg);
-                       if (ret != -1 || errno != EPERM) {
-                               printf("Failed to reject (ret=%d, errno=%d) ", ret, errno);
-                               print_reg(reg.id);
-                               putchar('\n');
-                               ++failed_reject;
+               for_each_sublist(c, s) {
+                       if (s->rejects_set && find_reg(s->rejects_set, s->rejects_set_n, reg.id)) {
+                               reject_reg = true;
+                               ret = _vcpu_ioctl(vm, 0, KVM_SET_ONE_REG, &reg);
+                               if (ret != -1 || errno != EPERM) {
+                                       printf("%s: Failed to reject (ret=%d, errno=%d) ", config_name(c), ret, errno);
+                                       print_reg(c, reg.id);
+                                       putchar('\n');
+                                       ++failed_reject;
+                               }
+                               break;
                        }
-                       continue;
                }
 
-               ret = _vcpu_ioctl(vm, 0, KVM_SET_ONE_REG, &reg);
-               if (ret) {
-                       puts("Failed to set ");
-                       print_reg(reg.id);
-                       putchar('\n');
-                       ++failed_set;
+               if (!reject_reg) {
+                       ret = _vcpu_ioctl(vm, 0, KVM_SET_ONE_REG, &reg);
+                       if (ret) {
+                               printf("%s: Failed to set ", config_name(c));
+                               print_reg(c, reg.id);
+                               putchar('\n');
+                               ++failed_set;
+                       }
                }
        }
 
-       if (reg_list_sve()) {
-               blessed_n = base_regs_n + sve_regs_n;
-               vec_regs = sve_regs;
-       } else {
-               blessed_n = base_regs_n + vregs_n;
-               vec_regs = vregs;
-       }
-
+       for_each_sublist(c, s)
+               blessed_n += s->regs_n;
        blessed_reg = calloc(blessed_n, sizeof(__u64));
-       for (i = 0; i < base_regs_n; ++i)
-               blessed_reg[i] = base_regs[i];
-       for (i = 0; i < blessed_n - base_regs_n; ++i)
-               blessed_reg[base_regs_n + i] = vec_regs[i];
+
+       n = 0;
+       for_each_sublist(c, s) {
+               for (i = 0; i < s->regs_n; ++i)
+                       blessed_reg[n++] = s->regs[i];
+       }
 
        for_each_new_reg(i)
                ++new_regs;
@@ -448,40 +503,141 @@ int main(int ac, char **av)
                ++missing_regs;
 
        if (new_regs || missing_regs) {
-               printf("Number blessed registers: %5lld\n", blessed_n);
-               printf("Number registers:         %5lld\n", reg_list->n);
+               printf("%s: Number blessed registers: %5lld\n", config_name(c), blessed_n);
+               printf("%s: Number registers:         %5lld\n", config_name(c), reg_list->n);
        }
 
        if (new_regs) {
-               printf("\nThere are %d new registers.\n"
+               printf("\n%s: There are %d new registers.\n"
                       "Consider adding them to the blessed reg "
-                      "list with the following lines:\n\n", new_regs);
+                      "list with the following lines:\n\n", config_name(c), new_regs);
                for_each_new_reg(i)
-                       print_reg(reg_list->reg[i]);
+                       print_reg(c, reg_list->reg[i]);
                putchar('\n');
        }
 
        if (missing_regs) {
-               printf("\nThere are %d missing registers.\n"
-                      "The following lines are missing registers:\n\n", missing_regs);
+               printf("\n%s: There are %d missing registers.\n"
+                      "The following lines are missing registers:\n\n", config_name(c), missing_regs);
                for_each_missing_reg(i)
-                       print_reg(blessed_reg[i]);
+                       print_reg(c, blessed_reg[i]);
                putchar('\n');
        }
 
        TEST_ASSERT(!missing_regs && !failed_get && !failed_set && !failed_reject,
-                   "There are %d missing registers; "
+                   "%s: There are %d missing registers; "
                    "%d registers failed get; %d registers failed set; %d registers failed reject",
-                   missing_regs, failed_get, failed_set, failed_reject);
+                   config_name(c), missing_regs, failed_get, failed_set, failed_reject);
 
-       return 0;
+       pr_info("%s: PASS\n", config_name(c));
+       blessed_n = 0;
+       free(blessed_reg);
+       free(reg_list);
+       kvm_vm_free(vm);
+}
+
+static void help(void)
+{
+       struct vcpu_config *c;
+       int i;
+
+       printf(
+       "\n"
+       "usage: get-reg-list [--config=<selection>] [--list] [--list-filtered] [--core-reg-fixup]\n\n"
+       " --config=<selection>        Used to select a specific vcpu configuration for the test/listing\n"
+       "                             '<selection>' may be\n");
+
+       for (i = 0; i < vcpu_configs_n; ++i) {
+               c = vcpu_configs[i];
+               printf(
+       "                               '%s'\n", config_name(c));
+       }
+
+       printf(
+       "\n"
+       " --list                      Print the register list rather than test it (requires --config)\n"
+       " --list-filtered             Print registers that would normally be filtered out (requires --config)\n"
+       " --core-reg-fixup            Needed when running on old kernels with broken core reg listings\n"
+       "\n"
+       );
+}
+
+static struct vcpu_config *parse_config(const char *config)
+{
+       struct vcpu_config *c;
+       int i;
+
+       if (config[8] != '=')
+               help(), exit(1);
+
+       for (i = 0; i < vcpu_configs_n; ++i) {
+               c = vcpu_configs[i];
+               if (strcmp(config_name(c), &config[9]) == 0)
+                       break;
+       }
+
+       if (i == vcpu_configs_n)
+               help(), exit(1);
+
+       return c;
+}
+
+int main(int ac, char **av)
+{
+       struct vcpu_config *c, *sel = NULL;
+       int i, ret = 0;
+       pid_t pid;
+
+       for (i = 1; i < ac; ++i) {
+               if (strcmp(av[i], "--core-reg-fixup") == 0)
+                       fixup_core_regs = true;
+               else if (strncmp(av[i], "--config", 8) == 0)
+                       sel = parse_config(av[i]);
+               else if (strcmp(av[i], "--list") == 0)
+                       print_list = true;
+               else if (strcmp(av[i], "--list-filtered") == 0)
+                       print_filtered = true;
+               else if (strcmp(av[i], "--help") == 0 || strcmp(av[1], "-h") == 0)
+                       help(), exit(0);
+               else
+                       help(), exit(1);
+       }
+
+       if (print_list || print_filtered) {
+               /*
+                * We only want to print the register list of a single config.
+                */
+               if (!sel)
+                       help(), exit(1);
+       }
+
+       for (i = 0; i < vcpu_configs_n; ++i) {
+               c = vcpu_configs[i];
+               if (sel && c != sel)
+                       continue;
+
+               pid = fork();
+
+               if (!pid) {
+                       run_test(c);
+                       exit(0);
+               } else {
+                       int wstatus;
+                       pid_t wpid = wait(&wstatus);
+                       TEST_ASSERT(wpid == pid && WIFEXITED(wstatus), "wait: Unexpected return");
+                       if (WEXITSTATUS(wstatus) && WEXITSTATUS(wstatus) != KSFT_SKIP)
+                               ret = KSFT_FAIL;
+               }
+       }
+
+       return ret;
 }
 
 /*
  * The current blessed list was primed with the output of kernel version
  * v4.15 with --core-reg-fixup and then later updated with new registers.
  *
- * The blessed list is up to date with kernel version v5.10-rc5
+ * The blessed list is up to date with kernel version v5.13-rc3
  */
 static __u64 base_regs[] = {
        KVM_REG_ARM64 | KVM_REG_SIZE_U64 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(regs.regs[0]),
@@ -673,8 +829,6 @@ static __u64 base_regs[] = {
        ARM64_SYS_REG(3, 0, 5, 2, 0),   /* ESR_EL1 */
        ARM64_SYS_REG(3, 0, 6, 0, 0),   /* FAR_EL1 */
        ARM64_SYS_REG(3, 0, 7, 4, 0),   /* PAR_EL1 */
-       ARM64_SYS_REG(3, 0, 9, 14, 1),  /* PMINTENSET_EL1 */
-       ARM64_SYS_REG(3, 0, 9, 14, 2),  /* PMINTENCLR_EL1 */
        ARM64_SYS_REG(3, 0, 10, 2, 0),  /* MAIR_EL1 */
        ARM64_SYS_REG(3, 0, 10, 3, 0),  /* AMAIR_EL1 */
        ARM64_SYS_REG(3, 0, 12, 0, 0),  /* VBAR_EL1 */
@@ -683,6 +837,16 @@ static __u64 base_regs[] = {
        ARM64_SYS_REG(3, 0, 13, 0, 4),  /* TPIDR_EL1 */
        ARM64_SYS_REG(3, 0, 14, 1, 0),  /* CNTKCTL_EL1 */
        ARM64_SYS_REG(3, 2, 0, 0, 0),   /* CSSELR_EL1 */
+       ARM64_SYS_REG(3, 3, 13, 0, 2),  /* TPIDR_EL0 */
+       ARM64_SYS_REG(3, 3, 13, 0, 3),  /* TPIDRRO_EL0 */
+       ARM64_SYS_REG(3, 4, 3, 0, 0),   /* DACR32_EL2 */
+       ARM64_SYS_REG(3, 4, 5, 0, 1),   /* IFSR32_EL2 */
+       ARM64_SYS_REG(3, 4, 5, 3, 0),   /* FPEXC32_EL2 */
+};
+
+static __u64 pmu_regs[] = {
+       ARM64_SYS_REG(3, 0, 9, 14, 1),  /* PMINTENSET_EL1 */
+       ARM64_SYS_REG(3, 0, 9, 14, 2),  /* PMINTENCLR_EL1 */
        ARM64_SYS_REG(3, 3, 9, 12, 0),  /* PMCR_EL0 */
        ARM64_SYS_REG(3, 3, 9, 12, 1),  /* PMCNTENSET_EL0 */
        ARM64_SYS_REG(3, 3, 9, 12, 2),  /* PMCNTENCLR_EL0 */
@@ -692,8 +856,6 @@ static __u64 base_regs[] = {
        ARM64_SYS_REG(3, 3, 9, 13, 0),  /* PMCCNTR_EL0 */
        ARM64_SYS_REG(3, 3, 9, 14, 0),  /* PMUSERENR_EL0 */
        ARM64_SYS_REG(3, 3, 9, 14, 3),  /* PMOVSSET_EL0 */
-       ARM64_SYS_REG(3, 3, 13, 0, 2),  /* TPIDR_EL0 */
-       ARM64_SYS_REG(3, 3, 13, 0, 3),  /* TPIDRRO_EL0 */
        ARM64_SYS_REG(3, 3, 14, 8, 0),
        ARM64_SYS_REG(3, 3, 14, 8, 1),
        ARM64_SYS_REG(3, 3, 14, 8, 2),
@@ -757,11 +919,7 @@ static __u64 base_regs[] = {
        ARM64_SYS_REG(3, 3, 14, 15, 5),
        ARM64_SYS_REG(3, 3, 14, 15, 6),
        ARM64_SYS_REG(3, 3, 14, 15, 7), /* PMCCFILTR_EL0 */
-       ARM64_SYS_REG(3, 4, 3, 0, 0),   /* DACR32_EL2 */
-       ARM64_SYS_REG(3, 4, 5, 0, 1),   /* IFSR32_EL2 */
-       ARM64_SYS_REG(3, 4, 5, 3, 0),   /* FPEXC32_EL2 */
 };
-static __u64 base_regs_n = ARRAY_SIZE(base_regs);
 
 static __u64 vregs[] = {
        KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[0]),
@@ -797,7 +955,6 @@ static __u64 vregs[] = {
        KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[30]),
        KVM_REG_ARM64 | KVM_REG_SIZE_U128 | KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(fp_regs.vregs[31]),
 };
-static __u64 vregs_n = ARRAY_SIZE(vregs);
 
 static __u64 sve_regs[] = {
        KVM_REG_ARM64_SVE_VLS,
@@ -852,11 +1009,57 @@ static __u64 sve_regs[] = {
        KVM_REG_ARM64_SVE_FFR(0),
        ARM64_SYS_REG(3, 0, 1, 2, 0),   /* ZCR_EL1 */
 };
-static __u64 sve_regs_n = ARRAY_SIZE(sve_regs);
 
-static __u64 rejects_set[] = {
-#ifdef REG_LIST_SVE
+static __u64 sve_rejects_set[] = {
        KVM_REG_ARM64_SVE_VLS,
-#endif
 };
-static __u64 rejects_set_n = ARRAY_SIZE(rejects_set);
+
+#define BASE_SUBLIST \
+       { "base", .regs = base_regs, .regs_n = ARRAY_SIZE(base_regs), }
+#define VREGS_SUBLIST \
+       { "vregs", .regs = vregs, .regs_n = ARRAY_SIZE(vregs), }
+#define PMU_SUBLIST \
+       { "pmu", .regs = pmu_regs, .regs_n = ARRAY_SIZE(pmu_regs), }
+#define SVE_SUBLIST \
+       { "sve", .capability = KVM_CAP_ARM_SVE, .feature = KVM_ARM_VCPU_SVE, .finalize = true, \
+         .regs = sve_regs, .regs_n = ARRAY_SIZE(sve_regs), \
+         .rejects_set = sve_rejects_set, .rejects_set_n = ARRAY_SIZE(sve_rejects_set), }
+
+static struct vcpu_config vregs_config = {
+       .sublists = {
+       BASE_SUBLIST,
+       VREGS_SUBLIST,
+       {0},
+       },
+};
+static struct vcpu_config vregs_pmu_config = {
+       .sublists = {
+       BASE_SUBLIST,
+       VREGS_SUBLIST,
+       PMU_SUBLIST,
+       {0},
+       },
+};
+static struct vcpu_config sve_config = {
+       .sublists = {
+       BASE_SUBLIST,
+       SVE_SUBLIST,
+       {0},
+       },
+};
+static struct vcpu_config sve_pmu_config = {
+       .sublists = {
+       BASE_SUBLIST,
+       SVE_SUBLIST,
+       PMU_SUBLIST,
+       {0},
+       },
+};
+
+static struct vcpu_config *vcpu_configs[] = {
+       &vregs_config,
+       &vregs_pmu_config,
+       &sve_config,
+       &sve_pmu_config,
+};
+static int vcpu_configs_n = ARRAY_SIZE(vcpu_configs);
index b7fa0c8551db4b2d84dad3fca42572d299e5cdd6..27dc5c2e56b93cdc5e9fc919d0eb52bd4a85a554 100644 (file)
@@ -8,16 +8,20 @@
 #define SELFTEST_KVM_PROCESSOR_H
 
 #include "kvm_util.h"
+#include <linux/stringify.h>
 
 
 #define ARM64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
                           KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
 
-#define CPACR_EL1      3, 0,  1, 0, 2
-#define TCR_EL1                3, 0,  2, 0, 2
-#define MAIR_EL1       3, 0, 10, 2, 0
-#define TTBR0_EL1      3, 0,  2, 0, 0
-#define SCTLR_EL1      3, 0,  1, 0, 0
+#define CPACR_EL1               3, 0,  1, 0, 2
+#define TCR_EL1                 3, 0,  2, 0, 2
+#define MAIR_EL1                3, 0, 10, 2, 0
+#define TTBR0_EL1               3, 0,  2, 0, 0
+#define SCTLR_EL1               3, 0,  1, 0, 0
+#define VBAR_EL1                3, 0, 12, 0, 0
+
+#define ID_AA64DFR0_EL1         3, 0,  0, 5, 0
 
 /*
  * Default MAIR
@@ -56,4 +60,73 @@ void aarch64_vcpu_setup(struct kvm_vm *vm, int vcpuid, struct kvm_vcpu_init *ini
 void aarch64_vcpu_add_default(struct kvm_vm *vm, uint32_t vcpuid,
                              struct kvm_vcpu_init *init, void *guest_code);
 
+struct ex_regs {
+       u64 regs[31];
+       u64 sp;
+       u64 pc;
+       u64 pstate;
+};
+
+#define VECTOR_NUM     16
+
+enum {
+       VECTOR_SYNC_CURRENT_SP0,
+       VECTOR_IRQ_CURRENT_SP0,
+       VECTOR_FIQ_CURRENT_SP0,
+       VECTOR_ERROR_CURRENT_SP0,
+
+       VECTOR_SYNC_CURRENT,
+       VECTOR_IRQ_CURRENT,
+       VECTOR_FIQ_CURRENT,
+       VECTOR_ERROR_CURRENT,
+
+       VECTOR_SYNC_LOWER_64,
+       VECTOR_IRQ_LOWER_64,
+       VECTOR_FIQ_LOWER_64,
+       VECTOR_ERROR_LOWER_64,
+
+       VECTOR_SYNC_LOWER_32,
+       VECTOR_IRQ_LOWER_32,
+       VECTOR_FIQ_LOWER_32,
+       VECTOR_ERROR_LOWER_32,
+};
+
+#define VECTOR_IS_SYNC(v) ((v) == VECTOR_SYNC_CURRENT_SP0 || \
+                          (v) == VECTOR_SYNC_CURRENT     || \
+                          (v) == VECTOR_SYNC_LOWER_64    || \
+                          (v) == VECTOR_SYNC_LOWER_32)
+
+#define ESR_EC_NUM             64
+#define ESR_EC_SHIFT           26
+#define ESR_EC_MASK            (ESR_EC_NUM - 1)
+
+#define ESR_EC_SVC64           0x15
+#define ESR_EC_HW_BP_CURRENT   0x31
+#define ESR_EC_SSTEP_CURRENT   0x33
+#define ESR_EC_WP_CURRENT      0x35
+#define ESR_EC_BRK_INS         0x3c
+
+void vm_init_descriptor_tables(struct kvm_vm *vm);
+void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid);
+
+typedef void(*handler_fn)(struct ex_regs *);
+void vm_install_exception_handler(struct kvm_vm *vm,
+               int vector, handler_fn handler);
+void vm_install_sync_handler(struct kvm_vm *vm,
+               int vector, int ec, handler_fn handler);
+
+#define write_sysreg(reg, val)                                           \
+({                                                                       \
+       u64 __val = (u64)(val);                                           \
+       asm volatile("msr " __stringify(reg) ", %x0" : : "rZ" (__val));   \
+})
+
+#define read_sysreg(reg)                                                 \
+({     u64 val;                                                          \
+       asm volatile("mrs %0, "__stringify(reg) : "=r"(val) : : "memory");\
+       val;                                                              \
+})
+
+#define isb()  asm volatile("isb" : : : "memory")
+
 #endif /* SELFTEST_KVM_PROCESSOR_H */
index 45678a2566dd6a2657b12a20671b4e20a2c9bb51..615ab254899d3b7311287c3ef86837694b6d4b74 100644 (file)
@@ -353,6 +353,7 @@ enum {
        UCALL_SYNC,
        UCALL_ABORT,
        UCALL_DONE,
+       UCALL_UNHANDLED,
 };
 
 #define UCALL_MAX_ARGS 6
@@ -371,27 +372,29 @@ uint64_t get_ucall(struct kvm_vm *vm, uint32_t vcpu_id, struct ucall *uc);
                                ucall(UCALL_SYNC, 6, "hello", stage, arg1, arg2, arg3, arg4)
 #define GUEST_SYNC(stage)      ucall(UCALL_SYNC, 2, "hello", stage)
 #define GUEST_DONE()           ucall(UCALL_DONE, 0)
-#define __GUEST_ASSERT(_condition, _nargs, _args...) do {      \
-       if (!(_condition))                                      \
-               ucall(UCALL_ABORT, 2 + _nargs,                  \
-                       "Failed guest assert: "                 \
-                       #_condition, __LINE__, _args);          \
+#define __GUEST_ASSERT(_condition, _condstr, _nargs, _args...) do {    \
+       if (!(_condition))                                              \
+               ucall(UCALL_ABORT, 2 + _nargs,                          \
+                       "Failed guest assert: "                         \
+                       _condstr, __LINE__, _args);                     \
 } while (0)
 
 #define GUEST_ASSERT(_condition) \
-       __GUEST_ASSERT((_condition), 0, 0)
+       __GUEST_ASSERT(_condition, #_condition, 0, 0)
 
 #define GUEST_ASSERT_1(_condition, arg1) \
-       __GUEST_ASSERT((_condition), 1, (arg1))
+       __GUEST_ASSERT(_condition, #_condition, 1, (arg1))
 
 #define GUEST_ASSERT_2(_condition, arg1, arg2) \
-       __GUEST_ASSERT((_condition), 2, (arg1), (arg2))
+       __GUEST_ASSERT(_condition, #_condition, 2, (arg1), (arg2))
 
 #define GUEST_ASSERT_3(_condition, arg1, arg2, arg3) \
-       __GUEST_ASSERT((_condition), 3, (arg1), (arg2), (arg3))
+       __GUEST_ASSERT(_condition, #_condition, 3, (arg1), (arg2), (arg3))
 
 #define GUEST_ASSERT_4(_condition, arg1, arg2, arg3, arg4) \
-       __GUEST_ASSERT((_condition), 4, (arg1), (arg2), (arg3), (arg4))
+       __GUEST_ASSERT(_condition, #_condition, 4, (arg1), (arg2), (arg3), (arg4))
+
+#define GUEST_ASSERT_EQ(a, b) __GUEST_ASSERT((a) == (b), #a " == " #b, 2, a, b)
 
 int vm_get_stats_fd(struct kvm_vm *vm);
 int vcpu_get_stats_fd(struct kvm_vm *vm, uint32_t vcpuid);
index 6d27a54359719c79951466094cb9f60de14ff416..242ae8e09a653a8362959a03b099cd4f620ff864 100644 (file)
@@ -58,8 +58,6 @@
 /* CPUID.0x8000_0001.EDX */
 #define CPUID_GBPAGES          (1ul << 26)
 
-#define UNEXPECTED_VECTOR_PORT 0xfff0u
-
 /* General Registers in 64-Bit Mode */
 struct gpr64_regs {
        u64 rax;
@@ -396,7 +394,7 @@ struct ex_regs {
 
 void vm_init_descriptor_tables(struct kvm_vm *vm);
 void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid);
-void vm_handle_exception(struct kvm_vm *vm, int vector,
+void vm_install_exception_handler(struct kvm_vm *vm, int vector,
                        void (*handler)(struct ex_regs *));
 
 uint64_t vm_get_page_table_entry(struct kvm_vm *vm, int vcpuid, uint64_t vaddr);
diff --git a/tools/testing/selftests/kvm/lib/aarch64/handlers.S b/tools/testing/selftests/kvm/lib/aarch64/handlers.S
new file mode 100644 (file)
index 0000000..0e443ea
--- /dev/null
@@ -0,0 +1,126 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+.macro save_registers
+       add     sp, sp, #-16 * 17
+
+       stp     x0, x1, [sp, #16 * 0]
+       stp     x2, x3, [sp, #16 * 1]
+       stp     x4, x5, [sp, #16 * 2]
+       stp     x6, x7, [sp, #16 * 3]
+       stp     x8, x9, [sp, #16 * 4]
+       stp     x10, x11, [sp, #16 * 5]
+       stp     x12, x13, [sp, #16 * 6]
+       stp     x14, x15, [sp, #16 * 7]
+       stp     x16, x17, [sp, #16 * 8]
+       stp     x18, x19, [sp, #16 * 9]
+       stp     x20, x21, [sp, #16 * 10]
+       stp     x22, x23, [sp, #16 * 11]
+       stp     x24, x25, [sp, #16 * 12]
+       stp     x26, x27, [sp, #16 * 13]
+       stp     x28, x29, [sp, #16 * 14]
+
+       /*
+        * This stores sp_el1 into ex_regs.sp so exception handlers can "look"
+        * at it. It will _not_ be used to restore the sp on return from the
+        * exception so handlers can not update it.
+        */
+       add     x1, sp, #16 * 17
+       stp     x30, x1, [sp, #16 * 15] /* x30, SP */
+
+       mrs     x1, elr_el1
+       mrs     x2, spsr_el1
+       stp     x1, x2, [sp, #16 * 16] /* PC, PSTATE */
+.endm
+
+.macro restore_registers
+       ldp     x1, x2, [sp, #16 * 16] /* PC, PSTATE */
+       msr     elr_el1, x1
+       msr     spsr_el1, x2
+
+       /* sp is not restored */
+       ldp     x30, xzr, [sp, #16 * 15] /* x30, SP */
+
+       ldp     x28, x29, [sp, #16 * 14]
+       ldp     x26, x27, [sp, #16 * 13]
+       ldp     x24, x25, [sp, #16 * 12]
+       ldp     x22, x23, [sp, #16 * 11]
+       ldp     x20, x21, [sp, #16 * 10]
+       ldp     x18, x19, [sp, #16 * 9]
+       ldp     x16, x17, [sp, #16 * 8]
+       ldp     x14, x15, [sp, #16 * 7]
+       ldp     x12, x13, [sp, #16 * 6]
+       ldp     x10, x11, [sp, #16 * 5]
+       ldp     x8, x9, [sp, #16 * 4]
+       ldp     x6, x7, [sp, #16 * 3]
+       ldp     x4, x5, [sp, #16 * 2]
+       ldp     x2, x3, [sp, #16 * 1]
+       ldp     x0, x1, [sp, #16 * 0]
+
+       add     sp, sp, #16 * 17
+
+       eret
+.endm
+
+.pushsection ".entry.text", "ax"
+.balign 0x800
+.global vectors
+vectors:
+.popsection
+
+.set   vector, 0
+
+/*
+ * Build an exception handler for vector and append a jump to it into
+ * vectors (while making sure that it's 0x80 aligned).
+ */
+.macro HANDLER, label
+handler_\label:
+       save_registers
+       mov     x0, sp
+       mov     x1, #vector
+       bl      route_exception
+       restore_registers
+
+.pushsection ".entry.text", "ax"
+.balign 0x80
+       b       handler_\label
+.popsection
+
+.set   vector, vector + 1
+.endm
+
+.macro HANDLER_INVALID
+.pushsection ".entry.text", "ax"
+.balign 0x80
+/* This will abort so no need to save and restore registers. */
+       mov     x0, #vector
+       mov     x1, #0 /* ec */
+       mov     x2, #0 /* valid_ec */
+       b       kvm_exit_unexpected_exception
+.popsection
+
+.set   vector, vector + 1
+.endm
+
+/*
+ * Caution: be sure to not add anything between the declaration of vectors
+ * above and these macro calls that will build the vectors table below it.
+ */
+       HANDLER_INVALID                         // Synchronous EL1t
+       HANDLER_INVALID                         // IRQ EL1t
+       HANDLER_INVALID                         // FIQ EL1t
+       HANDLER_INVALID                         // Error EL1t
+
+       HANDLER el1h_sync                       // Synchronous EL1h
+       HANDLER el1h_irq                        // IRQ EL1h
+       HANDLER el1h_fiq                        // FIQ EL1h
+       HANDLER el1h_error                      // Error EL1h
+
+       HANDLER el0_sync_64                     // Synchronous 64-bit EL0
+       HANDLER el0_irq_64                      // IRQ 64-bit EL0
+       HANDLER el0_fiq_64                      // FIQ 64-bit EL0
+       HANDLER el0_error_64                    // Error 64-bit EL0
+
+       HANDLER el0_sync_32                     // Synchronous 32-bit EL0
+       HANDLER el0_irq_32                      // IRQ 32-bit EL0
+       HANDLER el0_fiq_32                      // FIQ 32-bit EL0
+       HANDLER el0_error_32                    // Error 32-bit EL0
index ad465ca16237856d73cafd7dfd1b37bd0dd641ac..9f49f6caafe5d6b394f7d36f644ad7a9304d5a6d 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include <linux/compiler.h>
+#include <assert.h>
 
 #include "kvm_util.h"
 #include "../kvm_util_internal.h"
@@ -13,6 +14,8 @@
 
 #define DEFAULT_ARM64_GUEST_STACK_VADDR_MIN    0xac0000
 
+static vm_vaddr_t exception_handlers;
+
 static uint64_t page_align(struct kvm_vm *vm, uint64_t v)
 {
        return (v + vm->page_size) & ~(vm->page_size - 1);
@@ -326,6 +329,100 @@ void vcpu_args_set(struct kvm_vm *vm, uint32_t vcpuid, unsigned int num, ...)
        va_end(ap);
 }
 
+void kvm_exit_unexpected_exception(int vector, uint64_t ec, bool valid_ec)
+{
+       ucall(UCALL_UNHANDLED, 3, vector, ec, valid_ec);
+       while (1)
+               ;
+}
+
 void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid)
 {
+       struct ucall uc;
+
+       if (get_ucall(vm, vcpuid, &uc) != UCALL_UNHANDLED)
+               return;
+
+       if (uc.args[2]) /* valid_ec */ {
+               assert(VECTOR_IS_SYNC(uc.args[0]));
+               TEST_FAIL("Unexpected exception (vector:0x%lx, ec:0x%lx)",
+                         uc.args[0], uc.args[1]);
+       } else {
+               assert(!VECTOR_IS_SYNC(uc.args[0]));
+               TEST_FAIL("Unexpected exception (vector:0x%lx)",
+                         uc.args[0]);
+       }
+}
+
+struct handlers {
+       handler_fn exception_handlers[VECTOR_NUM][ESR_EC_NUM];
+};
+
+void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid)
+{
+       extern char vectors;
+
+       set_reg(vm, vcpuid, ARM64_SYS_REG(VBAR_EL1), (uint64_t)&vectors);
+}
+
+void route_exception(struct ex_regs *regs, int vector)
+{
+       struct handlers *handlers = (struct handlers *)exception_handlers;
+       bool valid_ec;
+       int ec = 0;
+
+       switch (vector) {
+       case VECTOR_SYNC_CURRENT:
+       case VECTOR_SYNC_LOWER_64:
+               ec = (read_sysreg(esr_el1) >> ESR_EC_SHIFT) & ESR_EC_MASK;
+               valid_ec = true;
+               break;
+       case VECTOR_IRQ_CURRENT:
+       case VECTOR_IRQ_LOWER_64:
+       case VECTOR_FIQ_CURRENT:
+       case VECTOR_FIQ_LOWER_64:
+       case VECTOR_ERROR_CURRENT:
+       case VECTOR_ERROR_LOWER_64:
+               ec = 0;
+               valid_ec = false;
+               break;
+       default:
+               valid_ec = false;
+               goto unexpected_exception;
+       }
+
+       if (handlers && handlers->exception_handlers[vector][ec])
+               return handlers->exception_handlers[vector][ec](regs);
+
+unexpected_exception:
+       kvm_exit_unexpected_exception(vector, ec, valid_ec);
+}
+
+void vm_init_descriptor_tables(struct kvm_vm *vm)
+{
+       vm->handlers = vm_vaddr_alloc(vm, sizeof(struct handlers),
+                       vm->page_size, 0, 0);
+
+       *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
+}
+
+void vm_install_sync_handler(struct kvm_vm *vm, int vector, int ec,
+                        void (*handler)(struct ex_regs *))
+{
+       struct handlers *handlers = addr_gva2hva(vm, vm->handlers);
+
+       assert(VECTOR_IS_SYNC(vector));
+       assert(vector < VECTOR_NUM);
+       assert(ec < ESR_EC_NUM);
+       handlers->exception_handlers[vector][ec] = handler;
+}
+
+void vm_install_exception_handler(struct kvm_vm *vm, int vector,
+                        void (*handler)(struct ex_regs *))
+{
+       struct handlers *handlers = addr_gva2hva(vm, vm->handlers);
+
+       assert(!VECTOR_IS_SYNC(vector));
+       assert(vector < VECTOR_NUM);
+       handlers->exception_handlers[vector][0] = handler;
 }
index 3114b18454d5f3b7befa178620bfcb3bef0d20b7..28cb881f440d04f170af3cbaeca4e378e2aea545 100644 (file)
@@ -1276,7 +1276,7 @@ static void set_idt_entry(struct kvm_vm *vm, int vector, unsigned long addr,
 
 void kvm_exit_unexpected_vector(uint32_t value)
 {
-       outl(UNEXPECTED_VECTOR_PORT, value);
+       ucall(UCALL_UNHANDLED, 1, value);
 }
 
 void route_exception(struct ex_regs *regs)
@@ -1319,8 +1319,8 @@ void vcpu_init_descriptor_tables(struct kvm_vm *vm, uint32_t vcpuid)
        *(vm_vaddr_t *)addr_gva2hva(vm, (vm_vaddr_t)(&exception_handlers)) = vm->handlers;
 }
 
-void vm_handle_exception(struct kvm_vm *vm, int vector,
-                        void (*handler)(struct ex_regs *))
+void vm_install_exception_handler(struct kvm_vm *vm, int vector,
+                              void (*handler)(struct ex_regs *))
 {
        vm_vaddr_t *handlers = (vm_vaddr_t *)addr_gva2hva(vm, vm->handlers);
 
@@ -1329,16 +1329,13 @@ void vm_handle_exception(struct kvm_vm *vm, int vector,
 
 void assert_on_unhandled_exception(struct kvm_vm *vm, uint32_t vcpuid)
 {
-       if (vcpu_state(vm, vcpuid)->exit_reason == KVM_EXIT_IO
-               && vcpu_state(vm, vcpuid)->io.port == UNEXPECTED_VECTOR_PORT
-               && vcpu_state(vm, vcpuid)->io.size == 4) {
-               /* Grab pointer to io data */
-               uint32_t *data = (void *)vcpu_state(vm, vcpuid)
-                       + vcpu_state(vm, vcpuid)->io.data_offset;
-
-               TEST_ASSERT(false,
-                           "Unexpected vectored event in guest (vector:0x%x)",
-                           *data);
+       struct ucall uc;
+
+       if (get_ucall(vm, vcpuid, &uc) == UCALL_UNHANDLED) {
+               uint64_t vector = uc.args[0];
+
+               TEST_FAIL("Unexpected vectored event in guest (vector:0x%lx)",
+                         vector);
        }
 }
 
index d0a7a998e84042a801ca8dab04b3bf80c07e31e0..2b46dcca86a8f63ced99ccdfbe263997357388dd 100644 (file)
@@ -165,8 +165,8 @@ int main(int argc, char *argv[])
 
        vm_init_descriptor_tables(vm);
        vcpu_init_descriptor_tables(vm, VCPU_ID);
-       vm_handle_exception(vm, UD_VECTOR, guest_ud_handler);
-       vm_handle_exception(vm, NMI_VECTOR, guest_nmi_handler);
+       vm_install_exception_handler(vm, UD_VECTOR, guest_ud_handler);
+       vm_install_exception_handler(vm, NMI_VECTOR, guest_nmi_handler);
 
        pr_info("Running L1 which uses EVMCS to run L2\n");
 
index 732b244d6956460bf6aba7a5e1f609cdccadbddd..04ed975662c96ca0aa403a72c468e69e1188caa7 100644 (file)
@@ -227,7 +227,7 @@ int main(void)
 
        vm_init_descriptor_tables(vm);
        vcpu_init_descriptor_tables(vm, VCPU_ID);
-       vm_handle_exception(vm, GP_VECTOR, guest_gp_handler);
+       vm_install_exception_handler(vm, GP_VECTOR, guest_gp_handler);
 
        enter_guest(vm);
        kvm_vm_free(vm);
index d672f0a473f872ddbde2beec1002fd4bb6d5aece..fc03a150278d0328ae001a5cfd52627fe8a41268 100644 (file)
 
 #define UCALL_PIO_PORT ((uint16_t)0x1000)
 
+struct ucall uc_none = {
+       .cmd = UCALL_NONE,
+};
+
 /*
  * ucall is embedded here to protect against compiler reshuffling registers
  * before calling a function. In this test we only need to get KVM_EXIT_IO
@@ -34,7 +38,8 @@ void guest_code(void)
        asm volatile("1: in %[port], %%al\n"
                     "add $0x1, %%rbx\n"
                     "jmp 1b"
-                    : : [port] "d" (UCALL_PIO_PORT) : "rax", "rbx");
+                    : : [port] "d" (UCALL_PIO_PORT), "D" (&uc_none)
+                    : "rax", "rbx");
 }
 
 static void compare_regs(struct kvm_regs *left, struct kvm_regs *right)
index e357d8e222d4722f639f698dcfc66c8c5ea52245..5a6a662f2e590ec4da7959b99c2df230c7d3a071 100644 (file)
 #define rounded_rdmsr(x)       ROUND(rdmsr(x))
 #define rounded_host_rdmsr(x)  ROUND(vcpu_get_msr(vm, 0, x))
 
-#define GUEST_ASSERT_EQ(a, b) do {                             \
-       __typeof(a) _a = (a);                                   \
-       __typeof(b) _b = (b);                                   \
-       if (_a != _b)                                           \
-                ucall(UCALL_ABORT, 4,                          \
-                        "Failed guest assert: "                        \
-                        #a " == " #b, __LINE__, _a, _b);       \
-  } while(0)
-
 static void guest_code(void)
 {
        u64 val = 0;
index 72c0d07975221fe30be58bf542f646b56c58f977..e3e20e8848d0c61c0b25db9ad1a949256ff2f6ed 100644 (file)
@@ -574,7 +574,7 @@ static void test_msr_filter_allow(void) {
        vm_init_descriptor_tables(vm);
        vcpu_init_descriptor_tables(vm, VCPU_ID);
 
-       vm_handle_exception(vm, GP_VECTOR, guest_gp_handler);
+       vm_install_exception_handler(vm, GP_VECTOR, guest_gp_handler);
 
        /* Process guest code userspace exits. */
        run_guest_then_process_rdmsr(vm, MSR_IA32_XSS);
@@ -588,12 +588,12 @@ static void test_msr_filter_allow(void) {
        run_guest_then_process_wrmsr(vm, MSR_NON_EXISTENT);
        run_guest_then_process_rdmsr(vm, MSR_NON_EXISTENT);
 
-       vm_handle_exception(vm, UD_VECTOR, guest_ud_handler);
+       vm_install_exception_handler(vm, UD_VECTOR, guest_ud_handler);
        run_guest(vm);
-       vm_handle_exception(vm, UD_VECTOR, NULL);
+       vm_install_exception_handler(vm, UD_VECTOR, NULL);
 
        if (process_ucall(vm) != UCALL_DONE) {
-               vm_handle_exception(vm, GP_VECTOR, guest_fep_gp_handler);
+               vm_install_exception_handler(vm, GP_VECTOR, guest_fep_gp_handler);
 
                /* Process emulated rdmsr and wrmsr instructions. */
                run_guest_then_process_rdmsr(vm, MSR_IA32_XSS);
index 1846117ad584085a4241efaec82b67d0f30be5f3..afbbc40df88408f205c23994e78b0786ba787014 100644 (file)
@@ -421,7 +421,7 @@ int main(int argc, char *argv[])
 
        vm_init_descriptor_tables(vm);
        vcpu_init_descriptor_tables(vm, HALTER_VCPU_ID);
-       vm_handle_exception(vm, IPI_VECTOR, guest_ipi_handler);
+       vm_install_exception_handler(vm, IPI_VECTOR, guest_ipi_handler);
 
        virt_pg_map(vm, APIC_DEFAULT_GPA, APIC_DEFAULT_GPA);
 
diff --git a/tools/testing/selftests/nci/.gitignore b/tools/testing/selftests/nci/.gitignore
new file mode 100644 (file)
index 0000000..448eeb4
--- /dev/null
@@ -0,0 +1 @@
+/nci_dev
index 78ddf5e116254fc685dd508c0a4faa8e5990379c..8e83cf91513a684072bef3caa0161297cae07fa0 100644 (file)
@@ -43,7 +43,7 @@ static struct {
        siginfo_t first_siginfo;        /* First observed siginfo_t. */
 } ctx;
 
-/* Unique value to check si_perf is correctly set from perf_event_attr::sig_data. */
+/* Unique value to check si_perf_data is correctly set from perf_event_attr::sig_data. */
 #define TEST_SIG_DATA(addr) (~(unsigned long)(addr))
 
 static struct perf_event_attr make_event_attr(bool enabled, volatile void *addr)
@@ -164,8 +164,8 @@ TEST_F(sigtrap_threads, enable_event)
        EXPECT_EQ(ctx.signal_count, NUM_THREADS);
        EXPECT_EQ(ctx.tids_want_signal, 0);
        EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
-       EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT);
-       EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on));
+       EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
+       EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on));
 
        /* Check enabled for parent. */
        ctx.iterate_on = 0;
@@ -183,8 +183,8 @@ TEST_F(sigtrap_threads, modify_and_enable_event)
        EXPECT_EQ(ctx.signal_count, NUM_THREADS);
        EXPECT_EQ(ctx.tids_want_signal, 0);
        EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
-       EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT);
-       EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on));
+       EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
+       EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on));
 
        /* Check enabled for parent. */
        ctx.iterate_on = 0;
@@ -203,8 +203,8 @@ TEST_F(sigtrap_threads, signal_stress)
        EXPECT_EQ(ctx.signal_count, NUM_THREADS * ctx.iterate_on);
        EXPECT_EQ(ctx.tids_want_signal, 0);
        EXPECT_EQ(ctx.first_siginfo.si_addr, &ctx.iterate_on);
-       EXPECT_EQ(ctx.first_siginfo.si_errno, PERF_TYPE_BREAKPOINT);
-       EXPECT_EQ(ctx.first_siginfo.si_perf, TEST_SIG_DATA(&ctx.iterate_on));
+       EXPECT_EQ(ctx.first_siginfo.si_perf_type, PERF_TYPE_BREAKPOINT);
+       EXPECT_EQ(ctx.first_siginfo.si_perf_data, TEST_SIG_DATA(&ctx.iterate_on));
 }
 
 TEST_HARNESS_MAIN
index 98c3b647f54dcd982983de4d0ae8ac622d36e8fa..e3d5c77a861213b7628d91957af377f717be8565 100644 (file)
@@ -1753,16 +1753,25 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 # define SYSCALL_RET_SET(_regs, _val)                          \
        do {                                                    \
                typeof(_val) _result = (_val);                  \
-               /*                                              \
-                * A syscall error is signaled by CR0 SO bit    \
-                * and the code is stored as a positive value.  \
-                */                                             \
-               if (_result < 0) {                              \
-                       SYSCALL_RET(_regs) = -_result;          \
-                       (_regs).ccr |= 0x10000000;              \
-               } else {                                        \
+               if ((_regs.trap & 0xfff0) == 0x3000) {          \
+                       /*                                      \
+                        * scv 0 system call uses -ve result    \
+                        * for error, so no need to adjust.     \
+                        */                                     \
                        SYSCALL_RET(_regs) = _result;           \
-                       (_regs).ccr &= ~0x10000000;             \
+               } else {                                        \
+                       /*                                      \
+                        * A syscall error is signaled by the   \
+                        * CR0 SO bit and the code is stored as \
+                        * a positive value.                    \
+                        */                                     \
+                       if (_result < 0) {                      \
+                               SYSCALL_RET(_regs) = -_result;  \
+                               (_regs).ccr |= 0x10000000;      \
+                       } else {                                \
+                               SYSCALL_RET(_regs) = _result;   \
+                               (_regs).ccr &= ~0x10000000;     \
+                       }                                       \
                }                                               \
        } while (0)
 # define SYSCALL_RET_SET_ON_PTRACE_EXIT
index 1cda2e11b3ad9958d5564e204ac20ce0f9a1c6c3..773c5027553d2a607787f447b6b7ca4bf5537fe3 100644 (file)
@@ -9,11 +9,11 @@
         "setup": [
             "$IP link add dev $DUMMY type dummy || /bin/true"
         ],
-        "cmdUnderTest": "$TC qdisc add dev $DUMMY root fq_pie flows 65536",
-        "expExitCode": "2",
+        "cmdUnderTest": "$TC qdisc add dev $DUMMY handle 1: root fq_pie flows 65536",
+        "expExitCode": "0",
         "verifyCmd": "$TC qdisc show dev $DUMMY",
-        "matchPattern": "qdisc",
-        "matchCount": "0",
+        "matchPattern": "qdisc fq_pie 1: root refcnt 2 limit 10240p flows 65536",
+        "matchCount": "1",
         "teardown": [
             "$IP link del dev $DUMMY"
         ]